diff --git a/libpthread/Makefile b/libpthread/Makefile index 7662e693..68739a5b 100644 --- a/libpthread/Makefile +++ b/libpthread/Makefile @@ -24,6 +24,8 @@ pthread_cond_wait.o \ pthread_equal.o \ pthread_exit.o \ pthread_initialize.o \ +pthread_key_create.o \ +pthread_key_delete.o \ pthread_mutexattr_destroy.o \ pthread_mutexattr_gettype.o \ pthread_mutexattr_init.o \ diff --git a/libpthread/include/__/pthread.h b/libpthread/include/__/pthread.h index 83638622..608e47a4 100644 --- a/libpthread/include/__/pthread.h +++ b/libpthread/include/__/pthread.h @@ -67,7 +67,7 @@ typedef struct } __pthread_condattr_t; #endif -typedef int __pthread_key_t; +typedef __SIZE_TYPE__ __pthread_key_t; #if defined(__is_sortix_libpthread) typedef struct diff --git a/libpthread/include/pthread.h b/libpthread/include/pthread.h index d0642748..e9bb1f72 100644 --- a/libpthread/include/pthread.h +++ b/libpthread/include/pthread.h @@ -161,6 +161,20 @@ struct pthread_cond_elem void pthread_initialize(void); +#if defined(__is_sortix_libpthread) + +struct pthread_key +{ + void (*destructor)(void*); +}; + +extern pthread_mutex_t __pthread_keys_lock; +extern struct pthread_key* __pthread_keys; +extern size_t __pthread_keys_used; +extern size_t __pthread_keys_length; + +#endif + /* TODO: pthread_atfork */ /* TODO: pthread_attr_destroy */ /* TODO: pthread_attr_getdetachstate */ @@ -216,8 +230,8 @@ void pthread_exit(void*); /* TODO: pthread_getschedparam */ /* TODO: pthread_getspecific */ /* TODO: pthread_join */ -/* TODO: pthread_key_create */ -/* TODO: pthread_key_delete */ +int pthread_key_create(pthread_key_t*, void (*)(void*)); +int pthread_key_delete(pthread_key_t); /* TODO: pthread_mutex_consistent */ int pthread_mutex_destroy(pthread_mutex_t*); /* TODO: pthread_mutex_getprioceiling */ diff --git a/libpthread/pthread_initialize.c++ b/libpthread/pthread_initialize.c++ index bc313025..644a4db3 100644 --- a/libpthread/pthread_initialize.c++ +++ b/libpthread/pthread_initialize.c++ @@ -33,6 +33,12 @@ #include +extern "C" { pthread_mutex_t __pthread_keys_lock = + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; } +extern "C" { struct pthread_key* __pthread_keys = NULL; } +extern "C" { size_t __pthread_keys_used = 0; } +extern "C" { size_t __pthread_keys_length = 0; } + // Emit an ELF note containing the size and alignment of struct pthread. __attribute__((used)) static void elf_note_sortix_pthread_size() diff --git a/libpthread/pthread_key_create.c++ b/libpthread/pthread_key_create.c++ new file mode 100644 index 00000000..5fa513d3 --- /dev/null +++ b/libpthread/pthread_key_create.c++ @@ -0,0 +1,71 @@ +/******************************************************************************* + + 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_key_create.c++ + Thread-specific data key creation. + +*******************************************************************************/ + +#include +#include +#include + +static void noop_destructor(void*) +{ +} + +extern "C" +int pthread_key_create(pthread_key_t* key, void (*destructor)(void*)) +{ + if ( !destructor ) + destructor = noop_destructor; + + pthread_mutex_lock(&__pthread_keys_lock); + + if ( __pthread_keys_used < __pthread_keys_length ) + { + size_t result_key = 0; + while ( __pthread_keys[result_key].destructor ) + result_key++; + __pthread_keys[__pthread_keys_used++, *key = result_key].destructor = destructor; + } + else + { + size_t old_length = __pthread_keys_length; + size_t new_length = old_length ? old_length * 2 : 8; + size_t new_size = sizeof(struct pthread_key) * new_length; + struct pthread_key* new_keys = + (struct pthread_key*) realloc(__pthread_keys, new_size); + if ( !new_keys ) + { + pthread_mutex_unlock(&__pthread_keys_lock); + return errno; + } + __pthread_keys = new_keys; + __pthread_keys_length = new_length; + for ( size_t i = old_length; i < new_length; i++ ) + new_keys[i].destructor = NULL; + + __pthread_keys[__pthread_keys_used++, *key = old_length].destructor = destructor; + } + + pthread_mutex_unlock(&__pthread_keys_lock); + + return 0; +} diff --git a/libpthread/pthread_key_delete.c++ b/libpthread/pthread_key_delete.c++ new file mode 100644 index 00000000..d0538867 --- /dev/null +++ b/libpthread/pthread_key_delete.c++ @@ -0,0 +1,41 @@ +/******************************************************************************* + + 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_key_delete.c++ + Thread-specific data key deletion. + +*******************************************************************************/ + +#include +#include +#include + +extern "C" int pthread_key_delete(pthread_key_t key) +{ + pthread_mutex_lock(&__pthread_keys_lock); + + assert(key < __pthread_keys_length); + assert(__pthread_keys[key].destructor); + + __pthread_keys[key].destructor = NULL; + + pthread_mutex_unlock(&__pthread_keys_lock); + + return 0; +}