[Mesa-dev] [PATCH 2/6] util: move pipe_barrier into src/util and rename to util_barrier
Nicolai Hähnle
nhaehnle at gmail.com
Sun Oct 22 18:45:36 UTC 2017
From: Nicolai Hähnle <nicolai.haehnle at amd.com>
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.
---
src/gallium/auxiliary/os/os_thread.h | 76 -----------------------------
src/gallium/drivers/llvmpipe/lp_rast.c | 9 ++--
src/gallium/drivers/llvmpipe/lp_rast_priv.h | 4 +-
src/gallium/tests/unit/pipe_barrier_test.c | 12 ++---
src/util/u_thread.h | 74 ++++++++++++++++++++++++++++
5 files changed, 87 insertions(+), 88 deletions(-)
diff --git a/src/gallium/auxiliary/os/os_thread.h b/src/gallium/auxiliary/os/os_thread.h
index 10d4695da68..d9c685922a5 100644
--- a/src/gallium/auxiliary/os/os_thread.h
+++ b/src/gallium/auxiliary/os/os_thread.h
@@ -54,96 +54,20 @@ __pipe_mutex_assert_locked(mtx_t *mutex)
*/
int ret = mtx_trylock(mutex);
assert(ret == thrd_busy);
if (ret == thrd_success)
mtx_unlock(mutex);
#endif
}
/*
- * 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
*/
typedef struct
{
mtx_t mutex;
cnd_t cond;
int counter;
} pipe_semaphore;
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 0050655d9e3..9e2780ca1d7 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -25,20 +25,21 @@
*
**************************************************************************/
#include <limits.h>
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_rect.h"
#include "util/u_surface.h"
#include "util/u_pack_color.h"
#include "util/u_string.h"
+#include "util/u_thread.h"
#include "os/os_time.h"
#include "lp_scene_queue.h"
#include "lp_context.h"
#include "lp_debug.h"
#include "lp_fence.h"
#include "lp_perf.h"
#include "lp_query.h"
#include "lp_rast.h"
@@ -815,31 +816,31 @@ thread_function(void *init_data)
* - get next scene to rasterize
* - map the framebuffer surfaces
*/
lp_rast_begin( rast,
lp_scene_dequeue( rast->full_scenes, TRUE ) );
}
/* Wait for all threads to get here so that threads[1+] don't
* get a null rast->curr_scene pointer.
*/
- pipe_barrier_wait( &rast->barrier );
+ util_barrier_wait( &rast->barrier );
/* do work */
if (debug)
debug_printf("thread %d doing work\n", task->thread_index);
rasterize_scene(task,
rast->curr_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:
*/
if (task->thread_index == 0) {
lp_rast_end( rast );
}
/* signal done with work */
if (debug)
debug_printf("thread %d done working\n", task->thread_index);
@@ -907,21 +908,21 @@ lp_rast_create( unsigned num_threads )
}
rast->num_threads = num_threads;
rast->no_rast = debug_get_bool_option("LP_NO_RAST", FALSE);
create_rast_threads(rast);
/* for synchronizing rasterization threads */
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);
return rast;
no_thread_data_cache:
for (i = 0; i < MAX2(1, rast->num_threads); i++) {
if (rast->tasks[i].thread_data.cache) {
align_free(rast->tasks[i].thread_data.cache);
@@ -966,19 +967,19 @@ void lp_rast_destroy( struct lp_rasterizer *rast )
for (i = 0; i < rast->num_threads; i++) {
pipe_semaphore_destroy(&rast->tasks[i].work_ready);
pipe_semaphore_destroy(&rast->tasks[i].work_done);
}
for (i = 0; i < MAX2(1, rast->num_threads); i++) {
align_free(rast->tasks[i].thread_data.cache);
}
/* for synchronizing rasterization threads */
if (rast->num_threads > 0) {
- pipe_barrier_destroy( &rast->barrier );
+ util_barrier_destroy( &rast->barrier );
}
lp_scene_queue_destroy(rast->full_scenes);
FREE(rast);
}
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index 3cc52b8d4fd..fe078d5b869 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -21,22 +21,22 @@
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
*
**************************************************************************/
#ifndef LP_RAST_PRIV_H
#define LP_RAST_PRIV_H
-#include "os/os_thread.h"
#include "util/u_format.h"
+#include "util/u_thread.h"
#include "gallivm/lp_bld_debug.h"
#include "lp_memory.h"
#include "lp_rast.h"
#include "lp_scene.h"
#include "lp_state.h"
#include "lp_texture.h"
#include "lp_limits.h"
#define TILE_VECTOR_HEIGHT 4
@@ -123,21 +123,21 @@ struct lp_rasterizer
/** The scene currently being rasterized by the threads */
struct lp_scene *curr_scene;
/** A task object for each rasterization thread */
struct lp_rasterizer_task tasks[LP_MAX_THREADS];
unsigned num_threads;
thrd_t threads[LP_MAX_THREADS];
/** For synchronizing the rasterization threads */
- pipe_barrier barrier;
+ util_barrier barrier;
};
void
lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
const struct lp_rast_shader_inputs *inputs,
unsigned x, unsigned y,
unsigned mask);
diff --git a/src/gallium/tests/unit/pipe_barrier_test.c b/src/gallium/tests/unit/pipe_barrier_test.c
index 58ad7e29630..6bd46b8d964 100644
--- a/src/gallium/tests/unit/pipe_barrier_test.c
+++ b/src/gallium/tests/unit/pipe_barrier_test.c
@@ -20,41 +20,41 @@
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
*
**************************************************************************/
/*
- * Test case for pipe_barrier.
+ * Test case for util_barrier.
*
* The test succeeds if no thread exits before all the other threads reach
* the barrier.
*/
#include <stdio.h>
#include <stdlib.h>
-#include "os/os_thread.h"
#include "os/os_time.h"
#include "util/u_atomic.h"
+#include "util/u_thread.h"
#define NUM_THREADS 10
static int verbosity = 0;
static thrd_t threads[NUM_THREADS];
-static pipe_barrier barrier;
+static util_barrier barrier;
static int thread_ids[NUM_THREADS];
static volatile int waiting = 0;
static volatile int proceeded = 0;
#define LOG(fmt, ...) \
if (verbosity > 0) { \
fprintf(stdout, fmt, ##__VA_ARGS__); \
}
@@ -71,21 +71,21 @@ thread_function(void *thread_data)
{
int thread_id = *((int *) thread_data);
LOG("thread %d starting\n", thread_id);
os_time_sleep(thread_id * 100 * 1000);
LOG("thread %d before barrier\n", thread_id);
CHECK(p_atomic_read(&proceeded) == 0);
p_atomic_inc(&waiting);
- pipe_barrier_wait(&barrier);
+ util_barrier_wait(&barrier);
CHECK(p_atomic_read(&waiting) == NUM_THREADS);
p_atomic_inc(&proceeded);
LOG("thread %d exiting\n", thread_id);
return 0;
}
@@ -102,29 +102,29 @@ int main(int argc, char *argv[])
fprintf(stderr, "error: unrecognized option `%s`\n", arg);
exit(EXIT_FAILURE);
}
}
// Disable buffering
setbuf(stdout, NULL);
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++) {
thread_ids[i] = i;
threads[i] = u_thread_create(thread_function, (void *) &thread_ids[i]);
}
for (i = 0; i < NUM_THREADS; i++ ) {
thrd_join(threads[i], NULL);
}
CHECK(p_atomic_read(&proceeded) == NUM_THREADS);
- pipe_barrier_destroy(&barrier);
+ util_barrier_destroy(&barrier);
LOG("pipe_barrier_test exiting\n");
return 0;
}
diff --git a/src/util/u_thread.h b/src/util/u_thread.h
index 6b5458af86a..e484d8aa74f 100644
--- a/src/util/u_thread.h
+++ b/src/util/u_thread.h
@@ -93,11 +93,85 @@ static inline bool u_thread_is_self(thrd_t 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 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_ */
--
2.11.0
More information about the mesa-dev
mailing list