B.3.2 HR_child.c
#include <stdio.h>
#include <strings.h>
#include <pmm/chPmm.h>
#include <hr/hr.h>
#include <exec/chExec.h>
#include <pd/chPd.h>
#include <errno.h>
#define PM_MEDIUM "RAM"
#define PM_NAME "CHILD_PM"
#define MESSAGE_NAME "CHILD_MESSAGE"
#define MESSAGE_SIZE 100
typedef struct _HR_Status {
int restarted;
int checkpoint;
} HR_Status;
/*
* Static variables
*/
static HR_Status *st;
/*
* Wait "sec" seconds.
*/
void
waitSec(int sec)
{
KnTimeVal delay;
delay.tmSec = sec;
delay.tmNSec = 0;
(void) threadDelay(&delay);
}
/*
* General operations in all steps.
*/
void
gen_step (char** message, char* m_out)
{
strcat(*message, m_out);
printf("%s", m_out);
fflush(NULL);
/*
* st is stored in persistent memory.
* If the actor does not reach the end of the next instruction
* before a hot restart, the current step will be repeated.
*/
st->checkpoint=++(st->checkpoint) % 4;
}
/*
* step1
*/
void
step1 (char** message)
{
gen_step(message, " STEP 1 ");
}
/*
* step2
*/
void
step2 (char** message)
{
gen_step(message, " STEP 2 ");
}
/*
* step3
*/
void
step3 (char** message)
{
gen_step(message, " STEP 3 ");
}
/*
* step4
*/
void
step4 (char** message)
{
gen_step(message, " STEP 4 ");
/*
* Print out the entire message at the end of the cycle.
* The entire message is printed even if the child actor is
* restarted during a cycle.
*
* =========== Message ===========
* STEP 1 STEP 2 STEP 3 STEP 4
* ======== End of message========
*
* Note that output from the parent actor may garble
* this output.
*/
printf("\n\n=========== Message ===========\n");
printf("%s", *message);
printf("\n======== End of message========\n\n");
/*
* Reset the message.
*/
bzero(*message, MESSAGE_SIZE);
}
/*
* Function to be executed before the actor exits for any reason.
*/
void
before_exit()
{
printf("CHILD EXITS!\n");
}
/*
* main
*/
int
main(int argc, char** argv, char**envp)
{
int res;
int counter;
static PmmName name;
static PmmName m_name;
size_t size;
PdKey key;
char message[MESSAGE_SIZE];
KnActorPrivilege curActPriv;
res = actorPrivilege(K_MYACTOR, &curActPriv, NULL);
if (res != K_OK) {
printf("actorPrivilege failed, res=%d\n", res);
HR_EXIT_HDL();
exit(-1);
}
if (curActPriv == K_SUPACTOR) {
/*
* Create a private actor data key with a destructor associated
* with it.
*/
res = padKeyCreate(&key, (KnPdHdl)before_exit);
if(res != 0) {
printf("Couldn't create PD key. Exit with errno %d\n", errno);
HR_EXIT_HDL();
exit(-1);
}
res = padSet(K_MYACTOR, key, "M");
if (res != K_OK) {
printf("Cannot set the PD key, error %d\n", res);
HR_EXIT_HDL();
exit(-1);
}
} else {
res=atexit(&before_exit);
/*
* atexit() accepts up to 32 functions so this cannot fail.
*/
}
/*
* Initialize the name and medium fields for the HR_Status structure.
*/
bzero(&name, sizeof(name));
strcpy(name.medium,PM_MEDIUM);
strcpy(name.name,PM_NAME);
/*
* Allocate or map the data in st in persistent memory.
*/
res=pmmAllocate((VmAddr *)&st,
&name,
sizeof(HR_Status),
HR_GROUP_KEY,
HR_GROUP_KEYSIZE);
if (res != K_OK) {
printf("Cannot allocate or map the persistent memory block called %s."
" Error = %d\n", name.name, res);
HR_EXIT_HDL();
exit(-1);
}
/*
* Initialize the name and medium fields for the message char buffer.
*/
bzero(&m_name, sizeof(m_name));
strcpy(m_name.medium,PM_MEDIUM);
strcpy(m_name.name,MESSAGE_NAME);
/*
* Allocate or map the message data in persistent memory.
*/
res=pmmAllocate((VmAddr *)&message,
&m_name,
MESSAGE_SIZE,
HR_GROUP_KEY,
HR_GROUP_KEYSIZE);
if (res != K_OK) {
printf("Cannot allocate or map the persistent memory block called %s."
" Error = %d\n", name.name, res);
HR_EXIT_HDL();
exit(-1);
}
/*
* If the actor has been restarted, print out a message.
*/
if (st->restarted>0) {
printf("CHILD RESTARTS (%d-th time)\n", st->restarted);
}
/*
* Increase the "restarted" counter.
*/
st->restarted++;
/*
* Loop forever.
* Each time the parent actor crashes, the child actor will be
* stopped with it since they belong
* to the same group.
*/
while ( 1 ) {
waitSec(1);
switch ( st->checkpoint ) {
case 0:
step1(&message);
break;
case 1:
step2(&message);
break;
case 2:
step3(&message);
break;
case 3:
step4(&message);
break;
default:
break;
}
}
return 0;
}