/* * Start system : "taskCONTROL" * taskCONTROL spawns "Alarm_task" and the 3 measuring tasks for temperature, pressure and position * "Alarm_task" installs "SignalHandler" * Signals are sent from measuring tasks and taskCONTROL * * Copyright: B. Skaali, Department of Physics, Oct. 2011 * Any patent infringement will be punished to maximum extent of the law */ #include "vxWorks.h" #include "sysLib.h" #include "stdio.h" #include "signal.h" #include "sigLIB.h" #include "sigCodes.h" #include "mqueue.h" #include "msgQLib.h" #include "fcntl.h" #include "intLib.h" #include "taskLib.h" #include "logLib.h" #include "time.h" #include "errno.h" #include "vwModNum.h" #include "stdlib.h" #include "tickLib.h" /* comment out next line to suppress debug printout */ /*#define DEBUGPRINT */ /* Global priorities (Wind), high priority for Alarm task */ #define PRI_tAlarm 101 #define PRI_tTemp 200 #define PRI_tPressure 200 #define PRI_tPosition 200 /* Real-Time signals in range SIGRTMIN - SIGRTMAX, signal.h */ #define SIGRT1 (SIGRTMIN) #define SIGRT2 (SIGRTMIN + 1) #define SIGRT_TEMP (SIGRTMIN + 2) #define SIGRT_PRESSURE (SIGRTMIN + 3) #define SIGRT_POSITION (SIGRTMIN + 4) /* Measuring loop control */ typedef unsigned int boolean; boolean MeasuringTasksON; /* Task ID's */ int taskIdTemp, taskIdPressure, taskIdPosition, taskIdAlarm; /* ### some stuff fetched from signal.h, C and POSIX stuff only ### */ #ifdef COMMENT_ONLY /* * The sa_flags in struct sigaction */ #define SA_NOCLDSTOP 0x0001 /* Do not generate SIGCHLD when children stop */ #define SA_SIGINFO 0x0002 /* Pass additional siginfo structure */ struct sigaction { union { #if defined(__STDC__) || defined(__cplusplus) void (*__sa_handler)(int); void (*__sa_sigaction)(int, siginfo_t *, void *); #else void (*__sa_handler)(); void (*__sa_sigaction)(); #endif /* __STDC__ */ } sa_u; #define sa_handler sa_u.__sa_handler #define sa_sigaction sa_u.__sa_sigaction sigset_t sa_mask; int sa_flags; }; #endif /*COMMENT_ONLY*/ /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ message queue for communication signal handler => error logger ensures lossless communication, as long as no buffer overflow note that msgQSend() is signal handler "safe", cf. vxworks_kernel_programmers_guide_6.2.pdf, Table 3-19 */ /* message queue name, mode, priority, max messages, message size */ #define MQ_SIGCOM_NAME "mq_sighandler_com" #define MQ_MODE 0 #define MQ_MSGPRI 31 #define MQ_MSGMX 100 #define MQ_MSGNB 8 mqd_t MQ_descriptor; /* POSIX message queue descriptor */ mode_t MQ_mode=(mode_t)MQ_MODE; /* mode, dummy */ struct mq_attr MQ_ma; /* queue attributes structure */ int MQ_mqpri = MQ_MSGPRI; /* priority */ size_t MQ_byte_length = MQ_MSGNB; /* message byte length */ /* The signal handler receives the value of the signal that has triggered the handler. * Additional, sigqueue( )can supply an application specified value to the handler * of type sigval (defined in "signal.h"); the signal handler finds it in the * si_value field of one of its arguments, a structure siginfo_t * * The data structure is as follows: typedef struct siginfo { int si_signo; int si_code; union sigval si_value; } siginfo_t; * sigval is defined in "sigeventCommon.h" union sigval { int sival_int; void *sival_ptr; }; */ /* Global counters for statistics */ int SignalHandlerTriggers; /* total number of signals received by handler */ int ErrorSigHandlerLostSignals; /* signals lost due to message queue full */ int Alarm_taskSIGRT1; /* SIGRT1 signals received */ int Alarm_taskSIGRT2; /* SIGRT2 signals received */ int Alarm_taskSIGRT_TEMP; /* SIGRT_TEMP signals received */ int Alarm_taskSIGRT_PRESSURE; /* SIGRT_PRESSURE signals received */ int Alarm_taskSIGRT_POSITION; /* SIGRT_POSITION signals received */ int Alarm_taskSIGKILL; /* SIGKILL signals received */ int taskCONTROLnoSIGRT1; /* number of SIGRT1 sent from taskCONTROL */ int taskCONTROLnoSIGRT2; /* number of SIGRT2 sent from taskCONTROL */ /* signal handler, sends signal value over message queue to alarm task */ /* see Reference Manual for sigLib */ void SignalHandler (int sig, struct siginfo *info, void *pContext) { char sig_buf[MQ_MSGNB], sival_buf[MQ_MSGNB]; /* send buffers */ #ifdef DEBUGPRINT /* show signal code and additional value as received by handler */ logMsg("SignalHandler: signal, info->si_value.sival_int = %d %d\n", sig, info->si_value.sival_int,0,0,0,0); #endif /* increment trigger counter */ SignalHandlerTriggers++; /* * your code please, for sending signal and sigval into message queue * */ } /* <=== end SignalHandler */ /* Alarm_task - the owner of SignalHandler */ void Alarm_task () { int exitErrno; struct sigaction Saction; ssize_t mq_receive_length; char rbuf[MQ_MSGNB]; /* receive buffer */ int signalToAlarm, sigvalToAlarm; MQ_ma.mq_flags = 0; MQ_ma.mq_maxmsg = MQ_MSGMX; MQ_ma.mq_msgsize = MQ_MSGNB; exitErrno = 0; /* reset global counters */ SignalHandlerTriggers = 0; ErrorSigHandlerLostSignals = 0; Alarm_taskSIGRT1 = 0; Alarm_taskSIGRT2 = 0; Alarm_taskSIGRT_TEMP = 0; Alarm_taskSIGRT_PRESSURE = 0; Alarm_taskSIGRT_POSITION = 0; taskCONTROLnoSIGRT1 = 0; taskCONTROLnoSIGRT2 = 0; /* create message queue for receiving values from signal handler */ if ((MQ_descriptor = mq_open (MQ_SIGCOM_NAME, O_RDWR|O_CREAT, MQ_mode, &MQ_ma)) == (mqd_t)-1) { /* fatal error, give up, go have a beer */ logMsg ("mq_open fatal error",0,0,0,0,0,0); exit(ERROR); } /* connect signal handler, can also be installed by sigvec() or signal() */ Saction.sa_sigaction = SignalHandler; Saction.sa_flags = SA_SIGINFO; /* required for passing additional siginfo structure */ sigemptyset (&Saction.sa_mask); sigaction (SIGRT1, &Saction, NULL); sigaction (SIGRT2, &Saction, NULL); sigaction (SIGRT_TEMP, &Saction, NULL); sigaction (SIGRT_PRESSURE, &Saction, NULL); sigaction (SIGRT_POSITION, &Saction, NULL); sigaction (SIGKILL, &Saction, NULL); /* while (TRUE) once Alarm_task can read SIGKILL from message queue */ while (MeasuringTasksON) { /* * * - here comes the code for reading "signal" and "sigval" from the message queue * * */ /* make some test values in the meantime */ signalToAlarm = SIGRT_TEMP; sigvalToAlarm = -273; taskDelay (200); /* now the alarm task must log the alarm on file and take relevant actions */ switch(signalToAlarm) { case SIGRT1: Alarm_taskSIGRT1++; break; case SIGRT2: Alarm_taskSIGRT2++; break; case SIGRT_TEMP: Alarm_taskSIGRT_TEMP++; logMsg ("ALARM at clock tick %d: temperature = %d\n", tickGet(), sigvalToAlarm,0,0,0,0); break; case SIGRT_PRESSURE: Alarm_taskSIGRT_PRESSURE++; logMsg ("ALARM at clock tick %d: pressure = %d\n", tickGet(), sigvalToAlarm,0,0,0,0); break; case SIGRT_POSITION: Alarm_taskSIGRT_POSITION++; logMsg ("ALARM at clock tick %d: position = %d\n", tickGet(), sigvalToAlarm,0,0,0,0); break; case SIGKILL: goto EndOfTheWorldIsNear; break; default: logMsg (" unknown signal received", 0,0,0,0,0,0); break; } } /* end while (TRUE) */ EndOfTheWorldIsNear: logMsg ("Alarm task terminated\n",0,0,0,0,0,0); } /* skeleton tasks for temperature, pressure and position */ /* simulate error reading with randomized values at random intervals */ STATUS taskTEMPERATURE () { int Alarm_values[10] = {37,52,44,49,46,64,59,77,68,48}; struct siginfo Sinfo; while (MeasuringTasksON) { Sinfo.si_value.sival_int = Alarm_values [rand() % 9]; if (Sinfo.si_value.sival_int > 50) { if (sigqueue (taskIdAlarm, SIGRT_TEMP, Sinfo.si_value) == ERROR) { logMsg (" signal SIGRT_TEMP failed\n",0,0,0,0,0,0); } } taskDelay (rand() % 100); } return OK; } STATUS taskPRESSURE () { int Alarm_values[10] = {88,87,94,92,86,89,91,95,84,93}; struct siginfo Sinfo; while (MeasuringTasksON) { Sinfo.si_value.sival_int = Alarm_values [rand() % 9]; if (Sinfo.si_value.sival_int > 90) { if (sigqueue (taskIdAlarm, SIGRT_PRESSURE, Sinfo.si_value) == ERROR) { logMsg (" signal SIGRT_PRESSURE failed\n",0,0,0,0,0,0); } } taskDelay (rand() % 100); } return OK; } STATUS taskPOSITION () { int Alarm_values[10] = {-3,3,7,-2,-6,-1,3,4,-2,0}; struct siginfo Sinfo; while (MeasuringTasksON) { Sinfo.si_value.sival_int = Alarm_values [rand() % 9]; if (Sinfo.si_value.sival_int < 0) { if (sigqueue (taskIdAlarm, SIGRT_POSITION, Sinfo.si_value) == ERROR) { logMsg (" signal SIGRT_PRESSURE failed\n",0,0,0,0,0,0); } } taskDelay (rand() % 100); } return OK; } /* =====> Control task - start here <===== */ STATUS taskCONTROL () { struct siginfo Sinfo; int CommandNo; void print_statistics(); printf("\nBienvenue, il est %s\n",__DATE__); /* spawn tasks */ if ((taskIdAlarm = taskSpawn ("tAlarm", PRI_tAlarm, 0, 4000, (FUNCPTR)Alarm_task, 0,0,0,0,0,0,0,0,0,0)) == ERROR) { logMsg ("Spawning taskALARM failed\n",0,0,0,0,0,0); return ERROR; } /* start the measuring tasks */ MeasuringTasksON = TRUE; if ((taskIdTemp = taskSpawn ("tTemp", PRI_tTemp, 0, 4000, (FUNCPTR)taskTEMPERATURE, 0,0,0,0,0,0,0,0,0,0)) == ERROR) { printf("Spawning taskTEMPERATURE failed\n"); return ERROR; } if ((taskIdPressure = taskSpawn ("tPressure", PRI_tPressure, 0, 4000, (FUNCPTR)taskPRESSURE, 0,0,0,0,0,0,0,0,0,0)) == ERROR) { printf("Spawning taskTEMPERATURE failed\n"); return ERROR; } if ((taskIdPosition = taskSpawn ("tPosition", PRI_tPosition, 0, 4000, (FUNCPTR)taskPOSITION, 0,0,0,0,0,0,0,0,0,0)) == ERROR) { printf("Spawning taskTEMPERATURE failed\n"); exit(ERROR); } /* Command loop */ while (TRUE) { printf("\nCommand menu"); printf("\n 1 : fire SIGRT1 and SIGRT2"); printf("\n 2 : print statistics"); printf("\n 3 : exit"); printf("\nType command no and RETURN:"); scanf("%d", &CommandNo); printf("%d\n", CommandNo); switch (CommandNo) { case (1): Sinfo.si_value.sival_int = 111; if (sigqueue (taskIdAlarm, SIGRT1, Sinfo.si_value) == ERROR) { printf("task CTRL, sigqueue (SIGRT1) failed \n"); taskCONTROLnoSIGRT1++; } else printf("taskCTRL: fire signal %d\n", SIGRT1); Sinfo.si_value.sival_int = 222; if (sigqueue (taskIdAlarm, SIGRT2, Sinfo.si_value) == ERROR) { printf("task CTRL, sigqueue (SIGRT2) failed \n"); taskCONTROLnoSIGRT2++; } else printf("taskCTRL: fire signal %d\n", SIGRT2); break; case (2): print_statistics(); break; case (3): /* blow out the temperature, pressure and position monitoring tasks */ MeasuringTasksON = FALSE; Sinfo.si_value.sival_int = -999; if (sigqueue (taskIdAlarm, SIGKILL, Sinfo.si_value) == ERROR) { printf("task CTRL, sigqueue (SIGKILL) failed (no buffer) \n"); print_statistics(); return ERROR; } else { printf("Alarm task terminated\n"); print_statistics(); printf("Control_task: Bye-Bye \n\n"); return OK; } break; default: printf("Completely unknown command\n"); break; } /* end switch */ } /* end command loop */ return OK; } void print_statistics() { printf("\n"); printf("*** signal statistics at tick %d\n", (int)tickGet()); printf("SignalHandler trigger count = %d\n", SignalHandlerTriggers); printf("SignalHandler mq_send() buffer full error = %d\n", ErrorSigHandlerLostSignals); printf("taskCONTROL SIGRT1 sigqueue() error = %d\n", taskCONTROLnoSIGRT1); printf("taskCONTROL SIGRT2 sigqueue() error = %d\n", taskCONTROLnoSIGRT2); printf("Alarm_task SIGRT1 signals received = %d\n", Alarm_taskSIGRT1); printf("Alarm_task SIGRT2 signals received = %d\n", Alarm_taskSIGRT2); printf("Alarm_task SIGRT_TEMP signals received = %d\n", Alarm_taskSIGRT_TEMP); printf("Alarm_task SIGRT_PRESSURE signals received = %d\n", Alarm_taskSIGRT_PRESSURE); printf("Alarm_task SIGRT_POSITION signals received = %d\n", Alarm_taskSIGRT_POSITION); }