[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