Changeset 4dc8981 in rtems


Ignore:
Timestamp:
Nov 2, 1999, 5:00:35 PM (20 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, master
Children:
b95e303f
Parents:
4c1b914
Message:

Split mqueue.c into a variety of files.

Files:
30 added
3 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/posix/src/Makefile.in

    r4c1b914 r4dc8981  
    2323    wait waitpid
    2424
     25MESSAGE_QUEUE_PIECES= mqueue mqueueclose mqueuecreatesupp mqueuedeletesupp \
     26    mqueuegetattr mqueuenametoid mqueuenotify mqueueopen mqueuereceive \
     27    mqueuerecvsupp mqueuesend mqueuesendsupp mqueuesetattr \
     28    mqueuetimedreceive mqueuetimedsend mqueueunlink \
     29
    2530PTHREAD_C_PIECES = pthread pthreadsetcputime pthreadgetcputime \
    2631    pthreadgetcpuclockid pthreadonce pthreadequal pthreadself pthreadexit \
     
    3944    sigwait sigwaitinfo signal_2
    4045
    41 C_PIECES = adasupp cond getpid key mutex $(PTHREAD_C_PIECES) \
     46C_PIECES = adasupp cond getpid key $(MESSAGE_QUEUE_PIECES) \
     47    mutex $(PTHREAD_C_PIECES) \
    4248    $(PSIGNAL_C_PIECES) ptimer sched time types unistd $(ENOSYS_C_PIECES) \
    4349    $(BUILD_FOR_NOW_C_PIECES)
  • c/src/exec/posix/src/mqueue.c

    r4c1b914 r4dc8981  
    5656  );
    5757}
    58 
    59 /*PAGE
    60  *
    61  *  _POSIX_Message_queue_Create_support
    62  */
    63  
    64 int _POSIX_Message_queue_Create_support(
    65   const char                    *name,
    66   int                            pshared,
    67   unsigned int                   oflag,
    68   struct mq_attr                *attr,
    69   POSIX_Message_queue_Control  **message_queue
    70 )
    71 {
    72   POSIX_Message_queue_Control   *the_mq;
    73  
    74   _Thread_Disable_dispatch();
    75  
    76   the_mq = _POSIX_Message_queue_Allocate();
    77  
    78   if ( !the_mq ) {
    79     _Thread_Enable_dispatch();
    80     set_errno_and_return_minus_one( ENFILE );
    81   }
    82  
    83 #if defined(RTEMS_MULTIPROCESSING)
    84   if ( pshared == PTHREAD_PROCESS_SHARED &&
    85        !( _Objects_MP_Allocate_and_open( &_POSIX_Message_queue_Information, 0,
    86                             the_mq->Object.id, FALSE ) ) ) {
    87     _POSIX_Message_queue_Free( the_mq );
    88     _Thread_Enable_dispatch();
    89     set_errno_and_return_minus_one( ENFILE );
    90   }
    91 #endif
    92  
    93   the_mq->process_shared  = pshared;
    94  
    95   if ( name ) {
    96     the_mq->named = TRUE;
    97     the_mq->open_count = 1;
    98     the_mq->linked = TRUE;
    99   }
    100   else
    101     the_mq->named = FALSE;
    102  
    103   if ( oflag & O_NONBLOCK )
    104     the_mq->blocking = FALSE;
    105   else
    106     the_mq->blocking = TRUE;
    107  
    108   /* XXX
    109    *
    110    *  Note that this should be based on the current scheduling policy.
    111    */
    112 
    113   /* XXX
    114    *
    115    *  Message and waiting disciplines are not distinguished.
    116    */
    117 /*
    118   the_mq_attr->message_discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
    119   the_mq_attr->waiting_discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
    120  */
    121 
    122   the_mq->Message_queue.Attributes.discipline =
    123                                          CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
    124  
    125   if ( ! _CORE_message_queue_Initialize(
    126            &the_mq->Message_queue,
    127            OBJECTS_POSIX_MESSAGE_QUEUES,
    128            &the_mq->Message_queue.Attributes,
    129            attr->mq_maxmsg,
    130            attr->mq_msgsize,
    131 #if defined(RTEMS_MULTIPROCESSING)
    132            _POSIX_Message_queue_MP_Send_extract_proxy
    133 #else
    134            NULL
    135 #endif
    136       ) ) {
    137 
    138 #if defined(RTEMS_MULTIPROCESSING)
    139     if ( pshared == PTHREAD_PROCESS_SHARED )
    140       _Objects_MP_Close( &_POSIX_Message_queue_Information, the_mq->Object.id );
    141 #endif
    142  
    143     _POSIX_Message_queue_Free( the_mq );
    144     _Thread_Enable_dispatch();
    145     set_errno_and_return_minus_one( ENOSPC );
    146   }
    147 
    148  
    149   /* XXX - need Names to be a string!!! */
    150   _Objects_Open(
    151     &_POSIX_Message_queue_Information,
    152     &the_mq->Object,
    153     (char *) name
    154   );
    155  
    156   *message_queue = the_mq;
    157  
    158 #if defined(RTEMS_MULTIPROCESSING)
    159   if ( pshared == PTHREAD_PROCESS_SHARED )
    160     _POSIX_Message_queue_MP_Send_process_packet(
    161       POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_CREATE,
    162       the_mq->Object.id,
    163       (char *) name,
    164       0                          /* Not used */
    165     );
    166 #endif
    167  
    168   _Thread_Enable_dispatch();
    169   return 0;
    170 }
    171 
    172 /*PAGE
    173  *
    174  *  15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
    175  */
    176 
    177 mqd_t mq_open(
    178   const char *name,
    179   int         oflag,
    180   ...
    181   /* mode_t mode, */
    182   /* struct mq_attr  attr */
    183 )
    184 {
    185   va_list arg;
    186   mode_t mode;
    187   struct mq_attr *attr;
    188   int                        status;
    189   Objects_Id                 the_mq_id;
    190   POSIX_Message_queue_Control   *the_mq;
    191  
    192   if ( oflag & O_CREAT ) {
    193     va_start(arg, oflag);
    194     mode = (mode_t) va_arg( arg, mode_t * );
    195     attr = (struct mq_attr *) va_arg( arg, struct mq_attr ** );
    196     va_end(arg);
    197   }
    198  
    199   status = _POSIX_Message_queue_Name_to_id( name, &the_mq_id );
    200  
    201   /*
    202    *  If the name to id translation worked, then the message queue exists
    203    *  and we can just return a pointer to the id.  Otherwise we may
    204    *  need to check to see if this is a "message queue does not exist"
    205    *  or some other miscellaneous error on the name.
    206    */
    207  
    208   if ( status ) {
    209  
    210     if ( status == EINVAL ) {      /* name -> ID translation failed */
    211       if ( !(oflag & O_CREAT) ) {  /* willing to create it? */
    212         set_errno_and_return_minus_one( ENOENT );
    213         return (mqd_t) -1;
    214       }
    215       /* we are willing to create it */
    216     }
    217     set_errno_and_return_minus_one( status ); /* some type of error */
    218     return (mqd_t) -1;
    219  
    220   } else {                /* name -> ID translation succeeded */
    221  
    222     if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) {
    223       set_errno_and_return_minus_one( EEXIST );
    224       return (mqd_t) -1;
    225     }
    226  
    227     /*
    228      * XXX In this case we need to do an ID->pointer conversion to
    229      *     check the mode.   This is probably a good place for a subroutine.
    230      */
    231  
    232     the_mq->open_count += 1;
    233  
    234     return (mqd_t)&the_mq->Object.id;
    235  
    236   }
    237  
    238   /* XXX verify this comment...
    239    *
    240    *  At this point, the message queue does not exist and everything has been
    241    *  checked. We should go ahead and create a message queue.
    242    */
    243  
    244   status = _POSIX_Message_queue_Create_support(
    245     name,
    246     TRUE,         /* shared across processes */
    247     oflag,
    248     attr,
    249     &the_mq
    250   );
    251  
    252   if ( status == -1 )
    253     return (mqd_t) -1;
    254  
    255   return (mqd_t) &the_mq->Object.id;
    256 }
    257 
    258 /*PAGE
    259  *
    260  *  _POSIX_Message_queue_Delete
    261  */
    262  
    263 void _POSIX_Message_queue_Delete(
    264   POSIX_Message_queue_Control *the_mq
    265 )
    266 {
    267   if ( !the_mq->linked && !the_mq->open_count ) {
    268     _POSIX_Message_queue_Free( the_mq );
    269  
    270 #if defined(RTEMS_MULTIPROCESSING)
    271     if ( the_mq->process_shared == PTHREAD_PROCESS_SHARED ) {
    272  
    273       _Objects_MP_Close(
    274         &_POSIX_Message_queue_Information,
    275         the_mq->Object.id
    276       );
    277  
    278       _POSIX_Message_queue_MP_Send_process_packet(
    279         POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_DELETE,
    280         the_mq->Object.id,
    281         0,                         /* Not used */
    282         0                          /* Not used */
    283       );
    284     }
    285 #endif
    286  
    287   }
    288 }
    289 
    290 /*PAGE
    291  *
    292  *  15.2.2 Close a Message Queue, P1003.1b-1993, p. 275
    293  */
    294 
    295 int mq_close(
    296   mqd_t  mqdes
    297 )
    298 {
    299   register POSIX_Message_queue_Control *the_mq;
    300   Objects_Locations                     location;
    301  
    302   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    303   switch ( location ) {
    304     case OBJECTS_ERROR:
    305       set_errno_and_return_minus_one( EINVAL );
    306     case OBJECTS_REMOTE:
    307       _Thread_Dispatch();
    308       return POSIX_MP_NOT_IMPLEMENTED();
    309       set_errno_and_return_minus_one( EINVAL );
    310     case OBJECTS_LOCAL:
    311       the_mq->open_count -= 1;
    312       _POSIX_Message_queue_Delete( the_mq );
    313       _Thread_Enable_dispatch();
    314       return 0;
    315   }
    316   return POSIX_BOTTOM_REACHED();
    317 }
    318 
    319 /*PAGE
    320  *
    321  *  15.2.2 Remove a Message Queue, P1003.1b-1993, p. 276
    322  */
    323 
    324 int mq_unlink(
    325   const char *name
    326 )
    327 {
    328   int  status;
    329   register POSIX_Message_queue_Control *the_mq;
    330   Objects_Id                        the_mq_id;
    331   Objects_Locations                 location;
    332  
    333   status = _POSIX_Message_queue_Name_to_id( name, &the_mq_id );
    334  
    335   if ( !status )
    336     set_errno_and_return_minus_one( status );
    337  
    338   the_mq = _POSIX_Message_queue_Get( the_mq_id, &location );
    339   switch ( location ) {
    340     case OBJECTS_ERROR:
    341       set_errno_and_return_minus_one( EINVAL );
    342     case OBJECTS_REMOTE:
    343       _Thread_Dispatch();
    344       return POSIX_MP_NOT_IMPLEMENTED();
    345       set_errno_and_return_minus_one( EINVAL );
    346     case OBJECTS_LOCAL:
    347  
    348 #if defined(RTEMS_MULTIPROCESSING)
    349       _Objects_MP_Close(
    350         &_POSIX_Message_queue_Information,
    351         the_mq->Object.id
    352       );
    353 #endif
    354  
    355       the_mq->linked = FALSE;
    356  
    357       _POSIX_Message_queue_Delete( the_mq );
    358  
    359       _Thread_Enable_dispatch();
    360       return 0;
    361   }
    362   return POSIX_BOTTOM_REACHED();
    363 }
    364 
    365 /*PAGE
    366  *
    367  *  _POSIX_Message_queue_Send_support
    368  */
    369  
    370 int _POSIX_Message_queue_Send_support(
    371   mqd_t               mqdes,
    372   const char         *msg_ptr,
    373   unsigned32          msg_len,
    374   Priority_Control    msg_prio,
    375   Watchdog_Interval   timeout
    376 )
    377 {
    378   register POSIX_Message_queue_Control *the_mq;
    379   Objects_Locations                     location;
    380  
    381   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    382   switch ( location ) {
    383     case OBJECTS_ERROR:
    384       set_errno_and_return_minus_one( EINVAL );
    385     case OBJECTS_REMOTE:
    386       _Thread_Dispatch();
    387       return POSIX_MP_NOT_IMPLEMENTED();
    388       set_errno_and_return_minus_one( EINVAL );
    389     case OBJECTS_LOCAL:
    390       /* XXX must add support for timeout and priority */
    391       _CORE_message_queue_Send(
    392         &the_mq->Message_queue,
    393         (void *) msg_ptr,
    394         msg_len,
    395         mqdes,
    396 #if defined(RTEMS_MULTIPROCESSING)
    397         NULL       /* XXX _POSIX_Message_queue_Core_message_queue_mp_support*/
    398 #else
    399         NULL
    400 #endif
    401       );
    402       _Thread_Enable_dispatch();
    403       return _Thread_Executing->Wait.return_code;
    404   }
    405   return POSIX_BOTTOM_REACHED();
    406 }
    407 
    408 /*PAGE
    409  *
    410  *  15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277
    411  *
    412  *  NOTE: P1003.4b/D8, p. 45 adds mq_timedsend().
    413  */
    414 
    415 int mq_send(
    416   mqd_t         mqdes,
    417   const char   *msg_ptr,
    418   size_t        msg_len,
    419   unsigned int  msg_prio
    420 )
    421 {
    422   return _POSIX_Message_queue_Send_support(
    423     mqdes,
    424     msg_ptr,
    425     msg_len,
    426     msg_prio,
    427     THREAD_QUEUE_WAIT_FOREVER
    428   );
    429 }
    430 
    431 /*PAGE
    432  *
    433  *  15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277
    434  *
    435  *  NOTE: P1003.4b/D8, p. 45 adds mq_timedsend().
    436  */
    437 
    438 int mq_timedsend(
    439   mqd_t                  mqdes,
    440   const char            *msg_ptr,
    441   size_t                 msg_len,
    442   unsigned int           msg_prio,
    443   const struct timespec *timeout
    444 )
    445 {
    446   return _POSIX_Message_queue_Send_support(
    447     mqdes,
    448     msg_ptr,
    449     msg_len,
    450     msg_prio,
    451     _POSIX_Timespec_to_interval( timeout )
    452   );
    453 }
    454 
    455 /*PAGE
    456  *
    457  *  _POSIX_Message_queue_Receive_support
    458  */
    459  
    460 /* XXX be careful ... watch the size going through all the layers ... */
    461 
    462 ssize_t _POSIX_Message_queue_Receive_support(
    463   mqd_t               mqdes,
    464   char               *msg_ptr,
    465   size_t              msg_len,
    466   unsigned int       *msg_prio,
    467   Watchdog_Interval   timeout
    468 )
    469 {
    470   register POSIX_Message_queue_Control *the_mq;
    471   Objects_Locations                     location;
    472   unsigned32                            status = 0;
    473   unsigned32                            length_out;
    474  
    475   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    476   switch ( location ) {
    477     case OBJECTS_ERROR:
    478       set_errno_and_return_minus_one( EINVAL );
    479     case OBJECTS_REMOTE:
    480       _Thread_Dispatch();
    481       return POSIX_MP_NOT_IMPLEMENTED();
    482       set_errno_and_return_minus_one( EINVAL );
    483     case OBJECTS_LOCAL:
    484       /* XXX need to define the options argument to this */
    485       length_out = msg_len;
    486       _CORE_message_queue_Seize(
    487         &the_mq->Message_queue,
    488         mqdes,
    489         msg_ptr,
    490         &length_out,
    491         /* msg_prio,    XXXX */
    492         the_mq->blocking,
    493         timeout
    494       );
    495       _Thread_Enable_dispatch();
    496       if ( !status )
    497         return length_out;
    498       /* XXX --- the return codes gotta be looked at .. fix this */
    499       return _Thread_Executing->Wait.return_code;
    500   }
    501   return POSIX_BOTTOM_REACHED();
    502 }
    503 
    504 /*PAGE
    505  *
    506  *  15.2.5 Receive a Message From a Message Queue, P1003.1b-1993, p. 279
    507  *
    508  *  NOTE: P1003.4b/D8, p. 45 adds mq_timedreceive().
    509  */
    510 
    511 ssize_t mq_receive(
    512   mqd_t         mqdes,
    513   char         *msg_ptr,
    514   size_t        msg_len,
    515   unsigned int *msg_prio
    516 )
    517 {
    518   return _POSIX_Message_queue_Receive_support(
    519     mqdes,
    520     msg_ptr,
    521     msg_len,
    522     msg_prio,
    523     THREAD_QUEUE_WAIT_FOREVER
    524   );
    525 }
    526 
    527 /*PAGE
    528  *
    529  *  15.2.5 Receive a Message From a Message Queue, P1003.1b-1993, p. 279
    530  *
    531  *  NOTE: P1003.4b/D8, p. 45 adds mq_timedreceive().
    532  */
    533 
    534 int mq_timedreceive(                  /* XXX: should this be ssize_t */
    535   mqd_t                  mqdes,
    536   char                  *msg_ptr,
    537   size_t                 msg_len,
    538   unsigned int          *msg_prio,
    539   const struct timespec *timeout
    540 )
    541 {
    542   return _POSIX_Message_queue_Receive_support(
    543     mqdes,
    544     msg_ptr,
    545     msg_len,
    546     msg_prio,
    547     _POSIX_Timespec_to_interval( timeout )
    548   );
    549 }
    550 
    551 /*PAGE
    552  *
    553  *  _POSIX_Message_queue_Notify_handler
    554  *
    555  */
    556 
    557 void _POSIX_Message_queue_Notify_handler(
    558   void    *user_data
    559 )
    560 {
    561   POSIX_Message_queue_Control *the_mq;
    562 
    563   the_mq = user_data;
    564 
    565   /* XXX do something with signals here!!!! */
    566 }
    567 
    568 /*PAGE
    569  *
    570  *  15.2.6 Notify Process that a Message is Available on a Queue,
    571  *         P1003.1b-1993, p. 280
    572  */
    573 
    574 int mq_notify(
    575   mqd_t                  mqdes,
    576   const struct sigevent *notification
    577 )
    578 {
    579   register POSIX_Message_queue_Control *the_mq;
    580   Objects_Locations                     location;
    581  
    582   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    583   switch ( location ) {
    584     case OBJECTS_ERROR:
    585       set_errno_and_return_minus_one( EBADF );
    586     case OBJECTS_REMOTE:
    587       _Thread_Dispatch();
    588       return POSIX_MP_NOT_IMPLEMENTED();
    589       set_errno_and_return_minus_one( EINVAL );
    590     case OBJECTS_LOCAL:
    591       if ( notification ) {
    592         if ( _CORE_message_queue_Is_notify_enabled( &the_mq->Message_queue ) ) {
    593           _Thread_Enable_dispatch();
    594           set_errno_and_return_minus_one( EBUSY );
    595         }
    596 
    597         _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
    598 
    599         the_mq->notification = *notification;
    600      
    601         _CORE_message_queue_Set_notify(
    602           &the_mq->Message_queue,
    603           _POSIX_Message_queue_Notify_handler,
    604           the_mq
    605         );
    606       } else {
    607 
    608         _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
    609 
    610       }
    611 
    612       _Thread_Enable_dispatch();
    613       return 0;
    614   }
    615   return POSIX_BOTTOM_REACHED();
    616 }
    617 
    618 /*PAGE
    619  *
    620  *  15.2.7 Set Message Queue Attributes, P1003.1b-1993, p. 281
    621  */
    622 
    623 int mq_setattr(
    624   mqd_t                 mqdes,
    625   const struct mq_attr *mqstat,
    626   struct mq_attr       *omqstat
    627 )
    628 {
    629   register POSIX_Message_queue_Control *the_mq;
    630   Objects_Locations                     location;
    631   CORE_message_queue_Attributes        *the_mq_attr;
    632  
    633   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    634   switch ( location ) {
    635     case OBJECTS_ERROR:
    636       set_errno_and_return_minus_one( EINVAL );
    637     case OBJECTS_REMOTE:
    638       _Thread_Dispatch();
    639       return POSIX_MP_NOT_IMPLEMENTED();
    640       set_errno_and_return_minus_one( EINVAL );
    641     case OBJECTS_LOCAL:
    642       /*
    643        *  Return the old values.
    644        */
    645 
    646       /* XXX this is the same stuff as is in mq_getattr... and probably */
    647       /* XXX should be in an inlined private routine */
    648 
    649       the_mq_attr = &the_mq->Message_queue.Attributes;
    650 
    651       omqstat->mq_flags   = the_mq->flags;
    652       omqstat->mq_msgsize = the_mq->Message_queue.maximum_message_size;
    653       omqstat->mq_maxmsg  = the_mq->Message_queue.maximum_pending_messages;
    654       omqstat->mq_curmsgs = the_mq->Message_queue.number_of_pending_messages;
    655  
    656       /*
    657        *  Ignore everything except the O_NONBLOCK bit.
    658        */
    659 
    660       if (  mqstat->mq_flags & O_NONBLOCK )
    661         the_mq->blocking = FALSE;
    662       else
    663         the_mq->blocking = TRUE;
    664  
    665       the_mq->flags = mqstat->mq_flags;
    666 
    667       _Thread_Enable_dispatch();
    668       return 0;
    669   }
    670   return POSIX_BOTTOM_REACHED();
    671 }
    672 
    673 /*PAGE
    674  *
    675  *  15.2.8 Get Message Queue Attributes, P1003.1b-1993, p. 283
    676  */
    677 
    678 int mq_getattr(
    679   mqd_t           mqdes,
    680   struct mq_attr *mqstat
    681 )
    682 {
    683   register POSIX_Message_queue_Control *the_mq;
    684   Objects_Locations                     location;
    685   CORE_message_queue_Attributes        *the_mq_attr;
    686  
    687   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    688   switch ( location ) {
    689     case OBJECTS_ERROR:
    690       set_errno_and_return_minus_one( EINVAL );
    691     case OBJECTS_REMOTE:
    692       _Thread_Dispatch();
    693       return POSIX_MP_NOT_IMPLEMENTED();
    694       set_errno_and_return_minus_one( EINVAL );
    695     case OBJECTS_LOCAL:
    696       /*
    697        *  Return the old values.
    698        */
    699  
    700       /* XXX this is the same stuff as is in mq_setattr... and probably */
    701       /* XXX should be in an inlined private routine */
    702  
    703       the_mq_attr = &the_mq->Message_queue.Attributes;
    704  
    705       mqstat->mq_flags   = the_mq->flags;
    706       mqstat->mq_msgsize = the_mq->Message_queue.maximum_message_size;
    707       mqstat->mq_maxmsg  = the_mq->Message_queue.maximum_pending_messages;
    708       mqstat->mq_curmsgs = the_mq->Message_queue.number_of_pending_messages;
    709  
    710       _Thread_Enable_dispatch();
    711       return 0;
    712   }
    713   return POSIX_BOTTOM_REACHED();
    714 }
    715 
    716 /*PAGE
    717  *
    718  *  _POSIX_Message_queue_Name_to_id
    719  *
    720  *  XXX
    721  */
    722 
    723 int _POSIX_Message_queue_Name_to_id(
    724   const char          *name,
    725   Objects_Id          *id
    726 )
    727 {
    728   return 0; /* XXX fill me in */
    729 }
  • cpukit/posix/src/mqueue.c

    r4c1b914 r4dc8981  
    5656  );
    5757}
    58 
    59 /*PAGE
    60  *
    61  *  _POSIX_Message_queue_Create_support
    62  */
    63  
    64 int _POSIX_Message_queue_Create_support(
    65   const char                    *name,
    66   int                            pshared,
    67   unsigned int                   oflag,
    68   struct mq_attr                *attr,
    69   POSIX_Message_queue_Control  **message_queue
    70 )
    71 {
    72   POSIX_Message_queue_Control   *the_mq;
    73  
    74   _Thread_Disable_dispatch();
    75  
    76   the_mq = _POSIX_Message_queue_Allocate();
    77  
    78   if ( !the_mq ) {
    79     _Thread_Enable_dispatch();
    80     set_errno_and_return_minus_one( ENFILE );
    81   }
    82  
    83 #if defined(RTEMS_MULTIPROCESSING)
    84   if ( pshared == PTHREAD_PROCESS_SHARED &&
    85        !( _Objects_MP_Allocate_and_open( &_POSIX_Message_queue_Information, 0,
    86                             the_mq->Object.id, FALSE ) ) ) {
    87     _POSIX_Message_queue_Free( the_mq );
    88     _Thread_Enable_dispatch();
    89     set_errno_and_return_minus_one( ENFILE );
    90   }
    91 #endif
    92  
    93   the_mq->process_shared  = pshared;
    94  
    95   if ( name ) {
    96     the_mq->named = TRUE;
    97     the_mq->open_count = 1;
    98     the_mq->linked = TRUE;
    99   }
    100   else
    101     the_mq->named = FALSE;
    102  
    103   if ( oflag & O_NONBLOCK )
    104     the_mq->blocking = FALSE;
    105   else
    106     the_mq->blocking = TRUE;
    107  
    108   /* XXX
    109    *
    110    *  Note that this should be based on the current scheduling policy.
    111    */
    112 
    113   /* XXX
    114    *
    115    *  Message and waiting disciplines are not distinguished.
    116    */
    117 /*
    118   the_mq_attr->message_discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
    119   the_mq_attr->waiting_discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
    120  */
    121 
    122   the_mq->Message_queue.Attributes.discipline =
    123                                          CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
    124  
    125   if ( ! _CORE_message_queue_Initialize(
    126            &the_mq->Message_queue,
    127            OBJECTS_POSIX_MESSAGE_QUEUES,
    128            &the_mq->Message_queue.Attributes,
    129            attr->mq_maxmsg,
    130            attr->mq_msgsize,
    131 #if defined(RTEMS_MULTIPROCESSING)
    132            _POSIX_Message_queue_MP_Send_extract_proxy
    133 #else
    134            NULL
    135 #endif
    136       ) ) {
    137 
    138 #if defined(RTEMS_MULTIPROCESSING)
    139     if ( pshared == PTHREAD_PROCESS_SHARED )
    140       _Objects_MP_Close( &_POSIX_Message_queue_Information, the_mq->Object.id );
    141 #endif
    142  
    143     _POSIX_Message_queue_Free( the_mq );
    144     _Thread_Enable_dispatch();
    145     set_errno_and_return_minus_one( ENOSPC );
    146   }
    147 
    148  
    149   /* XXX - need Names to be a string!!! */
    150   _Objects_Open(
    151     &_POSIX_Message_queue_Information,
    152     &the_mq->Object,
    153     (char *) name
    154   );
    155  
    156   *message_queue = the_mq;
    157  
    158 #if defined(RTEMS_MULTIPROCESSING)
    159   if ( pshared == PTHREAD_PROCESS_SHARED )
    160     _POSIX_Message_queue_MP_Send_process_packet(
    161       POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_CREATE,
    162       the_mq->Object.id,
    163       (char *) name,
    164       0                          /* Not used */
    165     );
    166 #endif
    167  
    168   _Thread_Enable_dispatch();
    169   return 0;
    170 }
    171 
    172 /*PAGE
    173  *
    174  *  15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
    175  */
    176 
    177 mqd_t mq_open(
    178   const char *name,
    179   int         oflag,
    180   ...
    181   /* mode_t mode, */
    182   /* struct mq_attr  attr */
    183 )
    184 {
    185   va_list arg;
    186   mode_t mode;
    187   struct mq_attr *attr;
    188   int                        status;
    189   Objects_Id                 the_mq_id;
    190   POSIX_Message_queue_Control   *the_mq;
    191  
    192   if ( oflag & O_CREAT ) {
    193     va_start(arg, oflag);
    194     mode = (mode_t) va_arg( arg, mode_t * );
    195     attr = (struct mq_attr *) va_arg( arg, struct mq_attr ** );
    196     va_end(arg);
    197   }
    198  
    199   status = _POSIX_Message_queue_Name_to_id( name, &the_mq_id );
    200  
    201   /*
    202    *  If the name to id translation worked, then the message queue exists
    203    *  and we can just return a pointer to the id.  Otherwise we may
    204    *  need to check to see if this is a "message queue does not exist"
    205    *  or some other miscellaneous error on the name.
    206    */
    207  
    208   if ( status ) {
    209  
    210     if ( status == EINVAL ) {      /* name -> ID translation failed */
    211       if ( !(oflag & O_CREAT) ) {  /* willing to create it? */
    212         set_errno_and_return_minus_one( ENOENT );
    213         return (mqd_t) -1;
    214       }
    215       /* we are willing to create it */
    216     }
    217     set_errno_and_return_minus_one( status ); /* some type of error */
    218     return (mqd_t) -1;
    219  
    220   } else {                /* name -> ID translation succeeded */
    221  
    222     if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) {
    223       set_errno_and_return_minus_one( EEXIST );
    224       return (mqd_t) -1;
    225     }
    226  
    227     /*
    228      * XXX In this case we need to do an ID->pointer conversion to
    229      *     check the mode.   This is probably a good place for a subroutine.
    230      */
    231  
    232     the_mq->open_count += 1;
    233  
    234     return (mqd_t)&the_mq->Object.id;
    235  
    236   }
    237  
    238   /* XXX verify this comment...
    239    *
    240    *  At this point, the message queue does not exist and everything has been
    241    *  checked. We should go ahead and create a message queue.
    242    */
    243  
    244   status = _POSIX_Message_queue_Create_support(
    245     name,
    246     TRUE,         /* shared across processes */
    247     oflag,
    248     attr,
    249     &the_mq
    250   );
    251  
    252   if ( status == -1 )
    253     return (mqd_t) -1;
    254  
    255   return (mqd_t) &the_mq->Object.id;
    256 }
    257 
    258 /*PAGE
    259  *
    260  *  _POSIX_Message_queue_Delete
    261  */
    262  
    263 void _POSIX_Message_queue_Delete(
    264   POSIX_Message_queue_Control *the_mq
    265 )
    266 {
    267   if ( !the_mq->linked && !the_mq->open_count ) {
    268     _POSIX_Message_queue_Free( the_mq );
    269  
    270 #if defined(RTEMS_MULTIPROCESSING)
    271     if ( the_mq->process_shared == PTHREAD_PROCESS_SHARED ) {
    272  
    273       _Objects_MP_Close(
    274         &_POSIX_Message_queue_Information,
    275         the_mq->Object.id
    276       );
    277  
    278       _POSIX_Message_queue_MP_Send_process_packet(
    279         POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_DELETE,
    280         the_mq->Object.id,
    281         0,                         /* Not used */
    282         0                          /* Not used */
    283       );
    284     }
    285 #endif
    286  
    287   }
    288 }
    289 
    290 /*PAGE
    291  *
    292  *  15.2.2 Close a Message Queue, P1003.1b-1993, p. 275
    293  */
    294 
    295 int mq_close(
    296   mqd_t  mqdes
    297 )
    298 {
    299   register POSIX_Message_queue_Control *the_mq;
    300   Objects_Locations                     location;
    301  
    302   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    303   switch ( location ) {
    304     case OBJECTS_ERROR:
    305       set_errno_and_return_minus_one( EINVAL );
    306     case OBJECTS_REMOTE:
    307       _Thread_Dispatch();
    308       return POSIX_MP_NOT_IMPLEMENTED();
    309       set_errno_and_return_minus_one( EINVAL );
    310     case OBJECTS_LOCAL:
    311       the_mq->open_count -= 1;
    312       _POSIX_Message_queue_Delete( the_mq );
    313       _Thread_Enable_dispatch();
    314       return 0;
    315   }
    316   return POSIX_BOTTOM_REACHED();
    317 }
    318 
    319 /*PAGE
    320  *
    321  *  15.2.2 Remove a Message Queue, P1003.1b-1993, p. 276
    322  */
    323 
    324 int mq_unlink(
    325   const char *name
    326 )
    327 {
    328   int  status;
    329   register POSIX_Message_queue_Control *the_mq;
    330   Objects_Id                        the_mq_id;
    331   Objects_Locations                 location;
    332  
    333   status = _POSIX_Message_queue_Name_to_id( name, &the_mq_id );
    334  
    335   if ( !status )
    336     set_errno_and_return_minus_one( status );
    337  
    338   the_mq = _POSIX_Message_queue_Get( the_mq_id, &location );
    339   switch ( location ) {
    340     case OBJECTS_ERROR:
    341       set_errno_and_return_minus_one( EINVAL );
    342     case OBJECTS_REMOTE:
    343       _Thread_Dispatch();
    344       return POSIX_MP_NOT_IMPLEMENTED();
    345       set_errno_and_return_minus_one( EINVAL );
    346     case OBJECTS_LOCAL:
    347  
    348 #if defined(RTEMS_MULTIPROCESSING)
    349       _Objects_MP_Close(
    350         &_POSIX_Message_queue_Information,
    351         the_mq->Object.id
    352       );
    353 #endif
    354  
    355       the_mq->linked = FALSE;
    356  
    357       _POSIX_Message_queue_Delete( the_mq );
    358  
    359       _Thread_Enable_dispatch();
    360       return 0;
    361   }
    362   return POSIX_BOTTOM_REACHED();
    363 }
    364 
    365 /*PAGE
    366  *
    367  *  _POSIX_Message_queue_Send_support
    368  */
    369  
    370 int _POSIX_Message_queue_Send_support(
    371   mqd_t               mqdes,
    372   const char         *msg_ptr,
    373   unsigned32          msg_len,
    374   Priority_Control    msg_prio,
    375   Watchdog_Interval   timeout
    376 )
    377 {
    378   register POSIX_Message_queue_Control *the_mq;
    379   Objects_Locations                     location;
    380  
    381   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    382   switch ( location ) {
    383     case OBJECTS_ERROR:
    384       set_errno_and_return_minus_one( EINVAL );
    385     case OBJECTS_REMOTE:
    386       _Thread_Dispatch();
    387       return POSIX_MP_NOT_IMPLEMENTED();
    388       set_errno_and_return_minus_one( EINVAL );
    389     case OBJECTS_LOCAL:
    390       /* XXX must add support for timeout and priority */
    391       _CORE_message_queue_Send(
    392         &the_mq->Message_queue,
    393         (void *) msg_ptr,
    394         msg_len,
    395         mqdes,
    396 #if defined(RTEMS_MULTIPROCESSING)
    397         NULL       /* XXX _POSIX_Message_queue_Core_message_queue_mp_support*/
    398 #else
    399         NULL
    400 #endif
    401       );
    402       _Thread_Enable_dispatch();
    403       return _Thread_Executing->Wait.return_code;
    404   }
    405   return POSIX_BOTTOM_REACHED();
    406 }
    407 
    408 /*PAGE
    409  *
    410  *  15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277
    411  *
    412  *  NOTE: P1003.4b/D8, p. 45 adds mq_timedsend().
    413  */
    414 
    415 int mq_send(
    416   mqd_t         mqdes,
    417   const char   *msg_ptr,
    418   size_t        msg_len,
    419   unsigned int  msg_prio
    420 )
    421 {
    422   return _POSIX_Message_queue_Send_support(
    423     mqdes,
    424     msg_ptr,
    425     msg_len,
    426     msg_prio,
    427     THREAD_QUEUE_WAIT_FOREVER
    428   );
    429 }
    430 
    431 /*PAGE
    432  *
    433  *  15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277
    434  *
    435  *  NOTE: P1003.4b/D8, p. 45 adds mq_timedsend().
    436  */
    437 
    438 int mq_timedsend(
    439   mqd_t                  mqdes,
    440   const char            *msg_ptr,
    441   size_t                 msg_len,
    442   unsigned int           msg_prio,
    443   const struct timespec *timeout
    444 )
    445 {
    446   return _POSIX_Message_queue_Send_support(
    447     mqdes,
    448     msg_ptr,
    449     msg_len,
    450     msg_prio,
    451     _POSIX_Timespec_to_interval( timeout )
    452   );
    453 }
    454 
    455 /*PAGE
    456  *
    457  *  _POSIX_Message_queue_Receive_support
    458  */
    459  
    460 /* XXX be careful ... watch the size going through all the layers ... */
    461 
    462 ssize_t _POSIX_Message_queue_Receive_support(
    463   mqd_t               mqdes,
    464   char               *msg_ptr,
    465   size_t              msg_len,
    466   unsigned int       *msg_prio,
    467   Watchdog_Interval   timeout
    468 )
    469 {
    470   register POSIX_Message_queue_Control *the_mq;
    471   Objects_Locations                     location;
    472   unsigned32                            status = 0;
    473   unsigned32                            length_out;
    474  
    475   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    476   switch ( location ) {
    477     case OBJECTS_ERROR:
    478       set_errno_and_return_minus_one( EINVAL );
    479     case OBJECTS_REMOTE:
    480       _Thread_Dispatch();
    481       return POSIX_MP_NOT_IMPLEMENTED();
    482       set_errno_and_return_minus_one( EINVAL );
    483     case OBJECTS_LOCAL:
    484       /* XXX need to define the options argument to this */
    485       length_out = msg_len;
    486       _CORE_message_queue_Seize(
    487         &the_mq->Message_queue,
    488         mqdes,
    489         msg_ptr,
    490         &length_out,
    491         /* msg_prio,    XXXX */
    492         the_mq->blocking,
    493         timeout
    494       );
    495       _Thread_Enable_dispatch();
    496       if ( !status )
    497         return length_out;
    498       /* XXX --- the return codes gotta be looked at .. fix this */
    499       return _Thread_Executing->Wait.return_code;
    500   }
    501   return POSIX_BOTTOM_REACHED();
    502 }
    503 
    504 /*PAGE
    505  *
    506  *  15.2.5 Receive a Message From a Message Queue, P1003.1b-1993, p. 279
    507  *
    508  *  NOTE: P1003.4b/D8, p. 45 adds mq_timedreceive().
    509  */
    510 
    511 ssize_t mq_receive(
    512   mqd_t         mqdes,
    513   char         *msg_ptr,
    514   size_t        msg_len,
    515   unsigned int *msg_prio
    516 )
    517 {
    518   return _POSIX_Message_queue_Receive_support(
    519     mqdes,
    520     msg_ptr,
    521     msg_len,
    522     msg_prio,
    523     THREAD_QUEUE_WAIT_FOREVER
    524   );
    525 }
    526 
    527 /*PAGE
    528  *
    529  *  15.2.5 Receive a Message From a Message Queue, P1003.1b-1993, p. 279
    530  *
    531  *  NOTE: P1003.4b/D8, p. 45 adds mq_timedreceive().
    532  */
    533 
    534 int mq_timedreceive(                  /* XXX: should this be ssize_t */
    535   mqd_t                  mqdes,
    536   char                  *msg_ptr,
    537   size_t                 msg_len,
    538   unsigned int          *msg_prio,
    539   const struct timespec *timeout
    540 )
    541 {
    542   return _POSIX_Message_queue_Receive_support(
    543     mqdes,
    544     msg_ptr,
    545     msg_len,
    546     msg_prio,
    547     _POSIX_Timespec_to_interval( timeout )
    548   );
    549 }
    550 
    551 /*PAGE
    552  *
    553  *  _POSIX_Message_queue_Notify_handler
    554  *
    555  */
    556 
    557 void _POSIX_Message_queue_Notify_handler(
    558   void    *user_data
    559 )
    560 {
    561   POSIX_Message_queue_Control *the_mq;
    562 
    563   the_mq = user_data;
    564 
    565   /* XXX do something with signals here!!!! */
    566 }
    567 
    568 /*PAGE
    569  *
    570  *  15.2.6 Notify Process that a Message is Available on a Queue,
    571  *         P1003.1b-1993, p. 280
    572  */
    573 
    574 int mq_notify(
    575   mqd_t                  mqdes,
    576   const struct sigevent *notification
    577 )
    578 {
    579   register POSIX_Message_queue_Control *the_mq;
    580   Objects_Locations                     location;
    581  
    582   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    583   switch ( location ) {
    584     case OBJECTS_ERROR:
    585       set_errno_and_return_minus_one( EBADF );
    586     case OBJECTS_REMOTE:
    587       _Thread_Dispatch();
    588       return POSIX_MP_NOT_IMPLEMENTED();
    589       set_errno_and_return_minus_one( EINVAL );
    590     case OBJECTS_LOCAL:
    591       if ( notification ) {
    592         if ( _CORE_message_queue_Is_notify_enabled( &the_mq->Message_queue ) ) {
    593           _Thread_Enable_dispatch();
    594           set_errno_and_return_minus_one( EBUSY );
    595         }
    596 
    597         _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
    598 
    599         the_mq->notification = *notification;
    600      
    601         _CORE_message_queue_Set_notify(
    602           &the_mq->Message_queue,
    603           _POSIX_Message_queue_Notify_handler,
    604           the_mq
    605         );
    606       } else {
    607 
    608         _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
    609 
    610       }
    611 
    612       _Thread_Enable_dispatch();
    613       return 0;
    614   }
    615   return POSIX_BOTTOM_REACHED();
    616 }
    617 
    618 /*PAGE
    619  *
    620  *  15.2.7 Set Message Queue Attributes, P1003.1b-1993, p. 281
    621  */
    622 
    623 int mq_setattr(
    624   mqd_t                 mqdes,
    625   const struct mq_attr *mqstat,
    626   struct mq_attr       *omqstat
    627 )
    628 {
    629   register POSIX_Message_queue_Control *the_mq;
    630   Objects_Locations                     location;
    631   CORE_message_queue_Attributes        *the_mq_attr;
    632  
    633   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    634   switch ( location ) {
    635     case OBJECTS_ERROR:
    636       set_errno_and_return_minus_one( EINVAL );
    637     case OBJECTS_REMOTE:
    638       _Thread_Dispatch();
    639       return POSIX_MP_NOT_IMPLEMENTED();
    640       set_errno_and_return_minus_one( EINVAL );
    641     case OBJECTS_LOCAL:
    642       /*
    643        *  Return the old values.
    644        */
    645 
    646       /* XXX this is the same stuff as is in mq_getattr... and probably */
    647       /* XXX should be in an inlined private routine */
    648 
    649       the_mq_attr = &the_mq->Message_queue.Attributes;
    650 
    651       omqstat->mq_flags   = the_mq->flags;
    652       omqstat->mq_msgsize = the_mq->Message_queue.maximum_message_size;
    653       omqstat->mq_maxmsg  = the_mq->Message_queue.maximum_pending_messages;
    654       omqstat->mq_curmsgs = the_mq->Message_queue.number_of_pending_messages;
    655  
    656       /*
    657        *  Ignore everything except the O_NONBLOCK bit.
    658        */
    659 
    660       if (  mqstat->mq_flags & O_NONBLOCK )
    661         the_mq->blocking = FALSE;
    662       else
    663         the_mq->blocking = TRUE;
    664  
    665       the_mq->flags = mqstat->mq_flags;
    666 
    667       _Thread_Enable_dispatch();
    668       return 0;
    669   }
    670   return POSIX_BOTTOM_REACHED();
    671 }
    672 
    673 /*PAGE
    674  *
    675  *  15.2.8 Get Message Queue Attributes, P1003.1b-1993, p. 283
    676  */
    677 
    678 int mq_getattr(
    679   mqd_t           mqdes,
    680   struct mq_attr *mqstat
    681 )
    682 {
    683   register POSIX_Message_queue_Control *the_mq;
    684   Objects_Locations                     location;
    685   CORE_message_queue_Attributes        *the_mq_attr;
    686  
    687   the_mq = _POSIX_Message_queue_Get( mqdes, &location );
    688   switch ( location ) {
    689     case OBJECTS_ERROR:
    690       set_errno_and_return_minus_one( EINVAL );
    691     case OBJECTS_REMOTE:
    692       _Thread_Dispatch();
    693       return POSIX_MP_NOT_IMPLEMENTED();
    694       set_errno_and_return_minus_one( EINVAL );
    695     case OBJECTS_LOCAL:
    696       /*
    697        *  Return the old values.
    698        */
    699  
    700       /* XXX this is the same stuff as is in mq_setattr... and probably */
    701       /* XXX should be in an inlined private routine */
    702  
    703       the_mq_attr = &the_mq->Message_queue.Attributes;
    704  
    705       mqstat->mq_flags   = the_mq->flags;
    706       mqstat->mq_msgsize = the_mq->Message_queue.maximum_message_size;
    707       mqstat->mq_maxmsg  = the_mq->Message_queue.maximum_pending_messages;
    708       mqstat->mq_curmsgs = the_mq->Message_queue.number_of_pending_messages;
    709  
    710       _Thread_Enable_dispatch();
    711       return 0;
    712   }
    713   return POSIX_BOTTOM_REACHED();
    714 }
    715 
    716 /*PAGE
    717  *
    718  *  _POSIX_Message_queue_Name_to_id
    719  *
    720  *  XXX
    721  */
    722 
    723 int _POSIX_Message_queue_Name_to_id(
    724   const char          *name,
    725   Objects_Id          *id
    726 )
    727 {
    728   return 0; /* XXX fill me in */
    729 }
Note: See TracChangeset for help on using the changeset viewer.