From fcc493a76fdc58dda41a45667dab7c99d95461ee Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 6 Apr 2021 23:52:43 -0500 Subject: [PATCH] Update: add pthread semaphore support and correct comments. This includes named semaphores, using the words "semaphore_file". Fix several problems with the comments. --- level_0/f_thread/c/private-thread.c | 63 ++++ level_0/f_thread/c/private-thread.h | 98 ++++++ level_0/f_thread/c/thread-common.h | 46 +++ level_0/f_thread/c/thread.c | 270 ++++++++++++++++ level_0/f_thread/c/thread.h | 528 ++++++++++++++++++++++++++++++- level_0/f_thread/data/build/dependencies | 1 + level_0/f_thread/data/build/settings | 2 +- 7 files changed, 991 insertions(+), 17 deletions(-) diff --git a/level_0/f_thread/c/private-thread.c b/level_0/f_thread/c/private-thread.c index 7eb0ec9..a4df8c7 100644 --- a/level_0/f_thread/c/private-thread.c +++ b/level_0/f_thread/c/private-thread.c @@ -633,6 +633,69 @@ extern "C" { } #endif // !defined(_di_f_thread_mutexs_decrease_) || !defined(_di_f_thread_mutexs_decrease_by_) || !defined(_di_f_thread_mutexs_increase_) || !defined(_di_f_thread_mutexs_increase_by_) +#if !defined(_di_f_thread_semaphores_adjust_) || !defined(_di_f_thread_semaphores_decimate_by_) || !defined(_di_f_thread_semaphores_decrease_) || !defined(_di_f_thread_semaphores_decrease_by_) || !defined(_di_f_thread_semaphores_increase_) || !defined(_di_f_thread_semaphores_increase_by_) || !defined(_di_f_thread_semaphores_resize_) + f_status_t private_f_thread_semaphore_delete(f_thread_semaphore_t *semaphore) { + + const int result = sem_destroy(semaphore); + + if (result == -1) { + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_thread_semaphores_adjust_) || !defined(_di_f_thread_semaphores_decimate_by_) || !defined(_di_f_thread_semaphores_decrease_) || !defined(_di_f_thread_semaphores_decrease_by_) || !defined(_di_f_thread_semaphores_increase_) || !defined(_di_f_thread_semaphores_increase_by_) || !defined(_di_f_thread_semaphores_resize_) + +#if !defined(_di_f_thread_semaphores_adjust_) || !defined(_di_f_thread_semaphores_decimate_by_) + f_status_t private_f_thread_semaphores_adjust(const f_array_length_t length, f_thread_semaphores_t *semaphores) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < semaphores->size; ++i) { + + status = private_f_thread_semaphore_delete(&semaphores->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_adjust(semaphores->size, length, sizeof(f_thread_semaphore_t), (void **) & semaphores->array); + + if (F_status_is_error_not(status)) { + semaphores->size = length; + + if (semaphores->used > semaphores->size) { + semaphores->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_semaphores_adjust_) || !defined(_di_f_thread_semaphores_decimate_by_) + +#if !defined(_di_f_thread_semaphores_decrease_) || !defined(_di_f_thread_semaphores_decrease_by_) || !defined(_di_f_thread_semaphores_increase_) || !defined(_di_f_thread_semaphores_increase_by_) + f_status_t private_f_thread_semaphores_resize(const f_array_length_t length, f_thread_semaphores_t *semaphores) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < semaphores->size; ++i) { + + status = private_f_thread_semaphore_delete(&semaphores->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_resize(semaphores->size, length, sizeof(f_thread_semaphore_t), (void **) & semaphores->array); + + if (F_status_is_error_not(status)) { + semaphores->size = length; + + if (semaphores->used > semaphores->size) { + semaphores->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_semaphores_decrease_) || !defined(_di_f_thread_semaphores_decrease_by_) || !defined(_di_f_thread_semaphores_increase_) || !defined(_di_f_thread_semaphores_increase_by_) + #if !defined(_di_f_thread_sets_adjust_) || !defined(_di_f_thread_sets_decimate_by_) f_status_t private_f_thread_sets_adjust(const f_array_length_t length, f_thread_sets_t *sets) { f_status_t status = F_none; diff --git a/level_0/f_thread/c/private-thread.h b/level_0/f_thread/c/private-thread.h index e917e9b..d44169a 100644 --- a/level_0/f_thread/c/private-thread.h +++ b/level_0/f_thread/c/private-thread.h @@ -28,7 +28,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_attr_destroy() * @@ -111,7 +113,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_attr_destroy() * @@ -187,7 +191,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_attr_destroy() * @@ -263,7 +269,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_condattr_destroy() * @@ -339,7 +347,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_cond_destroy() * @@ -413,7 +423,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_key_destroy() * @@ -487,7 +499,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_rwlock_destroy() * @@ -561,7 +575,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_rwlockattr_destroy() * @@ -635,7 +651,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_mutexattr_destroy() * @@ -709,7 +727,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_mutex_destroy() * @@ -773,6 +793,82 @@ extern "C" { #endif // !defined(_di_f_thread_mutexs_decrease_by_) || !defined(_di_f_thread_mutexs_increase_) || !defined(_di_f_thread_mutexs_increase_by_) /** + * Private implementation for deleting (and destroying). + * + * Intended to be shared to each of the different implementation variations. + * + * @param semaphore + * The semaphores to delete. + * + * @return + * F_none on success. + * + * F_busy (with error bit) if the lock is busy. + * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see sem_destroy() + * + * @see f_thread_semaphores_adjust() + * @see f_thread_semaphores_decimate_by() + * @see f_thread_semaphores_decrease() + * @see f_thread_semaphores_decrease_by() + * @see f_thread_semaphores_increase() + * @see f_thread_semaphores_increase_by() + * @see f_thread_semaphores_resize() + */ +#if !defined(_di_f_thread_semaphores_adjust_) || !defined(_di_f_thread_semaphores_decimate_by_) || !defined(_di_f_thread_semaphores_decrease_) || !defined(_di_f_thread_semaphores_decrease_by_) || !defined(_di_f_thread_semaphores_increase_) || !defined(_di_f_thread_semaphores_increase_by_) || !defined(_di_f_thread_semaphores_resize_) + extern f_status_t private_f_thread_semaphore_delete(f_thread_semaphore_t *semaphore) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_semaphores_adjust_) || !defined(_di_f_thread_semaphores_decimate_by_) || !defined(_di_f_thread_semaphores_decrease_) || !defined(_di_f_thread_semaphores_decrease_by_) || !defined(_di_f_thread_semaphores_increase_) || !defined(_di_f_thread_semaphores_increase_by_) || !defined(_di_f_thread_semaphores_resize_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param semaphores + * The semaphores to adjust. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_memory_adjust() + * @see f_thread_semaphores_adjust() + * @see f_thread_semaphores_decimate_by() + */ +#if !defined(_di_f_thread_semaphores_adjust_) || !defined(_di_f_thread_semaphores_decimate_by_) + extern f_status_t private_f_thread_semaphores_adjust(const f_array_length_t length, f_thread_semaphores_t *semaphores) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_semaphores_adjust_) || !defined(_di_f_thread_semaphores_decimate_by_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param semaphores + * The semaphores to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_thread_semaphores_decrease_by() + * @see f_thread_semaphores_increase() + * @see f_thread_semaphores_increase_by() + */ +#if !defined(_di_f_thread_semaphores_decrease_by_) || !defined(_di_f_thread_semaphores_increase_) || !defined(_di_f_thread_semaphores_increase_by_) + extern f_status_t private_f_thread_semaphores_resize(const f_array_length_t length, f_thread_semaphores_t *semaphores) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_semaphores_decrease_by_) || !defined(_di_f_thread_semaphores_increase_) || !defined(_di_f_thread_semaphores_increase_by_) + +/** * Private implementation for resizing. * * Intended to be shared to each of the different implementation variations. @@ -830,7 +926,9 @@ extern "C" { * @return * F_none on success. * + * F_busy (with error bit) if the lock is busy. * F_failure (with error bit) on error. + * F_parameter (with error bit) if a parameter is invalid. * * @see pthread_spin_destroy() * diff --git a/level_0/f_thread/c/thread-common.h b/level_0/f_thread/c/thread-common.h index 5a01981..ebff43a 100644 --- a/level_0/f_thread/c/thread-common.h +++ b/level_0/f_thread/c/thread-common.h @@ -545,6 +545,52 @@ extern "C" { #endif // _di_f_thread_onces_t_ /** + * A typedef representing sem_t. + * + * This variable cannot be cleared by setting value to 0, so there is no clear macro provided. + * + * This must be dynamically initialized using f_thread_semaphore_create(). + */ +#ifndef _di_f_thread_semaphore_t_ + typedef sem_t f_thread_semaphore_t; + + #define f_thread_semaphore_t_initialize 0 + + #define f_macro_thread_semaphore_t_delete_simple(semaphore) f_thread_semaphore_delete(&semaphore); +#endif // _di_f_thread_semaphore_t_ + +/** + * An array of thread semaphorees. + * + * array: the array of f_thread_semaphore_t. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_f_thread_semaphores_t_ + typedef struct { + f_thread_semaphore_t *array; + + f_array_length_t size; + f_array_length_t used; + } f_thread_semaphores_t; + + #define f_thread_semaphores_t_initialize { 0, 0, 0 } + + #define f_macro_thread_semaphores_t_clear(semaphores) f_macro_memory_structure_clear(semaphores) + + #define f_macro_thread_semaphores_t_resize(status, semaphores, length) status = f_thread_semaphores_resize(length, &semaphores); + #define f_macro_thread_semaphores_t_adjust(status, semaphores, length) status = f_thread_semaphores_adjust(length, &semaphores); + + #define f_macro_thread_semaphores_t_delete_simple(semaphores) f_thread_semaphores_resize(0, &semaphores); + #define f_macro_thread_semaphores_t_destroy_simple(semaphores) f_thread_semaphores_adjust(0, &semaphores); + + #define f_macro_thread_semaphores_t_increase(status, semaphores) status = f_thread_semaphores_increase(semaphores); + #define f_macro_thread_semaphores_t_increase_by(status, semaphores, amount) status = f_thread_semaphores_increase_by(amount, semaphores); + #define f_macro_thread_semaphores_t_decrease_by(status, semaphores, amount) status = f_thread_semaphores_decrease_by(amount, semaphores); + #define f_macro_thread_semaphores_t_decimate_by(status, semaphores, amount) status = f_thread_semaphores_decimate_by(amount, semaphores); +#endif // _di_f_thread_semaphores_t_ + +/** * A structure containing basic thread information. * * attribute: The thread attributes (which is a union). diff --git a/level_0/f_thread/c/thread.c b/level_0/f_thread/c/thread.c index 6b3af45..d0c410c 100644 --- a/level_0/f_thread/c/thread.c +++ b/level_0/f_thread/c/thread.c @@ -2324,6 +2324,183 @@ extern "C" { } #endif // _di_f_thread_mutex_lock_try_ +#ifndef _di_f_thread_semaphore_create_ + f_status_t f_thread_semaphore_create(const bool shared, const unsigned int value, f_thread_semaphore_t *semaphore) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphore) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sem_init(semaphore, shared, value) == -1) { + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ENOSYS) return F_status_set_error(F_supported_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_semaphore_create_ + +#ifndef _di_f_thread_semaphore_delete_ + f_status_t f_thread_semaphore_delete(f_thread_semaphore_t *semaphore) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphore) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_semaphore_delete(semaphore); + } +#endif // _di_f_thread_semaphore_delete_ + +#ifndef _di_f_thread_semaphore_file_create_ + f_status_t f_thread_semaphore_file_create(const f_string_t name, const int flag, mode_t mode, unsigned int value, f_thread_semaphore_t *semaphore) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphore) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (flag & O_CREAT) { + semaphore = sem_open(name, flag, mode, value); + } + else { + semaphore = sem_open(name, flag); + } + + if (semaphore == SEM_FAILED) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EEXIST) return F_status_set_error(F_file_found); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not); + if (errno == ENFILE) return F_status_set_error(F_file_open_max); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + if (errno == ENOMEM) return F_status_set_error(F_memory_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_semaphore_file_create_ + +#ifndef _di_f_thread_semaphore_file_delete_ + f_status_t f_thread_semaphore_file_delete(f_thread_semaphore_t *semaphore) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphore) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sem_close(semaphore) == -1) { + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_semaphore_file_delete_ + +#ifndef _di_f_thread_semaphore_file_destroy_ + f_status_t f_thread_semaphore_file_destroy(const f_string_t name) { + + if (sem_unlink(name) == -1) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not); + if (errno == ENOENT) return F_file_found_not; + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_semaphore_file_destroy_ + +#ifndef _di_f_thread_semaphore_lock_ + f_status_t f_thread_semaphore_lock(f_thread_semaphore_t *semaphore) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphore) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sem_wait(semaphore) == -1) { + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_semaphore_lock_ + +#ifndef _di_f_thread_semaphore_lock_timed_ + f_status_t f_thread_semaphore_lock_timed(const struct timespec *timeout, f_thread_semaphore_t *semaphore) { + #ifndef _di_level_0_parameter_checking_ + if (!timeout) return F_status_set_error(F_parameter); + if (!semaphore) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sem_timedwait(semaphore, timeout) == -1) { + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ETIMEDOUT) return F_time; + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_semaphore_lock_timed_ + +#ifndef _di_f_thread_semaphore_lock_try_ + f_status_t f_thread_semaphore_lock_try(f_thread_semaphore_t *semaphore) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphore) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sem_trywait(semaphore) == -1) { + if (errno == EAGAIN) return F_status_set_error(F_resource_not); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_semaphore_lock_try_ + +#ifndef _di_f_thread_semaphore_unlock_ + f_status_t f_thread_semaphore_unlock(f_thread_semaphore_t *semaphore) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphore) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sem_post(semaphore) == -1) { + if (errno == EOVERFLOW) return F_status_set_error(F_number_overflow); + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_semaphore_unlock_ + +#ifndef _di_f_thread_semaphore_value_get_ + f_status_t f_thread_semaphore_value_get(f_thread_semaphore_t *semaphore, int *value) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphore) return F_status_set_error(F_parameter); + if (!value) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (sem_getvalue(semaphore, value) == -1) { + if (errno == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_semaphore_value_get_ + #ifndef _di_f_thread_mutex_priority_ceiling_get_ f_status_t f_thread_mutex_priority_ceiling_get(f_thread_mutex_t *mutex, int *ceiling) { #ifndef _di_level_0_parameter_checking_ @@ -2556,6 +2733,99 @@ extern "C" { } #endif // _di_f_thread_scheduler_priority_set_ +#ifndef _di_f_thread_semaphores_adjust_ + f_status_t f_thread_semaphores_adjust(const f_array_length_t length, f_thread_semaphores_t *semaphores) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphores) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_semaphores_adjust(length, semaphores); + } +#endif // _di_f_thread_semaphores_adjust_ + +#ifndef _di_f_thread_semaphores_decimate_by_ + f_status_t f_thread_semaphores_decimate_by(const f_array_length_t amount, f_thread_semaphores_t *semaphores) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!semaphores) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (semaphores->size - amount > 0) { + return private_f_thread_semaphores_adjust(semaphores->size - amount, semaphores); + } + + return private_f_thread_semaphores_adjust(0, semaphores); + } +#endif // _di_f_thread_semaphores_decimate_by_ + +#ifndef _di_f_thread_semaphores_decrease_by_ + f_status_t f_thread_semaphores_decrease_by(const f_array_length_t amount, f_thread_semaphores_t *semaphores) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!semaphores) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (semaphores->size - amount > 0) { + return private_f_thread_semaphores_resize(semaphores->size - amount, semaphores); + } + + return private_f_thread_semaphores_resize(0, semaphores); + } +#endif // _di_f_thread_semaphores_decrease_by_ + +#ifndef _di_f_thread_semaphores_increase_ + f_status_t f_thread_semaphores_increase(f_thread_semaphores_t *semaphores) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphores) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (semaphores->used + 1 > semaphores->size) { + f_array_length_t size = semaphores->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (semaphores->used + 1 > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + size = f_array_length_t_size; + } + + return private_f_thread_semaphores_resize(size, semaphores); + } + + return F_data_not; + } +#endif // _di_f_thread_semaphores_increase_ + +#ifndef _di_f_thread_semaphores_increase_by_ + f_status_t f_thread_semaphores_increase_by(const f_array_length_t amount, f_thread_semaphores_t *semaphores) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!semaphores) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (semaphores->used + amount > semaphores->size) { + if (semaphores->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_thread_semaphores_resize(semaphores->used + amount, semaphores); + } + + return F_data_not; + } +#endif // _di_f_thread_semaphores_increase_by_ + +#ifndef _di_f_thread_semaphores_resize_ + f_status_t f_thread_semaphores_resize(const f_array_length_t length, f_thread_semaphores_t *semaphores) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphores) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_semaphores_resize(length, semaphores); + } +#endif // _di_f_thread_semaphores_resize_ + #ifndef _di_f_thread_sets_adjust_ f_status_t f_thread_sets_adjust(const f_array_length_t length, f_thread_sets_t *sets) { #ifndef _di_level_0_parameter_checking_ diff --git a/level_0/f_thread/c/thread.h b/level_0/f_thread/c/thread.h index ebacc31..22ba1f6 100644 --- a/level_0/f_thread/c/thread.h +++ b/level_0/f_thread/c/thread.h @@ -14,6 +14,8 @@ #define _GNU_SOURCE // libc includes +#include +#include #include #include #include @@ -24,6 +26,7 @@ #include #include #include +#include // fll-0 thread includes #include @@ -47,6 +50,7 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * F_memory_not (with error bit) if out of memory. + * * F_failure (with error bit) on any other error. * * @see pthread_atfork() @@ -69,6 +73,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_getaffinity_np() @@ -92,6 +97,7 @@ extern "C" { * * F_memory_not (with error bit) if out of memory. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_setaffinity_np() @@ -112,6 +118,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_condattr_getclock() @@ -132,6 +139,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_condattr_setclock() @@ -152,6 +160,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_condattr_getpshared() @@ -172,6 +181,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_condattr_setpshared() @@ -192,6 +202,7 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * F_memory_not (with error bit) if out of memory. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_init() @@ -210,6 +221,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_getattr_default_np() @@ -229,6 +241,7 @@ extern "C" { * * F_memory_not (with error bit) if out of memory. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_setattr_default_np() @@ -252,6 +265,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_destroy() @@ -272,6 +286,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_getdetachstate() @@ -292,6 +307,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_setdetachstate() @@ -312,6 +328,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_getguardsize() @@ -332,6 +349,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_setguardsize() @@ -352,6 +370,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_getinheritsched() @@ -372,6 +391,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_setinheritsched() @@ -392,6 +412,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_getschedparam() @@ -412,6 +433,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_setschedparam() @@ -432,6 +454,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_getschedpolicy() @@ -452,6 +475,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_setschedpolicy() @@ -472,6 +496,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_getscope() @@ -493,6 +518,7 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * F_supported_not (with error bit) if the scope is not supported by the current OS (such as Linux not supporting PTHREAD_SCOPE_PROCESS). + * * F_failure (with error bit) on any other error. * * @see pthread_attr_setscope() @@ -516,6 +542,7 @@ extern "C" { * * F_access_denied (with error bit) if the caller cannot both read and write to the stack address. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_getstack() @@ -539,6 +566,7 @@ extern "C" { * * F_access_denied (with error bit) if the caller cannot both read and write to the stack address. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_setstack() @@ -559,6 +587,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_getstacksize() @@ -579,6 +608,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_attr_setstacksize() @@ -686,9 +716,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_attributes_increase_by_ extern f_status_t f_thread_attributes_increase_by(const f_array_length_t amount, f_thread_attributes_t *attributes); @@ -724,6 +754,7 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * F_memory_not (with error bit) if out of memory. + * * F_failure (with error bit) on any other error. * * @see pthread_barrierattr_init() @@ -747,6 +778,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_barrierattr_destroy() @@ -767,6 +799,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_barrierattr_getpshared() @@ -787,6 +820,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_barrierattr_setpshared() @@ -894,9 +928,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_barrier_attributes_increase_by_ extern f_status_t f_thread_barrier_attributes_increase_by(const f_array_length_t amount, f_thread_barrier_attributes_t *attributes); @@ -932,6 +966,7 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * F_memory_not (with error bit) if out of memory. + * * F_failure (with error bit) on any other error. * * @see pthread_barrier_init() @@ -955,6 +990,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_barrier_destroy() @@ -1082,9 +1118,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_barriers_increase_by_ extern f_status_t f_thread_barriers_increase_by(const f_array_length_t amount, f_thread_barriers_t *barriers); @@ -1130,6 +1166,7 @@ extern "C" { * F_none on success. * * F_found_not (with error bit) if no thread by the given ID was found. + * * F_failure (with error bit) on any other error. * * @see pthread_cancel() @@ -1152,6 +1189,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_setcancelstate() @@ -1189,6 +1227,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_setcanceltype() @@ -1210,6 +1249,7 @@ extern "C" { * * F_found_not (with error bit) if no thread by the given ID was found. * F_supported_not (with error bit) if per-CPU clocks are not supported by the OS. + * * F_failure (with error bit) on any other error. * * @see pthread_getcpuclockid() @@ -1248,6 +1288,7 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if the new level would cause the system to exceed available resources. + * * F_failure (with error bit) on any other error. * * @see pthread_getconcurrency() @@ -1269,6 +1310,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_setconcurrency() @@ -1288,6 +1330,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_condattr_init() @@ -1310,6 +1353,7 @@ extern "C" { * * F_busy (with error bit) if the attribute is busy. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_condattr_destroy() @@ -1417,9 +1461,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_condition_attributes_increase_by_ extern f_status_t f_thread_condition_attributes_increase_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes); @@ -1456,6 +1500,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_cond_init() @@ -1496,6 +1541,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_cond_broadcast() @@ -1516,6 +1562,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_cond_signal() @@ -1538,6 +1585,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_cond_wait() @@ -1566,6 +1614,7 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if not allowed to perform the operation (possibly because mutex is not owned by current thread). + * * F_failure (with error bit) on any other error. * * @see pthread_cond_timedwait() @@ -1673,9 +1722,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_conditions_increase_by_ extern f_status_t f_thread_conditions_increase_by(const f_array_length_t amount, f_thread_conditions_t *conditions); @@ -1720,6 +1769,7 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if not allowed to set the scheduling policy and parameters specified in attribute. * F_resource_not (with error bit) if there are not enough resources to create another thread. + * * F_failure (with error bit) on any other error. * * @see pthread_create() @@ -1746,6 +1796,7 @@ extern "C" { * F_found_not (with error bit) if no thread by the given ID was found. * F_parameter (with error bit) if a parameter is invalid. * + * F_failure (with error bit) on any other error. * * @see pthread_detach() */ @@ -1790,6 +1841,7 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_supported_not (with error bit) if the thread is not joinable or is already being joined by another thread. * + * F_failure (with error bit) on any other error. * * @see pthread_join() */ @@ -1816,8 +1868,9 @@ extern "C" { * F_deadlock (with error bit) if operation would cause a deadlock.ead. * F_found_not (with error bit) if no thread by the given ID was found. * F_parameter (with error bit) if a parameter is invalid. - * F_supported_not (with error bit) if the thread is not joinable or is already being joined by another thr + * F_supported_not (with error bit) if the thread is not joinable or is already being joined by another thread. * + * F_failure (with error bit) on any other error. * * @see pthread_tryjoin_np() */ @@ -1851,6 +1904,7 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_supported_not (with error bit) if the thread is not joinable or is already being joined by another thread. * + * F_failure (with error bit) on any other error. * * @see pthread_timedjoin_np() */ @@ -1872,6 +1926,7 @@ extern "C" { * F_memory_not (with error bit) if out of memory. * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if not allowed to set the scheduling policy and parameters specified in attribute. + * * F_failure (with error bit) on any other error. * * @see pthread_key_create() @@ -1893,6 +1948,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_key_delete() @@ -1933,6 +1989,8 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * + * F_failure (with error bit) on any other error. + * * @see pthread_setspecific() */ #ifndef _di_f_thread_key_set_ @@ -2038,9 +2096,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_keys_increase_by_ extern f_status_t f_thread_keys_increase_by(const f_array_length_t amount, f_thread_keys_t *keys); @@ -2078,6 +2136,7 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if not allowed to perform the operation. * F_resource_not (with error bit) if max lockes is reached. + * * F_failure (with error bit) on any other error. * * @see pthread_rwlockattr_init() @@ -2100,6 +2159,7 @@ extern "C" { * * F_busy (with error bit) if the lock is busy. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_rwlockattr_destroy() @@ -2120,6 +2180,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_rwlockattr_getpshared() @@ -2140,6 +2201,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_rwlockattr_setpshared() @@ -2247,9 +2309,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_lock_attributes_increase_by_ extern f_status_t f_thread_lock_attributes_increase_by(const f_array_length_t amount, f_thread_lock_attributes_t *attributes); @@ -2287,6 +2349,7 @@ extern "C" { * F_memory_not (with error bit) if out of memory. * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if max lockes is reached. + * * F_failure (with error bit) on any other error. * * @see pthread_rwlock_init() @@ -2309,6 +2372,7 @@ extern "C" { * * F_busy (with error bit) if the lock is busy. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_rwlock_destroy() @@ -2331,6 +2395,8 @@ extern "C" { * F_deadlock (with error bit) if operation would cause a deadlock. * F_parameter (with error bit) if a parameter is invalid. * + * F_failure (with error bit) on any other error. + * * @see pthread_rwlock_rdlock() */ #ifndef _di_f_thread_lock_read_ @@ -2356,6 +2422,8 @@ extern "C" { * F_deadlock (with error bit) if operation would cause a deadlock. * F_parameter (with error bit) if a parameter is invalid. * + * F_failure (with error bit) on any other error. + * * @see pthread_rwlock_timedrdlock() */ #ifndef _di_f_thread_lock_read_timed_ @@ -2379,6 +2447,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if max locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_rwlock_tryrdlock() */ #ifndef _di_f_thread_lock_read_try_ @@ -2400,6 +2470,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if max locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_rwlock_wrlock() */ #ifndef _di_f_thread_lock_write_ @@ -2425,6 +2497,8 @@ extern "C" { * F_deadlock (with error bit) if operation would cause a deadlock. * F_parameter (with error bit) if a parameter is invalid. * + * F_failure (with error bit) on any other error. + * * @see pthread_rwlock_timedwrlock() */ #ifndef _di_f_thread_lock_write_timed_ @@ -2448,6 +2522,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if max locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_rwlock_trywrlock() */ #ifndef _di_f_thread_lock_write_try_ @@ -2553,9 +2629,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_locks_increase_by_ extern f_status_t f_thread_locks_increase_by(const f_array_length_t amount, f_thread_locks_t *locks); @@ -2675,6 +2751,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_mutexattr_getpshared() @@ -2695,6 +2772,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_mutexattr_setpshared() @@ -2715,6 +2793,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_mutexattr_gettype() @@ -2735,6 +2814,7 @@ extern "C" { * F_none on success. * * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_mutexattr_settype() @@ -2757,6 +2837,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if not allowed to perform the operation. * + * F_failure (with error bit) on any other error. + * * @see pthread_mutexattr_getprotocol() */ #ifndef _di_f_thread_mutex_attribute_protocol_get_ @@ -2778,6 +2860,8 @@ extern "C" { * F_prohibited (with error bit) if not allowed to perform the operation. * F_supported_not (with error bit) if the protocol is not supported. * + * F_failure (with error bit) on any other error. + * * @see pthread_mutexattr_setprotocol() */ #ifndef _di_f_thread_mutex_attribute_protocol_set_ @@ -2883,9 +2967,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_mutex_attributes_increase_by_ extern f_status_t f_thread_mutex_attributes_increase_by(const f_array_length_t amount, f_thread_mutex_attributes_t *attributes); @@ -2926,6 +3010,7 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if not allowed to perform the operation. * F_resource_not (with error bit) if max mutexes is reached. + * * F_failure (with error bit) on any other error. * * @see pthread_mutex_init() @@ -2948,6 +3033,7 @@ extern "C" { * * F_busy (with error bit) if the mutex is busy. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_mutex_destroy() @@ -2971,6 +3057,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if max mutex locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_mutex_lock() */ #ifndef _di_f_thread_mutex_lock_ @@ -3000,6 +3088,8 @@ extern "C" { * F_resource_not (with error bit) if max mutex locks is reached. * F_thread_not (with error bit) if the owning thread terminated while holding the mutex lock (thread is dead). * + * F_failure (with error bit) on any other error. + * * @see pthread_mutex_timedlock() */ #ifndef _di_f_thread_mutex_lock_timed_ @@ -3023,6 +3113,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if max mutex locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_mutex_trylock() */ #ifndef _di_f_thread_mutex_lock_try_ @@ -3043,6 +3135,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if not allowed to perform the operation. * + * F_failure (with error bit) on any other error. + * * @see pthread_mutex_getprioceiling() */ #ifndef _di_f_thread_mutex_priority_ceiling_get_ @@ -3070,6 +3164,8 @@ extern "C" { * F_resource_not (with error bit) if max mutex locks is reached. * F_thread_not (with error bit) if the owning thread terminated while holding the mutex lock (thread is dead). * + * F_failure (with error bit) on any other error. + * * @see pthread_mutex_setprioceiling() */ #ifndef _di_f_thread_mutex_priority_ceiling_set_ @@ -3089,6 +3185,8 @@ extern "C" { * F_prohibited (with error bit) if not allowed to perform the operation (possibly because mutex is not owned by current thread). * F_resource_not (with error bit) if max mutex locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_mutex_unlock() */ #ifndef _di_f_thread_mutex_unlock_ @@ -3194,9 +3292,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_mutexs_increase_by_ extern f_status_t f_thread_mutexs_increase_by(const f_array_length_t amount, f_thread_mutexs_t *mutexs); @@ -3233,6 +3331,8 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * + * F_failure (with error bit) on any other error. + * * @see pthread_once() */ #ifndef _di_f_thread_once_ @@ -3254,6 +3354,7 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * F_supported_not (with error bit) if the policy or scheduling parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_getschedparam() @@ -3277,6 +3378,7 @@ extern "C" { * * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if insufficient privileges or scheduler (or policy) does not allow operation. + * * F_failure (with error bit) on any other error. * * @see pthread_setschedparam() @@ -3296,9 +3398,10 @@ extern "C" { * @return * F_none on success. * + * F_found_not (with error bit) no thread by the given ID was found. * F_parameter (with error bit) if a parameter is invalid. * F_prohibited (with error bit) if insufficient privileges. - * F_found_not (with error bit) no thread by the given ID was found. + * * F_failure (with error bit) on any other error. * * @see pthread_setschedprio() @@ -3308,6 +3411,387 @@ extern "C" { #endif // _di_f_thread_scheduler_priority_set_ /** + * Create a thread semaphore. + * + * @param shared + * If TRUE, then the semaphore is shared between processes (stored as posix shared memory, memory mapped, etc..). + * IF FALSE, then the semphore is shared between threads of a process (stored as a global variable or in the heap). + * Not all systems support semaphores shared amongst processes. + * @param value + * The value to initially assign the semaphore on creation. + * @param semaphore + * The semaphore to create. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_supported_not (with error bit) if the system does not support the process shared semaphore (shared == true). + * + * F_failure (with error bit) on any other error. + * + * @see sem_init() + */ +#ifndef _di_f_thread_semaphore_create_ + extern f_status_t f_thread_semaphore_create(const bool shared, const unsigned int value, f_thread_semaphore_t *semaphore); +#endif // _di_f_thread_semaphore_create_ + +/** + * Delete a thread semaphore. + * + * The sem_destroy() function has no distinction like the *_destroy() and the *_delete() used by the FLL project. + * Therefore there is only this function for both deleting and destroying. + * + * @param semaphore + * The semaphore to delete. + * + * @return + * F_none on success. + * + * F_busy (with error bit) if the semaphore is busy. + * F_parameter (with error bit) if a parameter is invalid. + * + * F_failure (with error bit) on any other error. + * + * @see sem_destroy() + */ +#ifndef _di_f_thread_semaphore_delete_ + extern f_status_t f_thread_semaphore_delete(f_thread_semaphore_t *semaphore); +#endif // _di_f_thread_semaphore_delete_ + +/** + * Create a thread (named) semaphore. + * + * @param name + * The semaphore file name to create. + * @param flag + * The file create/open flags. + * @param mode + * (optional) The file permissions to assign the semaphore. + * Ignored if O_CREAT is not used in flag. + * Ignored if the named semaphore already exists. + * @param value + * (optional) The value to initially assign the semaphore on creation. + * Ignored if O_CREAT is not used in flag. + * Ignored if the named semaphore already exists. + * @param semaphore + * The thread semaphore. + * + * @return + * F_none on success. + * + * F_access_denied (with error bit) on access denied. + * F_file_descriptor_max (with error bit) if max file descrriptors was reached. + * F_file_found (with error bit) if the file was found and both the O_CREAT and O_EXCL flags are set. + * F_file_open_max (with error bit) too many open files. + * F_file_found_not (with error bit) if the file was not found and the O_CREAT is not set. + * F_name_not (with error bit) if file name is too long. + * F_parameter (with error bit) if a parameter is invalid. + * F_supported_not (with error bit) if the system does not support the process shared semaphore (shared == true). + * F_memory_not (with error bit) if out of memory. + * + * F_failure (with error bit) on any other error. + * + * @see sem_open() + */ +#ifndef _di_f_thread_semaphore_file_create_ + extern f_status_t f_thread_semaphore_file_create(const f_string_t name, const int flag, mode_t mode, unsigned int value, f_thread_semaphore_t *semaphore); +#endif // _di_f_thread_semaphore_file_create_ + +/** + * Delete a thread (named) semaphore. + * + * A named semaphore should be deleted with this function or with f_thread_semephore_file_destroy(). + * + * @param semaphore + * The semaphore to delete. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * F_failure (with error bit) on any other error. + * + * A named semaphore should be deleted with this function or with f_thread_semephore_file_destroy(). + * + * @see sem_close() + * + * @see f_thread_semaphore_file_destroy() + */ +#ifndef _di_f_thread_semaphore_file_delete_ + extern f_status_t f_thread_semaphore_file_delete(f_thread_semaphore_t *semaphore); +#endif // _di_f_thread_semaphore_file_delete_ + +/** + * Destroy a thread (named) semaphore. + * + * This will immediately delete the semaphore file and all processes holding this semaphore will be forced to close. + * + * A named semaphore should be deleted with this function or with f_thread_semephore_file_delete(). + * + * @param name + * The semaphore name to delete. + * + * @return + * F_none on success. + * F_file_found_not the named file was not found. + * + * F_access_denied (with error bit) on access denied. + * F_name_not (with error bit) if file name is too long. + * F_parameter (with error bit) if a parameter is invalid. + * + * F_failure (with error bit) on any other error. + * + * @see sem_unlink() + * + * @see f_thread_semaphore_file_delete() + */ +#ifndef _di_f_thread_semaphore_file_destroy_ + extern f_status_t f_thread_semaphore_file_destroy(const f_string_t name); +#endif // _di_f_thread_semaphore_file_destroy_ + +/** + * Lock the semaphore. + * + * This is a blocking function. + * + * @param semaphore + * The thread semaphore. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_interrupt (with error bit) if returned due to an interrupt signal. + * + * F_failure (with error bit) on any other error. + * + * @see sem_wait() + */ +#ifndef _di_f_thread_semaphore_lock_ + extern f_status_t f_thread_semaphore_lock(f_thread_semaphore_t *semaphore); +#endif // _di_f_thread_semaphore_lock_ + +/** + * Lock the semaphore, waiting for a set period of time to get the lock if already locked. + * + * If the semaphore is already locked and the timeout expires, then the lock attempt fails. + * + * This is a blocking function (until timeout expires). + * + * @param timeout + * The timeout. + * @param semaphore + * The thread semaphore. + * + * @return + * F_none on success. + * F_time if the timeout was reached before obtaining the lock. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_interrupt (with error bit) if returned due to an interrupt signal. + * + * F_failure (with error bit) on any other error. + * + * @see sem_timedwait() + */ +#ifndef _di_f_thread_semaphore_lock_timed_ + extern f_status_t f_thread_semaphore_lock_timed(const struct timespec *timeout, f_thread_semaphore_t *semaphore); +#endif // _di_f_thread_semaphore_lock_timed_ + +/** + * Try to lock the semaphore. + * + * If semaphore is already locked, return immediately. + * + * This is a non-blocking function. + * + * @param semaphore + * The thread semaphore. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_interrupt (with error bit) if returned due to an interrupt signal. + * F_resource_not (with error bit) if max semaphore locks is reached. + * + * F_failure (with error bit) on any other error. + * + * @see sem_trywait() + */ +#ifndef _di_f_thread_semaphore_lock_try_ + extern f_status_t f_thread_semaphore_lock_try(f_thread_semaphore_t *semaphore); +#endif // _di_f_thread_semaphore_lock_try_ + +/** + * Unlock the semaphore. + * + * @param semaphore + * The thread semaphore. + * + * @return + * F_none on success. + * + * F_number_overflow (with error bit) if max semaphore value is reached. + * F_parameter (with error bit) if a parameter is invalid. + * + * F_failure (with error bit) on any other error. + * + * @see sem_post() + */ +#ifndef _di_f_thread_semaphore_unlock_ + extern f_status_t f_thread_semaphore_unlock(f_thread_semaphore_t *semaphore); +#endif // _di_f_thread_semaphore_unlock_ + +/** + * Get the semaphore value. + * + * @param semaphore + * The thread semaphore. + * @param value + * The semaphore's value. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * F_failure (with error bit) on any other error. + * + * @see sem_getvalue() + */ +#ifndef _di_f_thread_semaphore_value_get_ + extern f_status_t f_thread_semaphore_value_get(f_thread_semaphore_t *semaphore, int *value); +#endif // _di_f_thread_semaphore_value_get_ + +/** + * Resize the thread semaphores array. + * + * @param length + * The new size to use. + * @param semaphores + * The string semaphores array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_semaphores_adjust_ + extern f_status_t f_thread_semaphores_adjust(const f_array_length_t length, f_thread_semaphores_t *semaphores); +#endif // _di_f_thread_semaphores_adjust_ + +/** + * Resize the thread semaphores array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decimate the size by. + * @param semaphores + * The string semaphores array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_semaphores_decimate_by_ + extern f_status_t f_thread_semaphores_decimate_by(const f_array_length_t amount, f_thread_semaphores_t *semaphores); +#endif // _di_f_thread_semaphores_decimate_by_ + +/** + * Resize the thread semaphores array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decrease the size by. + * @param semaphores + * The string semaphores array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_semaphores_decrease_by_ + extern f_status_t f_thread_semaphores_decrease_by(const f_array_length_t amount, f_thread_semaphores_t *semaphores); +#endif // _di_f_thread_semaphores_decrease_by_ + +/** + * Increase the size of the thread semaphores array, but only if necessary. + * + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param semaphores + * The string semaphores array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + 1 <= size). + * + * F_array_too_large (with error bit) if the new array length is too large. + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_semaphores_increase_ + extern f_status_t f_thread_semaphores_increase(f_thread_semaphores_t *semaphores); +#endif // _di_f_thread_semaphores_increase_ + +/** + * Resize the thread semaphores array to a larger size. + * + * This will resize making the array larger based on the given length. + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param amount + * A positive number representing how much to increase the size by. + * @param semaphores + * The string semaphores array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + amount <= size). + * + * F_array_too_large (with error bit) if the new array length is too large. + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_semaphores_increase_by_ + extern f_status_t f_thread_semaphores_increase_by(const f_array_length_t amount, f_thread_semaphores_t *semaphores); +#endif // _di_f_thread_semaphores_increase_by_ + +/** + * Resize the thread semaphores array. + * + * @param length + * The new size to use. + * @param semaphores + * The string semaphores array to adjust. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_semaphores_resize_ + extern f_status_t f_thread_semaphores_resize(const f_array_length_t length, f_thread_semaphores_t *semaphores); +#endif // _di_f_thread_semaphores_resize_ + +/** * Resize the thread sets array. * * @param length @@ -3406,9 +3890,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_sets_increase_by_ extern f_status_t f_thread_sets_increase_by(const f_array_length_t amount, f_thread_sets_t *sets); @@ -3474,7 +3958,8 @@ extern "C" { * F_none on success but no signal found. * * F_parameter (with error bit) if a parameter is invalid. - * F_failure (with error bit) for any other error. + * + * F_failure (with error bit) on any other error. * * @see pthread_sigmask() */ @@ -3499,7 +3984,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if the max signals is reached. * F_supported_not (with error bit) if this action is not supported by the current OS. - * F_failure (with error bit) for any other error. + * + * F_failure (with error bit) on any other error. * * @see pthread_sigqueue() */ @@ -3521,6 +4007,7 @@ extern "C" { * F_memory_not (with error bit) if out of memory. * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if max spines is reached. + * * F_failure (with error bit) on any other error. * * @see pthread_spin_init() @@ -3543,6 +4030,7 @@ extern "C" { * * F_busy (with error bit) if the spin is busy. * F_parameter (with error bit) if a parameter is invalid. + * * F_failure (with error bit) on any other error. * * @see pthread_spin_destroy() @@ -3566,6 +4054,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if max spin locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_spin_lock() */ #ifndef _di_f_thread_spin_lock_ @@ -3589,6 +4079,8 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_resource_not (with error bit) if max spin locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_spin_trylock() */ #ifndef _di_f_thread_spin_lock_try_ @@ -3608,6 +4100,8 @@ extern "C" { * F_prohibited (with error bit) if not allowed to perform the operation (possibly because spin is not owned by current thread). * F_resource_not (with error bit) if max spin locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_spin_unlock() */ #ifndef _di_f_thread_spin_unlock_ @@ -3713,9 +4207,9 @@ extern "C" { * F_none on success. * F_data_not on success, but there is no reason to increase size (used + amount <= size). * + * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. */ #ifndef _di_f_thread_spins_increase_by_ extern f_status_t f_thread_spins_increase_by(const f_array_length_t amount, f_thread_spins_t *spins); @@ -3752,6 +4246,8 @@ extern "C" { * F_prohibited (with error bit) if not allowed to perform the operation (possibly because lock is not owned by current thread). * F_resource_not (with error bit) if max lock locks is reached. * + * F_failure (with error bit) on any other error. + * * @see pthread_rwlock_unlock() */ #ifndef _di_f_thread_unlock_ diff --git a/level_0/f_thread/data/build/dependencies b/level_0/f_thread/data/build/dependencies index 66dca29..d798245 100644 --- a/level_0/f_thread/data/build/dependencies +++ b/level_0/f_thread/data/build/dependencies @@ -3,3 +3,4 @@ f_type f_status f_memory +f_string diff --git a/level_0/f_thread/data/build/settings b/level_0/f_thread/data/build/settings index 204bc1a..351bfb4 100644 --- a/level_0/f_thread/data/build/settings +++ b/level_0/f_thread/data/build/settings @@ -19,7 +19,7 @@ build_compiler gcc build_indexer ar build_language c build_libraries -pthread -lc -build_libraries-individual -lf_memory +build_libraries-individual -lf_memory -lf_string build_sources_library thread.c private-thread.c build_sources_program build_sources_headers thread.h thread-common.h -- 1.8.3.1