2 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2007, Ryan Leavengood, leavengood@gmail.com.
4 * All rights reserved. Distributed under the terms of the MIT License.
9 #include "pthread_private.h"
15 #include <syscall_utils.h>
18 #include <user_mutex_defs.h>
21 #define COND_FLAG_SHARED 0x01
22 #define COND_FLAG_MONOTONIC 0x02
25 static const pthread_condattr pthread_condattr_default
= {
32 pthread_cond_init(pthread_cond_t
* cond
, const pthread_condattr_t
* _attr
)
34 const pthread_condattr
* attr
= _attr
!= NULL
35 ? *_attr
: &pthread_condattr_default
;
38 if (attr
->process_shared
)
39 cond
->flags
|= COND_FLAG_SHARED
;
41 if (attr
->clock_id
== CLOCK_MONOTONIC
)
42 cond
->flags
|= COND_FLAG_MONOTONIC
;
45 cond
->waiter_count
= 0;
53 pthread_cond_destroy(pthread_cond_t
* cond
)
60 cond_wait(pthread_cond_t
* cond
, pthread_mutex_t
* mutex
, bigtime_t timeout
)
62 if (mutex
->owner
!= find_thread(NULL
)) {
63 // calling thread isn't mutex owner
67 if (cond
->mutex
!= NULL
&& cond
->mutex
!= mutex
) {
68 // condition variable already used with different mutex
75 // make sure the user mutex we use for blocking is locked
76 atomic_or((int32
*)&cond
->lock
, B_USER_MUTEX_LOCKED
);
78 // atomically unlock the mutex and start waiting on the user mutex
80 mutex
->owner_count
= 0;
82 int32 flags
= (cond
->flags
& COND_FLAG_MONOTONIC
) != 0 ? B_ABSOLUTE_TIMEOUT
83 : B_ABSOLUTE_REAL_TIME_TIMEOUT
;
85 status_t status
= _kern_mutex_switch_lock((int32
*)&mutex
->lock
,
86 (int32
*)&cond
->lock
, "pthread condition",
87 timeout
== B_INFINITE_TIMEOUT
? 0 : flags
, timeout
);
89 if (status
== B_INTERRUPTED
) {
90 // EINTR is not an allowed return value. We either have to restart
91 // waiting -- which we can't atomically -- or return a spurious 0.
95 pthread_mutex_lock(mutex
);
98 // If there are no more waiters, we can change mutexes.
99 if (cond
->waiter_count
== 0)
107 cond_signal(pthread_cond_t
* cond
, bool broadcast
)
109 if (cond
->waiter_count
== 0)
112 // release the condition lock
113 _kern_mutex_unlock((int32
*)&cond
->lock
,
114 broadcast
? B_USER_MUTEX_UNBLOCK_ALL
: 0);
119 pthread_cond_wait(pthread_cond_t
* cond
, pthread_mutex_t
* _mutex
)
121 RETURN_AND_TEST_CANCEL(cond_wait(cond
, _mutex
, B_INFINITE_TIMEOUT
));
126 pthread_cond_timedwait(pthread_cond_t
* cond
, pthread_mutex_t
* mutex
,
127 const struct timespec
* tv
)
129 if (tv
== NULL
|| tv
->tv_nsec
< 0 || tv
->tv_nsec
>= 1000 * 1000 * 1000)
130 RETURN_AND_TEST_CANCEL(EINVAL
);
132 RETURN_AND_TEST_CANCEL(
133 cond_wait(cond
, mutex
, tv
->tv_sec
* 1000000LL + tv
->tv_nsec
/ 1000LL));
138 pthread_cond_broadcast(pthread_cond_t
* cond
)
140 cond_signal(cond
, true);
146 pthread_cond_signal(pthread_cond_t
* cond
)
148 cond_signal(cond
, false);