source: rtems/cpukit/score/src/coremsgseize.c @ d17c114

Last change on this file since d17c114 was d17c114, checked in by Joel Sherrill <joel.sherrill@…>, on 07/24/08 at 20:43:24

2008-07-24 Joel Sherrill <joel.sherrill@…>

PR 1291/cpukit

  • posix/src/posixtimespecabsolutetimeout.c: New file.
  • itron/inline/rtems/itron/semaphore.inl, itron/src/twai_sem.c, posix/Makefile.am, posix/include/mqueue.h, posix/include/rtems/posix/mqueue.h, posix/include/rtems/posix/semaphore.h, posix/include/rtems/posix/time.h, posix/src/condtimedwait.c, posix/src/mqueuereceive.c, posix/src/mqueuerecvsupp.c, posix/src/mqueuesend.c, posix/src/mqueuesendsupp.c, posix/src/mqueuetimedreceive.c, posix/src/mqueuetimedsend.c, posix/src/mutexfromcorestatus.c, posix/src/mutextimedlock.c, posix/src/semaphorewaitsupp.c, posix/src/semtimedwait.c, posix/src/semtrywait.c, posix/src/semwait.c, rtems/src/semobtain.c, rtems/src/semtranslatereturncode.c, score/include/rtems/score/coresem.h, score/src/coremsgseize.c, score/src/coresemseize.c: This patch addresses issues on implementation of the timeout on the following POSIX services. Some of these services incorrectly took a timeout as a relative time. Others would compute a 0 delta to timeout if the absolute time and the current time were equal and thus incorrectly block the caller forever. The root of the confusion is that POSIX specifies that if the timeout is incorrect (e.g. in the past, is now, or is numerically invalid), that it does not matter if the call would succeed without blocking. This is in contrast to RTEMS programming style where all errors are checked before any critical sections are entered. This fix implemented a more uniform way of handling POSIX absolute time timeouts.

+ pthread_cond_timedwait - could block forever
+ mq_timedreceive - used relative not absolute time
+ mq_timedsend - used relative not absolute time
+ pthread_mutex_timedlock - used relative not absolute time
+ pthread_rwlock_timedrdlock- used relative not absolute time
+ pthread_rwlock_timedwrlock- used relative not absolute time
+ sem_timedwait - could block forever

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/*
2 *  CORE Message Queue Handler
3 *
4 *  DESCRIPTION:
5 *
6 *  This package is the implementation of the CORE Message Queue Handler.
7 *  This core object provides task synchronization and communication functions
8 *  via messages passed to queue objects.
9 *
10 *  COPYRIGHT (c) 1989-1999.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.com/license/LICENSE.
16 *
17 *  $Id$
18 */
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <rtems/system.h>
25#include <rtems/score/chain.h>
26#include <rtems/score/isr.h>
27#include <rtems/score/object.h>
28#include <rtems/score/coremsg.h>
29#include <rtems/score/states.h>
30#include <rtems/score/thread.h>
31#include <rtems/score/wkspace.h>
32#if defined(RTEMS_MULTIPROCESSING)
33#include <rtems/score/mpci.h>
34#endif
35
36/*PAGE
37 *
38 *  _CORE_message_queue_Seize
39 *
40 *  This kernel routine dequeues a message, copies the message buffer to
41 *  a given destination buffer, and frees the message buffer to the
42 *  inactive message pool.  The thread will be blocked if wait is TRUE,
43 *  otherwise an error will be given to the thread if no messages are available.
44 *
45 *  Input parameters:
46 *    the_message_queue - pointer to message queue
47 *    id                - id of object we are waitig on
48 *    buffer            - pointer to message buffer to be filled
49 *    size              - pointer to the size of buffer to be filled
50 *    wait              - TRUE if wait is allowed, FALSE otherwise
51 *    timeout           - time to wait for a message
52 *
53 *  Output parameters:  NONE
54 *
55 *  NOTE: Dependent on BUFFER_LENGTH
56 *
57 *  INTERRUPT LATENCY:
58 *    available
59 *    wait
60 */
61
62void _CORE_message_queue_Seize(
63  CORE_message_queue_Control      *the_message_queue,
64  Objects_Id                       id,
65  void                            *buffer,
66  size_t                          *size,
67  boolean                          wait,
68  Watchdog_Interval                timeout
69)
70{
71  ISR_Level                          level;
72  CORE_message_queue_Buffer_control *the_message;
73  Thread_Control                    *executing;
74  Thread_Control                    *the_thread;
75
76  executing = _Thread_Executing;
77  executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
78  _ISR_Disable( level );
79  if ( the_message_queue->number_of_pending_messages != 0 ) {
80    the_message_queue->number_of_pending_messages -= 1;
81
82    the_message = _CORE_message_queue_Get_pending_message( the_message_queue );
83    _ISR_Enable( level );
84
85    *size = the_message->Contents.size;
86    _Thread_Executing->Wait.count = the_message->priority;
87    _CORE_message_queue_Copy_buffer(the_message->Contents.buffer, buffer,*size);
88
89    /*
90     *  There could be a thread waiting to send a message.  If there
91     *  is not, then we can go ahead and free the buffer.
92     *
93     *  NOTE: If we note that the queue was not full before this receive,
94     *  then we can avoid this dequeue.
95     */
96
97    the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
98    if ( !the_thread ) {
99      _CORE_message_queue_Free_message_buffer( the_message_queue, the_message );
100      return;
101    }
102
103    /*
104     *  There was a thread waiting to send a message.  This code
105     *  puts the messages in the message queue on behalf of the
106     *  waiting task.
107     */
108
109    the_message->priority  = the_thread->Wait.count;
110    the_message->Contents.size = (uint32_t)the_thread->Wait.option;
111    _CORE_message_queue_Copy_buffer(
112      the_thread->Wait.return_argument,
113      the_message->Contents.buffer,
114      the_message->Contents.size
115    );
116
117    _CORE_message_queue_Insert_message(
118       the_message_queue,
119       the_message,
120       the_message->priority
121    );
122    return;
123  }
124
125  if ( !wait ) {
126    _ISR_Enable( level );
127    executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT;
128    return;
129  }
130
131  _Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
132  executing->Wait.queue              = &the_message_queue->Wait_queue;
133  executing->Wait.id                 = id;
134  executing->Wait.return_argument    = buffer;
135  executing->Wait.return_argument_1  = (void *)size;
136  /* Wait.count will be filled in with the message priority */
137  _ISR_Enable( level );
138
139  _Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
140}
Note: See TracBrowser for help on using the repository browser.