libc: synchronize implicit pthread mutex initialization

Fixes #5386
This commit is contained in:
Christian Prochaska 2024-11-26 01:08:15 +01:00
parent fa9473ce58
commit 37842757ac

View File

@ -950,12 +950,19 @@ extern "C" {
__attribute__((alias("pthread_mutexattr_settype"))); __attribute__((alias("pthread_mutexattr_settype")));
int pthread_mutex_init(pthread_mutex_t *mutex, int mutex_init(pthread_mutex_t *mutex,
pthread_mutexattr_t const *attr) pthread_mutexattr_t const *attr)
{ {
if (!mutex) static Mutex mutex_init_mutex { };
return EINVAL;
Mutex::Guard guard(mutex_init_mutex);
/*
* '*mutex' could have been initialized by a different
* thread which got the init mutex earlier.
*/
if (*mutex != PTHREAD_MUTEX_INITIALIZER)
return 0;
Libc::Allocator alloc { }; Libc::Allocator alloc { };
@ -966,15 +973,24 @@ extern "C" {
case PTHREAD_MUTEX_ADAPTIVE_NP: *mutex = new (alloc) Pthread_mutex_normal; break; case PTHREAD_MUTEX_ADAPTIVE_NP: *mutex = new (alloc) Pthread_mutex_normal; break;
case PTHREAD_MUTEX_ERRORCHECK: *mutex = new (alloc) Pthread_mutex_errorcheck; break; case PTHREAD_MUTEX_ERRORCHECK: *mutex = new (alloc) Pthread_mutex_errorcheck; break;
case PTHREAD_MUTEX_RECURSIVE: *mutex = new (alloc) Pthread_mutex_recursive; break; case PTHREAD_MUTEX_RECURSIVE: *mutex = new (alloc) Pthread_mutex_recursive; break;
default: return EINVAL;
default:
*mutex = nullptr;
return EINVAL;
} }
return 0; return 0;
} }
int pthread_mutex_init(pthread_mutex_t *mutex,
pthread_mutexattr_t const *attr)
{
if (!mutex)
return EINVAL;
/* mark as uninitialized for 'mutex_init()' */
*mutex = PTHREAD_MUTEX_INITIALIZER;
return mutex_init(mutex, attr);
}
typeof(pthread_mutex_init) _pthread_mutex_init typeof(pthread_mutex_init) _pthread_mutex_init
__attribute__((alias("pthread_mutex_init"))); __attribute__((alias("pthread_mutex_init")));
@ -1001,7 +1017,7 @@ extern "C" {
return EINVAL; return EINVAL;
if (*mutex == PTHREAD_MUTEX_INITIALIZER) if (*mutex == PTHREAD_MUTEX_INITIALIZER)
pthread_mutex_init(mutex, nullptr); mutex_init(mutex, nullptr);
return (*mutex)->lock(); return (*mutex)->lock();
} }
@ -1016,7 +1032,7 @@ extern "C" {
return EINVAL; return EINVAL;
if (*mutex == PTHREAD_MUTEX_INITIALIZER) if (*mutex == PTHREAD_MUTEX_INITIALIZER)
pthread_mutex_init(mutex, nullptr); mutex_init(mutex, nullptr);
return (*mutex)->trylock(); return (*mutex)->trylock();
} }
@ -1032,7 +1048,7 @@ extern "C" {
return EINVAL; return EINVAL;
if (*mutex == PTHREAD_MUTEX_INITIALIZER) if (*mutex == PTHREAD_MUTEX_INITIALIZER)
pthread_mutex_init(mutex, nullptr); mutex_init(mutex, nullptr);
/* abstime must be non-null according to the spec */ /* abstime must be non-null according to the spec */
return (*mutex)->timedlock(*abstimeout); return (*mutex)->timedlock(*abstimeout);