2008-01-20 18:36:23 +00:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
2008-02-19 06:07:53 +00:00
|
|
|
* Copyright 1999-2006 Brian Paul
|
s/Tungsten Graphics/VMware/
Tungsten Graphics Inc. was acquired by VMware Inc. in 2008. Leaving the
old copyright name is creating unnecessary confusion, hence this change.
This was the sed script I used:
$ cat tg2vmw.sed
# Run as:
#
# git reset --hard HEAD && find include scons src -type f -not -name 'sed*' -print0 | xargs -0 sed -i -f tg2vmw.sed
#
# Rename copyrights
s/Tungsten Gra\(ph\|hp\)ics,\? [iI]nc\.\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./g
/Copyright/s/Tungsten Graphics\(,\? [iI]nc\.\)\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./
s/TUNGSTEN GRAPHICS/VMWARE/g
# Rename emails
s/alanh@tungstengraphics.com/alanh@vmware.com/
s/jens@tungstengraphics.com/jowen@vmware.com/g
s/jrfonseca-at-tungstengraphics-dot-com/jfonseca-at-vmware-dot-com/
s/jrfonseca\?@tungstengraphics.com/jfonseca@vmware.com/g
s/keithw\?@tungstengraphics.com/keithw@vmware.com/g
s/michel@tungstengraphics.com/daenzer@vmware.com/g
s/thomas-at-tungstengraphics-dot-com/thellstom-at-vmware-dot-com/
s/zack@tungstengraphics.com/zackr@vmware.com/
# Remove dead links
s@Tungsten Graphics (http://www.tungstengraphics.com)@Tungsten Graphics@g
# C string src/gallium/state_trackers/vega/api_misc.c
s/"Tungsten Graphics, Inc"/"VMware, Inc"/
Reviewed-by: Brian Paul <brianp@vmware.com>
2014-01-17 16:27:50 +00:00
|
|
|
* Copyright 2008 VMware, Inc.
|
2008-01-20 18:36:23 +00:00
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
2008-02-19 06:07:53 +00:00
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
* in all copies or substantial portions of the Software.
|
|
|
|
*
|
2008-01-20 18:36:23 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
2008-02-19 06:07:53 +00:00
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
2013-04-21 21:46:48 +01:00
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
2008-01-20 18:36:23 +00:00
|
|
|
**************************************************************************/
|
|
|
|
|
2008-08-26 23:35:12 +01:00
|
|
|
|
2008-02-19 06:07:53 +00:00
|
|
|
/**
|
2008-09-19 02:40:42 +01:00
|
|
|
* @file
|
|
|
|
*
|
2009-12-11 21:00:25 +00:00
|
|
|
* Thread, mutex, condition variable, barrier, semaphore and
|
|
|
|
* thread-specific data functions.
|
2008-02-19 06:07:53 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2010-02-02 15:18:01 +00:00
|
|
|
#ifndef OS_THREAD_H_
|
|
|
|
#define OS_THREAD_H_
|
2008-02-19 06:07:53 +00:00
|
|
|
|
|
|
|
|
2008-08-26 23:35:12 +01:00
|
|
|
#include "pipe/p_compiler.h"
|
2009-06-15 18:57:45 +01:00
|
|
|
#include "util/u_debug.h" /* for assert */
|
2008-02-19 06:07:53 +00:00
|
|
|
|
2013-04-26 08:03:33 +01:00
|
|
|
#include "c11/threads.h"
|
2008-02-19 06:07:53 +00:00
|
|
|
|
2013-04-26 08:03:33 +01:00
|
|
|
#ifdef HAVE_PTHREAD
|
2012-05-05 04:50:19 +01:00
|
|
|
#include <signal.h>
|
2013-04-26 08:03:33 +01:00
|
|
|
#endif
|
2008-02-19 06:07:53 +00:00
|
|
|
|
2009-06-05 02:57:19 +01:00
|
|
|
|
2009-12-11 21:07:01 +00:00
|
|
|
/* pipe_thread
|
|
|
|
*/
|
2013-04-26 08:03:33 +01:00
|
|
|
typedef thrd_t pipe_thread;
|
2008-09-05 15:47:06 +01:00
|
|
|
|
|
|
|
#define PIPE_THREAD_ROUTINE( name, param ) \
|
2013-04-26 08:03:33 +01:00
|
|
|
int name( void *param )
|
2008-09-05 15:47:06 +01:00
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline pipe_thread pipe_thread_create( PIPE_THREAD_ROUTINE((*routine), ), void *param )
|
2008-09-05 15:47:06 +01:00
|
|
|
{
|
|
|
|
pipe_thread thread;
|
2013-04-26 08:03:33 +01:00
|
|
|
#ifdef HAVE_PTHREAD
|
2011-05-15 07:41:54 +01:00
|
|
|
sigset_t saved_set, new_set;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
sigfillset(&new_set);
|
|
|
|
pthread_sigmask(SIG_SETMASK, &new_set, &saved_set);
|
2013-04-26 08:03:33 +01:00
|
|
|
ret = thrd_create( &thread, routine, param );
|
2011-05-15 07:41:54 +01:00
|
|
|
pthread_sigmask(SIG_SETMASK, &saved_set, NULL);
|
2013-04-26 08:03:33 +01:00
|
|
|
#else
|
|
|
|
int ret;
|
|
|
|
ret = thrd_create( &thread, routine, param );
|
|
|
|
#endif
|
2011-05-15 07:41:54 +01:00
|
|
|
if (ret)
|
2008-09-05 15:47:06 +01:00
|
|
|
return 0;
|
2013-04-26 08:03:33 +01:00
|
|
|
|
2008-09-05 15:47:06 +01:00
|
|
|
return thread;
|
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline int pipe_thread_wait( pipe_thread thread )
|
2008-09-05 15:47:06 +01:00
|
|
|
{
|
2013-04-26 08:03:33 +01:00
|
|
|
return thrd_join( thread, NULL );
|
2008-09-05 15:47:06 +01:00
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline int pipe_thread_destroy( pipe_thread thread )
|
2008-09-05 15:47:06 +01:00
|
|
|
{
|
2013-04-26 08:03:33 +01:00
|
|
|
return thrd_detach( thread );
|
2008-09-05 15:47:06 +01:00
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void pipe_thread_setname( const char *name )
|
2015-02-13 13:51:28 +00:00
|
|
|
{
|
|
|
|
#if defined(HAVE_PTHREAD)
|
|
|
|
# if defined(__GNU_LIBRARY__) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \
|
|
|
|
(__GLIBC__ >= 3 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 12))
|
|
|
|
pthread_setname_np(pthread_self(), name);
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
(void)name;
|
|
|
|
}
|
|
|
|
|
2009-12-11 21:07:01 +00:00
|
|
|
|
2016-10-26 16:11:00 +01:00
|
|
|
static inline int pipe_thread_is_self( pipe_thread thread )
|
|
|
|
{
|
|
|
|
#if defined(HAVE_PTHREAD)
|
|
|
|
# if defined(__GNU_LIBRARY__) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \
|
|
|
|
(__GLIBC__ >= 3 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 12))
|
|
|
|
return pthread_equal(pthread_self(), thread);
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-08-26 23:35:12 +01:00
|
|
|
#define pipe_mutex_destroy(mutex) \
|
2013-04-26 08:03:33 +01:00
|
|
|
mtx_destroy(&(mutex))
|
2008-02-19 06:07:53 +00:00
|
|
|
|
2008-08-26 23:35:12 +01:00
|
|
|
#define pipe_mutex_lock(mutex) \
|
2013-04-26 08:03:33 +01:00
|
|
|
(void) mtx_lock(&(mutex))
|
2008-02-19 06:07:53 +00:00
|
|
|
|
2008-08-26 23:35:12 +01:00
|
|
|
#define pipe_mutex_unlock(mutex) \
|
2013-04-26 08:03:33 +01:00
|
|
|
(void) mtx_unlock(&(mutex))
|
2008-04-11 04:11:14 +01:00
|
|
|
|
2016-07-21 18:51:36 +01:00
|
|
|
#define pipe_mutex_assert_locked(mutex) \
|
|
|
|
__pipe_mutex_assert_locked(&(mutex))
|
|
|
|
|
|
|
|
static inline void
|
2017-03-05 01:32:01 +00:00
|
|
|
__pipe_mutex_assert_locked(mtx_t *mutex)
|
2016-07-21 18:51:36 +01:00
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
/* NOTE: this would not work for recursive mutexes, but
|
2017-03-05 01:32:01 +00:00
|
|
|
* mtx_t doesn't support those
|
2016-07-21 18:51:36 +01:00
|
|
|
*/
|
|
|
|
int ret = mtx_trylock(mutex);
|
|
|
|
assert(ret == thrd_busy);
|
|
|
|
if (ret == thrd_success)
|
|
|
|
mtx_unlock(mutex);
|
|
|
|
#endif
|
|
|
|
}
|
2009-12-11 21:07:01 +00:00
|
|
|
|
|
|
|
/* pipe_condvar
|
|
|
|
*/
|
2013-04-26 08:03:33 +01:00
|
|
|
typedef cnd_t pipe_condvar;
|
2009-12-11 21:07:01 +00:00
|
|
|
|
2010-02-11 02:12:10 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* pipe_barrier
|
|
|
|
*/
|
|
|
|
|
2014-01-23 13:44:10 +00:00
|
|
|
#if (defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HURD)) && !defined(PIPE_OS_ANDROID)
|
2010-02-11 02:12:10 +00:00
|
|
|
|
|
|
|
typedef pthread_barrier_t pipe_barrier;
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
|
2010-02-11 02:12:10 +00:00
|
|
|
{
|
|
|
|
pthread_barrier_init(barrier, NULL, count);
|
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void pipe_barrier_destroy(pipe_barrier *barrier)
|
2010-02-11 02:12:10 +00:00
|
|
|
{
|
|
|
|
pthread_barrier_destroy(barrier);
|
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void pipe_barrier_wait(pipe_barrier *barrier)
|
2010-02-11 02:12:10 +00:00
|
|
|
{
|
|
|
|
pthread_barrier_wait(barrier);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-03 21:49:48 +01:00
|
|
|
#else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */
|
2010-02-11 02:12:10 +00:00
|
|
|
|
2010-04-17 22:24:23 +01:00
|
|
|
typedef struct {
|
|
|
|
unsigned count;
|
|
|
|
unsigned waiters;
|
2010-04-26 08:25:30 +01:00
|
|
|
uint64_t sequence;
|
2017-03-05 01:32:01 +00:00
|
|
|
mtx_t mutex;
|
2010-04-17 22:24:23 +01:00
|
|
|
pipe_condvar condvar;
|
|
|
|
} pipe_barrier;
|
2010-02-11 02:12:10 +00:00
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
|
2009-12-11 21:00:25 +00:00
|
|
|
{
|
2010-04-17 22:24:23 +01:00
|
|
|
barrier->count = count;
|
|
|
|
barrier->waiters = 0;
|
2010-04-26 08:25:30 +01:00
|
|
|
barrier->sequence = 0;
|
2017-03-05 01:00:15 +00:00
|
|
|
(void) mtx_init(&barrier->mutex, mtx_plain);
|
2017-03-04 23:41:29 +00:00
|
|
|
cnd_init(&barrier->condvar);
|
2009-12-11 21:00:25 +00:00
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void pipe_barrier_destroy(pipe_barrier *barrier)
|
2009-12-11 21:00:25 +00:00
|
|
|
{
|
2010-04-17 22:24:23 +01:00
|
|
|
assert(barrier->waiters == 0);
|
|
|
|
pipe_mutex_destroy(barrier->mutex);
|
2017-03-04 23:41:30 +00:00
|
|
|
cnd_destroy(&barrier->condvar);
|
2009-12-11 21:00:25 +00:00
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void pipe_barrier_wait(pipe_barrier *barrier)
|
2009-12-11 21:00:25 +00:00
|
|
|
{
|
2010-04-17 22:24:23 +01:00
|
|
|
pipe_mutex_lock(barrier->mutex);
|
|
|
|
|
|
|
|
assert(barrier->waiters < barrier->count);
|
|
|
|
barrier->waiters++;
|
|
|
|
|
|
|
|
if (barrier->waiters < barrier->count) {
|
2010-04-26 08:25:30 +01:00
|
|
|
uint64_t sequence = barrier->sequence;
|
|
|
|
|
|
|
|
do {
|
2017-03-04 23:41:31 +00:00
|
|
|
cnd_wait(&barrier->condvar, &barrier->mutex);
|
2010-04-26 08:25:30 +01:00
|
|
|
} while (sequence == barrier->sequence);
|
2010-04-17 22:24:23 +01:00
|
|
|
} else {
|
|
|
|
barrier->waiters = 0;
|
2010-04-26 08:25:30 +01:00
|
|
|
barrier->sequence++;
|
2017-03-04 23:41:33 +00:00
|
|
|
cnd_broadcast(&barrier->condvar);
|
2010-04-17 22:24:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pipe_mutex_unlock(barrier->mutex);
|
2009-12-11 21:00:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-11 02:12:10 +00:00
|
|
|
#endif
|
2008-02-19 06:07:53 +00:00
|
|
|
|
|
|
|
|
2009-12-08 00:58:46 +00:00
|
|
|
/*
|
|
|
|
* Semaphores
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2017-03-05 01:32:01 +00:00
|
|
|
mtx_t mutex;
|
2009-12-08 00:58:46 +00:00
|
|
|
pipe_condvar cond;
|
|
|
|
int counter;
|
|
|
|
} pipe_semaphore;
|
|
|
|
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void
|
2009-12-08 00:58:46 +00:00
|
|
|
pipe_semaphore_init(pipe_semaphore *sema, int init_val)
|
|
|
|
{
|
2017-03-05 01:00:15 +00:00
|
|
|
(void) mtx_init(&sema->mutex, mtx_plain);
|
2017-03-04 23:41:29 +00:00
|
|
|
cnd_init(&sema->cond);
|
2009-12-08 00:58:46 +00:00
|
|
|
sema->counter = init_val;
|
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void
|
2009-12-08 00:58:46 +00:00
|
|
|
pipe_semaphore_destroy(pipe_semaphore *sema)
|
|
|
|
{
|
|
|
|
pipe_mutex_destroy(sema->mutex);
|
2017-03-04 23:41:30 +00:00
|
|
|
cnd_destroy(&sema->cond);
|
2009-12-08 00:58:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Signal/increment semaphore counter */
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void
|
2009-12-08 00:58:46 +00:00
|
|
|
pipe_semaphore_signal(pipe_semaphore *sema)
|
|
|
|
{
|
|
|
|
pipe_mutex_lock(sema->mutex);
|
|
|
|
sema->counter++;
|
2017-03-04 23:41:32 +00:00
|
|
|
cnd_signal(&sema->cond);
|
2009-12-08 00:58:46 +00:00
|
|
|
pipe_mutex_unlock(sema->mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Wait for semaphore counter to be greater than zero */
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void
|
2009-12-08 00:58:46 +00:00
|
|
|
pipe_semaphore_wait(pipe_semaphore *sema)
|
|
|
|
{
|
|
|
|
pipe_mutex_lock(sema->mutex);
|
|
|
|
while (sema->counter <= 0) {
|
2017-03-04 23:41:31 +00:00
|
|
|
cnd_wait(&sema->cond, &sema->mutex);
|
2009-12-08 00:58:46 +00:00
|
|
|
}
|
|
|
|
sema->counter--;
|
|
|
|
pipe_mutex_unlock(sema->mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-19 06:07:53 +00:00
|
|
|
|
|
|
|
/*
|
2008-08-26 23:35:12 +01:00
|
|
|
* Thread-specific data.
|
2008-02-19 06:07:53 +00:00
|
|
|
*/
|
|
|
|
|
2008-08-26 23:35:12 +01:00
|
|
|
typedef struct {
|
2013-04-26 08:03:33 +01:00
|
|
|
tss_t key;
|
2008-08-26 23:35:12 +01:00
|
|
|
int initMagic;
|
|
|
|
} pipe_tsd;
|
2008-02-19 06:07:53 +00:00
|
|
|
|
|
|
|
|
2008-08-26 23:35:12 +01:00
|
|
|
#define PIPE_TSD_INIT_MAGIC 0xff8adc98
|
2008-01-20 18:36:23 +00:00
|
|
|
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void
|
2008-08-26 23:35:12 +01:00
|
|
|
pipe_tsd_init(pipe_tsd *tsd)
|
|
|
|
{
|
2013-04-26 08:03:33 +01:00
|
|
|
if (tss_create(&tsd->key, NULL/*free*/) != 0) {
|
2008-08-26 23:35:12 +01:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
tsd->initMagic = PIPE_TSD_INIT_MAGIC;
|
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void *
|
2008-08-26 23:35:12 +01:00
|
|
|
pipe_tsd_get(pipe_tsd *tsd)
|
|
|
|
{
|
|
|
|
if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
|
|
|
|
pipe_tsd_init(tsd);
|
|
|
|
}
|
2013-04-26 08:03:33 +01:00
|
|
|
return tss_get(tsd->key);
|
2008-08-26 23:35:12 +01:00
|
|
|
}
|
|
|
|
|
2015-07-21 00:58:43 +01:00
|
|
|
static inline void
|
2008-08-26 23:35:12 +01:00
|
|
|
pipe_tsd_set(pipe_tsd *tsd, void *value)
|
|
|
|
{
|
|
|
|
if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
|
|
|
|
pipe_tsd_init(tsd);
|
|
|
|
}
|
2013-04-26 08:03:33 +01:00
|
|
|
if (tss_set(tsd->key, value) != 0) {
|
2008-08-26 23:35:12 +01:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
}
|
2008-01-20 18:36:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-02-11 19:48:13 +00:00
|
|
|
/*
|
|
|
|
* Thread statistics.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Return the time of a thread's CPU time clock. */
|
|
|
|
static inline int64_t
|
|
|
|
pipe_thread_get_time_nano(pipe_thread thread)
|
|
|
|
{
|
|
|
|
#if defined(PIPE_OS_LINUX) && defined(HAVE_PTHREAD)
|
|
|
|
struct timespec ts;
|
|
|
|
clockid_t cid;
|
|
|
|
|
|
|
|
pthread_getcpuclockid(thread, &cid);
|
|
|
|
clock_gettime(cid, &ts);
|
|
|
|
return (int64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the time of the current thread's CPU time clock. */
|
|
|
|
static inline int64_t
|
|
|
|
pipe_current_thread_get_time_nano(void)
|
|
|
|
{
|
|
|
|
#if defined(HAVE_PTHREAD)
|
|
|
|
return pipe_thread_get_time_nano(pthread_self());
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-02-02 15:18:01 +00:00
|
|
|
#endif /* OS_THREAD_H_ */
|