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

5
Last change on this file since dce48791 was dce48791, checked in by Sebastian Huber <sebastian.huber@…>, on 05/23/16 at 11:37:59

score: Add Status_Control for all APIs

Unify the status codes of the Classic and POSIX API to use the new enum
Status_Control. This eliminates the Thread_Control::Wait::timeout_code
field and the timeout parameter of _Thread_queue_Enqueue_critical() and
_MPCI_Send_request_packet(). It gets rid of the status code translation
tables and instead uses simple bit operations to get the status for a
particular API. This enables translation of status code constants at
compile time. Add _Thread_Wait_get_status() to avoid direct access of
thread internal data structures.

  • 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/posix/posixapi.h>
24#include <rtems/score/assert.h>
25#include <rtems/score/statesimpl.h>
26#include <rtems/score/status.h>
27#include <rtems/score/threaddispatch.h>
28
29THREAD_QUEUE_OBJECT_ASSERT( POSIX_Condition_variables_Control, Wait_queue );
30
31int _POSIX_Condition_variables_Wait_support(
32  pthread_cond_t            *cond,
33  pthread_mutex_t           *mutex,
34  Watchdog_Interval          timeout,
35  bool                       already_timedout
36)
37{
38  POSIX_Condition_variables_Control *the_cond;
39  POSIX_Mutex_Control               *the_mutex;
40  Thread_queue_Context               queue_context;
41  int                                error;
42  int                                mutex_error;
43  Status_Control                     status;
44  Per_CPU_Control                   *cpu_self;
45  Thread_Control                    *executing;
46
47  if ( mutex == NULL ) {
48    return EINVAL;
49  }
50
51  the_cond = _POSIX_Condition_variables_Get( cond, &queue_context );
52
53  if ( the_cond == NULL ) {
54    return EINVAL;
55  }
56
57  _POSIX_Condition_variables_Acquire_critical( the_cond, &queue_context );
58
59  if (
60    the_cond->mutex != POSIX_CONDITION_VARIABLES_NO_MUTEX
61      && the_cond->mutex != *mutex
62  ) {
63    _POSIX_Condition_variables_Release( the_cond, &queue_context );
64    return EINVAL;
65  }
66
67  the_cond->mutex = *mutex;
68
69  cpu_self = _Thread_Dispatch_disable_critical( &queue_context.Lock_context );
70  executing = _Per_CPU_Get_executing( cpu_self );
71
72  /*
73   *  Historically, we ignored the unlock status since the behavior
74   *  is undefined by POSIX. But GNU/Linux returns EPERM in this
75   *  case, so we follow their lead.
76   */
77
78  the_mutex = _POSIX_Mutex_Get_no_protection( mutex );
79  if (
80    the_mutex == NULL
81      || !_CORE_mutex_Is_owner( &the_mutex->Mutex, executing )
82  ) {
83    _POSIX_Condition_variables_Release( the_cond, &queue_context );
84    _Thread_Dispatch_enable( cpu_self );
85    return EPERM;
86  }
87
88  if ( !already_timedout ) {
89    _Thread_queue_Enqueue_critical(
90      &the_cond->Wait_queue.Queue,
91      POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
92      executing,
93      STATES_WAITING_FOR_CONDITION_VARIABLE,
94      timeout,
95      &queue_context.Lock_context
96    );
97  } else {
98    _POSIX_Condition_variables_Release( the_cond, &queue_context );
99    executing->Wait.return_code = STATUS_TIMEOUT;
100  }
101
102  _ISR_lock_ISR_disable( &queue_context.Lock_context );
103  status = _CORE_mutex_Surrender( &the_mutex->Mutex, &queue_context );
104  _Assert( status == STATUS_SUCCESSFUL );
105  (void) status;
106
107  /*
108   *  Switch ourself out because we blocked as a result of the
109   *  _Thread_queue_Enqueue_critical().
110   */
111
112  _Thread_Dispatch_enable( cpu_self );
113
114  error = _POSIX_Get_error_after_wait( executing );
115
116  /*
117   *  If the thread is interrupted, while in the thread queue, by
118   *  a POSIX signal, then pthread_cond_wait returns spuriously,
119   *  according to the POSIX standard. It means that pthread_cond_wait
120   *  returns a success status, except for the fact that it was not
121   *  woken up a pthread_cond_signal() or a pthread_cond_broadcast().
122   */
123
124  if ( error == EINTR ) {
125    error = 0;
126  }
127
128  /*
129   *  When we get here the dispatch disable level is 0.
130   */
131
132  mutex_error = pthread_mutex_lock( mutex );
133  if ( mutex_error != 0 ) {
134    return EINVAL;
135  }
136
137  return error;
138}
Note: See TracBrowser for help on using the repository browser.