diff --git a/src/util/meson.build b/src/util/meson.build index 4b73ef029c1..37fdc8b299e 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -102,6 +102,7 @@ files_mesa_util = files( 'rounding.h', 'set.c', 'set.h', + 'simple_mtx.c', 'simple_mtx.h', 'slab.c', 'slab.h', diff --git a/src/util/simple_mtx.c b/src/util/simple_mtx.c new file mode 100644 index 00000000000..49f33efcaca --- /dev/null +++ b/src/util/simple_mtx.c @@ -0,0 +1,34 @@ +/* + * Copyright 2022 Yonggang Luo + * SPDX-License-Identifier: MIT + * + */ + +#include "simple_mtx.h" + +#if !UTIL_FUTEX_SUPPORTED + +void _simple_mtx_plain_init_once(simple_mtx_t *mtx) +{ + mtx_init(&mtx->mtx, mtx_plain); +} + +void +simple_mtx_init(simple_mtx_t *mtx, ASSERTED int type) +{ + const once_flag once = ONCE_FLAG_INIT; + assert(type == mtx_plain); + mtx->initialized = false; + mtx->once = once; + _simple_mtx_init_with_once(mtx); +} + +void +simple_mtx_destroy(simple_mtx_t *mtx) +{ + if (mtx->initialized) { + mtx_destroy(&mtx->mtx); + } +} + +#endif /* !UTIL_FUTEX_SUPPORTED */ diff --git a/src/util/simple_mtx.h b/src/util/simple_mtx.h index 3b7426e8cec..4b41e935717 100644 --- a/src/util/simple_mtx.h +++ b/src/util/simple_mtx.h @@ -26,6 +26,7 @@ #include "util/futex.h" #include "util/macros.h" +#include "util/u_call_once.h" #include "u_atomic.h" #include "c11/threads.h" @@ -145,45 +146,58 @@ simple_mtx_assert_locked(simple_mtx_t *mtx) #else /* !UTIL_FUTEX_SUPPORTED */ -typedef mtx_t simple_mtx_t; +typedef struct simple_mtx_t { + bool initialized; + once_flag once; + mtx_t mtx; +} simple_mtx_t; -#define _SIMPLE_MTX_INITIALIZER_NP _MTX_INITIALIZER_NP +#define _SIMPLE_MTX_INITIALIZER_NP { false, ONCE_FLAG_INIT } + +void _simple_mtx_plain_init_once(simple_mtx_t *mtx); static inline void -simple_mtx_init(simple_mtx_t *mtx, int type) +_simple_mtx_init_with_once(simple_mtx_t *mtx) { - mtx_init(mtx, type); + if (unlikely(!mtx->initialized)) { + util_call_once_with_context(&mtx->once, mtx, + (util_call_once_callback_t)_simple_mtx_plain_init_once); + mtx->initialized = true; + } } -static inline void -simple_mtx_destroy(simple_mtx_t *mtx) -{ - mtx_destroy(mtx); -} +void +simple_mtx_init(simple_mtx_t *mtx, int type); + +void +simple_mtx_destroy(simple_mtx_t *mtx); static inline void simple_mtx_lock(simple_mtx_t *mtx) { - mtx_lock(mtx); + _simple_mtx_init_with_once(mtx); + mtx_lock(&mtx->mtx); } static inline void simple_mtx_unlock(simple_mtx_t *mtx) { - mtx_unlock(mtx); + _simple_mtx_init_with_once(mtx); + mtx_unlock(&mtx->mtx); } static inline void simple_mtx_assert_locked(simple_mtx_t *mtx) { #ifndef NDEBUG + _simple_mtx_init_with_once(mtx); /* NOTE: this would not work for recursive mutexes, but * mtx_t doesn't support those */ - int ret = mtx_trylock(mtx); + int ret = mtx_trylock(&mtx->mtx); assert(ret == thrd_busy); if (ret == thrd_success) - mtx_unlock(mtx); + mtx_unlock(&mtx->mtx); #else (void)mtx; #endif