source: rtems/cpukit/posix/src/condwaitsupp.c @ 327fbd6

4.115
Last change on this file since 327fbd6 was 327fbd6, checked in by Joel Sherrill <joel.sherrill@…>, on 12/09/13 at 21:25:16

condwaitsupp.c: Return EPERM if waiting and mutex is not locked

This error check was commented out because it is not in the POSIX
specification. However, the GNU/Linux manual page does document
that EPERM is to be returned in this situation.

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