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

Last change on this file since beba41b was beba41b, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 18, 2016 at 3:10:03 PM

posix: _POSIX_Condition_variables_Wait_support()

Simplify _POSIX_Condition_variables_Wait_support(), since there is no
need to validate the mutex twice.

  • Property mode set to 100644
File size: 3.2 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 <pthread.h>
22#include <errno.h>
23
24#include <rtems/system.h>
25#include <rtems/score/watchdog.h>
26#include <rtems/score/statesimpl.h>
27#include <rtems/score/threadimpl.h>
28#include <rtems/posix/condimpl.h>
29#include <rtems/posix/muteximpl.h>
30
31THREAD_WAIT_QUEUE_OBJECT_ASSERT(
32  POSIX_Condition_variables_Control,
33  Wait_queue
34);
35
36int _POSIX_Condition_variables_Wait_support(
37  pthread_cond_t            *cond,
38  pthread_mutex_t           *mutex,
39  Watchdog_Interval          timeout,
40  bool                       already_timedout
41)
42{
43  POSIX_Condition_variables_Control *the_cond;
44  Objects_Locations                  location;
45  int                                status;
46  int                                mutex_status;
47  Thread_Control                    *executing;
48
49  the_cond = _POSIX_Condition_variables_Get( cond, &location );
50  switch ( location ) {
51
52    case OBJECTS_LOCAL:
53
54      if ( the_cond->Mutex && ( the_cond->Mutex != *mutex ) ) {
55        _Objects_Put( &the_cond->Object );
56        return EINVAL;
57      }
58
59
60      mutex_status = pthread_mutex_unlock( mutex );
61      /*
62       *  Historically, we ignored the return code since the behavior
63       *  is undefined by POSIX. But GNU/Linux returns EPERM in this
64       *  case, so we follow their lead.
65       */
66      if ( mutex_status ) {
67        _Objects_Put( &the_cond->Object );
68        return EPERM;
69      }
70
71      if ( !already_timedout ) {
72        the_cond->Mutex = *mutex;
73
74        executing = _Thread_Executing;
75        executing->Wait.return_code = 0;
76
77        _Thread_queue_Enqueue(
78          &the_cond->Wait_queue,
79          POSIX_CONDITION_VARIABLES_TQ_OPERATIONS,
80          executing,
81          STATES_WAITING_FOR_CONDITION_VARIABLE
82            | STATES_INTERRUPTIBLE_BY_SIGNAL,
83          timeout,
84          ETIMEDOUT
85        );
86
87        _Objects_Put( &the_cond->Object );
88
89        /*
90         *  Switch ourself out because we blocked as a result of the
91         *  _Thread_queue_Enqueue.
92         */
93
94        /*
95         *  If the thread is interrupted, while in the thread queue, by
96         *  a POSIX signal, then pthread_cond_wait returns spuriously,
97         *  according to the POSIX standard. It means that pthread_cond_wait
98         *  returns a success status, except for the fact that it was not
99         *  woken up a pthread_cond_signal or a pthread_cond_broadcast.
100         */
101        status = executing->Wait.return_code;
102        if ( status == EINTR )
103          status = 0;
104
105      } else {
106        _Objects_Put( &the_cond->Object );
107        status = ETIMEDOUT;
108      }
109
110      /*
111       *  When we get here the dispatch disable level is 0.
112       */
113
114      mutex_status = pthread_mutex_lock( mutex );
115      if ( mutex_status )
116        return EINVAL;
117
118      return status;
119
120#if defined(RTEMS_MULTIPROCESSING)
121    case OBJECTS_REMOTE:
122#endif
123    case OBJECTS_ERROR:
124      break;
125  }
126
127  return EINVAL;
128}
Note: See TracBrowser for help on using the repository browser.