diff --git a/config.h.meson b/config.h.meson index 69a4724..fc5db55 100644 --- a/config.h.meson +++ b/config.h.meson @@ -18,6 +18,7 @@ #mesondefine HAVE_TIMESPEC_GET #mesondefine HAVE_SYS_UIO_H #mesondefine HAVE_PTHREAD +#mesondefine HAVE_PTHREAD_SETAFFINITY #mesondefine HAVE_EPOXY_EGL_H #mesondefine HAVE_EPOXY_GLX_H #mesondefine ENABLE_MINIGBM_ALLOCATION diff --git a/meson.build b/meson.build index f8c1ef3..6d70d4f 100644 --- a/meson.build +++ b/meson.build @@ -116,6 +116,9 @@ endif if cc.has_header('pthread.h') conf_data.set('HAVE_PTHREAD', 1) + if cc.has_function('pthread_setaffinity_np', dependencies: thread_dep) + conf_data.set('HAVE_PTHREAD_SETAFFINITY', 1) + endif endif if cc.has_header('sys/eventfd.h') diff --git a/src/gallium/auxiliary/os/os_thread.h b/src/gallium/auxiliary/os/os_thread.h deleted file mode 100644 index a84ca64..0000000 --- a/src/gallium/auxiliary/os/os_thread.h +++ /dev/null @@ -1,312 +0,0 @@ -/************************************************************************** - * - * Copyright 1999-2006 Brian Paul - * Copyright 2008 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * 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. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * 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. - * - **************************************************************************/ - - -/** - * @file - * - * Thread, mutex, condition variable, barrier, semaphore and - * thread-specific data functions. - */ - - -#ifndef OS_THREAD_H_ -#define OS_THREAD_H_ - - -#include "pipe/p_compiler.h" -#include "util/u_debug.h" /* for assert */ - -#include "c11/threads.h" - -#ifdef HAVE_PTHREAD -#include -#endif - -#ifdef PIPE_OS_LINUX -#include -#endif - -/* pipe_thread - */ -typedef thrd_t pipe_thread; - -#define PIPE_THREAD_ROUTINE( name, param ) \ - int name( void *param ) - -static inline pipe_thread pipe_thread_create( PIPE_THREAD_ROUTINE((*routine), ), void *param ) -{ - pipe_thread thread; -#ifdef HAVE_PTHREAD - sigset_t saved_set, new_set; - int ret; - - sigfillset(&new_set); - pthread_sigmask(SIG_SETMASK, &new_set, &saved_set); - ret = thrd_create( &thread, routine, param ); - pthread_sigmask(SIG_SETMASK, &saved_set, NULL); -#else - int ret; - ret = thrd_create( &thread, routine, param ); -#endif - if (ret) - return 0; - - return thread; -} - -static inline int pipe_thread_wait( pipe_thread thread ) -{ - return thrd_join( thread, NULL ); -} - -static inline int pipe_thread_destroy( pipe_thread thread ) -{ - return thrd_detach( thread ); -} - -static inline void pipe_thread_setname( const char *name ) -{ -#ifdef PIPE_OS_LINUX - prctl(PR_SET_NAME, name, 0, 0, 0); -#else - (void)name; -#endif -} - - -/* pipe_mutex - */ -typedef mtx_t pipe_mutex; - -#define pipe_static_mutex(mutex) \ - static pipe_mutex mutex = _MTX_INITIALIZER_NP - -#define pipe_mutex_init(mutex) \ - (void) mtx_init(&(mutex), mtx_plain) - -#define pipe_mutex_destroy(mutex) \ - mtx_destroy(&(mutex)) - -#define pipe_mutex_lock(mutex) \ - (void) mtx_lock(&(mutex)) - -#define pipe_mutex_unlock(mutex) \ - (void) mtx_unlock(&(mutex)) - - -/* pipe_condvar - */ -typedef cnd_t pipe_condvar; - -#define pipe_condvar_init(cond) \ - cnd_init(&(cond)) - -#define pipe_condvar_destroy(cond) \ - cnd_destroy(&(cond)) - -#define pipe_condvar_wait(cond, mutex) \ - cnd_wait(&(cond), &(mutex)) - -#define pipe_condvar_signal(cond) \ - cnd_signal(&(cond)) - -#define pipe_condvar_broadcast(cond) \ - cnd_broadcast(&(cond)) - - -/* - * pipe_barrier - */ - -#if (defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HURD)) && !defined(PIPE_OS_ANDROID) - -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; - pipe_mutex mutex; - pipe_condvar condvar; -} pipe_barrier; - -static inline void pipe_barrier_init(pipe_barrier *barrier, unsigned count) -{ - barrier->count = count; - barrier->waiters = 0; - barrier->sequence = 0; - pipe_mutex_init(barrier->mutex); - pipe_condvar_init(barrier->condvar); -} - -static inline void pipe_barrier_destroy(pipe_barrier *barrier) -{ - assert(barrier->waiters == 0); - pipe_mutex_destroy(barrier->mutex); - pipe_condvar_destroy(barrier->condvar); -} - -static inline void pipe_barrier_wait(pipe_barrier *barrier) -{ - pipe_mutex_lock(barrier->mutex); - - assert(barrier->waiters < barrier->count); - barrier->waiters++; - - if (barrier->waiters < barrier->count) { - uint64_t sequence = barrier->sequence; - - do { - pipe_condvar_wait(barrier->condvar, barrier->mutex); - } while (sequence == barrier->sequence); - } else { - barrier->waiters = 0; - barrier->sequence++; - pipe_condvar_broadcast(barrier->condvar); - } - - pipe_mutex_unlock(barrier->mutex); -} - - -#endif - - -/* - * Semaphores - */ - -typedef struct -{ - pipe_mutex mutex; - pipe_condvar cond; - int counter; -} pipe_semaphore; - - -static inline void -pipe_semaphore_init(pipe_semaphore *sema, int init_val) -{ - pipe_mutex_init(sema->mutex); - pipe_condvar_init(sema->cond); - sema->counter = init_val; -} - -static inline void -pipe_semaphore_destroy(pipe_semaphore *sema) -{ - pipe_mutex_destroy(sema->mutex); - pipe_condvar_destroy(sema->cond); -} - -/** Signal/increment semaphore counter */ -static inline void -pipe_semaphore_signal(pipe_semaphore *sema) -{ - pipe_mutex_lock(sema->mutex); - sema->counter++; - pipe_condvar_signal(sema->cond); - pipe_mutex_unlock(sema->mutex); -} - -/** Wait for semaphore counter to be greater than zero */ -static inline void -pipe_semaphore_wait(pipe_semaphore *sema) -{ - pipe_mutex_lock(sema->mutex); - while (sema->counter <= 0) { - pipe_condvar_wait(sema->cond, sema->mutex); - } - sema->counter--; - pipe_mutex_unlock(sema->mutex); -} - - - -/* - * Thread-specific data. - */ - -typedef struct { - tss_t key; - int initMagic; -} pipe_tsd; - - -#define PIPE_TSD_INIT_MAGIC 0xff8adc98 - - -static inline void -pipe_tsd_init(pipe_tsd *tsd) -{ - if (tss_create(&tsd->key, NULL/*free*/) != 0) { - exit(-1); - } - tsd->initMagic = PIPE_TSD_INIT_MAGIC; -} - -static inline void * -pipe_tsd_get(pipe_tsd *tsd) -{ - if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) { - pipe_tsd_init(tsd); - } - return tss_get(tsd->key); -} - -static inline void -pipe_tsd_set(pipe_tsd *tsd, void *value) -{ - if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) { - pipe_tsd_init(tsd); - } - if (tss_set(tsd->key, value) != 0) { - exit(-1); - } -} - - - -#endif /* OS_THREAD_H_ */ diff --git a/src/gallium/meson.build b/src/gallium/meson.build index 1cb2917..72175fa 100644 --- a/src/gallium/meson.build +++ b/src/gallium/meson.build @@ -92,7 +92,6 @@ sources_libgallium = [ 'auxiliary/tgsi/tgsi_util.c', 'auxiliary/tgsi/tgsi_sanity.h', 'auxiliary/tgsi/tgsi_transform.c', - 'auxiliary/os/os_thread.h', 'auxiliary/os/os_mman.h', ] diff --git a/src/mesa/util/u_thread.h b/src/mesa/util/u_thread.h new file mode 100644 index 0000000..013e8be --- /dev/null +++ b/src/mesa/util/u_thread.h @@ -0,0 +1,396 @@ +/************************************************************************** + * + * Copyright 1999-2006 Brian Paul + * Copyright 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * 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. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * 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. + * + **************************************************************************/ + +#ifndef U_THREAD_H_ +#define U_THREAD_H_ + +#include +#include +#include +#include + +#include "c11/threads.h" +#include "detect_os.h" +#include "macros.h" + +#ifdef HAVE_PTHREAD +#include +#ifdef HAVE_PTHREAD_NP_H +#include +#endif +#endif + +#ifdef __HAIKU__ +#include +#endif + +#if DETECT_OS_LINUX && !defined(ANDROID) +#include +#elif defined(_WIN32) && !defined(__CYGWIN__) && _WIN32_WINNT >= 0x0600 +#include +#endif + +#ifdef __FreeBSD__ +/* pthread_np.h -> sys/param.h -> machine/param.h + * - defines ALIGN which clashes with our ALIGN + */ +#undef ALIGN +#define cpu_set_t cpuset_t +#endif + +/* For util_set_thread_affinity to size the mask. */ +#define UTIL_MAX_CPUS 1024 /* this should be enough */ +#define UTIL_MAX_L3_CACHES UTIL_MAX_CPUS + +/* Some highly performance-sensitive thread-local variables like the current GL + * context are declared with the initial-exec model on Linux. glibc allocates a + * fixed number of extra slots for initial-exec TLS variables at startup, and + * Mesa relies on (even if it's dlopen()ed after init) being able to fit into + * those. This model saves the call to look up the address of the TLS variable. + * + * However, if we don't have this TLS model available on the platform, then we + * still want to use normal TLS (which involves a function call, but not the + * expensive pthread_getspecific() or its equivalent). + */ +#ifdef _MSC_VER +#define __THREAD_INITIAL_EXEC __declspec(thread) +#elif defined(ANDROID) +/* Android 29 gained ELF TLS support, but it doesn't support initial-exec and + * it will throw: + * + * dlopen failed: TLS symbol "(null)" in dlopened + * "/vendor/lib64/egl/libEGL_mesa.so" referenced from + * "/vendor/lib64/egl/libEGL_mesa.so" using IE access model. + */ +#define __THREAD_INITIAL_EXEC __thread +#else +#define __THREAD_INITIAL_EXEC __thread __attribute__((tls_model("initial-exec"))) +#endif + +static inline int +util_get_current_cpu(void) +{ +#if DETECT_OS_LINUX && !defined(ANDROID) + return sched_getcpu(); + +#elif defined(_WIN32) && !defined(__CYGWIN__) && _WIN32_WINNT >= 0x0600 + return GetCurrentProcessorNumber(); + +#else + return -1; +#endif +} + +static inline thrd_t u_thread_create(int (*routine)(void *), void *param) +{ + thrd_t thread; +#ifdef HAVE_PTHREAD + sigset_t saved_set, new_set; + int ret; + + sigfillset(&new_set); + sigdelset(&new_set, SIGSYS); + pthread_sigmask(SIG_BLOCK, &new_set, &saved_set); + ret = thrd_create( &thread, routine, param ); + pthread_sigmask(SIG_SETMASK, &saved_set, NULL); +#else + int ret; + ret = thrd_create( &thread, routine, param ); +#endif + if (ret) + return 0; + + return thread; +} + +static inline void u_thread_setname( const char *name ) +{ +#if defined(HAVE_PTHREAD) +#if DETECT_OS_LINUX || DETECT_OS_CYGWIN || DETECT_OS_SOLARIS + int ret = pthread_setname_np(pthread_self(), name); + if (ret == ERANGE) { + char buf[16]; + const size_t len = MIN2(strlen(name), ARRAY_SIZE(buf) - 1); + memcpy(buf, name, len); + buf[len] = '\0'; + pthread_setname_np(pthread_self(), buf); + } +#elif DETECT_OS_FREEBSD || DETECT_OS_OPENBSD + pthread_set_name_np(pthread_self(), name); +#elif DETECT_OS_NETBSD + pthread_setname_np(pthread_self(), "%s", (void *)name); +#elif DETECT_OS_APPLE + pthread_setname_np(name); +#elif DETECT_OS_HAIKU + rename_thread(find_thread(NULL), name); +#else +#warning Not sure how to call pthread_setname_np +#endif +#endif + (void)name; +} + +/** + * Set thread affinity. + * + * \param thread Thread + * \param mask Set this affinity mask + * \param old_mask Previous affinity mask returned if not NULL + * \param num_mask_bits Number of bits in both masks + * \return true on success + */ +static inline bool +util_set_thread_affinity(thrd_t thread, + const uint32_t *mask, + uint32_t *old_mask, + unsigned num_mask_bits) +{ +#if defined(HAVE_PTHREAD_SETAFFINITY) + cpu_set_t cpuset; + + if (old_mask) { + if (pthread_getaffinity_np(thread, sizeof(cpuset), &cpuset) != 0) + return false; + + memset(old_mask, 0, num_mask_bits / 8); + for (unsigned i = 0; i < num_mask_bits && i < CPU_SETSIZE; i++) { + if (CPU_ISSET(i, &cpuset)) + old_mask[i / 32] |= 1u << (i % 32); + } + } + + CPU_ZERO(&cpuset); + for (unsigned i = 0; i < num_mask_bits && i < CPU_SETSIZE; i++) { + if (mask[i / 32] & (1u << (i % 32))) + CPU_SET(i, &cpuset); + } + return pthread_setaffinity_np(thread, sizeof(cpuset), &cpuset) == 0; + +#elif defined(_WIN32) && !defined(__CYGWIN__) + DWORD_PTR m = mask[0]; + + if (sizeof(m) > 4 && num_mask_bits > 32) + m |= (uint64_t)mask[1] << 32; + + m = SetThreadAffinityMask(thread, m); + if (!m) + return false; + + if (old_mask) { + memset(old_mask, 0, num_mask_bits / 8); + + old_mask[0] = m; +#ifdef _WIN64 + old_mask[1] = m >> 32; +#endif + } + + return true; +#else + return false; +#endif +} + +static inline bool +util_set_current_thread_affinity(const uint32_t *mask, + uint32_t *old_mask, + unsigned num_mask_bits) +{ +#if defined(HAVE_PTHREAD_SETAFFINITY) + return util_set_thread_affinity(pthread_self(), mask, old_mask, + num_mask_bits); + +#elif defined(_WIN32) && !defined(__CYGWIN__) + /* The GetCurrentThreadId() handle is only valid within the current thread. */ + return util_set_thread_affinity(GetCurrentThread(), mask, old_mask, + num_mask_bits); + +#else + return false; +#endif +} + + +/* + * Thread statistics. + */ + +/* Return the time of a thread's CPU time clock. */ +static inline int64_t +util_thread_get_time_nano(thrd_t thread) +{ +#if defined(HAVE_PTHREAD) && !defined(__APPLE__) && !defined(__HAIKU__) + 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 +util_current_thread_get_time_nano(void) +{ +#if defined(HAVE_PTHREAD) + return util_thread_get_time_nano(pthread_self()); + +#elif defined(_WIN32) && !defined(__CYGWIN__) + /* The GetCurrentThreadId() handle is only valid within the current thread. */ + return util_thread_get_time_nano(GetCurrentThread()); + +#else + return 0; +#endif +} + +static inline bool u_thread_is_self(thrd_t thread) +{ +#if defined(HAVE_PTHREAD) + return pthread_equal(pthread_self(), thread); +#endif + return false; +} + +/* + * util_barrier + */ + +#if defined(HAVE_PTHREAD) && !defined(__APPLE__) && !defined(__HAIKU__) + +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 + +/* + * Thread-id's. + * + * thrd_current() is not portable to windows (or at least not in a desirable + * way), so thread_id's provide an alternative mechanism + */ + +#ifdef _WIN32 +typedef DWORD thread_id; +#else +typedef thrd_t thread_id; +#endif + +static inline thread_id +util_get_thread_id(void) +{ + /* + * XXX: Callers of of this function assume it is a lightweight function. + * But unfortunately C11's thrd_current() gives no such guarantees. In + * fact, it's pretty hard to have a compliant implementation of + * thrd_current() on Windows with such characteristics. So for now, we + * side-step this mess and use Windows thread primitives directly here. + */ +#ifdef _WIN32 + return GetCurrentThreadId(); +#else + return thrd_current(); +#endif +} + + +static inline int +util_thread_id_equal(thread_id t1, thread_id t2) +{ +#ifdef _WIN32 + return t1 == t2; +#else + return thrd_equal(t1, t2); +#endif +} + +#endif /* U_THREAD_H_ */ diff --git a/src/venus/vkr_common.h b/src/venus/vkr_common.h index 18603cc..f9c5daa 100644 --- a/src/venus/vkr_common.h +++ b/src/venus/vkr_common.h @@ -18,7 +18,6 @@ #include #include "c11/threads.h" -#include "os/os_thread.h" #include "pipe/p_compiler.h" #include "util/os_misc.h" #include "util/u_double_list.h" @@ -26,6 +25,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_pointer.h" +#include "util/u_thread.h" #include "venus-protocol/vulkan.h" #include "virgl_util.h" #include "virglrenderer.h" diff --git a/src/venus/vkr_queue.c b/src/venus/vkr_queue.c index 3298e95..abb8f6e 100644 --- a/src/venus/vkr_queue.c +++ b/src/venus/vkr_queue.c @@ -186,7 +186,7 @@ vkr_queue_thread(void *arg) char thread_name[16]; snprintf(thread_name, ARRAY_SIZE(thread_name), "vkr-queue-%d", ctx->base.ctx_id); - pipe_thread_setname(thread_name); + u_thread_setname(thread_name); mtx_lock(&queue->mutex); while (true) { diff --git a/src/venus/vkr_ring.c b/src/venus/vkr_ring.c index c6aaeeb..b42ec1f 100644 --- a/src/venus/vkr_ring.c +++ b/src/venus/vkr_ring.c @@ -276,7 +276,7 @@ vkr_ring_thread(void *arg) char thread_name[16]; snprintf(thread_name, ARRAY_SIZE(thread_name), "vkr-ring-%d", ctx->ctx_id); - pipe_thread_setname(thread_name); + u_thread_setname(thread_name); uint64_t last_submit = vkr_ring_now(); uint32_t relax_iter = 0; diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 915f148..5f73b6a 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -38,7 +38,7 @@ #include "util/u_memory.h" #include "util/u_dual_blend.h" -#include "os/os_thread.h" +#include "util/u_thread.h" #include "util/u_format.h" #include "tgsi/tgsi_parse.h" @@ -6184,7 +6184,7 @@ static int thread_sync(UNUSED void *arg) virgl_gl_context gl_context = vrend_state.sync_context; struct vrend_fence *fence, *stor; - pipe_thread_setname("vrend-sync"); + u_thread_setname("vrend-sync"); mtx_lock(&vrend_state.fence_mutex); vrend_clicbs->make_current(gl_context); @@ -6241,7 +6241,7 @@ static void vrend_renderer_use_threaded_sync(void) cnd_init(&vrend_state.fence_cond); mtx_init(&vrend_state.fence_mutex, mtx_plain); - vrend_state.sync_thread = pipe_thread_create(thread_sync, NULL); + vrend_state.sync_thread = u_thread_create(thread_sync, NULL); if (!vrend_state.sync_thread) { if (vrend_state.eventfd != -1) { close(vrend_state.eventfd);