util: move pipe_barrier into src/util and rename to util_barrier
The #if guard is probably not 100% equivalent to the previous PIPE_OS check, but if anything it should be an over-approximation (are there pthread implementations without barriers?), so people will get either a good implementation or compile errors that are easy to fix. Reviewed-by: Marek Olšák <marek.olsak@amd.com>
This commit is contained in:
@@ -60,82 +60,6 @@ __pipe_mutex_assert_locked(mtx_t *mutex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pipe_barrier
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HURD)) && (!defined(PIPE_OS_ANDROID) || ANDROID_API_LEVEL >= 24)
|
|
||||||
|
|
||||||
typedef pthread_barrier_t pipe_barrier;
|
|
||||||
|
|
||||||
static inline void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
|
|
||||||
{
|
|
||||||
pthread_barrier_init(barrier, NULL, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void pipe_barrier_destroy(pipe_barrier *barrier)
|
|
||||||
{
|
|
||||||
pthread_barrier_destroy(barrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void pipe_barrier_wait(pipe_barrier *barrier)
|
|
||||||
{
|
|
||||||
pthread_barrier_wait(barrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned count;
|
|
||||||
unsigned waiters;
|
|
||||||
uint64_t sequence;
|
|
||||||
mtx_t mutex;
|
|
||||||
cnd_t condvar;
|
|
||||||
} pipe_barrier;
|
|
||||||
|
|
||||||
static inline void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
|
|
||||||
{
|
|
||||||
barrier->count = count;
|
|
||||||
barrier->waiters = 0;
|
|
||||||
barrier->sequence = 0;
|
|
||||||
(void) mtx_init(&barrier->mutex, mtx_plain);
|
|
||||||
cnd_init(&barrier->condvar);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void pipe_barrier_destroy(pipe_barrier *barrier)
|
|
||||||
{
|
|
||||||
assert(barrier->waiters == 0);
|
|
||||||
mtx_destroy(&barrier->mutex);
|
|
||||||
cnd_destroy(&barrier->condvar);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void pipe_barrier_wait(pipe_barrier *barrier)
|
|
||||||
{
|
|
||||||
mtx_lock(&barrier->mutex);
|
|
||||||
|
|
||||||
assert(barrier->waiters < barrier->count);
|
|
||||||
barrier->waiters++;
|
|
||||||
|
|
||||||
if (barrier->waiters < barrier->count) {
|
|
||||||
uint64_t sequence = barrier->sequence;
|
|
||||||
|
|
||||||
do {
|
|
||||||
cnd_wait(&barrier->condvar, &barrier->mutex);
|
|
||||||
} while (sequence == barrier->sequence);
|
|
||||||
} else {
|
|
||||||
barrier->waiters = 0;
|
|
||||||
barrier->sequence++;
|
|
||||||
cnd_broadcast(&barrier->condvar);
|
|
||||||
}
|
|
||||||
|
|
||||||
mtx_unlock(&barrier->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Semaphores
|
* Semaphores
|
||||||
*/
|
*/
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "util/u_surface.h"
|
#include "util/u_surface.h"
|
||||||
#include "util/u_pack_color.h"
|
#include "util/u_pack_color.h"
|
||||||
#include "util/u_string.h"
|
#include "util/u_string.h"
|
||||||
|
#include "util/u_thread.h"
|
||||||
|
|
||||||
#include "os/os_time.h"
|
#include "os/os_time.h"
|
||||||
|
|
||||||
@@ -822,7 +823,7 @@ thread_function(void *init_data)
|
|||||||
/* Wait for all threads to get here so that threads[1+] don't
|
/* Wait for all threads to get here so that threads[1+] don't
|
||||||
* get a null rast->curr_scene pointer.
|
* get a null rast->curr_scene pointer.
|
||||||
*/
|
*/
|
||||||
pipe_barrier_wait( &rast->barrier );
|
util_barrier_wait( &rast->barrier );
|
||||||
|
|
||||||
/* do work */
|
/* do work */
|
||||||
if (debug)
|
if (debug)
|
||||||
@@ -832,7 +833,7 @@ thread_function(void *init_data)
|
|||||||
rast->curr_scene);
|
rast->curr_scene);
|
||||||
|
|
||||||
/* wait for all threads to finish with this scene */
|
/* wait for all threads to finish with this scene */
|
||||||
pipe_barrier_wait( &rast->barrier );
|
util_barrier_wait( &rast->barrier );
|
||||||
|
|
||||||
/* XXX: shouldn't be necessary:
|
/* XXX: shouldn't be necessary:
|
||||||
*/
|
*/
|
||||||
@@ -914,7 +915,7 @@ lp_rast_create( unsigned num_threads )
|
|||||||
|
|
||||||
/* for synchronizing rasterization threads */
|
/* for synchronizing rasterization threads */
|
||||||
if (rast->num_threads > 0) {
|
if (rast->num_threads > 0) {
|
||||||
pipe_barrier_init( &rast->barrier, rast->num_threads );
|
util_barrier_init( &rast->barrier, rast->num_threads );
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(lp_dummy_tile, 0, sizeof lp_dummy_tile);
|
memset(lp_dummy_tile, 0, sizeof lp_dummy_tile);
|
||||||
@@ -973,7 +974,7 @@ void lp_rast_destroy( struct lp_rasterizer *rast )
|
|||||||
|
|
||||||
/* for synchronizing rasterization threads */
|
/* for synchronizing rasterization threads */
|
||||||
if (rast->num_threads > 0) {
|
if (rast->num_threads > 0) {
|
||||||
pipe_barrier_destroy( &rast->barrier );
|
util_barrier_destroy( &rast->barrier );
|
||||||
}
|
}
|
||||||
|
|
||||||
lp_scene_queue_destroy(rast->full_scenes);
|
lp_scene_queue_destroy(rast->full_scenes);
|
||||||
|
@@ -28,8 +28,8 @@
|
|||||||
#ifndef LP_RAST_PRIV_H
|
#ifndef LP_RAST_PRIV_H
|
||||||
#define LP_RAST_PRIV_H
|
#define LP_RAST_PRIV_H
|
||||||
|
|
||||||
#include "os/os_thread.h"
|
|
||||||
#include "util/u_format.h"
|
#include "util/u_format.h"
|
||||||
|
#include "util/u_thread.h"
|
||||||
#include "gallivm/lp_bld_debug.h"
|
#include "gallivm/lp_bld_debug.h"
|
||||||
#include "lp_memory.h"
|
#include "lp_memory.h"
|
||||||
#include "lp_rast.h"
|
#include "lp_rast.h"
|
||||||
@@ -130,7 +130,7 @@ struct lp_rasterizer
|
|||||||
thrd_t threads[LP_MAX_THREADS];
|
thrd_t threads[LP_MAX_THREADS];
|
||||||
|
|
||||||
/** For synchronizing the rasterization threads */
|
/** For synchronizing the rasterization threads */
|
||||||
pipe_barrier barrier;
|
util_barrier barrier;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test case for pipe_barrier.
|
* Test case for util_barrier.
|
||||||
*
|
*
|
||||||
* The test succeeds if no thread exits before all the other threads reach
|
* The test succeeds if no thread exits before all the other threads reach
|
||||||
* the barrier.
|
* the barrier.
|
||||||
@@ -37,9 +37,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "os/os_thread.h"
|
|
||||||
#include "os/os_time.h"
|
#include "os/os_time.h"
|
||||||
#include "util/u_atomic.h"
|
#include "util/u_atomic.h"
|
||||||
|
#include "util/u_thread.h"
|
||||||
|
|
||||||
|
|
||||||
#define NUM_THREADS 10
|
#define NUM_THREADS 10
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
static int verbosity = 0;
|
static int verbosity = 0;
|
||||||
|
|
||||||
static thrd_t threads[NUM_THREADS];
|
static thrd_t threads[NUM_THREADS];
|
||||||
static pipe_barrier barrier;
|
static util_barrier barrier;
|
||||||
static int thread_ids[NUM_THREADS];
|
static int thread_ids[NUM_THREADS];
|
||||||
|
|
||||||
static volatile int waiting = 0;
|
static volatile int waiting = 0;
|
||||||
@@ -78,7 +78,7 @@ thread_function(void *thread_data)
|
|||||||
CHECK(p_atomic_read(&proceeded) == 0);
|
CHECK(p_atomic_read(&proceeded) == 0);
|
||||||
p_atomic_inc(&waiting);
|
p_atomic_inc(&waiting);
|
||||||
|
|
||||||
pipe_barrier_wait(&barrier);
|
util_barrier_wait(&barrier);
|
||||||
|
|
||||||
CHECK(p_atomic_read(&waiting) == NUM_THREADS);
|
CHECK(p_atomic_read(&waiting) == NUM_THREADS);
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
LOG("pipe_barrier_test starting\n");
|
LOG("pipe_barrier_test starting\n");
|
||||||
|
|
||||||
pipe_barrier_init(&barrier, NUM_THREADS);
|
util_barrier_init(&barrier, NUM_THREADS);
|
||||||
|
|
||||||
for (i = 0; i < NUM_THREADS; i++) {
|
for (i = 0; i < NUM_THREADS; i++) {
|
||||||
thread_ids[i] = i;
|
thread_ids[i] = i;
|
||||||
@@ -122,7 +122,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
CHECK(p_atomic_read(&proceeded) == NUM_THREADS);
|
CHECK(p_atomic_read(&proceeded) == NUM_THREADS);
|
||||||
|
|
||||||
pipe_barrier_destroy(&barrier);
|
util_barrier_destroy(&barrier);
|
||||||
|
|
||||||
LOG("pipe_barrier_test exiting\n");
|
LOG("pipe_barrier_test exiting\n");
|
||||||
|
|
||||||
|
@@ -100,4 +100,78 @@ static inline bool u_thread_is_self(thrd_t thread)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* util_barrier
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(HAVE_PTHREAD)
|
||||||
|
|
||||||
|
typedef pthread_barrier_t util_barrier;
|
||||||
|
|
||||||
|
static inline void util_barrier_init(util_barrier *barrier, unsigned count)
|
||||||
|
{
|
||||||
|
pthread_barrier_init(barrier, NULL, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void util_barrier_destroy(util_barrier *barrier)
|
||||||
|
{
|
||||||
|
pthread_barrier_destroy(barrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void util_barrier_wait(util_barrier *barrier)
|
||||||
|
{
|
||||||
|
pthread_barrier_wait(barrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned count;
|
||||||
|
unsigned waiters;
|
||||||
|
uint64_t sequence;
|
||||||
|
mtx_t mutex;
|
||||||
|
cnd_t condvar;
|
||||||
|
} util_barrier;
|
||||||
|
|
||||||
|
static inline void util_barrier_init(util_barrier *barrier, unsigned count)
|
||||||
|
{
|
||||||
|
barrier->count = count;
|
||||||
|
barrier->waiters = 0;
|
||||||
|
barrier->sequence = 0;
|
||||||
|
(void) mtx_init(&barrier->mutex, mtx_plain);
|
||||||
|
cnd_init(&barrier->condvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void util_barrier_destroy(util_barrier *barrier)
|
||||||
|
{
|
||||||
|
assert(barrier->waiters == 0);
|
||||||
|
mtx_destroy(&barrier->mutex);
|
||||||
|
cnd_destroy(&barrier->condvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void util_barrier_wait(util_barrier *barrier)
|
||||||
|
{
|
||||||
|
mtx_lock(&barrier->mutex);
|
||||||
|
|
||||||
|
assert(barrier->waiters < barrier->count);
|
||||||
|
barrier->waiters++;
|
||||||
|
|
||||||
|
if (barrier->waiters < barrier->count) {
|
||||||
|
uint64_t sequence = barrier->sequence;
|
||||||
|
|
||||||
|
do {
|
||||||
|
cnd_wait(&barrier->condvar, &barrier->mutex);
|
||||||
|
} while (sequence == barrier->sequence);
|
||||||
|
} else {
|
||||||
|
barrier->waiters = 0;
|
||||||
|
barrier->sequence++;
|
||||||
|
cnd_broadcast(&barrier->condvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
mtx_unlock(&barrier->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* U_THREAD_H_ */
|
#endif /* U_THREAD_H_ */
|
||||||
|
Reference in New Issue
Block a user