# rtai_mq.h

    00001 /*
    00002  * pqueues interface for Real Time Linux.
    00003  *
    00004  * Copyright (©) 1999 Zentropic Computing, All rights reserved
    00005  *
    00006  * Authors:         Trevor Woolven (trevw@zentropix.com)
    00007  *
    00008  * Original date:   Thu 15 Jul 1999
    00009  *
    00010  * This program is free software; you can redistribute it and/or
    00011  * modify it under the terms of the GNU General Public License as
    00012  * published by the Free Software Foundation; either version 2 of the
    00013  * License, or (at your option) any later version.
    00014  *
    00015  * This program is distributed in the hope that it will be useful,
    00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00018  * GNU General Public License for more details.
    00019  *
    00020  * You should have received a copy of the GNU General Public License
    00021  * along with this program; if not, write to the Free Software
    00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    00023  */
    00024
    00025 #ifndef _RTAI_MQ_H
    00026 #define _RTAI_MQ_H
    00027
    00028 #include <linux/version.h>
    00029 #include <rtai_sem.h>
    00030
    00031 #define MQ_OPEN_MAX     8       /* Maximum number of message queues per process */
    00032 #define MQ_PRIO_MAX     32      /* Maximum number of message priorities */
    00033 #define MQ_BLOCK        0       /* Flag to set queue into blocking mode */
    00034 #define MQ_NONBLOCK     1       /* Flag to set queue into non-blocking mode */
    00035 #define MQ_NAME_MAX     80      /* Maximum length of a queue name string */
    00036
    00037 #define MQ_MIN_MSG_PRIORITY 0           /* Lowest priority message */
    00038 #define MQ_MAX_MSG_PRIORITY MQ_PRIO_MAX /* Highest priority message */
    00039
    00040 #define MAX_PQUEUES     4       /* Maximum number of message queues in module */
    00041 #define MAX_MSGSIZE     50      /* Maximum message size per queue (bytes) */
    00042 #define MAX_MSGS        10      /* Maximum number of messages per queue */
    00043 #define MAX_BLOCKED_TASKS 10    /* Maximum number of tasks blocked on a */
    00044                                 /* queue at any one time  */
    00045 #define MSG_HDR_SIZE    16      /* Note that this is hard-coded (urgh!) ensure */
    00046                                 /*  it always matches pqueues sizeof(MSG_HDR) */
    00047                                 /*  or do it a better way! (sic) */
    00048 typedef enum {
    00049     FIFO_BASED,
    00050     PRIORITY_BASED
    00051 } QUEUEING_POLICY;
    00052
    00053 typedef enum {
    00054     POSIX,
    00055     VxWORKS
    00056 } QUEUE_TYPE;
    00057
    00058 typedef struct mq_attr {
    00059     long mq_maxmsg;             /* Maximum number of messages in queue */
    00060     long mq_msgsize;            /* Maximum size of a message (in bytes) */
    00061     long mq_flags;              /* Blocking/Non-blocking behaviour specifier */
    00062     long mq_curmsgs;            /* Number of messages currently in queue */
    00063 } MQ_ATTR;
    00064
    00065 #define INVALID_PQUEUE  0
    00066
    00067 #ifdef __KERNEL__
    00068
    00069 #include <linux/types.h>
    00070
    00071 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
    00072 typedef int mqd_t;
    00073 #endif
    00074
    00075 #ifndef __cplusplus
    00076
    00077 typedef int mq_bool_t;
    00078
    00079 #ifndef TRUE
    00080 #define TRUE 1
    00081 #define FALSE 0
    00082 #endif
    00083
    00084 typedef struct msg_hdr {
    00085     mq_bool_t in_use;
    00086     size_t size;                /* Actual message size */
    00087     uint priority;              /* Usage priority (message/task) */
    00088     void *next;                 /* Pointer to next message on queue */
    00089 } MSG_HDR;
    00090
    00091 typedef struct queue_control {
    00092     void *base;         /* Pointer to the base of the queue in memory */
    00093     void *head;         /* Pointer to the element at the front of the queue */
    00094     void *tail;         /* Pointer to the element at the back of the queue */
    00095     MQ_ATTR attrs;      /* Queue attributes */
    00096 } Q_CTRL;
    00097
    00098 typedef struct msg {
    00099     MSG_HDR hdr;
    00100     char data;          /* Anchor point for message data */
    00101 } MQMSG;
    00102
    00103 struct notify {
    00104     RT_TASK *task;
    00105     struct sigevent data;
    00106 };
    00107
    00108 typedef struct _pqueue_descr_struct {
    00109     RT_TASK *owner;             /* Task that created the queue */
    00110     int open_count;             /* Count of the number of tasks that have */
    00111                                 /*  'opened' the queue for access */
    00112     char q_name[MQ_NAME_MAX];   /* Name supplied for queue */
    00113     uint q_id;                  /* Queue Id (index into static list of queues) */
    00114     mq_bool_t marked_for_deletion;      /* Queue can be deleted once all tasks have  */
    00115                                 /*  closed it   */
    00116     Q_CTRL data;                /* Data queue (real messages) */
    00117     mode_t permissions;         /* Permissions granted by creator (ugo, rwx) */
    00118     struct notify notify;       /* Notification data (empty -> !empty) */
    00119     SEM emp_cond;               /* For blocking on empty queue */
    00120     SEM full_cond;              /* For blocking on full queue */
    00121     SEM mutex;                  /* For synchronisation of queue */
    00122 } MSG_QUEUE;
    00123
    00124 struct _pqueue_access_data {
    00125     int q_id;
    00126     int oflags;                 /* Queue access permissions & blocking spec */
    00127 };
    00128
    00129 typedef struct _pqueue_access_struct {
    00130     RT_TASK *this_task;
    00131     int n_open_pqueues;
    00132     struct _pqueue_access_data q_access[MQ_OPEN_MAX];
    00133 } *QUEUE_CTRL;
    00134
    00135 typedef enum {
    00136     FOR_READ,
    00137     FOR_WRITE
    00138 } Q_ACCESS;
    00139
    00140 /*
    00141  * a) A single Posix queue ( (MAX_MSGSIZE + sizeof(MSG_HDR) * MAX_MSGS) ) or
    00142  * b) A blocked tasks queue (MAX_BLOCKED_TASKS * sizeof(MSG_HDR) ) or
    00143  * c) A Zentropix application data staging structure (sizeof(Z_APPS))
    00144  *
    00145  * It is assumed that the first two are both bigger than a Z_APPS structure
    00146  * and so the choice is made between a) and b).
    00147  *
    00148  * Note that one control mechanism is used to allocate memory 'chunks' for a
    00149  * number of different application uses. This means that if the 'chunk' size
    00150  * becomes large in relation to the amount of memory required by one or other
    00151  * of these applications, memory usage becomes wasteful.
    00152  *
    00153  * Set of pointers to Application-Specific extensions to RTAI
    00154  * such as POSIX Threads, POSIX Queues, VxWorks Compatibility Library, etc
    00155  */
    00156
    00157 typedef struct z_apps {
    00158     int in_use_count;   // Incremented whenever an application is initialised
    00159     void *pthreads;
    00160     void *pqueues;
    00161     void *vxtasks;
    00162                         // anticipate... pclocks, psosTasks,
    00163 } Z_APPS;
    00164
    00165 #else /* __cplusplus */
    00166 extern "C" {
    00167 #endif /* !__cplusplus */
    00168
    00169 int __rtai_mq_init(void);
    00170
    00171 void __rtai_mq_exit(void);
    00172
    00173 QUEUEING_POLICY get_task_queueing_policy(void);
    00174
    00175 QUEUEING_POLICY set_task_queuing_policy(QUEUEING_POLICY policy);
    00176
    00177 QUEUE_TYPE get_queue_type(void);
    00178
    00179 QUEUE_TYPE set_queue_type(QUEUE_TYPE type);
    00180
    00181 void *init_z_apps(void *this_task);
    00182
    00183 void free_z_apps(void *this_task);
    00184
    00185 mqd_t mq_open(char *mq_name, int oflags, mode_t permissions, struct mq_attr *mq_attr);
    00186
    00187 size_t _mq_receive(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio, int space);
    00188 static inline size_t mq_receive(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio)
    00189 {
    00190         return _mq_receive(mq, msg_buffer, buflen, msgprio, 1);
    00191 }
    00192
    00193 int _mq_send(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio, int space);
    00194 static inline int mq_send(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio)
    00195 {
    00196         return _mq_send(mq, msg, msglen, msgprio, 1);
    00197 }
    00198
    00199 int mq_close(mqd_t mq);
    00200
    00201 int mq_getattr(mqd_t mq, struct mq_attr *attrbuf);
    00202
    00203 int mq_setattr(mqd_t mq, const struct mq_attr *new_attrs, struct mq_attr *old_attrs);
    00204
    00205 int mq_notify(mqd_t mq, const struct sigevent *notification);
    00206
    00207 int mq_unlink(char *mq_name);
    00208
    00209 size_t _mq_timedreceive(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio, const struct timespec *abstime, int space);
    00210 static inline size_t mq_timedreceive(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio, const struct timespec *abstime)
    00211 {
    00212         return _mq_timedreceive(mq, msg_buffer, buflen, msgprio, abstime, 1);
    00213 }
    00214
    00215 int _mq_timedsend(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio, const struct timespec *abstime, int space);
    00216 static inline int mq_timedsend(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio, const struct timespec *abstime)
    00217 {
    00218         return _mq_timedsend(mq, msg, msglen, msgprio, abstime, 1);
    00219 }
    00220
    00221 #ifdef __cplusplus
    00222 }
    00223 #endif /* __cplusplus */
    00224
    00225 #else /* !__KERNEL__ */
    00226
    00227 #include <signal.h>
    00228 #include <rtai_lxrt.h>
    00229
    00230 #define MQIDX  0
    00231
    00232 typedef int mqd_t;
    00233
    00234 #ifdef __cplusplus
    00235 extern "C" {
    00236 #endif /* __cplusplus */
    00237
    00238 RTAI_PROTO(mqd_t, mq_open,(char *mq_name, int oflags, mode_t permissions, struct mq_attr *mq_attr))
    00239 {
    00240         struct {char *mq_name; int oflags; mode_t permissions; struct mq_attr *mq_attr; int namesize, attrsize; } arg = { mq_name, oflags, permissions, mq_attr, strlen(mq_name) + 1, sizeof(struct mq_attr) };
    00241         return (mqd_t)rtai_lxrt(MQIDX, SIZARG, MQ_OPEN, &arg).i[LOW];
    00242 }
    00243
    00244 RTAI_PROTO(size_t, mq_receive,(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio))
    00245 {
    00246         struct { mqd_t mq; char *msg_buffer; size_t buflen; unsigned int *msgprio; int space; } arg = { mq, msg_buffer, buflen, msgprio, 0 };
    00247         return (size_t)rtai_lxrt(MQIDX, SIZARG, MQ_RECEIVE, &arg).i[LOW];
    00248 }
    00249
    00250 RTAI_PROTO(int, mq_send,(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio))
    00251 {
    00252         struct { mqd_t mq; const char *msg; size_t msglen; unsigned int msgprio; int space; } arg = { mq, msg, msglen, msgprio, 0 };
    00253         return rtai_lxrt(MQIDX, SIZARG, MQ_SEND, &arg).i[LOW];
    00254 }
    00255
    00256 RTAI_PROTO(int, mq_close,(mqd_t mq))
    00257 {
    00258         struct { mqd_t mq; } arg = { mq };
    00259         return rtai_lxrt(MQIDX, SIZARG, MQ_CLOSE, &arg).i[LOW];
    00260 }
    00261
    00262 RTAI_PROTO(int, mq_getattr,(mqd_t mq, struct mq_attr *attrbuf))
    00263 {
    00264         struct { mqd_t mq; struct mq_attr *attrbuf; int attrsize; } arg = { mq, attrbuf, sizeof(struct mq_attr) };
    00265         return rtai_lxrt(MQIDX, SIZARG, MQ_GETATTR, &arg).i[LOW];
    00266 }
    00267
    00268 RTAI_PROTO(int, mq_setattr,(mqd_t mq, const struct mq_attr *new_attrs, struct mq_attr *old_attrs))
    00269 {
    00270         struct { mqd_t mq; const struct mq_attr *new_attrs; struct mq_attr *old_attrs; int attrsize; } arg = { mq, new_attrs, old_attrs, sizeof(struct mq_attr) };
    00271         return rtai_lxrt(MQIDX, SIZARG, MQ_SETATTR, &arg).i[LOW];
    00272 }
    00273
    00274 RTAI_PROTO(int, mq_notify,(mqd_t mq, const struct sigevent *notification))
    00275 {
    00276         struct { mqd_t mq; const struct sigevent *notification; int size; } arg = { mq, notification, sizeof(struct sigevent) };
    00277         return rtai_lxrt(MQIDX, SIZARG, MQ_NOTIFY, &arg).i[LOW];
    00278 }
    00279
    00280 RTAI_PROTO(int, mq_unlink,(char *mq_name))
    00281 {
    00282         struct { char *mq_name; int size; } arg = { mq_name, strlen(mq_name) + 1};
    00283         return rtai_lxrt(MQIDX, SIZARG, MQ_UNLINK, &arg).i[LOW];
    00284 }
    00285
    00286 RTAI_PROTO(size_t, mq_timedreceive,(mqd_t mq, char *msg_buffer, size_t buflen, unsigned int *msgprio, const struct timespec *abstime))
    00287 {
    00288         struct { mqd_t mq; char *msg_buffer; size_t buflen; unsigned int *msgprio; const struct timespec *abstime; int space; } arg = { mq, msg_buffer, buflen, msgprio, abstime, 0 };
    00289         return (size_t)rtai_lxrt(MQIDX, SIZARG, MQ_TIMEDRECEIVE, &arg).i[LOW];
    00290 }
    00291
    00292 RTAI_PROTO(int, mq_timedsend,(mqd_t mq, const char *msg, size_t msglen, unsigned int msgprio, const struct timespec *abstime))
    00293 {
    00294         struct { mqd_t mq; const char *msg; size_t msglen; unsigned int msgprio; const struct timespec *abstime; int space; } arg = { mq, msg, msglen, msgprio, abstime, 0 };
    00295         return rtai_lxrt(MQIDX, SIZARG, MQ_TIMEDSEND, &arg).i[LOW];
    00296 }
    00297
    00298 #ifdef __cplusplus
    00299 }
    00300 #endif /* __cplusplus */
    00301
    00302 #endif /* __KERNEL__ */
    00303
    00304 #endif  /* !_RTAI_MQ_H */