From 4d71c96fdcb71657dde4780693f3646a41cf5343 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Fri, 10 Jan 2014 16:01:28 +0100 Subject: [PATCH] Add pthread_once(3). --- libpthread/Makefile | 1 + libpthread/include/__/pthread.h | 14 ++++++++++- libpthread/include/pthread.h | 5 ++-- libpthread/pthread_once.c++ | 42 +++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 libpthread/pthread_once.c++ diff --git a/libpthread/Makefile b/libpthread/Makefile index a9b3316e..2f63fe21 100644 --- a/libpthread/Makefile +++ b/libpthread/Makefile @@ -36,6 +36,7 @@ pthread_mutex_init.o \ pthread_mutex_lock.o \ pthread_mutex_trylock.o \ pthread_mutex_unlock.o \ +pthread_once.o \ pthread_rwlock_destroy.o \ pthread_rwlock_init.o \ pthread_rwlock_rdlock.o \ diff --git a/libpthread/include/__/pthread.h b/libpthread/include/__/pthread.h index 608e47a4..85ebafb4 100644 --- a/libpthread/include/__/pthread.h +++ b/libpthread/include/__/pthread.h @@ -99,7 +99,19 @@ typedef struct } __pthread_mutexattr_t; #endif -typedef int __pthread_once_t; +#if defined(__is_sortix_libpthread) +typedef struct +{ + __pthread_mutex_t lock; + int executed; +} __pthread_once_t; +#else +typedef struct +{ + __pthread_mutex_t __pthread_lock; + int __pthread_executed; +} __pthread_once_t; +#endif #if defined(__is_sortix_libpthread) typedef struct diff --git a/libpthread/include/pthread.h b/libpthread/include/pthread.h index d046bc75..56ba4e48 100644 --- a/libpthread/include/pthread.h +++ b/libpthread/include/pthread.h @@ -61,7 +61,6 @@ __BEGIN_DECLS #define PTHREAD_MUTEX_RECURSIVE 1 /* TODO: #define PTHREAD_MUTEX_ROBUST */ /* TODO: #define PTHREAD_MUTEX_STALLED */ -/* TODO: #define PTHREAD_ONCE_INIT */ /* TODO: #define PTHREAD_PRIO_INHERIT */ /* TODO: #define PTHREAD_PRIO_NONE */ /* TODO: #define PTHREAD_PRIO_PROTECT */ @@ -161,6 +160,8 @@ struct pthread_cond_elem #define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP { 0, PTHREAD_MUTEX_NORMAL, 0, 0 } #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP { 0, PTHREAD_MUTEX_RECURSIVE, 0, 0 } +#define PTHREAD_ONCE_INIT { PTHREAD_NORMAL_MUTEX_INITIALIZER_NP, 0 } + void pthread_initialize(void); #if defined(__is_sortix_libpthread) @@ -256,7 +257,7 @@ int pthread_mutexattr_init(pthread_mutexattr_t*); /* TODO: pthread_mutexattr_setpshared */ /* TODO: pthread_mutexattr_setrobust */ int pthread_mutexattr_settype(pthread_mutexattr_t*, int); -/* TODO: pthread_once */ +int pthread_once(pthread_once_t*, void (*)(void)); int pthread_rwlock_destroy(pthread_rwlock_t*); int pthread_rwlock_init(pthread_rwlock_t* __restrict, const pthread_rwlockattr_t* __restrict); diff --git a/libpthread/pthread_once.c++ b/libpthread/pthread_once.c++ new file mode 100644 index 00000000..f8bb10cd --- /dev/null +++ b/libpthread/pthread_once.c++ @@ -0,0 +1,42 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2014. + + This file is part of Sortix libpthread. + + Sortix libpthread is free software: you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + Sortix libpthread is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Sortix libpthread. If not, see . + + pthread_once.c++ + Dynamic package initialization. + +*******************************************************************************/ + +#include + +extern "C" +int pthread_once(pthread_once_t* once_control, void (*init_routine)(void)) +{ + pthread_mutex_lock(&once_control->lock); + if ( !once_control->executed ) + { + // TODO: If this thread is a cancellation point and is canceled, we must + // pretend this pthread_once was never called. This means that we + // need to ensure that once_control->lock is unlocked in the event + // of a cancellation. + init_routine(); + once_control->executed = 1; + } + pthread_mutex_unlock(&once_control->lock); + return 0; +}