00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 #ifndef _RTAI_MQ_H
00029 #define _RTAI_MQ_H
00030 
00031 #include <linux/version.h>
00032 #include <rtai_sem.h>
00033 #include <rtai_schedcore.h>
00034 
00035 #define MQ_OPEN_MAX 8   
00036 #ifndef MQ_PRIO_MAX
00037 #define MQ_PRIO_MAX 32  
00038 #endif
00039 #define MQ_BLOCK    0   
00040 #define MQ_NONBLOCK 1   
00041 #define MQ_NAME_MAX 80  
00042 
00043 #define MQ_MIN_MSG_PRIORITY 0           
00044 #define MQ_MAX_MSG_PRIORITY MQ_PRIO_MAX     
00045 
00046 #define MAX_PQUEUES     4       
00047 
00048 #define MAX_MSGSIZE     50      
00049 #define MAX_MSGS        10      
00050 
00051 #define O_NOTIFY_NP     0x1000
00052 
00053 typedef struct mq_attr {
00054     long mq_maxmsg;     
00055     long mq_msgsize;        
00056     long mq_flags;      
00057     long mq_curmsgs;        
00058 } MQ_ATTR;
00059 
00060 #define INVALID_PQUEUE  0
00061 
00062 #ifdef __KERNEL__
00063 
00064 #include <linux/types.h>
00065 
00066 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
00067 typedef int mqd_t;
00068 #endif
00069 
00070 #ifndef __cplusplus
00071 
00072 typedef int mq_bool_t;
00073 
00074 #ifndef TRUE
00075 #define TRUE 1
00076 #define FALSE 0
00077 #endif
00078 
00079 typedef struct msg_hdr {
00080     size_t size;        
00081     uint priority;      
00082     void *next;         
00083 } MSG_HDR;
00084 
00085 #define MSG_HDR_SIZE    (sizeof(MSG_HDR))
00086 
00087 typedef struct queue_control {
00088     int nodind;
00089     void **nodes;
00090     void *base;     
00091     void *head;     
00092     void *tail;     
00093     MQ_ATTR attrs;  
00094 } Q_CTRL;
00095 
00096 typedef struct msg {
00097     MSG_HDR hdr;
00098     char data;      
00099 } MQMSG;
00100 
00101 struct notify {
00102     RT_TASK *task;
00103     struct sigevent data;
00104 };
00105 
00106 typedef struct _pqueue_descr_struct {
00107     RT_TASK *owner;     
00108     int open_count;     
00109                 
00110     char q_name[MQ_NAME_MAX];   
00111     uint q_id;          
00112     mq_bool_t marked_for_deletion;  
00113                 
00114     Q_CTRL data;        
00115     mode_t permissions;     
00116     struct notify notify;   
00117     SEM emp_cond;       
00118     SEM full_cond;      
00119     SEM mutex;          
00120 } MSG_QUEUE;
00121 
00122 struct _pqueue_access_data {
00123     int q_id;
00124     int oflags;         
00125     struct sigevent *usp_notifier;
00126 };
00127 
00128 typedef struct _pqueue_access_struct {
00129     RT_TASK *this_task;
00130     int n_open_pqueues;
00131     struct _pqueue_access_data q_access[MQ_OPEN_MAX];
00132 } *QUEUE_CTRL;
00133 
00134 typedef enum {
00135     FOR_READ,
00136     FOR_WRITE
00137 } Q_ACCESS;
00138 
00139 #else 
00140 extern "C" {
00141 #endif 
00142 
00143 int __rtai_mq_init(void);
00144 
00145 void __rtai_mq_exit(void);
00146 
00147 RTAI_SYSCALL_MODE mqd_t _mq_open(char *mq_name, int oflags, mode_t permissions, struct mq_attr *mq_attr, long space);
00148 static inline mqd_t mq_open(char *mq_name, int oflags, mode_t permissions, struct mq_attr *mq_attr)
00149 {
00150     return _mq_open(mq_name, oflags, permissions, mq_attr, 0);
00151 }
00152 
00153 RTAI_SYSCALL_MODE size_t _mq_receive(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio, int space);
00154 static inline size_t mq_receive(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio)
00155 {
00156     return _mq_receive(mq, msg_buffer, buflen, msgprio, 1);
00157 }
00158 
00159 RTAI_SYSCALL_MODE int _mq_send(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio, int space);
00160 static inline int mq_send(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio)
00161 {
00162     return _mq_send(mq, msg, msglen, msgprio, 1);
00163 }
00164 
00165 RTAI_SYSCALL_MODE int mq_close(mqd_t mq);
00166 
00167 RTAI_SYSCALL_MODE int mq_getattr(mqd_t mq, struct mq_attr *attrbuf);
00168 
00169 RTAI_SYSCALL_MODE int mq_setattr(mqd_t mq, const struct mq_attr *new_attrs, struct mq_attr *old_attrs);
00170 
00171 RTAI_SYSCALL_MODE int _mq_notify(mqd_t mq, RT_TASK *task, long space, long rem, const struct sigevent *notification);
00172 static inline int mq_notify(mqd_t mq, const struct sigevent *notification)
00173 {
00174     return _mq_notify(mq, rt_whoami(), 0, (notification ? 0 : 1), notification );
00175 }
00176 
00177 RTAI_SYSCALL_MODE int mq_unlink(char *mq_name);
00178 
00179 RTAI_SYSCALL_MODE size_t _mq_timedreceive(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio, const struct timespec *abstime, int space);
00180 static inline size_t mq_timedreceive(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio, const struct timespec *abstime)
00181 {
00182     return _mq_timedreceive(mq, msg_buffer, buflen, msgprio, abstime, 1);
00183 }
00184 
00185 RTAI_SYSCALL_MODE int _mq_timedsend(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio, const struct timespec *abstime, int space);
00186 static inline int mq_timedsend(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio, const struct timespec *abstime)
00187 {
00188     return _mq_timedsend(mq, msg, msglen, msgprio, abstime, 1);
00189 }
00190 
00191 #ifdef __cplusplus
00192 }
00193 #endif 
00194 
00195 #else 
00196 
00197 #include <errno.h>
00198 #include <signal.h>
00199 #include <rtai_lxrt.h>
00200 #include <rtai_signal.h>
00201 #include <rtai_posix.h>
00202 
00203 #define MQIDX  0
00204 
00205 typedef int mqd_t;
00206 
00207 #ifdef __cplusplus
00208 extern "C" {
00209 #endif 
00210 
00211 struct suprt_fun_arg { mqd_t mq; RT_TASK *task; unsigned long cpuid; pthread_t self; };
00212 
00213 #ifndef __SIGNAL_SUPPORT_FUN_PMQ__
00214 #define __SIGNAL_SUPPORT_FUN_PMQ__
00215 
00216 static void signal_suprt_fun_mq(struct suprt_fun_arg *fun_arg)
00217 {       
00218     struct sigtsk_t { RT_TASK *sigtask; RT_TASK *task; };
00219     struct suprt_fun_arg arg = *fun_arg;
00220     struct sigreq_t { RT_TASK *sigtask; RT_TASK *task; long signal;} sigreq = {NULL, arg.task, (arg.mq + MAXSIGNALS)};  
00221     struct sigevent notification;
00222     
00223     if ((sigreq.sigtask = rt_thread_init(rt_get_name(0), SIGNAL_TASK_INIPRIO, 0, SCHED_FIFO, 1 << arg.cpuid))) {
00224         if (!rtai_lxrt(RTAI_SIGNALS_IDX, sizeof(struct sigreq_t), RT_SIGNAL_REQUEST, &sigreq).i[LOW]) {
00225             struct arg_reg { mqd_t mq; RT_TASK *task; struct sigevent *usp_notification;} arg_reg = {arg.mq, arg.task, ¬ification};
00226             rtai_lxrt(MQIDX, sizeof(struct arg_reg), MQ_REG_USP_NOTIFIER, &arg_reg);
00227             mlockall(MCL_CURRENT | MCL_FUTURE);
00228             rt_make_hard_real_time();
00229             while (rtai_lxrt(RTAI_SIGNALS_IDX, sizeof(struct sigtsk_t), RT_SIGNAL_WAITSIG, &sigreq).i[LOW]) {
00230                 if (notification.sigev_notify == SIGEV_THREAD) {
00231                     notification._sigev_un._sigev_thread._function((sigval_t)notification.sigev_value.sival_int);
00232                 } else if (notification.sigev_notify == SIGEV_SIGNAL) {
00233                     pthread_kill((pthread_t)arg.self, notification.sigev_signo);
00234                 }
00235             }
00236             rt_make_soft_real_time();
00237         }
00238         rt_task_delete(sigreq.sigtask);
00239     }
00240 }   
00241 
00242 #endif
00243 
00244 RTAI_PROTO(int, rt_request_signal_mq, (mqd_t mq))
00245 {
00246         struct suprt_fun_arg { mqd_t mq; RT_TASK *task; unsigned long cpuid; pthread_t self;} arg = { mq, NULL, 0, pthread_self() };
00247         arg.cpuid = rtai_lxrt(RTAI_SIGNALS_IDX, sizeof(void *), RT_SIGNAL_HELPER, (void *)&arg.task).i[LOW];
00248         arg.task = rt_buddy();  
00249         if (rt_thread_create(signal_suprt_fun_mq, &arg, SIGNAL_TASK_STACK_SIZE)) {
00250             int ret;
00251             ret = rtai_lxrt(RTAI_SIGNALS_IDX, sizeof(RT_TASK *), RT_SIGNAL_HELPER, &arg.task).i[LOW];
00252             return ret;
00253         }
00254     return -1;      
00255 }
00256 
00257 
00258 RTAI_PROTO(mqd_t, mq_open,(char *mq_name, int oflags, mode_t permissions, struct mq_attr *mq_attr))
00259 {
00260     mqd_t ret;
00261     struct {char *mq_name; long oflags; long permissions; struct mq_attr *mq_attr; long namesize, attrsize; long space; } arg = { mq_name, oflags, permissions, mq_attr, strlen(mq_name) + 1, sizeof(struct mq_attr), 1 };
00262     if ((ret = (mqd_t)rtai_lxrt(MQIDX, SIZARG, MQ_OPEN, &arg).i[LOW]) >= 0) {
00263         
00264         if (oflags & O_NOTIFY_NP)   {
00265             rt_request_signal_mq (ret);
00266         }
00267         return ret;
00268     }   
00269     errno = -ret;
00270     return -1;
00271 }
00272 
00273 RTAI_PROTO(size_t, mq_receive,(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio))
00274 {
00275     int oldtype, ret;
00276     struct { long mq; char *msg_buffer; long buflen; unsigned int *msgprio; long space; } arg = { mq, msg_buffer, buflen, msgprio, 0 };
00277     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
00278     pthread_testcancel();
00279     ret = (size_t)rtai_lxrt(MQIDX, SIZARG, MQ_RECEIVE, &arg).i[LOW];
00280     pthread_testcancel();
00281     pthread_setcanceltype(oldtype, NULL);
00282     if (ret >= 0) {
00283         return ret;
00284     }
00285     errno = -ret;
00286     return -1;
00287 }
00288 
00289 RTAI_PROTO(int, mq_send,(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio))
00290 {
00291     int oldtype, ret;
00292     struct { long mq; const char *msg; long msglen; unsigned long msgprio; long space; } arg = { mq, msg, msglen, msgprio, 0 };
00293     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
00294     pthread_testcancel();
00295     ret = rtai_lxrt(MQIDX, SIZARG, MQ_SEND, &arg).i[LOW];
00296     pthread_testcancel();
00297     pthread_setcanceltype(oldtype, NULL);
00298     if (ret >= 0) {
00299         return ret;
00300     }
00301     errno = -ret;
00302     return -1;
00303 }
00304 
00305 RTAI_PROTO(int, mq_close,(mqd_t mq))
00306 {
00307     int ret;
00308     struct { long mq; } arg = { mq };
00309     if ((ret = rtai_lxrt(MQIDX, SIZARG, MQ_CLOSE, &arg).i[LOW]) >= 0) {
00310         return ret;
00311     }
00312     errno = -ret;
00313     return -1;
00314 }
00315 
00316 RTAI_PROTO(int, mq_getattr,(mqd_t mq, struct mq_attr *attrbuf))
00317 {
00318     int ret;
00319     struct { long mq; struct mq_attr *attrbuf; long attrsize; } arg = { mq, attrbuf, sizeof(struct mq_attr) };
00320     if ((ret = rtai_lxrt(MQIDX, SIZARG, MQ_GETATTR, &arg).i[LOW]) >= 0) {
00321         return ret;
00322     }
00323     errno = -ret;
00324     return -1;
00325 }
00326 
00327 RTAI_PROTO(int, mq_setattr,(mqd_t mq, const struct mq_attr *new_attrs, struct mq_attr *old_attrs))
00328 {
00329     int ret;
00330     struct { long mq; const struct mq_attr *new_attrs; struct mq_attr *old_attrs; long attrsize; } arg = { mq, new_attrs, old_attrs, sizeof(struct mq_attr) };
00331     if ((ret = rtai_lxrt(MQIDX, SIZARG, MQ_SETATTR, &arg).i[LOW]) >= 0) {
00332         return ret;
00333     }
00334     errno = -ret;
00335     return -1;
00336 }
00337 
00338 RTAI_PROTO(int, mq_notify,(mqd_t mq, const struct sigevent *notification))
00339 {
00340     int ret;
00341     struct { long mq; RT_TASK* task; long space; long rem; const struct sigevent *notification; long size;} arg = { mq, rt_buddy(), 1, (notification ? 0 : 1), notification, sizeof(struct sigevent) };
00342     if ((ret = rtai_lxrt(MQIDX, SIZARG, MQ_NOTIFY, &arg).i[LOW]) >= 0) {
00343         if (ret == O_NOTIFY_NP) {
00344             rt_request_signal_mq (mq);
00345             ret = 0;
00346         }
00347         return ret;
00348     }
00349     errno = -ret;
00350     return -1;
00351 }
00352 
00353 RTAI_PROTO(int, mq_unlink,(char *mq_name))
00354 {
00355     int ret;
00356     struct { char *mq_name; long size; } arg = { mq_name, strlen(mq_name) + 1};
00357     if ((ret = rtai_lxrt(MQIDX, SIZARG, MQ_UNLINK, &arg).i[LOW]) >= 0) {
00358         return ret;
00359     }
00360     errno = -ret;
00361     return -1;
00362 }
00363 
00364 RTAI_PROTO(size_t, mq_timedreceive,(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio, const struct timespec *abstime))
00365 {
00366     int oldtype, ret;
00367     struct { long mq; char *msg_buffer; long buflen; unsigned int *msgprio; const struct timespec *abstime; long space; } arg = { mq, msg_buffer, buflen, msgprio, abstime, 0 };
00368     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
00369     pthread_testcancel();
00370     ret = (size_t)rtai_lxrt(MQIDX, SIZARG, MQ_TIMEDRECEIVE, &arg).i[LOW];
00371     pthread_testcancel();
00372     pthread_setcanceltype(oldtype, NULL);
00373     if (ret >= 0) {
00374         return ret;
00375     }
00376     errno = -ret;
00377     return -1;
00378 }
00379 
00380 RTAI_PROTO(int, mq_timedsend,(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio, const struct timespec *abstime))
00381 {
00382     int oldtype, ret;
00383     struct { long mq; const char *msg; long msglen; unsigned long msgprio; const struct timespec *abstime; long space; } arg = { mq, msg, msglen, msgprio, abstime, 0 };
00384     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
00385     pthread_testcancel();
00386     ret = rtai_lxrt(MQIDX, SIZARG, MQ_TIMEDSEND, &arg).i[LOW];
00387     pthread_testcancel();
00388     pthread_setcanceltype(oldtype, NULL);
00389     if (ret >= 0) {
00390         return ret;
00391     }
00392     errno = -ret;
00393     return -1;
00394 }
00395 
00396 #ifdef __cplusplus
00397 }
00398 #endif 
00399 
00400 #endif 
00401 
00402 #endif