1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 1999-2006 Brian Paul
4848b8605Smrg * Copyright 2008 VMware, Inc.
5848b8605Smrg * All Rights Reserved.
6848b8605Smrg *
7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8848b8605Smrg * copy of this software and associated documentation files (the "Software"),
9848b8605Smrg * to deal in the Software without restriction, including without limitation
10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
12848b8605Smrg * Software is furnished to do so, subject to the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice shall be included
15848b8605Smrg * in all copies or substantial portions of the Software.
16848b8605Smrg *
17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
24848b8605Smrg *
25848b8605Smrg **************************************************************************/
26848b8605Smrg
27848b8605Smrg
28848b8605Smrg/**
29848b8605Smrg * @file
30848b8605Smrg *
31848b8605Smrg * Thread, mutex, condition variable, barrier, semaphore and
32848b8605Smrg * thread-specific data functions.
33848b8605Smrg */
34848b8605Smrg
35848b8605Smrg
36848b8605Smrg#ifndef OS_THREAD_H_
37848b8605Smrg#define OS_THREAD_H_
38848b8605Smrg
39848b8605Smrg
40848b8605Smrg#include "pipe/p_compiler.h"
41848b8605Smrg#include "util/u_debug.h" /* for assert */
42b8e80941Smrg#include "util/u_thread.h"
43848b8605Smrg
44848b8605Smrg
45b8e80941Smrg#define pipe_mutex_assert_locked(mutex) \
46b8e80941Smrg   __pipe_mutex_assert_locked(&(mutex))
47848b8605Smrg
48b8e80941Smrgstatic inline void
49b8e80941Smrg__pipe_mutex_assert_locked(mtx_t *mutex)
50848b8605Smrg{
51b8e80941Smrg#ifdef DEBUG
52b8e80941Smrg   /* NOTE: this would not work for recursive mutexes, but
53b8e80941Smrg    * mtx_t doesn't support those
54b8e80941Smrg    */
55b8e80941Smrg   int ret = mtx_trylock(mutex);
56b8e80941Smrg   assert(ret == thrd_busy);
57b8e80941Smrg   if (ret == thrd_success)
58b8e80941Smrg      mtx_unlock(mutex);
59848b8605Smrg#else
60b8e80941Smrg   (void)mutex;
61848b8605Smrg#endif
62848b8605Smrg}
63848b8605Smrg
64848b8605Smrg
65848b8605Smrg/*
66848b8605Smrg * Semaphores
67848b8605Smrg */
68848b8605Smrg
69848b8605Smrgtypedef struct
70848b8605Smrg{
71b8e80941Smrg   mtx_t mutex;
72b8e80941Smrg   cnd_t cond;
73848b8605Smrg   int counter;
74848b8605Smrg} pipe_semaphore;
75848b8605Smrg
76848b8605Smrg
77b8e80941Smrgstatic inline void
78848b8605Smrgpipe_semaphore_init(pipe_semaphore *sema, int init_val)
79848b8605Smrg{
80b8e80941Smrg   (void) mtx_init(&sema->mutex, mtx_plain);
81b8e80941Smrg   cnd_init(&sema->cond);
82848b8605Smrg   sema->counter = init_val;
83848b8605Smrg}
84848b8605Smrg
85b8e80941Smrgstatic inline void
86848b8605Smrgpipe_semaphore_destroy(pipe_semaphore *sema)
87848b8605Smrg{
88b8e80941Smrg   mtx_destroy(&sema->mutex);
89b8e80941Smrg   cnd_destroy(&sema->cond);
90848b8605Smrg}
91848b8605Smrg
92848b8605Smrg/** Signal/increment semaphore counter */
93b8e80941Smrgstatic inline void
94848b8605Smrgpipe_semaphore_signal(pipe_semaphore *sema)
95848b8605Smrg{
96b8e80941Smrg   mtx_lock(&sema->mutex);
97848b8605Smrg   sema->counter++;
98b8e80941Smrg   cnd_signal(&sema->cond);
99b8e80941Smrg   mtx_unlock(&sema->mutex);
100848b8605Smrg}
101848b8605Smrg
102848b8605Smrg/** Wait for semaphore counter to be greater than zero */
103b8e80941Smrgstatic inline void
104848b8605Smrgpipe_semaphore_wait(pipe_semaphore *sema)
105848b8605Smrg{
106b8e80941Smrg   mtx_lock(&sema->mutex);
107848b8605Smrg   while (sema->counter <= 0) {
108b8e80941Smrg      cnd_wait(&sema->cond, &sema->mutex);
109848b8605Smrg   }
110848b8605Smrg   sema->counter--;
111b8e80941Smrg   mtx_unlock(&sema->mutex);
112848b8605Smrg}
113848b8605Smrg
114848b8605Smrg
115848b8605Smrg
116848b8605Smrg/*
117848b8605Smrg * Thread-specific data.
118848b8605Smrg */
119848b8605Smrg
120848b8605Smrgtypedef struct {
121848b8605Smrg   tss_t key;
122848b8605Smrg   int initMagic;
123848b8605Smrg} pipe_tsd;
124848b8605Smrg
125848b8605Smrg
126848b8605Smrg#define PIPE_TSD_INIT_MAGIC 0xff8adc98
127848b8605Smrg
128848b8605Smrg
129b8e80941Smrgstatic inline void
130848b8605Smrgpipe_tsd_init(pipe_tsd *tsd)
131848b8605Smrg{
132848b8605Smrg   if (tss_create(&tsd->key, NULL/*free*/) != 0) {
133848b8605Smrg      exit(-1);
134848b8605Smrg   }
135848b8605Smrg   tsd->initMagic = PIPE_TSD_INIT_MAGIC;
136848b8605Smrg}
137848b8605Smrg
138b8e80941Smrgstatic inline void *
139848b8605Smrgpipe_tsd_get(pipe_tsd *tsd)
140848b8605Smrg{
141848b8605Smrg   if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
142848b8605Smrg      pipe_tsd_init(tsd);
143848b8605Smrg   }
144848b8605Smrg   return tss_get(tsd->key);
145848b8605Smrg}
146848b8605Smrg
147b8e80941Smrgstatic inline void
148848b8605Smrgpipe_tsd_set(pipe_tsd *tsd, void *value)
149848b8605Smrg{
150848b8605Smrg   if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
151848b8605Smrg      pipe_tsd_init(tsd);
152848b8605Smrg   }
153848b8605Smrg   if (tss_set(tsd->key, value) != 0) {
154848b8605Smrg      exit(-1);
155848b8605Smrg   }
156848b8605Smrg}
157848b8605Smrg
158848b8605Smrg
159848b8605Smrg
160b8e80941Smrg/*
161b8e80941Smrg * Thread statistics.
162b8e80941Smrg */
163b8e80941Smrg
164b8e80941Smrg/* Return the time of the current thread's CPU time clock. */
165b8e80941Smrgstatic inline int64_t
166b8e80941Smrgpipe_current_thread_get_time_nano(void)
167b8e80941Smrg{
168b8e80941Smrg#if defined(HAVE_PTHREAD)
169b8e80941Smrg   return u_thread_get_time_nano(pthread_self());
170b8e80941Smrg#else
171b8e80941Smrg   return 0;
172b8e80941Smrg#endif
173b8e80941Smrg}
174b8e80941Smrg
175848b8605Smrg#endif /* OS_THREAD_H_ */
176