1cdc920a0Smrg/**************************************************************************
2cdc920a0Smrg *
3cdc920a0Smrg * Copyright 1999-2006 Brian Paul
4af69d88dSmrg * Copyright 2008 VMware, Inc.
5cdc920a0Smrg * All Rights Reserved.
6cdc920a0Smrg *
7cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8cdc920a0Smrg * copy of this software and associated documentation files (the "Software"),
9cdc920a0Smrg * to deal in the Software without restriction, including without limitation
10cdc920a0Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11cdc920a0Smrg * and/or sell copies of the Software, and to permit persons to whom the
12cdc920a0Smrg * Software is furnished to do so, subject to the following conditions:
13cdc920a0Smrg *
14cdc920a0Smrg * The above copyright notice and this permission notice shall be included
15cdc920a0Smrg * in all copies or substantial portions of the Software.
16cdc920a0Smrg *
17cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18cdc920a0Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19cdc920a0Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
24af69d88dSmrg *
25cdc920a0Smrg **************************************************************************/
26cdc920a0Smrg
27cdc920a0Smrg
28cdc920a0Smrg/**
29cdc920a0Smrg * @file
30cdc920a0Smrg *
31cdc920a0Smrg * Thread, mutex, condition variable, barrier, semaphore and
32cdc920a0Smrg * thread-specific data functions.
33cdc920a0Smrg */
34cdc920a0Smrg
35cdc920a0Smrg
36cdc920a0Smrg#ifndef OS_THREAD_H_
37cdc920a0Smrg#define OS_THREAD_H_
38cdc920a0Smrg
39cdc920a0Smrg
40cdc920a0Smrg#include "pipe/p_compiler.h"
41cdc920a0Smrg#include "util/u_debug.h" /* for assert */
4201e04c3fSmrg#include "util/u_thread.h"
43cdc920a0Smrg
44cdc920a0Smrg
4501e04c3fSmrg#define pipe_mutex_assert_locked(mutex) \
4601e04c3fSmrg   __pipe_mutex_assert_locked(&(mutex))
47cdc920a0Smrg
4801e04c3fSmrgstatic inline void
4901e04c3fSmrg__pipe_mutex_assert_locked(mtx_t *mutex)
50cdc920a0Smrg{
5101e04c3fSmrg#ifdef DEBUG
5201e04c3fSmrg   /* NOTE: this would not work for recursive mutexes, but
5301e04c3fSmrg    * mtx_t doesn't support those
5401e04c3fSmrg    */
5501e04c3fSmrg   int ret = mtx_trylock(mutex);
5601e04c3fSmrg   assert(ret == thrd_busy);
5701e04c3fSmrg   if (ret == thrd_success)
5801e04c3fSmrg      mtx_unlock(mutex);
59af69d88dSmrg#else
6001e04c3fSmrg   (void)mutex;
61af69d88dSmrg#endif
62cdc920a0Smrg}
63cdc920a0Smrg
64cdc920a0Smrg
65cdc920a0Smrg/*
66cdc920a0Smrg * Semaphores
67cdc920a0Smrg */
68cdc920a0Smrg
69cdc920a0Smrgtypedef struct
70cdc920a0Smrg{
7101e04c3fSmrg   mtx_t mutex;
7201e04c3fSmrg   cnd_t cond;
73cdc920a0Smrg   int counter;
74cdc920a0Smrg} pipe_semaphore;
75cdc920a0Smrg
76cdc920a0Smrg
7701e04c3fSmrgstatic inline void
78cdc920a0Smrgpipe_semaphore_init(pipe_semaphore *sema, int init_val)
79cdc920a0Smrg{
8001e04c3fSmrg   (void) mtx_init(&sema->mutex, mtx_plain);
8101e04c3fSmrg   cnd_init(&sema->cond);
82cdc920a0Smrg   sema->counter = init_val;
83cdc920a0Smrg}
84cdc920a0Smrg
8501e04c3fSmrgstatic inline void
86cdc920a0Smrgpipe_semaphore_destroy(pipe_semaphore *sema)
87cdc920a0Smrg{
8801e04c3fSmrg   mtx_destroy(&sema->mutex);
8901e04c3fSmrg   cnd_destroy(&sema->cond);
90cdc920a0Smrg}
91cdc920a0Smrg
92cdc920a0Smrg/** Signal/increment semaphore counter */
9301e04c3fSmrgstatic inline void
94cdc920a0Smrgpipe_semaphore_signal(pipe_semaphore *sema)
95cdc920a0Smrg{
9601e04c3fSmrg   mtx_lock(&sema->mutex);
97cdc920a0Smrg   sema->counter++;
9801e04c3fSmrg   cnd_signal(&sema->cond);
9901e04c3fSmrg   mtx_unlock(&sema->mutex);
100cdc920a0Smrg}
101cdc920a0Smrg
102cdc920a0Smrg/** Wait for semaphore counter to be greater than zero */
10301e04c3fSmrgstatic inline void
104cdc920a0Smrgpipe_semaphore_wait(pipe_semaphore *sema)
105cdc920a0Smrg{
10601e04c3fSmrg   mtx_lock(&sema->mutex);
107cdc920a0Smrg   while (sema->counter <= 0) {
10801e04c3fSmrg      cnd_wait(&sema->cond, &sema->mutex);
109cdc920a0Smrg   }
110cdc920a0Smrg   sema->counter--;
11101e04c3fSmrg   mtx_unlock(&sema->mutex);
112cdc920a0Smrg}
113cdc920a0Smrg
114cdc920a0Smrg
115cdc920a0Smrg
116cdc920a0Smrg/*
117cdc920a0Smrg * Thread-specific data.
118cdc920a0Smrg */
119cdc920a0Smrg
120cdc920a0Smrgtypedef struct {
121af69d88dSmrg   tss_t key;
122cdc920a0Smrg   int initMagic;
123cdc920a0Smrg} pipe_tsd;
124cdc920a0Smrg
125cdc920a0Smrg
126cdc920a0Smrg#define PIPE_TSD_INIT_MAGIC 0xff8adc98
127cdc920a0Smrg
128cdc920a0Smrg
12901e04c3fSmrgstatic inline void
130cdc920a0Smrgpipe_tsd_init(pipe_tsd *tsd)
131cdc920a0Smrg{
132af69d88dSmrg   if (tss_create(&tsd->key, NULL/*free*/) != 0) {
133cdc920a0Smrg      exit(-1);
134cdc920a0Smrg   }
135cdc920a0Smrg   tsd->initMagic = PIPE_TSD_INIT_MAGIC;
136cdc920a0Smrg}
137cdc920a0Smrg
13801e04c3fSmrgstatic inline void *
139cdc920a0Smrgpipe_tsd_get(pipe_tsd *tsd)
140cdc920a0Smrg{
141cdc920a0Smrg   if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
142cdc920a0Smrg      pipe_tsd_init(tsd);
143cdc920a0Smrg   }
144af69d88dSmrg   return tss_get(tsd->key);
145cdc920a0Smrg}
146cdc920a0Smrg
14701e04c3fSmrgstatic inline void
148cdc920a0Smrgpipe_tsd_set(pipe_tsd *tsd, void *value)
149cdc920a0Smrg{
150cdc920a0Smrg   if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
151cdc920a0Smrg      pipe_tsd_init(tsd);
152cdc920a0Smrg   }
153af69d88dSmrg   if (tss_set(tsd->key, value) != 0) {
154cdc920a0Smrg      exit(-1);
155cdc920a0Smrg   }
156cdc920a0Smrg}
157cdc920a0Smrg
158cdc920a0Smrg#endif /* OS_THREAD_H_ */
159