Back to home page

Enduro/X

 
 

    


0001 #include <cgreen/messaging.h>
0002 #include <cgreen/internal/cgreen_pipe.h>
0003 #include <sys/types.h>
0004 #include <stdio.h>
0005 #include <stdlib.h>
0006 #include <string.h>
0007 #include <unistd.h>
0008 
0009 #ifdef _MSC_VER
0010 #include <wincompat.h>
0011 //disable warning on windows
0012 //'getpid','write': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _getpid, _write
0013 #pragma warning(disable:4996)
0014 #else
0015 #include <sched.h>
0016 #endif
0017 
0018 #ifdef __cplusplus
0019 namespace cgreen {
0020 #endif
0021 
0022 #define message_content_size(Type) (sizeof(Type) - sizeof(long))
0023 
0024 typedef struct CgreenMessageQueue_ {
0025     int readpipe;
0026     int writepipe;
0027     pid_t owner;
0028     int tag;
0029 } CgreenMessageQueue;
0030 
0031 typedef struct CgreenMessage_ {
0032     long type;
0033     int result;
0034 } CgreenMessage;
0035 
0036 static CgreenMessageQueue *queues = NULL;
0037 static int queue_count = 0;
0038 
0039 int get_pipe_read_handle(void)
0040 {
0041     if (queue_count)
0042     {
0043         return queues[queue_count - 1].readpipe;
0044     }
0045 
0046     return 0;
0047 }
0048 
0049 int get_pipe_write_handle(void)
0050 {
0051     if (queue_count)
0052     {
0053         return queues[queue_count - 1].writepipe;
0054     }
0055 
0056     return 0;
0057 }
0058 
0059 
0060 
0061 static void clean_up_messaging(void);
0062 
0063 int start_cgreen_messaging(int tag) {
0064     CgreenMessageQueue *tmp;
0065     int pipes[2];
0066     int pipe_result;
0067 
0068     if (queue_count == 0) {
0069         int atexit_result = atexit(&clean_up_messaging);
0070 
0071         if (atexit_result != 0) {
0072             fprintf(stderr, "could not register clean up code\n");
0073             return -1;
0074         }
0075     }
0076 
0077     tmp = (CgreenMessageQueue *) realloc(queues, sizeof(CgreenMessageQueue) * ++queue_count);
0078     if (tmp == NULL) {
0079         /* ignoring return value here, as the world is ending anyways */
0080         (void)atexit(&clean_up_messaging);
0081         return -1;
0082     }
0083     queues = tmp;
0084 
0085     pipe_result = cgreen_pipe_open(pipes);
0086     if (pipe_result != 0) {
0087         fprintf(stderr, "could not create pipes\n");
0088         return -1;
0089     }
0090 
0091     queues[queue_count - 1].readpipe = pipes[0];
0092     queues[queue_count - 1].writepipe = pipes[1];
0093     queues[queue_count - 1].owner = getpid();
0094     queues[queue_count - 1].tag = tag;
0095     return queue_count - 1;
0096 }
0097 
0098 void send_cgreen_message(int messaging, int result) {
0099     CgreenMessage *message;
0100     
0101     message = (CgreenMessage *) malloc(sizeof(CgreenMessage));
0102     if (message == NULL) {
0103       return;
0104     }
0105     memset(message, 0, sizeof(*message));
0106     message->type = queues[messaging].tag;
0107     message->result = result;
0108     cgreen_pipe_write(queues[messaging].writepipe, message, sizeof(CgreenMessage));
0109     /* give the parent a chance to read so that failures are more likely to be output
0110      * before the child crashes
0111      */
0112     sched_yield();
0113 
0114     free(message);
0115 }
0116 
0117 int receive_cgreen_message(int messaging) {
0118     ssize_t received;
0119     int result;
0120     CgreenMessage *message = (CgreenMessage *) malloc(sizeof(CgreenMessage));
0121     if (message == NULL) {
0122       return -1;
0123     }
0124 
0125     received = cgreen_pipe_read(queues[messaging].readpipe, message, sizeof(CgreenMessage));
0126     result = (received > 0 ? message->result : 0);
0127     free(message);
0128     return result;
0129 }
0130 
0131 static void clean_up_messaging(void) {
0132     int i;
0133     for (i = 0; i < queue_count; i++) {
0134         if (queues[i].owner == getpid()) {
0135             cgreen_pipe_close(queues[i].readpipe);
0136             cgreen_pipe_close(queues[i].writepipe);
0137         }
0138     }
0139     free(queues);
0140     queues = NULL;
0141     queue_count = 0;
0142 }
0143 
0144 #ifdef __cplusplus
0145 } // namespace cgreen
0146 #endif
0147 
0148 /* vim: set ts=4 sw=4 et cindent: */