util: Remove the need of _MTX_INITIALIZER_NP in simple_mtx.h

The usage of _MTX_INITIALIZER_NP is a problem. Sure, the code builds on
Linux and Windows, and it even usually works, but is problematic.
It means that Windows lock debugging tools cannot be used with that code.
So we remove _MTX_INITIALIZER_NP to gain the following benefit:
  Aligning to the C11 standard threads.h definitions.
  Improving portability of the threading code to better support Windows.
This change removes one of the most prolific uses of _MTX_INITIALIZER_NP by
slightly increasing the cost of simple_mtx_lock when targeting platforms that
don't support futex, but it's cost are far less than the cost of syscall,
so the affect are negligible.

The futex code path are not affected. And Windows 8 and upper also
supports the futex codepath, so it's only affect the Windows version < 8, MacOS
or other platforms that doesn't support for futex.

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17122>
This commit is contained in:
Yonggang Luo 2022-08-17 01:42:52 +08:00 committed by Marge Bot
parent 064ec944c1
commit 296eb2918c
3 changed files with 62 additions and 13 deletions

View file

@ -102,6 +102,7 @@ files_mesa_util = files(
'rounding.h',
'set.c',
'set.h',
'simple_mtx.c',
'simple_mtx.h',
'slab.c',
'slab.h',

34
src/util/simple_mtx.c Normal file
View file

@ -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 */

View file

@ -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