Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / system / libroot / posix / pthread / pthread_cond.cpp
blob258fbab3cf1d80a34593fadbbdd837ee70e4a8d5
1 /*
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.
5 */
8 #include <pthread.h>
9 #include "pthread_private.h"
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
15 #include <syscall_utils.h>
17 #include <syscalls.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 = {
26 false,
27 CLOCK_REALTIME
31 int
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;
37 cond->flags = 0;
38 if (attr->process_shared)
39 cond->flags |= COND_FLAG_SHARED;
41 if (attr->clock_id == CLOCK_MONOTONIC)
42 cond->flags |= COND_FLAG_MONOTONIC;
44 cond->mutex = NULL;
45 cond->waiter_count = 0;
46 cond->lock = 0;
48 return 0;
52 int
53 pthread_cond_destroy(pthread_cond_t* cond)
55 return 0;
59 static status_t
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
64 return EPERM;
67 if (cond->mutex != NULL && cond->mutex != mutex) {
68 // condition variable already used with different mutex
69 return EINVAL;
72 cond->mutex = mutex;
73 cond->waiter_count++;
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
79 mutex->owner = -1;
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.
92 status = 0;
95 pthread_mutex_lock(mutex);
97 cond->waiter_count--;
98 // If there are no more waiters, we can change mutexes.
99 if (cond->waiter_count == 0)
100 cond->mutex = NULL;
102 return status;
106 static inline void
107 cond_signal(pthread_cond_t* cond, bool broadcast)
109 if (cond->waiter_count == 0)
110 return;
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);
141 return 0;
146 pthread_cond_signal(pthread_cond_t* cond)
148 cond_signal(cond, false);
149 return 0;