/* A clock program using message passing */ /* Simple_OS include */ #include /* standard library includes */ #include #include #include /* fig_begin message_types */ #define TIME_MESSAGE 0 #define SET_MESSAGE 1 /* fig_end message_types */ /* fig_begin time_struct */ /* time data type */ typedef struct { int hours; int minutes; int seconds; } time_data_type; /* fig_end time_struct */ /* fig_begin msg_struct */ /* data structure for messages */ typedef struct { /* message type */ int type; /* the time */ time_data_type time; } message_data_type; /* fig_end msg_struct */ /* stack size */ #define STACK_SIZE 5000 /* stack declarations */ /* stack for clock_task */ stack_item Clock_Stack[STACK_SIZE]; /* stack for time_task */ stack_item Time_Stack[STACK_SIZE]; /* stack for set_task */ stack_item Set_Stack[STACK_SIZE]; /* task identities, to be set when the tasks are created and then not modified */ int Clock_Task_Id; int Time_Task_Id; int Set_Task_Id; /* init_time: initialises a time variable */ void init_time(time_data_type *time) { /* set starting time */ time->hours = 23; time->minutes = 59; time->seconds = 30; } /* increment_time: increments time with one second */ void increment_time(time_data_type *time) { /* increment time */ time->seconds++; if (time->seconds > 59) { time->seconds = 0; time->minutes++; if (time->minutes > 59) { time->minutes = 0; time->hours++; if (time->hours > 23) { time->hours = 0; } } } } /* set_time: set time to hours, minutes and seconds */ void set_time(time_data_type *time, int hours, int minutes, int seconds) { /* assign values */ time->hours = hours; time->minutes = minutes; time->seconds = seconds; } /* get_time: read time */ void get_time(time_data_type *time, int *hours, int *minutes, int *seconds) { /* read values */ *hours = time->hours; *minutes = time->minutes; *seconds = time->seconds; } /* make_display_message: create string for printout, given a time expressed in hours, minutes and seconds */ void make_display_message(char display_message[], int hours, int minutes, int seconds) { display_message[0] = hours / 10 + '0'; display_message[1] = hours % 10 + '0'; display_message[2] = ':'; display_message[3] = minutes / 10 + '0'; display_message[4] = minutes % 10 + '0'; display_message[5] = ':'; display_message[6] = seconds / 10 + '0'; display_message[7] = seconds % 10 + '0'; display_message[8] = '\0'; } /* time_from_set_message: extract time from set message from user interface */ void time_from_set_message(char message[], int *hours, int *minutes, int *seconds) { sscanf(message,"set %d %d %d",hours, minutes, seconds); } /* time_ok: returns nonzero if hours, minutes and seconds represents a valid time */ int time_ok(int hours, int minutes, int seconds) { return hours >= 0 && hours <= 23 && minutes >= 0 && minutes <= 59 && seconds >= 0 && seconds <= 59; } /* display_time: displays hours, minutes and seconds by sending them to the user interface */ void display_time(time_data_type time) { char display_message[20]; char draw_message[100]; /* convert hours, minutes and seconds to display format */ make_display_message(display_message, time.hours, time.minutes, time.seconds); sprintf(draw_message, "Time: %s", display_message); /* write to user interface */ si_ui_draw_begin(); si_ui_draw_string("send \"set hh mm ss\" to set time", 90, 20); si_ui_draw_string(draw_message, 145, 55); si_ui_draw_end(); } /* tasks */ /* fig_begin clock_task */ /* clock_task: clock task */ void clock_task(void) { /* the current time */ time_data_type time; /* message */ message_data_type message; /* message length */ int length; /* task_id of message sending process */ int send_task_id; /* initialise the time */ set_time(&time, 23, 59, 50); /* infinite loop */ while (1) { /* receive message */ si_message_receive((char *) &message, &length, &send_task_id); /* check message type */ switch(message.type) { case TIME_MESSAGE: /* increment with one second */ increment_time(&time); /* display the time */ display_time(time); break; case SET_MESSAGE: /* assign new value to the current time */ time = message.time; /* display the time */ display_time(time); break; default: /* an error condition */ si_ui_show_error("Illegal message type to clock_task"); } } } /* fig_end clock_task */ /* fig_begin time_task */ /* time_task: time task */ void time_task(void) { /* message to be sent to clock task */ message_data_type message; /* infinite loop */ while (1) { /* it is a move message */ message.type = TIME_MESSAGE; /* send message to clock task */ si_message_send((char *) &message, sizeof(message), Clock_Task_Id); /* wait one second */ si_wait_n_ms(1000); } } /* fig_end time_task */ /* set_task: reads messages from the user interface, and sets the clock, or exits the program */ void set_task(void) { /* fig_begin ui_message */ /* message array */ char ui_message[SI_UI_MAX_MESSAGE_SIZE]; /* fig_end ui_message */ /* time read from user interface */ int hours, minutes, seconds; /* fig_begin clock_task_message */ /* message to be sent to clock task */ message_data_type message; /* fig_end clock_task_message */ /* time variable to use in message */ time_data_type time; /* set GUI size */ si_ui_set_size(400, 200); while(1) { /* read a message */ si_ui_receive(ui_message); /* fig_begin set_task_mod */ /* check if it is a set message */ if (strncmp(ui_message, "set", 3) == 0) { time_from_set_message(ui_message, &hours, &minutes, &seconds); if (time_ok(hours, minutes, seconds)) { /* it is a move message */ message.type = SET_MESSAGE; set_time(&time, hours, minutes, seconds); message.time = time; /* send message to clock task */ si_message_send((char *) &message, sizeof(message), Clock_Task_Id); } else { si_ui_show_error("Illegal value for hours, minutes or seconds"); } } /* fig_end set_task_mod */ /* check if it is an exit message */ else if (strcmp(ui_message, "exit") == 0) { exit(0); } /* not a legal message */ else { si_ui_show_error("unexpected message type"); } } } /* main */ int main(void) { /* initialise kernel */ si_kernel_init(); /* initialise UI channel */ si_ui_init(); /* initialise message handling */ si_message_init(); /* create tasks */ si_task_create(clock_task, &Clock_Stack[STACK_SIZE-1], 20); Clock_Task_Id = 1; si_task_create(time_task, &Time_Stack[STACK_SIZE-1], 10); Time_Task_Id = 2; si_task_create(set_task, &Set_Stack[STACK_SIZE-1], 15); Set_Task_Id = 3; /* start the kernel */ si_kernel_start(); /* will never be here! */ return 0; }