source: rtems/cpukit/posix/src/condwaitsupp.c @ c3d8d9e

5
Last change on this file since c3d8d9e was c3d8d9e, checked in by Sebastian Huber <sebastian.huber@…>, on 05/23/16 at 04:55:49

score: Get rid of mp_id parameter

Get rid of the mp_id parameter used for some thread queue methods. Use
THREAD_QUEUE_QUEUE_TO_OBJECT() instead.

  • Property mode set to 100644
File size: 3.7 KB
Line 
1/**
2 * @file
3 *
4 * @brief POSIX Condition Variables Wait Support
5 * @ingroup POSIX_COND_VARS
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2014.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/posix/condimpl.h>
22#include <rtems/posix/muteximpl.h>
23#include <rtems/score/assert.h>
24#include <rtems/score/statesimpl.h>
25#include <rtems/score/threaddispatch.h>
26
27THREAD_QUEUE_OBJECT_ASSERT( POSIX_Condition_variables_Control, Wait_queue );
28
29int _POSIX_Condition_variables_Wait_support(
30  pthread_cond_t            *cond,
31  pthread_mutex_t           *mutex,
32  Watchdog_Interval          timeout,
33  bool                       already_timedout
34)
35{
36  POSIX_Condition_variables_Control *the_cond;
37  POSIX_Mutex_Control               *the_mutex;
38  ISR_lock_Context                   lock_context;
39  int                                status;
40  int                                mutex_status;
41  CORE_mutex_Status                  core_mutex_status;
42  Per_CPU_Control                   *cpu_self;
43  Thread_Control                    *executing;
44
45  if ( mutex == NULL ) {
46    return EINVAL;
47  }
48
49  the_cond = _POSIX_Condition_variables_Get( cond, &lock_context );
50
51  if ( the_cond == NULL ) {
52    return EINVAL;
53  }
54
55  _POSIX_Condition_variables_Acquire_critical( the_cond, &lock_context );
56
57  if (
58    the_cond->mutex != POSIX_CONDITION_VARIABLES_NO_MUTEX
59      && the_cond->mutex != *mutex
60  ) {
61    _POSIX_Condition_variables_Release( the_cond, &lock_context );
62    return EINVAL;
63  }
64
65  the_cond->mutex = *mutex;
66
67  cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
68  executing = _Per_CPU_Get_executing( cpu_self );
69
70  /*
71   *  Historically, we ignored the unlock status since the behavior
72   *  is undefined by POSIX. But GNU/Linux returns EPERM in this
73   *  case, so we follow their lead.
74   */
75
76  the_mutex = _POSIX_Mutex_Get_no_protection( mutex );
77  if (
78    the_mutex == NULL
79      || !_CORE_mutex_Is_owner( &the_mutex->Mutex, executing )
80  ) {
81    _POSIX_Condition_variables_Release( the_cond, &lock_context );
82    _Thread_Dispatch_enable( cpu_self );
83    return EPERM;
84  }
85
86  if ( !already_timedout ) {
87    executing->Wait.return_code = 0;
88    _Thread_queue_Enqueue_critical(
89      &the_cond->Wait_queue.Queue,
90      POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
91      executing,
92      STATES_WAITING_FOR_CONDITION_VARIABLE,
93      timeout,
94      ETIMEDOUT,
95      &lock_context
96    );
97  } else {
98    _POSIX_Condition_variables_Release( the_cond, &lock_context );
99    executing->Wait.return_code = ETIMEDOUT;
100  }
101
102  _ISR_lock_ISR_disable( &lock_context );
103  core_mutex_status = _CORE_mutex_Surrender(
104    &the_mutex->Mutex,
105    NULL,
106    &lock_context
107  );
108  _Assert( core_mutex_status == CORE_MUTEX_STATUS_SUCCESSFUL );
109  (void) core_mutex_status;
110
111  /*
112   *  Switch ourself out because we blocked as a result of the
113   *  _Thread_queue_Enqueue_critical().
114   */
115
116  _Thread_Dispatch_enable( cpu_self );
117
118  status = (int) executing->Wait.return_code;
119
120  /*
121   *  If the thread is interrupted, while in the thread queue, by
122   *  a POSIX signal, then pthread_cond_wait returns spuriously,
123   *  according to the POSIX standard. It means that pthread_cond_wait
124   *  returns a success status, except for the fact that it was not
125   *  woken up a pthread_cond_signal() or a pthread_cond_broadcast().
126   */
127
128  if ( status == EINTR ) {
129    status = 0;
130  }
131
132  /*
133   *  When we get here the dispatch disable level is 0.
134   */
135
136  mutex_status = pthread_mutex_lock( mutex );
137  if ( mutex_status != 0 ) {
138    return EINVAL;
139  }
140
141  return status;
142}
Note: See TracBrowser for help on using the repository browser.