source: rtems/c/src/exec/posix/src/cond.c @ 7d5566e

4.104.114.84.95
Last change on this file since 7d5566e was 5cdcbd2, checked in by Joel Sherrill <joel.sherrill@…>, on 03/08/97 at 03:47:34

Added commit to indicate exepcted _Thread_Dispatch_disable_level. Hopefully
no one will ever get confused here again and try to enable dispatching. :(

  • Property mode set to 100644
File size: 11.1 KB
Line 
1/*
2 *  $Id$
3 */
4
5#include <pthread.h>
6#include <errno.h>
7
8#include <rtems/system.h>
9#include <rtems/score/object.h>
10#include <rtems/score/states.h>
11#include <rtems/score/watchdog.h>
12#include <rtems/posix/cond.h>
13#include <rtems/posix/time.h>
14#include <rtems/posix/mutex.h>
15
16/*
17 *  TEMPORARY
18 */
19
20void _POSIX_Condition_variables_MP_Send_process_packet (
21  POSIX_Condition_variables_MP_Remote_operations  operation,
22  Objects_Id                        condition_variables_id,
23  Objects_Name                      name,
24  Objects_Id                        proxy_id
25)
26{
27  (void) POSIX_MP_NOT_IMPLEMENTED();
28}
29
30void _POSIX_Condition_variables_MP_Send_extract_proxy(
31  Thread_Control *the_thread
32)
33{
34  (void) POSIX_MP_NOT_IMPLEMENTED();
35}
36
37/*
38 *  END OF TEMPORARY
39 */
40
41/*PAGE
42 *
43 *  The default condition variable attributes structure.
44 */
45 
46const pthread_condattr_t _POSIX_Condition_variables_Default_attributes = {
47  TRUE,                      /* is_initialized */
48  PTHREAD_PROCESS_PRIVATE    /* process_shared */
49};
50 
51/*PAGE
52 *
53 *  _POSIX_Condition_variables_Manager_initialization
54 *
55 *  This routine initializes all condition variable manager related data
56 *  structures.
57 *
58 *  Input parameters:
59 *    maximum_condition_variables - maximum configured condition_variables
60 *
61 *  Output parameters:  NONE
62 */
63 
64void _POSIX_Condition_variables_Manager_initialization(
65  unsigned32 maximum_condition_variables
66)
67{
68  _Objects_Initialize_information(
69    &_POSIX_Condition_variables_Information,
70    OBJECTS_POSIX_CONDITION_VARIABLES,
71    TRUE,
72    maximum_condition_variables,
73    sizeof( POSIX_Condition_variables_Control ),
74    FALSE,
75    0,
76    FALSE
77  );
78}
79
80/*PAGE
81 *
82 *  11.4.1 Condition Variable Initialization Attributes,
83 *            P1003.1c/Draft 10, p. 96
84 */
85 
86int pthread_condattr_init(
87  pthread_condattr_t *attr
88)
89{
90  if ( !attr )
91    return EINVAL;
92
93  *attr = _POSIX_Condition_variables_Default_attributes;
94  return 0;
95}
96 
97/*PAGE
98 *
99 *  11.4.1 Condition Variable Initialization Attributes,
100 *            P1003.1c/Draft 10, p. 96
101 */
102 
103int pthread_condattr_destroy(
104  pthread_condattr_t *attr
105)
106{
107  if ( !attr || attr->is_initialized == FALSE )
108    return EINVAL;
109
110  attr->is_initialized = FALSE;
111  return 0;
112}
113 
114/*PAGE
115 *
116 *  11.4.1 Condition Variable Initialization Attributes,
117 *            P1003.1c/Draft 10, p. 96
118 */
119 
120int pthread_condattr_getpshared(
121  const pthread_condattr_t *attr,
122  int                      *pshared
123)
124{
125  if ( !attr )
126    return EINVAL;
127
128  *pshared = attr->process_shared;
129  return 0;
130}
131 
132/*PAGE
133 *
134 *  11.4.1 Condition Variable Initialization Attributes,
135 *            P1003.1c/Draft 10, p. 96
136 */
137 
138int pthread_condattr_setpshared(
139  pthread_condattr_t *attr,
140  int                 pshared
141)
142{
143  if ( !attr )
144    return EINVAL;
145
146  switch ( pshared ) {
147    case PTHREAD_PROCESS_SHARED:
148    case PTHREAD_PROCESS_PRIVATE:
149      attr->process_shared = pshared;
150      return 0;
151
152    default:
153      return EINVAL;
154  }
155}
156 
157/*PAGE
158 *
159 *  11.4.2 Initializing and Destroying a Condition Variable,
160 *         P1003.1c/Draft 10, p. 87
161 */
162 
163int pthread_cond_init(
164  pthread_cond_t           *cond,
165  const pthread_condattr_t *attr
166)
167{
168  POSIX_Condition_variables_Control   *the_cond;
169  const pthread_condattr_t            *the_attr;
170 
171  if ( attr ) the_attr = attr;
172  else        the_attr = &_POSIX_Condition_variables_Default_attributes;
173 
174  /*
175   *  XXX: Be careful about attributes when global!!!
176   */
177 
178  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
179    return POSIX_MP_NOT_IMPLEMENTED();
180 
181  if ( !the_attr->is_initialized )
182    return EINVAL;
183 
184  _Thread_Disable_dispatch();
185 
186  the_cond = _POSIX_Condition_variables_Allocate();
187 
188  if ( !the_cond ) {
189    _Thread_Enable_dispatch();
190    return ENOMEM;
191  }
192 
193  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED &&
194     !( _Objects_MP_Allocate_and_open( &_POSIX_Condition_variables_Information,
195                0, the_cond->Object.id, FALSE ) ) ) {
196    _POSIX_Condition_variables_Free( the_cond );
197    _Thread_Enable_dispatch();
198    return EAGAIN;
199  }
200 
201  the_cond->process_shared  = the_attr->process_shared;
202
203  the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX;
204
205/* XXX some more initialization might need to go here */
206  _Thread_queue_Initialize(
207    &the_cond->Wait_queue,
208    OBJECTS_POSIX_CONDITION_VARIABLES,
209    THREAD_QUEUE_DISCIPLINE_FIFO,
210    STATES_WAITING_FOR_CONDITION_VARIABLE,
211    _POSIX_Condition_variables_MP_Send_extract_proxy,
212    ETIMEDOUT
213  );
214
215  _Objects_Open(
216    &_POSIX_Condition_variables_Information,
217    &the_cond->Object,
218    0
219  );
220 
221  *cond = the_cond->Object.id;
222 
223  if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
224    _POSIX_Condition_variables_MP_Send_process_packet(
225      POSIX_CONDITION_VARIABLES_MP_ANNOUNCE_CREATE,
226      the_cond->Object.id,
227      0,                         /* Name not used */
228      0                          /* Not used */
229    );
230 
231  _Thread_Enable_dispatch();
232
233  return 0;
234}
235 
236/*PAGE
237 *
238 *  11.4.2 Initializing and Destroying a Condition Variable,
239 *         P1003.1c/Draft 10, p. 87
240 */
241 
242int pthread_cond_destroy(
243  pthread_cond_t           *cond
244)
245{
246  register POSIX_Condition_variables_Control *the_cond;
247  Objects_Locations                           location;
248 
249  the_cond = _POSIX_Condition_variables_Get( cond, &location );
250  switch ( location ) {
251    case OBJECTS_ERROR:
252      return EINVAL;
253    case OBJECTS_REMOTE:
254      _Thread_Dispatch();
255      return POSIX_MP_NOT_IMPLEMENTED();
256      return EINVAL;
257    case OBJECTS_LOCAL:
258 
259      if ( _Thread_queue_First( &the_cond->Wait_queue ) ) {
260        _Thread_Enable_dispatch();
261        return EBUSY;
262      }
263 
264      _Objects_Close(
265        &_POSIX_Condition_variables_Information,
266        &the_cond->Object
267      );
268 
269      _POSIX_Condition_variables_Free( the_cond );
270 
271      if ( the_cond->process_shared == PTHREAD_PROCESS_SHARED ) {
272 
273        _Objects_MP_Close(
274          &_POSIX_Condition_variables_Information,
275          the_cond->Object.id
276        );
277 
278        _POSIX_Condition_variables_MP_Send_process_packet(
279          POSIX_CONDITION_VARIABLES_MP_ANNOUNCE_DELETE,
280          the_cond->Object.id,
281          0,                         /* Not used */
282          0                          /* Not used */
283        );
284      }
285      _Thread_Enable_dispatch();
286      return 0;
287  }
288  return POSIX_BOTTOM_REACHED();
289}
290 
291/*PAGE
292 *
293 *  _POSIX_Condition_variables_Signal_support
294 *
295 *  A support routine which implements guts of the broadcast and single task
296 *  wake up version of the "signal" operation.
297 */
298 
299int _POSIX_Condition_variables_Signal_support(
300  pthread_cond_t            *cond,
301  boolean                    is_broadcast
302)
303{
304  register POSIX_Condition_variables_Control *the_cond;
305  Objects_Locations                           location;
306  Thread_Control                             *the_thread;
307 
308  the_cond = _POSIX_Condition_variables_Get( cond, &location );
309  switch ( location ) {
310    case OBJECTS_ERROR:
311      return EINVAL;
312    case OBJECTS_REMOTE:
313      _Thread_Dispatch();
314      return POSIX_MP_NOT_IMPLEMENTED();
315      return EINVAL;
316    case OBJECTS_LOCAL:
317 
318      do {
319        the_thread = _Thread_queue_Dequeue( &the_cond->Wait_queue );
320        if ( !the_thread )
321          the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX;
322      } while ( is_broadcast && the_thread );
323
324      _Thread_Enable_dispatch();
325
326      return 0;
327  }
328  return POSIX_BOTTOM_REACHED();
329}
330
331/*PAGE
332 *
333 *  11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101
334 */
335 
336int pthread_cond_signal(
337  pthread_cond_t   *cond
338)
339{
340  return _POSIX_Condition_variables_Signal_support( cond, FALSE );
341}
342 
343/*PAGE
344 *
345 *  11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101
346 */
347 
348int pthread_cond_broadcast(
349  pthread_cond_t   *cond
350)
351{
352  return _POSIX_Condition_variables_Signal_support( cond, TRUE );
353}
354 
355/*PAGE
356 *
357 *  _POSIX_Condition_variables_Wait_support
358 *
359 *  A support routine which implements guts of the blocking, non-blocking, and
360 *  timed wait version of condition variable wait routines.
361 */
362 
363int _POSIX_Condition_variables_Wait_support(
364  pthread_cond_t            *cond,
365  pthread_mutex_t           *mutex,
366  Watchdog_Interval          timeout,
367  boolean                    already_timedout
368)
369{
370  register POSIX_Condition_variables_Control *the_cond;
371  Objects_Locations                           location;
372  int                                         status;
373  int                                         mutex_status;
374 
375  if ( !_POSIX_Mutex_Get( mutex, &location ) ) {
376     return EINVAL;
377  }
378
379  _Thread_Unnest_dispatch();
380
381  the_cond = _POSIX_Condition_variables_Get( cond, &location );
382  switch ( location ) {
383    case OBJECTS_ERROR:
384      return EINVAL;
385    case OBJECTS_REMOTE:
386      _Thread_Dispatch();
387      return POSIX_MP_NOT_IMPLEMENTED();
388      return EINVAL;
389    case OBJECTS_LOCAL:
390 
391      if ( the_cond->Mutex && ( the_cond->Mutex != *mutex ) ) {
392        _Thread_Enable_dispatch();
393        return EINVAL;
394      }
395 
396      (void) pthread_mutex_unlock( mutex );
397/* XXX ignore this for now  since behavior is undefined
398      if ( mutex_status ) {
399        _Thread_Enable_dispatch();
400        return EINVAL;
401      }
402*/
403
404      if ( !already_timedout ) {
405        the_cond->Mutex = *mutex;
406 
407        _Thread_queue_Enter_critical_section( &the_cond->Wait_queue );
408        _Thread_Executing->Wait.return_code = 0;
409        _Thread_Executing->Wait.queue       = &the_cond->Wait_queue;
410        _Thread_Executing->Wait.id          = *cond;
411
412        _Thread_queue_Enqueue( &the_cond->Wait_queue, timeout );
413
414        _Thread_Enable_dispatch();
415
416        /*
417         *  Switch ourself out because we blocked as a result of the
418         *  _Thread_queue_Enqueue.
419         */
420
421        status = _Thread_Executing->Wait.return_code;
422        if ( status && status != ETIMEDOUT )
423          return status;
424
425      }
426      else
427        status = ETIMEDOUT;
428
429      /*
430       *  When we get here the dispatch disable level is 0.
431       */
432
433      mutex_status = pthread_mutex_lock( mutex );
434      if ( mutex_status )
435        return EINVAL;
436   
437      return status;
438  }
439  return POSIX_BOTTOM_REACHED();
440}
441
442/*PAGE
443 *
444 *  11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105
445 */
446 
447int pthread_cond_wait(
448  pthread_cond_t     *cond,
449  pthread_mutex_t    *mutex
450)
451{
452  return _POSIX_Condition_variables_Wait_support(
453    cond,
454    mutex,
455    THREAD_QUEUE_WAIT_FOREVER,
456    FALSE
457  );
458}
459 
460/*PAGE
461 *
462 *  11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105
463 */
464 
465int pthread_cond_timedwait(
466  pthread_cond_t        *cond,
467  pthread_mutex_t       *mutex,
468  const struct timespec *abstime
469)
470{
471  Watchdog_Interval timeout;
472  struct timespec   current_time;
473  struct timespec   difference;
474  boolean           already_timedout = FALSE;
475
476  if ( !abstime )
477    return EINVAL;
478
479  /*
480   *  The abstime is a walltime.  We turn it into an interval.
481   */
482
483  (void) clock_gettime( CLOCK_REALTIME, &current_time );
484
485  /* XXX probably some error checking should go here */
486
487  _POSIX_Timespec_subtract( &current_time, abstime, &difference );
488
489  if ( ( difference.tv_sec < 0 ) || ( ( difference.tv_sec == 0 ) &&
490       ( difference.tv_nsec < 0 ) ) )
491    already_timedout = TRUE;   
492
493  timeout = _POSIX_Timespec_to_interval( &difference );
494
495  return _POSIX_Condition_variables_Wait_support(
496    cond,
497    mutex,
498    timeout,
499    already_timedout
500  );
501}
Note: See TracBrowser for help on using the repository browser.