source: rtems/cpukit/score/src/coremsg.c @ 3652ad35

4.104.114.84.95
Last change on this file since 3652ad35 was 3652ad35, checked in by Joel Sherrill <joel.sherrill@…>, on 09/19/95 at 14:53:29

Minor bug fixes to get all targets compilable and running. The
single biggest changes were the expansion of the workspace size
macro to include other types of objects and the increase in the
minimum stack size for most CPUs.

  • Property mode set to 100644
File size: 13.8 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, 1990, 1991, 1992, 1993, 1994.
11 *  On-Line Applications Research Corporation (OAR).
12 *  All rights assigned to U.S. Government, 1994.
13 *
14 *  This material may be reproduced by or for the U.S. Government pursuant
15 *  to the copyright license under the clause at DFARS 252.227-7013.  This
16 *  notice must appear in all copies of this file and its derivatives.
17 *
18 *  $Id$
19 */
20
21#include <rtems/system.h>
22#include <rtems/rtems/status.h>
23#include <rtems/rtems/attr.h>
24#include <rtems/core/chain.h>
25#include <rtems/core/isr.h>
26#include <rtems/rtems/message.h>
27#include <rtems/core/object.h>
28#include <rtems/rtems/options.h>
29#include <rtems/core/states.h>
30#include <rtems/rtems/support.h>
31#include <rtems/core/thread.h>
32#include <rtems/core/wkspace.h>
33#include <rtems/core/mpci.h>
34#include <rtems/sysstate.h>
35
36/*PAGE
37 *
38 *  _CORE_message_queue_Initialize
39 *
40 *  This routine initializes a newly created message queue based on the
41 *  specified data.
42 *
43 *  Input parameters:
44 *    the_message_queue            - the message queue to initialize
45 *    the_class                    - the API specific object class
46 *    the_message_queue_attributes - the message queue's attributes
47 *    maximum_pending_messages     - maximum message and reserved buffer count
48 *    maximum_message_size         - maximum size of each message
49 *    proxy_extract_callout        - remote extract support
50 *
51 *  Output parameters:
52 *    TRUE   - if the message queue is initialized
53 *    FALSE  - if the message queue is NOT initialized
54 */
55
56boolean _CORE_message_queue_Initialize(
57  CORE_message_queue_Control    *the_message_queue,
58  Objects_Classes                the_class,
59  CORE_message_queue_Attributes *the_message_queue_attributes,
60  unsigned32                     maximum_pending_messages,
61  unsigned32                     maximum_message_size,
62  Thread_queue_Extract_callout   proxy_extract_callout
63)
64{
65  unsigned32 message_buffering_required;
66  unsigned32 allocated_message_size;
67
68  the_message_queue->maximum_pending_messages   = maximum_pending_messages;
69  the_message_queue->number_of_pending_messages = 0;
70  the_message_queue->maximum_message_size       = maximum_message_size;
71 
72  /*
73   * round size up to multiple of a ptr for chain init
74   */
75 
76  allocated_message_size = maximum_message_size;
77  if (allocated_message_size & (sizeof(unsigned32) - 1)) {
78      allocated_message_size += sizeof(unsigned32);
79      allocated_message_size &= ~(sizeof(unsigned32) - 1);
80  }
81   
82  message_buffering_required = maximum_pending_messages *
83       (allocated_message_size + sizeof(CORE_message_queue_Buffer_control));
84 
85  the_message_queue->message_buffers = (CORE_message_queue_Buffer *)
86     _Workspace_Allocate( message_buffering_required );
87 
88  if (the_message_queue->message_buffers == 0)
89    return FALSE;
90 
91  _Chain_Initialize (
92    &the_message_queue->Inactive_messages,
93    the_message_queue->message_buffers,
94    maximum_pending_messages,
95    allocated_message_size + sizeof( CORE_message_queue_Buffer_control )
96  );
97 
98  _Chain_Initialize_empty( &the_message_queue->Pending_messages );
99 
100  _Thread_queue_Initialize(
101    &the_message_queue->Wait_queue,
102    the_class,
103    _CORE_message_queue_Is_priority( the_message_queue_attributes ) ?
104       THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
105    STATES_WAITING_FOR_MESSAGE,
106    proxy_extract_callout,
107    CORE_MESSAGE_QUEUE_STATUS_TIMEOUT
108  );
109
110  return TRUE;
111}
112
113/*PAGE
114 *
115 *  _CORE_message_queue_Close
116 *
117 *  This function closes a message by returning all allocated space and
118 *  flushing the message_queue's task wait queue.
119 *
120 *  Input parameters:
121 *    the_message_queue      - the message_queue to be flushed
122 *    remote_extract_callout - function to invoke remotely
123 *    status                 - status to pass to thread
124 *
125 *  Output parameters:  NONE
126 */
127 
128void _CORE_message_queue_Close(
129  CORE_message_queue_Control *the_message_queue,
130  Thread_queue_Flush_callout  remote_extract_callout,
131  unsigned32                  status
132)
133{
134 
135  if ( the_message_queue->number_of_pending_messages != 0 )
136        (void) _CORE_message_queue_Flush_support( the_message_queue );
137  else
138    _Thread_queue_Flush(
139      &the_message_queue->Wait_queue,
140      remote_extract_callout,
141      status
142    );
143
144  (void) _Workspace_Free( the_message_queue->message_buffers );
145
146}
147
148/*PAGE
149 *
150 *  _CORE_message_queue_Flush
151 *
152 *  This function flushes the message_queue's task wait queue.  The number
153 *  of messages flushed from the queue is returned.
154 *
155 *  Input parameters:
156 *    the_message_queue - the message_queue to be flushed
157 *
158 *  Output parameters:
159 *    returns - the number of messages flushed from the queue
160 */
161 
162unsigned32 _CORE_message_queue_Flush(
163  CORE_message_queue_Control *the_message_queue
164)
165{
166  if ( the_message_queue->number_of_pending_messages != 0 )
167    return _CORE_message_queue_Flush_support( the_message_queue );
168  else
169    return 0;
170}
171
172/*PAGE
173 *
174 *  _CORE_message_queue_Broadcast
175 *
176 *  This function sends a message for every thread waiting on the queue and
177 *  returns the number of threads made ready by the message.
178 *
179 *  Input parameters:
180 *    the_message_queue            - message is submitted to this message queue
181 *    buffer                       - pointer to message buffer
182 *    size                         - size in bytes of message to send
183 *    id                           - id of message queue
184 *    api_message_queue_mp_support - api specific mp support callout
185 *    count                        - area to store number of threads made ready
186 *
187 *  Output parameters:
188 *    count                         - number of threads made ready
189 *    CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
190 *    error code                    - if unsuccessful
191 */
192
193CORE_message_queue_Status _CORE_message_queue_Broadcast(
194  CORE_message_queue_Control                *the_message_queue,
195  void                                      *buffer,
196  unsigned32                                 size,
197  Objects_Id                                 id,
198  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
199  unsigned32                                *count
200)
201{
202  Thread_Control          *the_thread;
203  unsigned32               number_broadcasted;
204  Thread_Wait_information *waitp;
205  unsigned32               constrained_size;
206
207  number_broadcasted = 0;
208  while ((the_thread = _Thread_queue_Dequeue(&the_message_queue->Wait_queue))) {
209    waitp = &the_thread->Wait;
210    number_broadcasted += 1;
211
212    constrained_size = size;
213    if ( size > the_message_queue->maximum_message_size )
214        constrained_size = the_message_queue->maximum_message_size;
215
216    _CORE_message_queue_Copy_buffer(
217      buffer,
218      waitp->return_argument,
219      constrained_size
220    );
221
222    *(rtems_unsigned32 *)the_thread->Wait.return_argument_1 = size;
223
224    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
225      (*api_message_queue_mp_support) ( the_thread, id );
226
227  }
228  *count = number_broadcasted;
229  return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
230}
231
232/*PAGE
233 *
234 *  _CORE_message_queue_Seize
235 *
236 *  This kernel routine dequeues a message, copies the message buffer to
237 *  a given destination buffer, and frees the message buffer to the
238 *  inactive message pool.  The thread will be blocked if wait is TRUE,
239 *  otherwise an error will be given to the thread if no messages are available.
240 *
241 *  Input parameters:
242 *    the_message_queue - pointer to message queue
243 *    id                - id of object we are waitig on
244 *    buffer            - pointer to message buffer to be filled
245 *    size              - pointer to the size of buffer to be filled
246 *    wait              - TRUE if wait is allowed, FALSE otherwise
247 *    timeout           - time to wait for a message
248 *
249 *  Output parameters:  NONE
250 *
251 *  NOTE: Dependent on BUFFER_LENGTH
252 *
253 *  INTERRUPT LATENCY:
254 *    available
255 *    wait
256 */
257
258void _CORE_message_queue_Seize(
259  CORE_message_queue_Control *the_message_queue,
260  Objects_Id                  id,
261  void                       *buffer,
262  unsigned32                 *size,
263  boolean                     wait,
264  Watchdog_Interval           timeout
265)
266{
267  ISR_Level                          level;
268  CORE_message_queue_Buffer_control *the_message;
269  Thread_Control                    *executing;
270
271  executing = _Thread_Executing;
272  executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
273  _ISR_Disable( level );
274  if ( the_message_queue->number_of_pending_messages != 0 ) {
275    the_message_queue->number_of_pending_messages -= 1;
276
277    the_message = _CORE_message_queue_Get_pending_message( the_message_queue );
278    _ISR_Enable( level );
279    *size = the_message->Contents.size;
280    _CORE_message_queue_Copy_buffer(the_message->Contents.buffer,buffer,*size );
281    _CORE_message_queue_Free_message_buffer(the_message_queue, the_message );
282    return;
283  }
284
285  if ( !wait ) {
286    _ISR_Enable( level );
287    executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT;
288    return;
289  }
290
291  the_message_queue->Wait_queue.sync = TRUE;
292  executing->Wait.queue              = &the_message_queue->Wait_queue;
293  executing->Wait.id                 = id;
294  executing->Wait.return_argument    = (void *)buffer;
295  executing->Wait.return_argument_1  = (void *)size;
296  _ISR_Enable( level );
297
298  _Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
299}
300
301/*PAGE
302 *
303 *  _CORE_message_queue_Flush_support
304 *
305 *  This message handler routine removes all messages from a message queue
306 *  and returns them to the inactive message pool.  The number of messages
307 *  flushed from the queue is returned
308 *
309 *  Input parameters:
310 *    the_message_queue - pointer to message queue
311 *
312 *  Output parameters:
313 *    returns - number of messages placed on inactive chain
314 *
315 *  INTERRUPT LATENCY:
316 *    only case
317 */
318
319unsigned32 _CORE_message_queue_Flush_support(
320  CORE_message_queue_Control *the_message_queue
321)
322{
323  ISR_Level   level;
324  Chain_Node *inactive_first;
325  Chain_Node *message_queue_first;
326  Chain_Node *message_queue_last;
327  unsigned32  count;
328
329  _ISR_Disable( level );
330    inactive_first      = the_message_queue->Inactive_messages.first;
331    message_queue_first = the_message_queue->Pending_messages.first;
332    message_queue_last  = the_message_queue->Pending_messages.last;
333
334    the_message_queue->Inactive_messages.first = message_queue_first;
335    message_queue_last->next = inactive_first;
336    inactive_first->previous = message_queue_last;
337    message_queue_first->previous          =
338               _Chain_Head( &the_message_queue->Inactive_messages );
339
340    _Chain_Initialize_empty( &the_message_queue->Pending_messages );
341
342    count = the_message_queue->number_of_pending_messages;
343    the_message_queue->number_of_pending_messages = 0;
344  _ISR_Enable( level );
345  return count;
346}
347
348/*PAGE
349 *
350 *  _CORE_message_queue_Submit
351 *
352 *  This routine implements the send and urgent message functions. It
353 *  processes a message that is to be submitted to the designated
354 *  message queue.  The message will either be processed as a
355 *  send message which it will be inserted at the rear of the queue
356 *  or it will be processed as an urgent message which will be inserted
357 *  at the front of the queue.
358 *
359 *  Input parameters:
360 *    the_message_queue            - message is submitted to this message queue
361 *    buffer                       - pointer to message buffer
362 *    size                         - size in bytes of message to send
363 *    id                           - id of message queue
364 *    api_message_queue_mp_support - api specific mp support callout
365 *    submit_type                  - send or urgent message
366 *
367 *  Output parameters:
368 *    CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
369 *    error code                    - if unsuccessful
370 */
371
372CORE_message_queue_Status _CORE_message_queue_Submit(
373  CORE_message_queue_Control                *the_message_queue,
374  void                                      *buffer,
375  unsigned32                                 size,
376  Objects_Id                                 id,
377  CORE_message_queue_API_mp_support_callout  api_message_queue_mp_support,
378  CORE_message_queue_Submit_types            submit_type
379)
380{
381  CORE_message_queue_Buffer_control   *the_message;
382  Thread_Control                      *the_thread;
383
384  if ( size > the_message_queue->maximum_message_size )
385    return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
386
387  /*
388   * Is there a thread currently waiting on this message queue?
389   */
390     
391  the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
392  if ( the_thread )
393  {
394    _CORE_message_queue_Copy_buffer(
395      buffer,
396      the_thread->Wait.return_argument,
397      size
398    );
399    *(rtems_unsigned32 *)the_thread->Wait.return_argument_1 = size;
400   
401    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
402      (*api_message_queue_mp_support) ( the_thread, id );
403
404    return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
405  }
406
407  /*
408   * No one waiting on this one currently.
409   * Allocate a message buffer and store it away
410   */
411
412  if ( the_message_queue->number_of_pending_messages ==
413       the_message_queue->maximum_pending_messages ) {
414    return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
415  }
416
417  the_message = _CORE_message_queue_Allocate_message_buffer(the_message_queue);
418  if ( the_message == 0)
419    return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
420
421  _CORE_message_queue_Copy_buffer( buffer, the_message->Contents.buffer, size );
422  the_message->Contents.size = size;
423 
424  the_message_queue->number_of_pending_messages += 1;
425
426  switch ( submit_type ) {
427    case CORE_MESSAGE_QUEUE_SEND_REQUEST:
428      _CORE_message_queue_Append( the_message_queue, the_message );
429      break;
430    case CORE_MESSAGE_QUEUE_URGENT_REQUEST:
431      _CORE_message_queue_Prepend( the_message_queue, the_message );
432      break;
433  }
434
435  return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
436}
Note: See TracBrowser for help on using the repository browser.