source: rtems/cpukit/posix/src/cond.c @ 97e2729d

4.104.114.84.95
Last change on this file since 97e2729d was 97e2729d, checked in by Joel Sherrill <joel.sherrill@…>, on 11/23/98 at 17:38:09

Added --disable-multiprocessing flag and modified a lot of files to make
it work.

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