00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include <linux/module.h>
00022
#include <linux/kernel.h>
00023
#include <linux/errno.h>
00024
#include <asm/uaccess.h>
00025
00026
#include <rtai_registry.h>
00027
#include <rtai_schedcore.h>
00028
#include <rtai_tbx.h>
00029
00030
MODULE_LICENSE(
"GPL");
00031
00032 static inline void enq_msg(
RT_MSGQ *q, RT_MSGH *msg)
00033 {
00034 RT_MSGH *prev, *next;
00035
00036
for (prev = next = q->firstmsg; msg->priority >= next->priority; prev = next, next = next->next);
00037
if (next == prev) {
00038 msg->next = next;
00039 q->firstmsg = msg;
00040 }
else {
00041 msg->next = prev->next;
00042 prev->next = msg;
00043 }
00044 }
00045
00046 int rt_msgq_init(
RT_MSGQ *mq,
int nmsg,
int msg_size)
00047 {
00048
int i;
00049
void *p;
00050
00051
if (!(mq->slots =
rt_malloc((msg_size + RT_MSGH_SIZE +
sizeof(
void *))*nmsg + RT_MSGH_SIZE))) {
00052
return -ENOMEM;
00053 }
00054 mq->nmsg = nmsg;
00055 mq->fastsize = msg_size;
00056 mq->slot = 0;
00057 p = mq->slots + nmsg;
00058
for (i = 0; i < nmsg; i++) {
00059 mq->slots[i] = p;
00060 ((RT_MSGH *)p)->priority = 0;
00061 p += (msg_size + RT_MSGH_SIZE);
00062 }
00063 ((RT_MSGH *)(mq->firstmsg = p))->priority = (0xFFFFFFFF/2);
00064
rt_typed_sem_init(&mq->receivers, 1,
RES_SEM);
00065
rt_typed_sem_init(&mq->senders, 1,
RES_SEM);
00066
rt_typed_sem_init(&mq->received, 0,
CNT_SEM);
00067
rt_typed_sem_init(&mq->freslots, nmsg,
CNT_SEM);
00068 spin_lock_init(&mq->lock);
00069
return 0;
00070 }
00071
00072 int rt_msgq_delete(
RT_MSGQ *mq)
00073 {
00074
if (
rt_sem_delete(&mq->receivers) |
rt_sem_delete(&mq->senders) |
rt_sem_delete(&mq->received) |
rt_sem_delete(&mq->freslots) |
rt_sem_delete(&mq->broadcast)) {
00075
return -EFAULT;
00076 }
00077
rt_free(mq->slots);
00078
return 0;
00079 }
00080
00081 RT_MSGQ *
_rt_named_msgq_init(
unsigned long msgq_name,
int nmsg,
int msg_size)
00082 {
00083
RT_MSGQ *msgq;
00084
00085
if ((msgq =
rt_get_adr_cnt(msgq_name))) {
00086
return msgq;
00087 }
00088
if ((msgq =
rt_malloc(
sizeof(
RT_MSGQ)))) {
00089
rt_msgq_init(msgq, nmsg, msg_size);
00090
if (
rt_register(msgq_name, msgq,
IS_MBX, 0)) {
00091
return msgq;
00092 }
00093
rt_msgq_delete(msgq);
00094 }
00095
rt_free(msgq);
00096
return NULL;
00097 }
00098
00099 int rt_named_msgq_delete(
RT_MSGQ *msgq)
00100 {
00101
int ret;
00102
if (!(ret =
rt_drg_on_adr_cnt(msgq))) {
00103
if (!
rt_msgq_delete(msgq)) {
00104
rt_free(msgq);
00105
return 0;
00106 }
else {
00107
return -EFAULT;
00108 }
00109 }
00110
return ret;
00111 }
00112
00113 static int _send(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
int space)
00114 {
00115
unsigned long flags;
00116 RT_MSG *msg_ptr;
00117
void *p;
00118
00119
if (msg_size > mq->fastsize) {
00120
if (!(p =
rt_malloc(msg_size))) {
00121
rt_sem_signal(&mq->freslots);
00122
rt_sem_signal(&mq->senders);
00123
return -ENOMEM;
00124 }
00125 }
else {
00126 p = NULL;
00127 }
00128
flags =
rt_spin_lock_irqsave(&mq->lock);
00129 msg_ptr = mq->slots[mq->slot++];
00130
rt_spin_unlock_irqrestore(
flags, &mq->lock);
00131 msg_ptr->hdr.size = msg_size;
00132 msg_ptr->hdr.priority = msgpri;
00133 msg_ptr->hdr.malloc = p;
00134 msg_ptr->hdr.broadcast = 0;
00135
if (space) {
00136 memcpy(p ? p : msg_ptr->msg, msg, msg_size);
00137 }
else {
00138 rt_copy_from_user(p ? p : msg_ptr->msg, msg, msg_size);
00139 }
00140
flags =
rt_spin_lock_irqsave(&mq->lock);
00141
enq_msg(mq, &msg_ptr->hdr);
00142
rt_spin_unlock_irqrestore(
flags, &mq->lock);
00143
rt_sem_signal(&mq->received);
00144
rt_sem_signal(&mq->senders);
00145
return 0;
00146 }
00147
00148 int _rt_msg_send(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
int space)
00149 {
00150
if (
rt_sem_wait(&mq->senders) >=
SEM_TIMOUT) {
00151
return msg_size;
00152 }
00153
if (
rt_sem_wait(&mq->freslots) >=
SEM_TIMOUT) {
00154
rt_sem_signal(&mq->senders);
00155
return msg_size;
00156 }
00157
return _send(mq, msg, msg_size, msgpri, space);
00158 }
00159
00160 int _rt_msg_send_if(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
int space)
00161 {
00162
if (
rt_sem_wait_if(&mq->senders) <= 0) {
00163
return msg_size;
00164 }
00165
if (
rt_sem_wait_if(&mq->freslots) <= 0) {
00166
rt_sem_signal(&mq->senders);
00167
return msg_size;
00168 }
00169
return _send(mq, msg, msg_size, msgpri, space);
00170 }
00171
00172 int _rt_msg_send_until(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
RTIME until,
int space)
00173 {
00174
if (
rt_sem_wait_until(&mq->senders, until) >=
SEM_TIMOUT) {
00175
return msg_size;
00176 }
00177
if (
rt_sem_wait_until(&mq->freslots, until) >=
SEM_TIMOUT) {
00178
rt_sem_signal(&mq->senders);
00179
return msg_size;
00180 }
00181
return _send(mq, msg, msg_size, msgpri, space);
00182 }
00183
00184 int _rt_msg_send_timed(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
RTIME delay,
int space)
00185 {
00186
return _rt_msg_send_until(mq, msg, msg_size, msgpri, get_time() + delay, space);
00187 }
00188
00189 static int _receive(
RT_MSGQ *mq,
void *msg,
int msg_size,
int *msgpri,
int space)
00190 {
00191
int size;
00192 RT_MSG *msg_ptr;
00193
void *p;
00194
00195 size = min((msg_ptr = mq->firstmsg)->hdr.size, msg_size);
00196
if (space) {
00197 memcpy(msg, (p = msg_ptr->hdr.malloc) ? p : msg_ptr->msg, size);
00198
if (msgpri) {
00199 *msgpri = msg_ptr->hdr.priority;
00200 }
00201 }
else {
00202 rt_copy_to_user(msg, (p = msg_ptr->hdr.malloc) ? p : msg_ptr->msg, size);
00203
if (msgpri) {
00204 rt_put_user(msg_ptr->hdr.priority, msgpri);
00205 }
00206 }
00207
00208
if (msg_ptr->hdr.broadcast) {
00209
if (!--msg_ptr->hdr.broadcast) {
00210
rt_sem_wait_barrier(&mq->broadcast);
00211
goto relslot;
00212 }
else {
00213
rt_sem_signal(&mq->received);
00214
rt_sem_signal(&mq->receivers);
00215
rt_sem_wait_barrier(&mq->broadcast);
00216 }
00217 }
else {
00218
unsigned long flags;
00219 relslot:
flags =
rt_spin_lock_irqsave(&mq->lock);
00220 mq->firstmsg = msg_ptr->hdr.next;
00221 mq->slots[--mq->slot] = msg_ptr;
00222
rt_spin_unlock_irqrestore(
flags, &mq->lock);
00223
rt_sem_signal(&mq->freslots);
00224
rt_sem_signal(&mq->receivers);
00225
if (p) {
00226
rt_free(p);
00227 }
00228 }
00229
return msg_size - size;
00230 }
00231
00232 int _rt_msg_receive(
RT_MSGQ *mq,
void *msg,
int msg_size,
int *msgpri,
int space)
00233 {
00234
if (
rt_sem_wait(&mq->receivers) >=
SEM_TIMOUT) {
00235
return msg_size;
00236 }
00237
if (
rt_sem_wait(&mq->received) >=
SEM_TIMOUT) { ;
00238
rt_sem_signal(&mq->receivers);
00239
return msg_size;
00240 }
00241
return _receive(mq, msg, msg_size, msgpri, space);
00242 }
00243
00244 int _rt_msg_receive_if(
RT_MSGQ *mq,
void *msg,
int msg_size,
int *msgpri,
int space)
00245 {
00246
if (
rt_sem_wait_if(&mq->receivers) <= 0) {
00247
return msg_size;
00248 }
00249
if (
rt_sem_wait_if(&mq->received) <= 0) { ;
00250
rt_sem_signal(&mq->receivers);
00251
return msg_size;
00252 }
00253
return _receive(mq, msg, msg_size, msgpri, space);
00254 }
00255
00256 int _rt_msg_receive_until(
RT_MSGQ *mq,
void *msg,
int msg_size,
int *msgpri,
RTIME until,
int space)
00257 {
00258
if (
rt_sem_wait_until(&mq->receivers, until) >=
SEM_TIMOUT) {
00259
return msg_size;
00260 }
00261
if (
rt_sem_wait_until(&mq->received, until) >=
SEM_TIMOUT) { ;
00262
rt_sem_signal(&mq->receivers);
00263
return msg_size;
00264 }
00265
return _receive(mq, msg, msg_size, msgpri, space);
00266 }
00267
00268 int _rt_msg_receive_timed(
RT_MSGQ *mq,
void *msg,
int msg_size,
int *msgpri,
RTIME delay,
int space)
00269 {
00270
return _rt_msg_receive_until(mq, msg, msg_size, msgpri, get_time() + delay, space);
00271 }
00272
00273 int _rt_msg_evdrp(
RT_MSGQ *mq,
void *msg,
int msg_size,
int *msgpri,
int space)
00274 {
00275
int size;
00276 RT_MSG *msg_ptr;
00277
void *p;
00278
00279 size = min((msg_ptr = mq->firstmsg)->hdr.size, msg_size);
00280
if (space) {
00281 memcpy(msg, (p = msg_ptr->hdr.malloc) ? p : msg_ptr->msg, size);
00282
if (msgpri) {
00283 *msgpri = msg_ptr->hdr.priority;
00284 }
00285 }
else {
00286 rt_copy_to_user(msg, (p = msg_ptr->hdr.malloc) ? p : msg_ptr->msg, size);
00287
if (msgpri) {
00288 rt_put_user(msg_ptr->hdr.priority, msgpri);
00289 }
00290 }
00291
return 0;
00292 }
00293
00294 static int _broadcast(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
int broadcast,
int space)
00295 {
00296
unsigned long flags;
00297 RT_MSG *msg_ptr;
00298
void *p;
00299
00300
if (msg_size > mq->fastsize) {
00301
if (!(p =
rt_malloc(msg_size))) {
00302
rt_sem_signal(&mq->freslots);
00303
rt_sem_signal(&mq->senders);
00304
return -ENOMEM;
00305 }
00306 }
else {
00307 p = NULL;
00308 }
00309
flags =
rt_spin_lock_irqsave(&mq->lock);
00310 msg_ptr = mq->slots[mq->slot++];
00311
rt_spin_unlock_irqrestore(
flags, &mq->lock);
00312 msg_ptr->hdr.size = msg_size;
00313 msg_ptr->hdr.priority = msgpri;
00314 msg_ptr->hdr.malloc = p;
00315
if (space) {
00316 memcpy(p ? p : msg_ptr->msg, msg, msg_size);
00317 }
else {
00318 rt_copy_from_user(p ? p : msg_ptr->msg, msg, msg_size);
00319 }
00320
rt_typed_sem_init(&mq->broadcast, broadcast + 1,
CNT_SEM |
PRIO_Q);
00321 msg_ptr->hdr.broadcast = broadcast;
00322
flags =
rt_spin_lock_irqsave(&mq->lock);
00323
enq_msg(mq, &msg_ptr->hdr);
00324
rt_spin_unlock_irqrestore(
flags, &mq->lock);
00325
rt_sem_signal(&mq->received);
00326
rt_sem_wait_barrier(&mq->broadcast);
00327
rt_sem_signal(&mq->senders);
00328
return broadcast;
00329 }
00330
00331 int _rt_msg_broadcast(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
int space)
00332 {
00333
if (
rt_sem_wait(&mq->senders) >=
SEM_TIMOUT) {
00334
return 0;
00335 }
00336
if (mq->received.count >= 0) {
00337
rt_sem_signal(&mq->senders);
00338
return 0;
00339 }
00340
if (
rt_sem_wait(&mq->freslots) >=
SEM_TIMOUT) {
00341
rt_sem_signal(&mq->senders);
00342
return 0;
00343 }
00344
return _broadcast(mq, msg, msg_size, msgpri, -(mq->received.count + mq->receivers.count), space);
00345 }
00346
00347 int _rt_msg_broadcast_if(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
int space)
00348 {
00349
if (
rt_sem_wait_if(&mq->senders) <= 0) {
00350
return 0;
00351 }
00352
if (mq->received.count >= 0) {
00353
rt_sem_signal(&mq->senders);
00354
return 0;
00355 }
00356
if (
rt_sem_wait_if(&mq->freslots) <= 0) {
00357
rt_sem_signal(&mq->senders);
00358
return 0;
00359 }
00360
return _broadcast(mq, msg, msg_size, msgpri, -(mq->received.count + mq->receivers.count), space);
00361 }
00362
00363 int _rt_msg_broadcast_until(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
RTIME until,
int space)
00364 {
00365
if (
rt_sem_wait_until(&mq->senders, until) >=
SEM_TIMOUT) {
00366
return 0;
00367 }
00368
if (mq->received.count >= 0) {
00369
rt_sem_signal(&mq->senders);
00370
return 0;
00371 }
00372
if (
rt_sem_wait_until(&mq->freslots, until) >=
SEM_TIMOUT) {
00373
rt_sem_signal(&mq->senders);
00374
return 0;
00375 }
00376
return _broadcast(mq, msg, msg_size, msgpri, -(mq->received.count + mq->receivers.count), space);
00377 }
00378
00379 int _rt_msg_broadcast_timed(
RT_MSGQ *mq,
void *msg,
int msg_size,
int msgpri,
RTIME delay,
int space)
00380 {
00381
return _rt_msg_broadcast_until(mq, msg, msg_size, msgpri, get_time() + delay, space);
00382 }
00383
00384 struct rt_native_fun_entry
rt_msg_queue_entries[] = {
00385 { { 0,
rt_msgq_init },
MSGQ_INIT },
00386 { { 1,
rt_msgq_delete },
MSGQ_DELETE },
00387 { { 0,
_rt_named_msgq_init },
NAMED_MSGQ_INIT },
00388 { { 1,
rt_named_msgq_delete },
NAMED_MSGQ_DELETE },
00389 { { 1,
_rt_msg_send },
MSG_SEND },
00390 { { 1,
_rt_msg_send_if },
MSG_SEND_IF },
00391 { { 1,
_rt_msg_send_until },
MSG_SEND_UNTIL },
00392 { { 1,
_rt_msg_send_timed },
MSG_SEND_TIMED },
00393 { { 1,
_rt_msg_receive },
MSG_RECEIVE },
00394 { { 1,
_rt_msg_receive_if },
MSG_RECEIVE_IF },
00395 { { 1,
_rt_msg_receive_until },
MSG_RECEIVE_UNTIL },
00396 { { 1,
_rt_msg_receive_timed },
MSG_RECEIVE_TIMED },
00397 { { 1,
_rt_msg_broadcast },
MSG_BROADCAST },
00398 { { 1,
_rt_msg_broadcast_if },
MSG_BROADCAST_IF },
00399 { { 1,
_rt_msg_broadcast_until },
MSG_BROADCAST_UNTIL },
00400 { { 1,
_rt_msg_broadcast_timed },
MSG_BROADCAST_TIMED },
00401 { { 1,
_rt_msg_evdrp },
MSG_EVDRP },
00402 { { 0, 0 }, 000 }
00403 };
00404
00405
extern int set_rt_fun_entries(
struct rt_native_fun_entry *entry);
00406
extern void reset_rt_fun_entries(
struct rt_native_fun_entry *entry);
00407
00408 int __rtai_msg_queue_init(
void)
00409 {
00410
printk(KERN_INFO
"RTAI[rtai_msgq]: loaded.\n");
00411
return set_rt_fun_entries(
rt_msg_queue_entries);
00412 }
00413
00414 void __rtai_msg_queue_exit(
void)
00415 {
00416
reset_rt_fun_entries(
rt_msg_queue_entries);
00417
printk(KERN_INFO
"RTAI[rtai_msgq]: unloaded.\n");
00418 }
00419
00420
#ifndef CONFIG_RTAI_MQ_BUILTIN
00421
module_init(__rtai_msg_queue_init);
00422
module_exit(__rtai_msg_queue_exit);
00423
#endif
00424
00425
#ifdef CONFIG_KBUILD
00426
EXPORT_SYMBOL(rt_msgq_init);
00427
EXPORT_SYMBOL(rt_msgq_delete);
00428
EXPORT_SYMBOL(_rt_named_msgq_init);
00429
EXPORT_SYMBOL(rt_named_msgq_delete);
00430
EXPORT_SYMBOL(_rt_msg_send);
00431
EXPORT_SYMBOL(_rt_msg_send_if);
00432
EXPORT_SYMBOL(_rt_msg_send_until);
00433
EXPORT_SYMBOL(_rt_msg_send_timed);
00434
EXPORT_SYMBOL(_rt_msg_receive);
00435
EXPORT_SYMBOL(_rt_msg_receive_if);
00436
EXPORT_SYMBOL(_rt_msg_receive_until);
00437
EXPORT_SYMBOL(_rt_msg_receive_timed);
00438
EXPORT_SYMBOL(_rt_msg_broadcast);
00439
EXPORT_SYMBOL(_rt_msg_broadcast_if);
00440
EXPORT_SYMBOL(_rt_msg_broadcast_until);
00441
EXPORT_SYMBOL(_rt_msg_broadcast_timed);
00442
EXPORT_SYMBOL(_rt_msg_evdrp);
00443
#endif