ChorusOS 4.0 Hot Restart Programmer's Guide

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;
	
}