From defa529cb026735ef981bdc1fa44c71f4880c552 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 8 Feb 2021 21:57:05 -0600 Subject: [PATCH] Update: remaining thread functions and add f_recover (and f_recover_not) status codes. Implement the remaining POSIX thread functions that I am aware of. I took a break in the middle of writing some of this so I expect there may be some mistakes resulting from such an interrupt. I do not feel like focusing on this now and will address any problems as I discover them. --- level_0/f_status/c/status.h | 2 + level_0/f_thread/c/private-thread.c | 375 +++++ level_0/f_thread/c/private-thread.h | 448 ++++++ level_0/f_thread/c/thread-common.h | 194 ++- level_0/f_thread/c/thread.c | 2014 +++++++++++++++++++++----- level_0/f_thread/c/thread.h | 2738 ++++++++++++++++++++++++++++------- level_1/fl_status/c/status.c | 6 + level_1/fl_status/c/status.h | 4 + level_2/fll_status/c/status.c | 10 + 9 files changed, 4931 insertions(+), 860 deletions(-) diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index f54aa8c..279a3c6 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -249,6 +249,8 @@ extern "C" { F_read_only, F_ready, F_ready_not, + F_recover, + F_recover_not, F_recurse, F_recurse_not, F_relative, diff --git a/level_0/f_thread/c/private-thread.c b/level_0/f_thread/c/private-thread.c index e808662..7eb0ec9 100644 --- a/level_0/f_thread/c/private-thread.c +++ b/level_0/f_thread/c/private-thread.c @@ -66,6 +66,128 @@ extern "C" { } #endif // !defined(_di_f_thread_attributes_decrease_) || !defined(_di_f_thread_attributes_decrease_by_) || !defined(_di_f_thread_attributes_increase_) || !defined(_di_f_thread_attributes_increase_by_) +#if !defined(_di_f_thread_barriers_adjust_) || !defined(_di_f_thread_barriers_decimate_by_) || !defined(_di_f_thread_barriers_decrease_) || !defined(_di_f_thread_barriers_decrease_by_) || !defined(_di_f_thread_barriers_increase_) || !defined(_di_f_thread_barriers_increase_by_) || !defined(_di_f_thread_barriers_resize_) + f_status_t private_f_thread_barrier_delete(f_thread_barrier_t *barrier) { + + if (pthread_barrier_destroy(barrier)) { + return F_status_set_error(F_failure); + } + + barrier = 0; + + return F_none; + } +#endif // !defined(_di_f_thread_barriers_adjust_) || !defined(_di_f_thread_barriers_decimate_by_) || !defined(_di_f_thread_barriers_decrease_) || !defined(_di_f_thread_barriers_decrease_by_) || !defined(_di_f_thread_barriers_increase_) || !defined(_di_f_thread_barriers_increase_by_) || !defined(_di_f_thread_barriers_resize_) + +#if !defined(_di_f_thread_barriers_adjust_) || !defined(_di_f_thread_barriers_decimate_by_) + f_status_t private_f_thread_barriers_adjust(const f_array_length_t length, f_thread_barriers_t *barriers) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < barriers->size; ++i) { + + status = private_f_thread_barrier_delete(&barriers->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_adjust(barriers->size, length, sizeof(f_thread_barrier_t), (void **) & barriers->array); + + if (F_status_is_error_not(status)) { + barriers->size = length; + + if (barriers->used > barriers->size) { + barriers->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_barriers_adjust_) || !defined(_di_f_thread_barriers_decimate_by_) + +#if !defined(_di_f_thread_barriers_decrease_) || !defined(_di_f_thread_barriers_decrease_by_) || !defined(_di_f_thread_barriers_increase_) || !defined(_di_f_thread_barriers_increase_by_) + f_status_t private_f_thread_barriers_resize(const f_array_length_t length, f_thread_barriers_t *barriers) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < barriers->size; ++i) { + + status = private_f_thread_barrier_delete(&barriers->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_resize(barriers->size, length, sizeof(f_thread_barrier_t), (void **) & barriers->array); + + if (F_status_is_error_not(status)) { + barriers->size = length; + + if (barriers->used > barriers->size) { + barriers->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_barriers_decrease_) || !defined(_di_f_thread_barriers_decrease_by_) || !defined(_di_f_thread_barriers_increase_) || !defined(_di_f_thread_barriers_increase_by_) + +#if !defined(_di_f_thread_barrier_attributes_adjust_) || !defined(_di_f_thread_barrier_attributes_decimate_by_) || !defined(_di_f_thread_barrier_attributes_decrease_) || !defined(_di_f_thread_barrier_attributes_decrease_by_) || !defined(_di_f_thread_barrier_attributes_increase_) || !defined(_di_f_thread_barrier_attributes_increase_by_) || !defined(_di_f_thread_barrier_attributes_resize_) + f_status_t private_f_thread_barrier_attribute_delete(f_thread_barrier_attribute_t *attribute) { + + if (pthread_barrierattr_destroy(attribute)) { + return F_status_set_error(F_failure); + } + + attribute = 0; + + return F_none; + } +#endif // !defined(_di_f_thread_barrier_attributes_adjust_) || !defined(_di_f_thread_barrier_attributes_decimate_by_) || !defined(_di_f_thread_barrier_attributes_decrease_) || !defined(_di_f_thread_barrier_attributes_decrease_by_) || !defined(_di_f_thread_barrier_attributes_increase_) || !defined(_di_f_thread_barrier_attributes_increase_by_) || !defined(_di_f_thread_barrier_attributes_resize_) + +#if !defined(_di_f_thread_barrier_attributes_adjust_) || !defined(_di_f_thread_barrier_attributes_decimate_by_) + f_status_t private_f_thread_barrier_attributes_adjust(const f_array_length_t length, f_thread_barrier_attributes_t *attributes) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < attributes->size; ++i) { + + status = private_f_thread_barrier_attribute_delete(&attributes->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_adjust(attributes->size, length, sizeof(f_thread_barrier_attribute_t), (void **) & attributes->array); + + if (F_status_is_error_not(status)) { + attributes->size = length; + + if (attributes->used > attributes->size) { + attributes->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_barrier_attributes_adjust_) || !defined(_di_f_thread_barrier_attributes_decimate_by_) + +#if !defined(_di_f_thread_barrier_attributes_decrease_) || !defined(_di_f_thread_barrier_attributes_decrease_by_) || !defined(_di_f_thread_barrier_attributes_increase_) || !defined(_di_f_thread_barrier_attributes_increase_by_) + f_status_t private_f_thread_barrier_attributes_resize(const f_array_length_t length, f_thread_barrier_attributes_t *attributes) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < attributes->size; ++i) { + + status = private_f_thread_barrier_attribute_delete(&attributes->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_resize(attributes->size, length, sizeof(f_thread_barrier_attribute_t), (void **) & attributes->array); + + if (F_status_is_error_not(status)) { + attributes->size = length; + + if (attributes->used > attributes->size) { + attributes->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_barrier_attributes_decrease_) || !defined(_di_f_thread_barrier_attributes_decrease_by_) || !defined(_di_f_thread_barrier_attributes_increase_) || !defined(_di_f_thread_barrier_attributes_increase_by_) + #if !defined(_di_f_thread_condition_attributes_adjust_) || !defined(_di_f_thread_condition_attributes_decimate_by_) || !defined(_di_f_thread_condition_attributes_decrease_) || !defined(_di_f_thread_condition_attributes_decrease_by_) || !defined(_di_f_thread_condition_attributes_increase_) || !defined(_di_f_thread_condition_attributes_increase_by_) || !defined(_di_f_thread_condition_attributes_resize_) f_status_t private_f_thread_condition_attribute_delete(f_thread_condition_attribute_t *attribute) { @@ -194,6 +316,195 @@ extern "C" { } #endif // !defined(_di_f_thread_conditions_decrease_) || !defined(_di_f_thread_conditions_decrease_by_) || !defined(_di_f_thread_conditions_increase_) || !defined(_di_f_thread_conditions_increase_by_) +#if !defined(_di_f_thread_keys_adjust_) || !defined(_di_f_thread_keys_decimate_by_) || !defined(_di_f_thread_keys_decrease_) || !defined(_di_f_thread_keys_decrease_by_) || !defined(_di_f_thread_keys_increase_) || !defined(_di_f_thread_keys_increase_by_) || !defined(_di_f_thread_keys_resize_) + f_status_t private_f_thread_key_delete(f_thread_key_t *key) { + + if (pthread_key_delete(*key)) { + return F_status_set_error(F_failure); + } + + key = 0; + + return F_none; + } +#endif // !defined(_di_f_thread_keys_adjust_) || !defined(_di_f_thread_keys_decimate_by_) || !defined(_di_f_thread_keys_decrease_) || !defined(_di_f_thread_keys_decrease_by_) || !defined(_di_f_thread_keys_increase_) || !defined(_di_f_thread_keys_increase_by_) || !defined(_di_f_thread_keys_resize_) + +#if !defined(_di_f_thread_keys_adjust_) || !defined(_di_f_thread_keys_decimate_by_) + f_status_t private_f_thread_keys_adjust(const f_array_length_t length, f_thread_keys_t *keys) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < keys->size; ++i) { + + status = private_f_thread_key_delete(&keys->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_adjust(keys->size, length, sizeof(f_thread_key_t), (void **) & keys->array); + + if (F_status_is_error_not(status)) { + keys->size = length; + + if (keys->used > keys->size) { + keys->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_keys_adjust_) || !defined(_di_f_thread_keys_decimate_by_) + +#if !defined(_di_f_thread_keys_decrease_) || !defined(_di_f_thread_keys_decrease_by_) || !defined(_di_f_thread_keys_increase_) || !defined(_di_f_thread_keys_increase_by_) + f_status_t private_f_thread_keys_resize(const f_array_length_t length, f_thread_keys_t *keys) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < keys->size; ++i) { + + status = private_f_thread_key_delete(&keys->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_resize(keys->size, length, sizeof(f_thread_key_t), (void **) & keys->array); + + if (F_status_is_error_not(status)) { + keys->size = length; + + if (keys->used > keys->size) { + keys->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_keys_decrease_) || !defined(_di_f_thread_keys_decrease_by_) || !defined(_di_f_thread_keys_increase_) || !defined(_di_f_thread_keys_increase_by_) + +#if !defined(_di_f_thread_locks_adjust_) || !defined(_di_f_thread_locks_decimate_by_) || !defined(_di_f_thread_locks_decrease_) || !defined(_di_f_thread_locks_decrease_by_) || !defined(_di_f_thread_locks_increase_) || !defined(_di_f_thread_locks_increase_by_) || !defined(_di_f_thread_locks_resize_) + f_status_t private_f_thread_lock_delete(f_thread_lock_t *lock) { + + const int error = pthread_rwlock_destroy(lock); + + if (error) { + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_thread_locks_adjust_) || !defined(_di_f_thread_locks_decimate_by_) || !defined(_di_f_thread_locks_decrease_) || !defined(_di_f_thread_locks_decrease_by_) || !defined(_di_f_thread_locks_increase_) || !defined(_di_f_thread_locks_increase_by_) || !defined(_di_f_thread_locks_resize_) + +#if !defined(_di_f_thread_locks_adjust_) || !defined(_di_f_thread_locks_decimate_by_) + f_status_t private_f_thread_locks_adjust(const f_array_length_t length, f_thread_locks_t *locks) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < locks->size; ++i) { + + status = private_f_thread_lock_delete(&locks->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_adjust(locks->size, length, sizeof(f_thread_lock_t), (void **) & locks->array); + + if (F_status_is_error_not(status)) { + locks->size = length; + + if (locks->used > locks->size) { + locks->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_locks_adjust_) || !defined(_di_f_thread_locks_decimate_by_) + +#if !defined(_di_f_thread_locks_decrease_) || !defined(_di_f_thread_locks_decrease_by_) || !defined(_di_f_thread_locks_increase_) || !defined(_di_f_thread_locks_increase_by_) + f_status_t private_f_thread_locks_resize(const f_array_length_t length, f_thread_locks_t *locks) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < locks->size; ++i) { + + status = private_f_thread_lock_delete(&locks->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_resize(locks->size, length, sizeof(f_thread_lock_t), (void **) & locks->array); + + if (F_status_is_error_not(status)) { + locks->size = length; + + if (locks->used > locks->size) { + locks->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_locks_decrease_) || !defined(_di_f_thread_locks_decrease_by_) || !defined(_di_f_thread_locks_increase_) || !defined(_di_f_thread_locks_increase_by_) + +#if !defined(_di_f_thread_lock_attributes_adjust_) || !defined(_di_f_thread_lock_attributes_decimate_by_) || !defined(_di_f_thread_lock_attributes_decrease_) || !defined(_di_f_thread_lock_attributes_decrease_by_) || !defined(_di_f_thread_lock_attributes_increase_) || !defined(_di_f_thread_lock_attributes_increase_by_) || !defined(_di_f_thread_lock_attributes_resize_) + f_status_t private_f_thread_lock_attribute_delete(f_thread_lock_attribute_t *attribute) { + + const int error = pthread_rwlockattr_destroy(attribute); + + if (error) { + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_thread_lock_attributes_adjust_) || !defined(_di_f_thread_lock_attributes_decimate_by_) || !defined(_di_f_thread_lock_attributes_decrease_) || !defined(_di_f_thread_lock_attributes_decrease_by_) || !defined(_di_f_thread_lock_attributes_increase_) || !defined(_di_f_thread_lock_attributes_increase_by_) || !defined(_di_f_thread_lock_attributes_resize_) + +#if !defined(_di_f_thread_lock_attributes_adjust_) || !defined(_di_f_thread_lock_attributes_decimate_by_) + f_status_t private_f_thread_lock_attributes_adjust(const f_array_length_t length, f_thread_lock_attributes_t *attributes) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < attributes->size; ++i) { + + status = private_f_thread_lock_attribute_delete(&attributes->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_adjust(attributes->size, length, sizeof(f_thread_lock_t), (void **) & attributes->array); + + if (F_status_is_error_not(status)) { + attributes->size = length; + + if (attributes->used > attributes->size) { + attributes->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_lock_attributes_adjust_) || !defined(_di_f_thread_lock_attributes_decimate_by_) + +#if !defined(_di_f_thread_lock_attributes_decrease_) || !defined(_di_f_thread_lock_attributes_decrease_by_) || !defined(_di_f_thread_lock_attributes_increase_) || !defined(_di_f_thread_lock_attributes_increase_by_) + f_status_t private_f_thread_lock_attributes_resize(const f_array_length_t length, f_thread_lock_attributes_t *attributes) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < attributes->size; ++i) { + + status = private_f_thread_lock_attribute_delete(&attributes->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_resize(attributes->size, length, sizeof(f_thread_lock_t), (void **) & attributes->array); + + if (F_status_is_error_not(status)) { + attributes->size = length; + + if (attributes->used > attributes->size) { + attributes->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_lock_attributes_decrease_) || !defined(_di_f_thread_lock_attributes_decrease_by_) || !defined(_di_f_thread_lock_attributes_increase_) || !defined(_di_f_thread_lock_attributes_increase_by_) + #if !defined(_di_f_thread_mutex_attributes_adjust_) || !defined(_di_f_thread_mutex_attributes_decimate_by_) || !defined(_di_f_thread_mutex_attributes_decrease_) || !defined(_di_f_thread_mutex_attributes_decrease_by_) || !defined(_di_f_thread_mutex_attributes_increase_) || !defined(_di_f_thread_mutex_attributes_increase_by_) || !defined(_di_f_thread_mutex_attributes_resize_) f_status_t private_f_thread_mutex_attribute_delete(f_thread_mutex_attribute_t *attribute) { @@ -370,6 +681,70 @@ extern "C" { } #endif // !defined(_di_f_thread_sets_decrease_) || !defined(_di_f_thread_sets_decrease_by_) || !defined(_di_f_thread_sets_increase_) || !defined(_di_f_thread_sets_increase_by_) +#if !defined(_di_f_thread_spins_adjust_) || !defined(_di_f_thread_spins_decimate_by_) || !defined(_di_f_thread_spins_decrease_) || !defined(_di_f_thread_spins_decrease_by_) || !defined(_di_f_thread_spins_increase_) || !defined(_di_f_thread_spins_increase_by_) || !defined(_di_f_thread_spins_resize_) + f_status_t private_f_thread_spin_delete(f_thread_spin_t *spin) { + + const int error = pthread_spin_destroy(spin); + + if (error) { + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_thread_spins_adjust_) || !defined(_di_f_thread_spins_decimate_by_) || !defined(_di_f_thread_spins_decrease_) || !defined(_di_f_thread_spins_decrease_by_) || !defined(_di_f_thread_spins_increase_) || !defined(_di_f_thread_spins_increase_by_) || !defined(_di_f_thread_spins_resize_) + +#if !defined(_di_f_thread_spins_adjust_) || !defined(_di_f_thread_spins_decimate_by_) + f_status_t private_f_thread_spins_adjust(const f_array_length_t length, f_thread_spins_t *spins) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < spins->size; ++i) { + + status = private_f_thread_spin_delete(&spins->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_adjust(spins->size, length, sizeof(f_thread_spin_t), (void **) & spins->array); + + if (F_status_is_error_not(status)) { + spins->size = length; + + if (spins->used > spins->size) { + spins->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_spins_adjust_) || !defined(_di_f_thread_spins_decimate_by_) + +#if !defined(_di_f_thread_spins_decrease_) || !defined(_di_f_thread_spins_decrease_by_) || !defined(_di_f_thread_spins_increase_) || !defined(_di_f_thread_spins_increase_by_) + f_status_t private_f_thread_spins_resize(const f_array_length_t length, f_thread_spins_t *spins) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < spins->size; ++i) { + + status = private_f_thread_spin_delete(&spins->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_resize(spins->size, length, sizeof(f_thread_spin_t), (void **) & spins->array); + + if (F_status_is_error_not(status)) { + spins->size = length; + + if (spins->used > spins->size) { + spins->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_spins_decrease_) || !defined(_di_f_thread_spins_decrease_by_) || !defined(_di_f_thread_spins_increase_) || !defined(_di_f_thread_spins_increase_by_) + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_thread/c/private-thread.h b/level_0/f_thread/c/private-thread.h index a7340ee..e917e9b 100644 --- a/level_0/f_thread/c/private-thread.h +++ b/level_0/f_thread/c/private-thread.h @@ -105,6 +105,158 @@ extern "C" { * * @param length * The new size to use. + * @param barriers + * The barriers to adjust. + * + * @return + * F_none on success. + * + * F_failure (with error bit) on error. + * + * @see pthread_attr_destroy() + * + * @see f_thread_barriers_adjust() + * @see f_thread_barriers_decimate_by() + * @see f_thread_barriers_decrease() + * @see f_thread_barriers_decrease_by() + * @see f_thread_barriers_increase() + * @see f_thread_barriers_increase_by() + * @see f_thread_barriers_resize() + */ +#if !defined(_di_f_thread_barriers_adjust_) || !defined(_di_f_thread_barriers_decimate_by_) || !defined(_di_f_thread_barriers_decrease_) || !defined(_di_f_thread_barriers_decrease_by_) || !defined(_di_f_thread_barriers_increase_) || !defined(_di_f_thread_barriers_increase_by_) || !defined(_di_f_thread_barriers_resize_) + extern f_status_t private_f_thread_barrier_delete(f_thread_barrier_t *barrier) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_barriers_adjust_) || !defined(_di_f_thread_barriers_decimate_by_) || !defined(_di_f_thread_barriers_decrease_) || !defined(_di_f_thread_barriers_decrease_by_) || !defined(_di_f_thread_barriers_increase_) || !defined(_di_f_thread_barriers_increase_by_) || !defined(_di_f_thread_barriers_resize_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param barriers + * The barriers to adjust. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_memory_adjust() + * @see f_thread_barriers_adjust() + * @see f_thread_barriers_decimate_by() + */ +#if !defined(_di_f_thread_barriers_adjust_) || !defined(_di_f_thread_barriers_decimate_by_) + extern f_status_t private_f_thread_barriers_adjust(const f_array_length_t length, f_thread_barriers_t *barriers) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_barriers_adjust_) || !defined(_di_f_thread_barriers_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 barriers + * The barriers to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_thread_barriers_decrease_by() + * @see f_thread_barriers_increase() + * @see f_thread_barriers_increase_by() + */ +#if !defined(_di_f_thread_barriers_decrease_by_) || !defined(_di_f_thread_barriers_increase_) || !defined(_di_f_thread_barriers_increase_by_) + extern f_status_t private_f_thread_barriers_resize(const f_array_length_t length, f_thread_barriers_t *barriers) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_barriers_decrease_by_) || !defined(_di_f_thread_barriers_increase_) || !defined(_di_f_thread_barriers_increase_by_) + +/** + * Private implementation for deleting (and destroying). + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param attributes + * The attributes to adjust. + * + * @return + * F_none on success. + * + * F_failure (with error bit) on error. + * + * @see pthread_attr_destroy() + * + * @see f_thread_barrier_attributes_adjust() + * @see f_thread_barrier_attributes_decimate_by() + * @see f_thread_barrier_attributes_decrease() + * @see f_thread_barrier_attributes_decrease_by() + * @see f_thread_barrier_attributes_increase() + * @see f_thread_barrier_attributes_increase_by() + * @see f_thread_barrier_attributes_resize() + */ +#if !defined(_di_f_thread_barrier_attributes_adjust_) || !defined(_di_f_thread_barrier_attributes_decimate_by_) || !defined(_di_f_thread_barrier_attributes_decrease_) || !defined(_di_f_thread_barrier_attributes_decrease_by_) || !defined(_di_f_thread_barrier_attributes_increase_) || !defined(_di_f_thread_barrier_attributes_increase_by_) || !defined(_di_f_thread_barrier_attributes_resize_) + extern f_status_t private_f_thread_barrier_attribute_delete(f_thread_barrier_attribute_t *attribute) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_barrier_attributes_adjust_) || !defined(_di_f_thread_barrier_attributes_decimate_by_) || !defined(_di_f_thread_barrier_attributes_decrease_) || !defined(_di_f_thread_barrier_attributes_decrease_by_) || !defined(_di_f_thread_barrier_attributes_increase_) || !defined(_di_f_thread_barrier_attributes_increase_by_) || !defined(_di_f_thread_barrier_attributes_resize_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param attributes + * The attributes to adjust. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_memory_adjust() + * @see f_thread_barrier_attributes_adjust() + * @see f_thread_barrier_attributes_decimate_by() + */ +#if !defined(_di_f_thread_barrier_attributes_adjust_) || !defined(_di_f_thread_barrier_attributes_decimate_by_) + extern f_status_t private_f_thread_barrier_attributes_adjust(const f_array_length_t length, f_thread_barrier_attributes_t *attributes) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_barrier_attributes_adjust_) || !defined(_di_f_thread_barrier_attributes_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 attributes + * The attributes to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_thread_barrier_attributes_decrease_by() + * @see f_thread_barrier_attributes_increase() + * @see f_thread_barrier_attributes_increase_by() + */ +#if !defined(_di_f_thread_barrier_attributes_decrease_by_) || !defined(_di_f_thread_barrier_attributes_increase_) || !defined(_di_f_thread_barrier_attributes_increase_by_) + extern f_status_t private_f_thread_barrier_attributes_resize(const f_array_length_t length, f_thread_barrier_attributes_t *attributes) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_barrier_attributes_decrease_by_) || !defined(_di_f_thread_barrier_attributes_increase_) || !defined(_di_f_thread_barrier_attributes_increase_by_) + +/** + * Private implementation for deleting (and destroying). + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. * @param attribute * The attribute to adjust. * @@ -255,6 +407,228 @@ extern "C" { * * Intended to be shared to each of the different implementation variations. * + * @param key + * The keys to delete. + * + * @return + * F_none on success. + * + * F_failure (with error bit) on error. + * + * @see pthread_key_destroy() + * + * @see f_thread_keys_adjust() + * @see f_thread_keys_decimate_by() + * @see f_thread_keys_decrease() + * @see f_thread_keys_decrease_by() + * @see f_thread_keys_increase() + * @see f_thread_keys_increase_by() + * @see f_thread_keys_resize() + */ +#if !defined(_di_f_thread_keys_adjust_) || !defined(_di_f_thread_keys_decimate_by_) || !defined(_di_f_thread_keys_decrease_) || !defined(_di_f_thread_keys_decrease_by_) || !defined(_di_f_thread_keys_increase_) || !defined(_di_f_thread_keys_increase_by_) || !defined(_di_f_thread_keys_resize_) + extern f_status_t private_f_thread_key_delete(f_thread_key_t *key) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_keys_adjust_) || !defined(_di_f_thread_keys_decimate_by_) || !defined(_di_f_thread_keys_decrease_) || !defined(_di_f_thread_keys_decrease_by_) || !defined(_di_f_thread_keys_increase_) || !defined(_di_f_thread_keys_increase_by_) || !defined(_di_f_thread_keys_resize_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param keys + * The keys to adjust. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_memory_adjust() + * @see f_thread_keys_adjust() + * @see f_thread_keys_decimate_by() + */ +#if !defined(_di_f_thread_keys_adjust_) || !defined(_di_f_thread_keys_decimate_by_) + extern f_status_t private_f_thread_keys_adjust(const f_array_length_t length, f_thread_keys_t *keys) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_keys_adjust_) || !defined(_di_f_thread_keys_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 keys + * The keys to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_thread_keys_decrease_by() + * @see f_thread_keys_increase() + * @see f_thread_keys_increase_by() + */ +#if !defined(_di_f_thread_keys_decrease_by_) || !defined(_di_f_thread_keys_increase_) || !defined(_di_f_thread_keys_increase_by_) + extern f_status_t private_f_thread_keys_resize(const f_array_length_t length, f_thread_keys_t *keys) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_keys_decrease_by_) || !defined(_di_f_thread_keys_increase_) || !defined(_di_f_thread_keys_increase_by_) + +/** + * Private implementation for deleting (and destroying). + * + * Intended to be shared to each of the different implementation variations. + * + * @param lock + * The locks to delete. + * + * @return + * F_none on success. + * + * F_failure (with error bit) on error. + * + * @see pthread_rwlock_destroy() + * + * @see f_thread_locks_adjust() + * @see f_thread_locks_decimate_by() + * @see f_thread_locks_decrease() + * @see f_thread_locks_decrease_by() + * @see f_thread_locks_increase() + * @see f_thread_locks_increase_by() + * @see f_thread_locks_resize() + */ +#if !defined(_di_f_thread_locks_adjust_) || !defined(_di_f_thread_locks_decimate_by_) || !defined(_di_f_thread_locks_decrease_) || !defined(_di_f_thread_locks_decrease_by_) || !defined(_di_f_thread_locks_increase_) || !defined(_di_f_thread_locks_increase_by_) || !defined(_di_f_thread_locks_resize_) + extern f_status_t private_f_thread_lock_delete(f_thread_lock_t *lock) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_locks_adjust_) || !defined(_di_f_thread_locks_decimate_by_) || !defined(_di_f_thread_locks_decrease_) || !defined(_di_f_thread_locks_decrease_by_) || !defined(_di_f_thread_locks_increase_) || !defined(_di_f_thread_locks_increase_by_) || !defined(_di_f_thread_locks_resize_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param locks + * The locks to adjust. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_memory_adjust() + * @see f_thread_locks_adjust() + * @see f_thread_locks_decimate_by() + */ +#if !defined(_di_f_thread_locks_adjust_) || !defined(_di_f_thread_locks_decimate_by_) + extern f_status_t private_f_thread_locks_adjust(const f_array_length_t length, f_thread_locks_t *locks) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_locks_adjust_) || !defined(_di_f_thread_locks_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 locks + * The locks to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_thread_locks_decrease_by() + * @see f_thread_locks_increase() + * @see f_thread_locks_increase_by() + */ +#if !defined(_di_f_thread_locks_decrease_by_) || !defined(_di_f_thread_locks_increase_) || !defined(_di_f_thread_locks_increase_by_) + extern f_status_t private_f_thread_locks_resize(const f_array_length_t length, f_thread_locks_t *locks) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_locks_decrease_by_) || !defined(_di_f_thread_locks_increase_) || !defined(_di_f_thread_locks_increase_by_) + +/** + * Private implementation for deleting (and destroying). + * + * Intended to be shared to each of the different implementation variations. + * + * @param attribute + * The attribute to delete. + * + * @return + * F_none on success. + * + * F_failure (with error bit) on error. + * + * @see pthread_rwlockattr_destroy() + * + * @see f_thread_lock_attributes_adjust() + * @see f_thread_lock_attributes_decimate_by() + * @see f_thread_lock_attributes_decrease() + * @see f_thread_lock_attributes_decrease_by() + * @see f_thread_lock_attributes_increase() + * @see f_thread_lock_attributes_increase_by() + * @see f_thread_lock_attributes_resize() + */ +#if !defined(_di_f_thread_lock_attributes_adjust_) || !defined(_di_f_thread_lock_attributes_decimate_by_) || !defined(_di_f_thread_lock_attributes_decrease_) || !defined(_di_f_thread_lock_attributes_decrease_by_) || !defined(_di_f_thread_lock_attributes_increase_) || !defined(_di_f_thread_lock_attributes_increase_by_) || !defined(_di_f_thread_lock_attributes_resize_) + extern f_status_t private_f_thread_lock_attribute_delete(f_thread_lock_attribute_t *attribute) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_lock_attributes_adjust_) || !defined(_di_f_thread_lock_attributes_decimate_by_) || !defined(_di_f_thread_lock_attributes_decrease_) || !defined(_di_f_thread_lock_attributes_decrease_by_) || !defined(_di_f_thread_lock_attributes_increase_) || !defined(_di_f_thread_lock_attributes_increase_by_) || !defined(_di_f_thread_lock_attributes_resize_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param attributes + * The attributes to adjust. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_memory_adjust() + * @see f_thread_lock_attributes_adjust() + * @see f_thread_lock_attributes_decimate_by() + */ +#if !defined(_di_f_thread_lock_attributes_adjust_) || !defined(_di_f_thread_lock_attributes_decimate_by_) + extern f_status_t private_f_thread_lock_attributes_adjust(const f_array_length_t length, f_thread_lock_attributes_t *attributes) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_lock_attributes_adjust_) || !defined(_di_f_thread_lock_attributes_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 attributes + * The attributes to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_thread_lock_attributes_decrease_by() + * @see f_thread_lock_attributes_increase() + * @see f_thread_lock_attributes_increase_by() + */ +#if !defined(_di_f_thread_lock_attributes_decrease_by_) || !defined(_di_f_thread_lock_attributes_increase_) || !defined(_di_f_thread_lock_attributes_increase_by_) + extern f_status_t private_f_thread_lock_attributes_resize(const f_array_length_t length, f_thread_lock_attributes_t *attributes) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_lock_attributes_decrease_by_) || !defined(_di_f_thread_lock_attributes_increase_) || !defined(_di_f_thread_lock_attributes_increase_by_) + +/** + * Private implementation for deleting (and destroying). + * + * Intended to be shared to each of the different implementation variations. + * * @param attribute * The attribute to delete. * @@ -445,6 +819,80 @@ extern "C" { extern f_status_t private_f_thread_sets_resize(const f_array_length_t length, f_thread_sets_t *sets) f_gcc_attribute_visibility_internal; #endif // !defined(_di_f_thread_sets_decrease_by_) || !defined(_di_f_thread_sets_increase_) || !defined(_di_f_thread_sets_increase_by_) +/** + * Private implementation for deleting (and destroying). + * + * Intended to be shared to each of the different implementation variations. + * + * @param spin + * The spins to delete. + * + * @return + * F_none on success. + * + * F_failure (with error bit) on error. + * + * @see pthread_spin_destroy() + * + * @see f_thread_spins_adjust() + * @see f_thread_spins_decimate_by() + * @see f_thread_spins_decrease() + * @see f_thread_spins_decrease_by() + * @see f_thread_spins_increase() + * @see f_thread_spins_increase_by() + * @see f_thread_spins_resize() + */ +#if !defined(_di_f_thread_spins_adjust_) || !defined(_di_f_thread_spins_decimate_by_) || !defined(_di_f_thread_spins_decrease_) || !defined(_di_f_thread_spins_decrease_by_) || !defined(_di_f_thread_spins_increase_) || !defined(_di_f_thread_spins_increase_by_) || !defined(_di_f_thread_spins_resize_) + extern f_status_t private_f_thread_spin_delete(f_thread_spin_t *spin) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_spins_adjust_) || !defined(_di_f_thread_spins_decimate_by_) || !defined(_di_f_thread_spins_decrease_) || !defined(_di_f_thread_spins_decrease_by_) || !defined(_di_f_thread_spins_increase_) || !defined(_di_f_thread_spins_increase_by_) || !defined(_di_f_thread_spins_resize_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param spins + * The spins to adjust. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_memory_adjust() + * @see f_thread_spins_adjust() + * @see f_thread_spins_decimate_by() + */ +#if !defined(_di_f_thread_spins_adjust_) || !defined(_di_f_thread_spins_decimate_by_) + extern f_status_t private_f_thread_spins_adjust(const f_array_length_t length, f_thread_spins_t *spins) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_spins_adjust_) || !defined(_di_f_thread_spins_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 spins + * The spins to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_thread_spins_decrease_by() + * @see f_thread_spins_increase() + * @see f_thread_spins_increase_by() + */ +#if !defined(_di_f_thread_spins_decrease_by_) || !defined(_di_f_thread_spins_increase_) || !defined(_di_f_thread_spins_increase_by_) + extern f_status_t private_f_thread_spins_resize(const f_array_length_t length, f_thread_spins_t *spins) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_spins_decrease_by_) || !defined(_di_f_thread_spins_increase_) || !defined(_di_f_thread_spins_increase_by_) + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_thread/c/thread-common.h b/level_0/f_thread/c/thread-common.h index 7f445d7..68d5160 100644 --- a/level_0/f_thread/c/thread-common.h +++ b/level_0/f_thread/c/thread-common.h @@ -62,6 +62,94 @@ extern "C" { #endif // _di_f_thread_attributes_t_ /** + * A typedef representing pthread_barrier_t. + */ +#ifndef _di_f_thread_barrier_t_ + typedef pthread_barrier_t f_thread_barrier_t; + + #define f_thread_barrier_t_initialize { 0 } + + #define f_macro_thread_barrier_t_clear(barrier) barrier = 0 + + #define f_macro_thread_barrier_t_delete_simple(barrier) f_thread_barrier_delete(&barrier); +#endif // _di_f_thread_barrier_t_ + +/** + * An array of f_thread_barrier_t. + * + * array: the array of f_thread_barrier_t. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_f_thread_barriers_t_ + typedef struct { + f_thread_barrier_t *array; + + f_array_length_t size; + f_array_length_t used; + } f_thread_barriers_t; + + #define f_thread_barriers_t_initialize { 0, 0, 0 } + + #define f_macro_thread_barriers_t_clear(barriers) f_macro_memory_structure_clear(barriers) + + #define f_macro_thread_barriers_t_resize(status, barriers, length) status = f_thread_barriers_resize(length, &barriers); + #define f_macro_thread_barriers_t_adjust(status, barriers, length) status = f_thread_barriers_adjust(length, &barriers); + + #define f_macro_thread_barriers_t_delete_simple(barriers) f_thread_barriers_resize(0, &barriers); + #define f_macro_thread_barriers_t_destroy_simple(barriers) f_thread_barriers_adjust(0, &barriers); + + #define f_macro_thread_barriers_t_increase(status, barriers) status = f_thread_barriers_increase(barriers); + #define f_macro_thread_barriers_t_increase_by(status, barriers, amount) status = f_thread_barriers_increase_by(amount, barriers); + #define f_macro_thread_barriers_t_decrease_by(status, barriers, amount) status = f_thread_barriers_decrease_by(amount, barriers); + #define f_macro_thread_barriers_t_decimate_by(status, barriers, amount) status = f_thread_barriers_decimate_by(amount, barriers); +#endif // _di_f_thread_barriers_t_ + +/** + * A typedef representing pthread_barrierattr_t. + */ +#ifndef _di_f_thread_barrier_attribute_t_ + typedef pthread_barrierattr_t f_thread_barrier_attribute_t; + + #define f_thread_barrier_attribute_t_initialize { 0 } + + #define f_macro_thread_barrier_attribute_t_clear(barrier_attribute) barrier_attribute = 0 + + #define f_macro_thread_barrier_attribute_t_delete_simple(barrier_attribute) f_thread_barrier_attribute_delete(&barrier_attribute); +#endif // _di_f_thread_barrier_attribute_t_ + +/** + * An array of f_thread_barrier_attribute_t. + * + * array: the array of f_thread_barrier_attribute_t. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_f_thread_barrier_attributes_t_ + typedef struct { + f_thread_barrier_attribute_t *array; + + f_array_length_t size; + f_array_length_t used; + } f_thread_barrier_attributes_t; + + #define f_thread_barrier_attributes_t_initialize { 0, 0, 0 } + + #define f_macro_thread_barrier_attributes_t_clear(barrier_attributes) f_macro_memory_structure_clear(barrier_attributes) + + #define f_macro_thread_barrier_attributes_t_resize(status, barrier_attributes, length) status = f_thread_barrier_attributes_resize(length, &barrier_attributes); + #define f_macro_thread_barrier_attributes_t_adjust(status, barrier_attributes, length) status = f_thread_barrier_attributes_adjust(length, &barrier_attributes); + + #define f_macro_thread_barrier_attributes_t_delete_simple(barrier_attributes) f_thread_barrier_attributes_resize(0, &barrier_attributes); + #define f_macro_thread_barrier_attributes_t_destroy_simple(barrier_attributes) f_thread_barrier_attributes_adjust(0, &barrier_attributes); + + #define f_macro_thread_barrier_attributes_t_increase(status, barrier_attributes) status = f_thread_barrier_attributes_increase(barrier_attributes); + #define f_macro_thread_barrier_attributes_t_increase_by(status, barrier_attributes, amount) status = f_thread_barrier_attributes_increase_by(amount, barrier_attributes); + #define f_macro_thread_barrier_attributes_t_decrease_by(status, barrier_attributes, amount) status = f_thread_barrier_attributes_decrease_by(amount, barrier_attributes); + #define f_macro_thread_barrier_attributes_t_decimate_by(status, barrier_attributes, amount) status = f_thread_barrier_attributes_decimate_by(amount, barrier_attributes); +#endif // _di_f_thread_barrier_attributes_t_ + +/** * A typedef representing pthread_cond_t. */ #ifndef _di_f_thread_condition_t_ @@ -198,6 +286,8 @@ extern "C" { #define f_thread_key_t_initialize 0 #define f_macro_thread_key_t_clear(key) key = 0 + + #define f_macro_thread_key_t_delete_simple(key) f_thread_key_delete(&key); #endif // _di_f_thread_key_t_ /** @@ -217,16 +307,18 @@ extern "C" { #define f_thread_keys_t_initialize { 0, 0, 0 } - #define f_macro_thread_keys_t_resize(status, keys, length) f_macro_memory_structure_resize(status, keys, f_thread_key_t, length) - #define f_macro_thread_keys_t_adjust(status, keys, length) f_macro_memory_structure_adjust(status, keys, f_thread_key_t, length) + #define f_macro_thread_keys_t_clear(keys) f_macro_memory_structure_clear(keys) - #define f_macro_thread_keys_t_delete_simple(keys) f_macro_memory_structure_delete_simple(keys, f_thread_key_t) - #define f_macro_thread_keys_t_destroy_simple(keys) f_macro_memory_structure_destroy_simple(keys, f_thread_key_t) + #define f_macro_thread_keys_t_resize(status, keys, length) status = f_thread_keys_resize(length, &keys); + #define f_macro_thread_keys_t_adjust(status, keys, length) status = f_thread_keys_adjust(length, &keys); - #define f_macro_thread_keys_t_increase(status, keys) f_macro_memory_structure_increase(status, keys, f_thread_key_t) - #define f_macro_thread_keys_t_increase_by(status, keys, amount) f_macro_memory_structure_increase_by(status, keys, f_thread_key_t, amount) - #define f_macro_thread_keys_t_decrease_by(status, keys, amount) f_macro_memory_structure_decrease_by(status, keys, f_thread_key_t, amount) - #define f_macro_thread_keys_t_decimate_by(status, keys, amount) f_macro_memory_structure_decimate_by(status, keys, f_thread_key_t, amount) + #define f_macro_thread_keys_t_delete_simple(keys) f_thread_keys_resize(0, &keys); + #define f_macro_thread_keys_t_destroy_simple(keys) f_thread_keys_adjust(0, &keys); + + #define f_macro_thread_keys_t_increase(status, keys) status = f_thread_keys_increase(keys); + #define f_macro_thread_keys_t_increase_by(status, keys, amount) status = f_thread_keys_increase_by(amount, keys); + #define f_macro_thread_keys_t_decrease_by(status, keys, amount) status = f_thread_keys_decrease_by(amount, keys); + #define f_macro_thread_keys_t_decimate_by(status, keys, amount) status = f_thread_keys_decimate_by(amount, keys); #endif // _di_f_thread_keys_t_ /** @@ -270,6 +362,48 @@ extern "C" { #endif // _di_f_thread_locks_t_ /** + * A typedef representing pthread_rwlockattr_t. + */ +#ifndef _di_f_thread_lock_attribute_t_ + typedef pthread_rwlockattr_t f_thread_lock_attribute_t; + + #define f_thread_lock_attribute_t_initialize 0 + + #define f_macro_thread_lock_attribute_t_clear(attribute) attribute = 0 +#endif // _di_f_thread_lock_attribute_t_ + +/** + * An array of read/write lock attributees. + * + * array: the array of f_thread_lock_attribute_t. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_f_thread_lock_attributes_t_ + typedef struct { + f_thread_lock_attribute_t *array; + + f_array_length_t size; + f_array_length_t used; + } f_thread_lock_attributes_t; + + #define f_thread_lock_attributes_t_initialize { 0, 0, 0 } + + #define f_macro_thread_lock_attributes_t_clear(attributes) f_macro_memory_structure_clear(attributes) + + #define f_macro_thread_lock_attributes_t_resize(status, attributes, length) status = f_thread_lock_attributes_resize(length, &attributes); + #define f_macro_thread_lock_attributes_t_adjust(status, attributes, length) status = f_thread_lock_attributes_adjust(length, &attributes); + + #define f_macro_thread_lock_attributes_t_delete_simple(attributes) f_thread_lock_attributes_resize(0, &attributes); + #define f_macro_thread_lock_attributes_t_destroy_simple(attributes) f_thread_lock_attributes_adjust(0, &attributes); + + #define f_macro_thread_lock_attributes_t_increase(status, attributes) status = f_thread_lock_attributes_increase(attributes); + #define f_macro_thread_lock_attributes_t_increase_by(status, attributes, amount) status = f_thread_lock_attributes_increase_by(amount, attributes); + #define f_macro_thread_lock_attributes_t_decrease_by(status, attributes, amount) status = f_thread_lock_attributes_decrease_by(amount, attributes); + #define f_macro_thread_lock_attributes_t_decimate_by(status, attributes, amount) status = f_thread_lock_attributes_decimate_by(amount, attributes); +#endif // _di_f_thread_lock_attributes_t_ + +/** * A typedef representing pthread_mutex_t. */ #ifndef _di_f_thread_mutex_t_ @@ -449,6 +583,50 @@ extern "C" { #define f_macro_thread_sets_t_decimate_by(status, sets, amount) status = f_thread_sets_decimate_by(amount, sets); #endif // _di_f_thread_sets_t_ +/** + * A typedef representing pthread_spinlock_t. + */ +#ifndef _di_f_thread_spin_t_ + typedef pthread_spinlock_t f_thread_spin_t; + + #define f_thread_spin_t_initialize PTHREAD_MUTEX_INITIALIZER + + #define f_macro_thread_spin_t_clear(spin) spin = 0 + + #define f_macro_thread_spin_t_delete_simple(spin) f_thread_spin_delete(&spin); +#endif // _di_f_thread_spin_t_ + +/** + * An array of thread spins. + * + * array: the array of f_thread_spin_t. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_f_thread_spins_t_ + typedef struct { + f_thread_spin_t *array; + + f_array_length_t size; + f_array_length_t used; + } f_thread_spins_t; + + #define f_thread_spins_t_initialize { 0, 0, 0 } + + #define f_macro_thread_spins_t_clear(spins) f_macro_memory_structure_clear(spins) + + #define f_macro_thread_spins_t_resize(status, spins, length) status = f_thread_spins_resize(length, &spins); + #define f_macro_thread_spins_t_adjust(status, spins, length) status = f_thread_spins_adjust(length, &spins); + + #define f_macro_thread_spins_t_delete_simple(spins) f_thread_spins_resize(0, &spins); + #define f_macro_thread_spins_t_destroy_simple(spins) f_thread_spins_adjust(0, &spins); + + #define f_macro_thread_spins_t_increase(status, spins) status = f_thread_spins_increase(spins); + #define f_macro_thread_spins_t_increase_by(status, spins, amount) status = f_thread_spins_increase_by(amount, spins); + #define f_macro_thread_spins_t_decrease_by(status, spins, amount) status = f_thread_spins_decrease_by(amount, spins); + #define f_macro_thread_spins_t_decimate_by(status, spins, amount) status = f_thread_spins_decimate_by(amount, spins); +#endif // _di_f_thread_spins_t_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_thread/c/thread.c b/level_0/f_thread/c/thread.c index 0295b95..7a43f65 100644 --- a/level_0/f_thread/c/thread.c +++ b/level_0/f_thread/c/thread.c @@ -62,6 +62,72 @@ extern "C" { } #endif // _di_f_thread_attribute_affinity_set_ +#ifndef _di_f_thread_attribute_clock_get_ + f_status_t f_thread_attribute_clock_get(const f_thread_condition_attribute_t *attribute, clockid_t *id) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + if (!id) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (pthread_condattr_getclock(attribute, id)) { + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_attribute_clock_get_ + +#ifndef _di_f_thread_attribute_clock_set_ + f_status_t f_thread_attribute_clock_set(const clockid_t id, f_thread_condition_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_condattr_setclock(attribute, id); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_attribute_clock_set_ + +#ifndef _di_f_thread_attribute_condition_shared_get_ + f_status_t f_thread_attribute_condition_shared_get(const f_thread_condition_attribute_t *attribute, int *shared) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + if (!shared) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (pthread_condattr_getpshared(attribute, shared)) { + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_attribute_condition_shared_get_ + +#ifndef _di_f_thread_attribute_condition_shared_set_ + f_status_t f_thread_attribute_condition_shared_set(const int shared, f_thread_condition_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_condattr_setpshared(attribute, shared); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_attribute_condition_shared_set_ + #ifndef _di_f_thread_attribute_create_ f_status_t f_thread_attribute_create(f_thread_attribute_t *attribute) { @@ -379,6 +445,40 @@ extern "C" { } #endif // _di_f_thread_attribute_stack_set_ +#ifndef _di_f_thread_attribute_stack_size_get_ + f_status_t f_thread_attribute_stack_size_get(const f_thread_attribute_t attribute, size_t *stack_size) { + #ifndef _di_level_0_parameter_checking_ + if (!stack_size) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_attr_getstacksize(&attribute, stack_size); + + if (error) { + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_attribute_stack_size_get_ + +#ifndef _di_f_thread_attribute_stack_size_set_ + f_status_t f_thread_attribute_stack_size_set(const size_t stack_size, f_thread_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_attr_setstacksize(attribute, stack_size); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_attribute_stack_size_set_ + #ifndef _di_f_thread_attributes_adjust_ f_status_t f_thread_attributes_adjust(const f_array_length_t length, f_thread_attributes_t *attributes) { #ifndef _di_level_0_parameter_checking_ @@ -472,164 +572,106 @@ extern "C" { } #endif // _di_f_thread_attributes_resize_ -#ifndef _di_f_thread_caller_ - f_thread_id_t f_thread_caller() { - return pthread_self(); - } -#endif // _di_f_thread_caller_ - -#ifndef _di_f_thread_cancel_ - f_status_t f_thread_cancel(const f_thread_id_t id) { - - const int error = pthread_cancel(id); - - if (error) { - if (error == ESRCH) return F_status_set_error(F_found_not); - - return F_status_set_error(F_failure); - } - - return F_none; - } -#endif // _di_f_thread_cancel_ - -#ifndef _di_f_thread_cancel_state_set_ - f_status_t f_thread_cancel_state_set(const int state, int *previous) { +#ifndef _di_f_thread_barrier_attribute_create_ + f_status_t f_thread_barrier_attribute_create(f_thread_barrier_attribute_t *attribute) { - const int error = pthread_setcancelstate(state, previous); + const int error = pthread_barrierattr_init(attribute); if (error) { - if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ENOMEM) return F_status_set_error(F_memory_not); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_cancel_state_set_ - -#ifndef _di_f_thread_cancel_test_ - f_status_t f_thread_cancel_test() { - - pthread_testcancel(); - - return F_none; - } -#endif // _di_f_thread_cancel_test_ - -#ifndef _di_f_thread_cancel_type_set_ - f_status_t f_thread_cancel_type_set(const int type, int *previous) { - - const int error = pthread_setcanceltype(type, previous); - - if (error) { - if (error == EINVAL) return F_status_set_error(F_parameter); +#endif // _di_f_thread_barrier_attribute_create_ - return F_status_set_error(F_failure); - } +#ifndef _di_f_thread_barrier_attribute_delete_ + f_status_t f_thread_barrier_attribute_delete(f_thread_barrier_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ - return F_none; + return private_f_thread_barrier_attribute_delete(attribute); } -#endif // _di_f_thread_cancel_type_set_ - -#ifndef _di_f_thread_clock_get_id_ - f_status_t f_thread_clock_get_id(const f_thread_id_t id_thread, clockid_t *id_clock) { +#endif // _di_f_thread_barrier_attribute_delete_ - const int error = pthread_getcpuclockid(id_thread, id_clock); - - if (error) { - if (error == ENOENT) return F_status_set_error(F_supported_not); - if (error == ESRCH) return F_status_set_error(F_found_not); +#ifndef _di_f_thread_barrier_attribute_shared_get_ + f_status_t f_thread_barrier_attribute_shared_get(const f_thread_barrier_attribute_t *attribute, int *shared) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + if (!shared) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + if (pthread_barrierattr_getpshared(attribute, shared)) { return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_clock_get_id_ - -#ifndef _di_f_thread_compare_ - f_status_t f_thread_compare(const f_thread_id_t id1, const f_thread_id_t id2) { - - if (pthread_equal(id1, id2)) { - return F_equal_to; - } - - return F_equal_to_not; - } -#endif // _di_f_thread_compare_ +#endif // _di_f_thread_barrier_attribute_shared_get_ -#ifndef _di_f_thread_condition_attribute_create_ - f_status_t f_thread_condition_attribute_create(f_thread_condition_attribute_t *attribute) { +#ifndef _di_f_thread_barrier_attribute_shared_set_ + f_status_t f_thread_barrier_attribute_shared_set(const int shared, f_thread_barrier_attribute_t *attribute) { #ifndef _di_level_0_parameter_checking_ if (!attribute) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_condattr_init(attribute); + const int error = pthread_barrierattr_setpshared(attribute, shared); if (error) { if (error == EINVAL) return F_status_set_error(F_parameter); - if (error == ENOMEM) return F_status_set_error(F_memory_not); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_condition_attribute_create_ - -#ifndef _di_f_thread_condition_attribute_delete_ - f_status_t f_thread_condition_attribute_delete(f_thread_condition_attribute_t *condition_attribute) { - #ifndef _di_level_0_parameter_checking_ - if (!condition_attribute) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - return private_f_thread_condition_attribute_delete(condition_attribute); - } -#endif // _di_f_thread_condition_attribute_delete_ +#endif // _di_f_thread_barrier_attribute_shared_set_ -#ifndef _di_f_thread_condition_attributes_adjust_ - f_status_t f_thread_condition_attributes_adjust(const f_array_length_t length, f_thread_condition_attributes_t *attributes) { +#ifndef _di_f_thread_barrier_attributes_adjust_ + f_status_t f_thread_barrier_attributes_adjust(const f_array_length_t length, f_thread_barrier_attributes_t *attributes) { #ifndef _di_level_0_parameter_checking_ if (!attributes) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - return private_f_thread_condition_attributes_adjust(length, attributes); + return private_f_thread_barrier_attributes_adjust(length, attributes); } -#endif // _di_f_thread_condition_attributes_adjust_ +#endif // _di_f_thread_barrier_attributes_adjust_ -#ifndef _di_f_thread_condition_attributes_decimate_by_ - f_status_t f_thread_condition_attributes_decimate_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes) { +#ifndef _di_f_thread_barrier_attributes_decimate_by_ + f_status_t f_thread_barrier_attributes_decimate_by(const f_array_length_t amount, f_thread_barrier_attributes_t *attributes) { #ifndef _di_level_0_parameter_checking_ if (!amount) return F_status_set_error(F_parameter); if (!attributes) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ if (attributes->size - amount > 0) { - return private_f_thread_condition_attributes_adjust(attributes->size - amount, attributes); + return private_f_thread_barrier_attributes_adjust(attributes->size - amount, attributes); } - return private_f_thread_condition_attributes_adjust(0, attributes); + return private_f_thread_barrier_attributes_adjust(0, attributes); } -#endif // _di_f_thread_condition_attributes_decimate_by_ +#endif // _di_f_thread_barrier_attributes_decimate_by_ -#ifndef _di_f_thread_condition_attributes_decrease_by_ - f_status_t f_thread_condition_attributes_decrease_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes) { +#ifndef _di_f_thread_barrier_attributes_decrease_by_ + f_status_t f_thread_barrier_attributes_decrease_by(const f_array_length_t amount, f_thread_barrier_attributes_t *attributes) { #ifndef _di_level_0_parameter_checking_ if (!amount) return F_status_set_error(F_parameter); if (!attributes) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ if (attributes->size - amount > 0) { - return private_f_thread_condition_attributes_resize(attributes->size - amount, attributes); + return private_f_thread_barrier_attributes_resize(attributes->size - amount, attributes); } - return private_f_thread_condition_attributes_resize(0, attributes); + return private_f_thread_barrier_attributes_resize(0, attributes); } -#endif // _di_f_thread_condition_attributes_decrease_by_ +#endif // _di_f_thread_barrier_attributes_decrease_by_ -#ifndef _di_f_thread_condition_attributes_increase_ - f_status_t f_thread_condition_attributes_increase(f_thread_condition_attributes_t *attributes) { +#ifndef _di_f_thread_barrier_attributes_increase_ + f_status_t f_thread_barrier_attributes_increase(f_thread_barrier_attributes_t *attributes) { #ifndef _di_level_0_parameter_checking_ if (!attributes) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ @@ -645,15 +687,15 @@ extern "C" { size = f_array_length_t_size; } - return private_f_thread_condition_attributes_resize(size, attributes); + return private_f_thread_barrier_attributes_resize(size, attributes); } return F_data_not; } -#endif // _di_f_thread_condition_attributes_increase_ +#endif // _di_f_thread_barrier_attributes_increase_ -#ifndef _di_f_thread_condition_attributes_increase_by_ - f_status_t f_thread_condition_attributes_increase_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes) { +#ifndef _di_f_thread_barrier_attributes_increase_by_ + f_status_t f_thread_barrier_attributes_increase_by(const f_array_length_t amount, f_thread_barrier_attributes_t *attributes) { #ifndef _di_level_0_parameter_checking_ if (!amount) return F_status_set_error(F_parameter); if (!attributes) return F_status_set_error(F_parameter); @@ -664,35 +706,29 @@ extern "C" { return F_status_set_error(F_array_too_large); } - return private_f_thread_condition_attributes_resize(attributes->used + amount, attributes); + return private_f_thread_barrier_attributes_resize(attributes->used + amount, attributes); } return F_data_not; } -#endif // _di_f_thread_condition_attributes_increase_by_ +#endif // _di_f_thread_barrier_attributes_increase_by_ -#ifndef _di_f_thread_condition_attributes_resize_ - f_status_t f_thread_condition_attributes_resize(const f_array_length_t length, f_thread_condition_attributes_t *attributes) { +#ifndef _di_f_thread_barrier_attributes_resize_ + f_status_t f_thread_barrier_attributes_resize(const f_array_length_t length, f_thread_barrier_attributes_t *attributes) { #ifndef _di_level_0_parameter_checking_ if (!attributes) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - return private_f_thread_condition_attributes_resize(length, attributes); + return private_f_thread_barrier_attributes_resize(length, attributes); } -#endif // _di_f_thread_condition_attributes_resize_ +#endif // _di_f_thread_barrier_attributes_resize_ -#ifndef _di_f_thread_condition_create_ - f_status_t f_thread_condition_create(const f_thread_condition_attribute_t *attribute, f_thread_condition_t *condition) { - #ifndef _di_level_0_parameter_checking_ - if (!condition) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ +#ifndef _di_f_thread_barrier_create_ + f_status_t f_thread_barrier_create(const unsigned int count, f_thread_barrier_attribute_t * const attribute, f_thread_barrier_t *barrier) { - const int error = pthread_cond_init(condition, attribute); + const int error = pthread_barrier_init(barrier, attribute, count); if (error) { - if (error == EAGAIN) return F_status_set_error(F_resource_not); - if (error == EBUSY) return F_status_set_error(F_busy); - if (error == EINVAL) return F_status_set_error(F_parameter); if (error == ENOMEM) return F_status_set_error(F_memory_not); return F_status_set_error(F_failure); @@ -700,199 +736,1225 @@ extern "C" { return F_none; } -#endif // _di_f_thread_condition_create_ +#endif // _di_f_thread_barrier_create_ -#ifndef _di_f_thread_condition_delete_ - f_status_t f_thread_condition_delete(f_thread_condition_t *condition) { +#ifndef _di_f_thread_barrier_delete_ + f_status_t f_thread_barrier_delete(f_thread_barrier_t *barrier) { #ifndef _di_level_0_parameter_checking_ - if (!condition) return F_status_set_error(F_parameter); + if (!barrier) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - return private_f_thread_condition_delete(condition); + return private_f_thread_barrier_delete(barrier); } -#endif // _di_f_thread_condition_delete_ +#endif // _di_f_thread_barrier_delete_ -#ifndef _di_f_thread_condition_unblock_all_ - f_status_t f_thread_condition_unblock_all(f_thread_condition_t *condition) { +#ifndef _di_f_thread_barrier_wait_ + f_status_t f_thread_barrier_wait(f_thread_barrier_t *barrier, int *result) { #ifndef _di_level_0_parameter_checking_ - if (!condition) return F_status_set_error(F_parameter); + if (!barrier) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_cond_broadcast(condition); - - if (error) { - if (error == EINVAL) return F_status_set_error(F_parameter); - - return F_status_set_error(F_failure); + if (result) { + *result = pthread_barrier_wait(barrier); + } + else { + pthread_barrier_wait(barrier); } return F_none; } -#endif // _di_f_thread_condition_unblock_all_ +#endif // _di_f_thread_barrier_wait_ -#ifndef _di_f_thread_condition_unblock_any_ - f_status_t f_thread_condition_unblock_any(f_thread_condition_t *condition) { +#ifndef _di_f_thread_barriers_adjust_ + f_status_t f_thread_barriers_adjust(const f_array_length_t length, f_thread_barriers_t *barriers) { #ifndef _di_level_0_parameter_checking_ - if (!condition) return F_status_set_error(F_parameter); + if (!barriers) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_cond_signal(condition); + return private_f_thread_barriers_adjust(length, barriers); + } +#endif // _di_f_thread_barriers_adjust_ - if (error) { - if (error == EINVAL) return F_status_set_error(F_parameter); +#ifndef _di_f_thread_barriers_decimate_by_ + f_status_t f_thread_barriers_decimate_by(const f_array_length_t amount, f_thread_barriers_t *barriers) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!barriers) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ - return F_status_set_error(F_failure); + if (barriers->size - amount > 0) { + return private_f_thread_barriers_adjust(barriers->size - amount, barriers); } - return F_none; + return private_f_thread_barriers_adjust(0, barriers); } -#endif // _di_f_thread_condition_unblock_any_ +#endif // _di_f_thread_barriers_decimate_by_ -#ifndef _di_f_thread_condition_wait_ - f_status_t f_thread_condition_wait(f_thread_condition_t *condition, f_thread_mutex_t *mutex) { +#ifndef _di_f_thread_barriers_decrease_by_ + f_status_t f_thread_barriers_decrease_by(const f_array_length_t amount, f_thread_barriers_t *barriers) { #ifndef _di_level_0_parameter_checking_ - if (!condition) return F_status_set_error(F_parameter); - if (!mutex) return F_status_set_error(F_parameter); + if (!amount) return F_status_set_error(F_parameter); + if (!barriers) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_cond_wait(condition, mutex); - - if (error) { - if (error == EINVAL) return F_status_set_error(F_parameter); - if (error == EPERM) return F_status_set_error(F_prohibited); - - return F_status_set_error(F_failure); + if (barriers->size - amount > 0) { + return private_f_thread_barriers_resize(barriers->size - amount, barriers); } - return F_none; + return private_f_thread_barriers_resize(0, barriers); } -#endif // _di_f_thread_condition_wait_ +#endif // _di_f_thread_barriers_decrease_by_ -#ifndef _di_f_thread_condition_wait_timed_ - f_status_t f_thread_condition_wait_timed(const struct timespec *wait, f_thread_condition_t *condition, f_thread_mutex_t *mutex) { +#ifndef _di_f_thread_barriers_increase_ + f_status_t f_thread_barriers_increase(f_thread_barriers_t *barriers) { #ifndef _di_level_0_parameter_checking_ - if (!condition) return F_status_set_error(F_parameter); - if (!mutex) return F_status_set_error(F_parameter); + if (!barriers) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_cond_timedwait(condition, mutex, wait); - - if (error) { - if (error == EINVAL) return F_status_set_error(F_parameter); - if (error == EPERM) return F_status_set_error(F_prohibited); + if (barriers->used + 1 > barriers->size) { + f_array_length_t size = barriers->used + f_memory_default_allocation_step; - return F_status_set_error(F_failure); - } + if (size > f_array_length_t_size) { + if (barriers->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_barriers_resize(size, barriers); + } + + return F_data_not; + } +#endif // _di_f_thread_barriers_increase_ + +#ifndef _di_f_thread_barriers_increase_by_ + f_status_t f_thread_barriers_increase_by(const f_array_length_t amount, f_thread_barriers_t *barriers) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!barriers) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (barriers->used + amount > barriers->size) { + if (barriers->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_thread_barriers_resize(barriers->used + amount, barriers); + } + + return F_data_not; + } +#endif // _di_f_thread_barriers_increase_by_ + +#ifndef _di_f_thread_barriers_resize_ + f_status_t f_thread_barriers_resize(const f_array_length_t length, f_thread_barriers_t *barriers) { + #ifndef _di_level_0_parameter_checking_ + if (!barriers) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_barriers_resize(length, barriers); + } +#endif // _di_f_thread_barriers_resize_ + +#ifndef _di_f_thread_caller_ + f_thread_id_t f_thread_caller() { + return pthread_self(); + } +#endif // _di_f_thread_caller_ + +#ifndef _di_f_thread_cancel_ + f_status_t f_thread_cancel(const f_thread_id_t id) { + + const int error = pthread_cancel(id); + + if (error) { + if (error == ESRCH) return F_status_set_error(F_found_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_cancel_ + +#ifndef _di_f_thread_cancel_state_set_ + f_status_t f_thread_cancel_state_set(const int state, int *previous) { + + const int error = pthread_setcancelstate(state, previous); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_cancel_state_set_ + +#ifndef _di_f_thread_cancel_test_ + f_status_t f_thread_cancel_test() { + + pthread_testcancel(); + + return F_none; + } +#endif // _di_f_thread_cancel_test_ + +#ifndef _di_f_thread_cancel_type_set_ + f_status_t f_thread_cancel_type_set(const int type, int *previous) { + + const int error = pthread_setcanceltype(type, previous); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_cancel_type_set_ + +#ifndef _di_f_thread_clock_get_id_ + f_status_t f_thread_clock_get_id(const f_thread_id_t id_thread, clockid_t *id_clock) { + + const int error = pthread_getcpuclockid(id_thread, id_clock); + + if (error) { + if (error == ENOENT) return F_status_set_error(F_supported_not); + if (error == ESRCH) return F_status_set_error(F_found_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_clock_get_id_ + +#ifndef _di_f_thread_compare_ + f_status_t f_thread_compare(const f_thread_id_t id1, const f_thread_id_t id2) { + + if (pthread_equal(id1, id2)) { + return F_equal_to; + } + + return F_equal_to_not; + } +#endif // _di_f_thread_compare_ + +#ifndef _di_f_thread_attribute_concurrency_get_ + f_status_t f_thread_attribute_concurrency_get(int *level) { + #ifndef _di_level_0_parameter_checking_ + if (!level) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + *level = pthread_getconcurrency(); + + return F_none; + } +#endif // _di_f_thread_attribute_concurrency_get_ + +#ifndef _di_f_thread_attribute_concurrency_set_ + f_status_t f_thread_attribute_concurrency_set(const int level) { + + const int error = pthread_setconcurrency(level); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EAGAIN) return F_status_set_error(F_resource_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_attribute_concurrency_set_ + +#ifndef _di_f_thread_condition_attribute_create_ + f_status_t f_thread_condition_attribute_create(f_thread_condition_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_condattr_init(attribute); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ENOMEM) return F_status_set_error(F_memory_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_condition_attribute_create_ + +#ifndef _di_f_thread_condition_attribute_delete_ + f_status_t f_thread_condition_attribute_delete(f_thread_condition_attribute_t *condition_attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!condition_attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_condition_attribute_delete(condition_attribute); + } +#endif // _di_f_thread_condition_attribute_delete_ + +#ifndef _di_f_thread_condition_attributes_adjust_ + f_status_t f_thread_condition_attributes_adjust(const f_array_length_t length, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_condition_attributes_adjust(length, attributes); + } +#endif // _di_f_thread_condition_attributes_adjust_ + +#ifndef _di_f_thread_condition_attributes_decimate_by_ + f_status_t f_thread_condition_attributes_decimate_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->size - amount > 0) { + return private_f_thread_condition_attributes_adjust(attributes->size - amount, attributes); + } + + return private_f_thread_condition_attributes_adjust(0, attributes); + } +#endif // _di_f_thread_condition_attributes_decimate_by_ + +#ifndef _di_f_thread_condition_attributes_decrease_by_ + f_status_t f_thread_condition_attributes_decrease_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->size - amount > 0) { + return private_f_thread_condition_attributes_resize(attributes->size - amount, attributes); + } + + return private_f_thread_condition_attributes_resize(0, attributes); + } +#endif // _di_f_thread_condition_attributes_decrease_by_ + +#ifndef _di_f_thread_condition_attributes_increase_ + f_status_t f_thread_condition_attributes_increase(f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->used + 1 > attributes->size) { + f_array_length_t size = attributes->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (attributes->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_condition_attributes_resize(size, attributes); + } + + return F_data_not; + } +#endif // _di_f_thread_condition_attributes_increase_ + +#ifndef _di_f_thread_condition_attributes_increase_by_ + f_status_t f_thread_condition_attributes_increase_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->used + amount > attributes->size) { + if (attributes->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_thread_condition_attributes_resize(attributes->used + amount, attributes); + } + + return F_data_not; + } +#endif // _di_f_thread_condition_attributes_increase_by_ + +#ifndef _di_f_thread_condition_attributes_resize_ + f_status_t f_thread_condition_attributes_resize(const f_array_length_t length, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_condition_attributes_resize(length, attributes); + } +#endif // _di_f_thread_condition_attributes_resize_ + +#ifndef _di_f_thread_condition_create_ + f_status_t f_thread_condition_create(const f_thread_condition_attribute_t *attribute, f_thread_condition_t *condition) { + #ifndef _di_level_0_parameter_checking_ + if (!condition) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_cond_init(condition, attribute); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ENOMEM) return F_status_set_error(F_memory_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_condition_create_ + +#ifndef _di_f_thread_condition_delete_ + f_status_t f_thread_condition_delete(f_thread_condition_t *condition) { + #ifndef _di_level_0_parameter_checking_ + if (!condition) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_condition_delete(condition); + } +#endif // _di_f_thread_condition_delete_ + +#ifndef _di_f_thread_condition_unblock_all_ + f_status_t f_thread_condition_unblock_all(f_thread_condition_t *condition) { + #ifndef _di_level_0_parameter_checking_ + if (!condition) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_cond_broadcast(condition); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_condition_unblock_all_ + +#ifndef _di_f_thread_condition_unblock_any_ + f_status_t f_thread_condition_unblock_any(f_thread_condition_t *condition) { + #ifndef _di_level_0_parameter_checking_ + if (!condition) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_cond_signal(condition); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_condition_unblock_any_ + +#ifndef _di_f_thread_condition_wait_ + f_status_t f_thread_condition_wait(f_thread_condition_t *condition, f_thread_mutex_t *mutex) { + #ifndef _di_level_0_parameter_checking_ + if (!condition) return F_status_set_error(F_parameter); + if (!mutex) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_cond_wait(condition, mutex); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_condition_wait_ + +#ifndef _di_f_thread_condition_wait_timed_ + f_status_t f_thread_condition_wait_timed(const struct timespec *wait, f_thread_condition_t *condition, f_thread_mutex_t *mutex) { + #ifndef _di_level_0_parameter_checking_ + if (!condition) return F_status_set_error(F_parameter); + if (!mutex) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_cond_timedwait(condition, mutex, wait); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_condition_wait_timed_ + +#ifndef _di_f_thread_conditions_adjust_ + f_status_t f_thread_conditions_adjust(const f_array_length_t length, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_conditions_adjust(length, conditions); + } +#endif // _di_f_thread_conditions_adjust_ + +#ifndef _di_f_thread_conditions_decimate_by_ + f_status_t f_thread_conditions_decimate_by(const f_array_length_t amount, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (conditions->size - amount > 0) { + return private_f_thread_conditions_adjust(conditions->size - amount, conditions); + } + + return private_f_thread_conditions_adjust(0, conditions); + } +#endif // _di_f_thread_conditions_decimate_by_ + +#ifndef _di_f_thread_conditions_decrease_by_ + f_status_t f_thread_conditions_decrease_by(const f_array_length_t amount, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (conditions->size - amount > 0) { + return private_f_thread_conditions_resize(conditions->size - amount, conditions); + } + + return private_f_thread_conditions_resize(0, conditions); + } +#endif // _di_f_thread_conditions_decrease_by_ + +#ifndef _di_f_thread_conditions_increase_ + f_status_t f_thread_conditions_increase(f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (conditions->used + 1 > conditions->size) { + f_array_length_t size = conditions->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (conditions->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_conditions_resize(size, conditions); + } + + return F_data_not; + } +#endif // _di_f_thread_conditions_increase_ + +#ifndef _di_f_thread_conditions_increase_by_ + f_status_t f_thread_conditions_increase_by(const f_array_length_t amount, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (conditions->used + amount > conditions->size) { + if (conditions->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_thread_conditions_resize(conditions->used + amount, conditions); + } + + return F_data_not; + } +#endif // _di_f_thread_conditions_increase_by_ + +#ifndef _di_f_thread_conditions_resize_ + f_status_t f_thread_conditions_resize(const f_array_length_t length, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_conditions_resize(length, conditions); + } +#endif // _di_f_thread_conditions_resize_ + +#ifndef _di_f_thread_create_ + f_status_t f_thread_create(const f_thread_attribute_t *attribute, f_thread_id_t *id, void *(*routine) (void *), void *argument) { + #ifndef _di_level_0_parameter_checking_ + if (!id) return F_status_set_error(F_parameter); + if (!routine) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_create(id, attribute, routine, argument); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_create_ + +#ifndef _di_f_thread_exit_ + f_status_t f_thread_exit(int *result) { + #ifndef _di_level_0_parameter_checking_ + if (!result) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + pthread_exit(result); + + return F_none; + } +#endif // _di_f_thread_exit_ + +#ifndef _di_f_thread_join_ + f_status_t f_thread_join(const f_thread_id_t id, void **result) { + + const int error = pthread_join(id, result); + + if (error) { + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_supported_not); + if (error == ESRCH) return F_status_set_error(F_found_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_join_ + +#ifndef _di_f_thread_join_try_ + f_status_t f_thread_join_try(const f_thread_id_t id, void **result) { + + const int error = pthread_tryjoin_np(id, result); + + if (error) { + if (error == EBUSY) return F_busy; + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_supported_not); + if (error == ESRCH) return F_status_set_error(F_found_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_join_try_ + +#ifndef _di_f_thread_join_timed_ + f_status_t f_thread_join_timed(const f_thread_id_t id, const struct timespec wait, void **result) { + + const int error = pthread_timedjoin_np(id, result, &wait); + + if (error) { + if (error == EBUSY) return F_busy; + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_supported_not); + if (error == ESRCH) return F_status_set_error(F_found_not); + if (error == ETIMEDOUT) return F_time; + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_join_timed_ + +#ifndef _di_f_thread_key_create_ + f_status_t f_thread_key_create(void (*routine) (void *), f_thread_key_t *key) { + #ifndef _di_level_0_parameter_checking_ + if (!routine) return F_status_set_error(F_parameter); + if (!key) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_key_create(key, routine); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == ENOMEM) return F_status_set_error(F_memory_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_key_create_ + +#ifndef _di_f_thread_key_delete_ + f_status_t f_thread_key_delete(f_thread_key_t *key) { + #ifndef _di_level_0_parameter_checking_ + if (!key) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_key_delete(key); + } +#endif // _di_f_thread_key_delete_ + +#ifndef _di_f_thread_key_get_ + f_status_t f_thread_key_get(const f_thread_key_t key, void **value) { + #ifndef _di_level_0_parameter_checking_ + if (!value) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + *value = pthread_getspecific(key); + + return F_none; + } +#endif // _di_f_thread_key_get_ + +#ifndef _di_f_thread_key_set_ + f_status_t f_thread_key_set(const f_thread_key_t key, const void *value) { + #ifndef _di_level_0_parameter_checking_ + if (!value) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_setspecific(key, value); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_key_set_ + +#ifndef _di_f_thread_keys_adjust_ + f_status_t f_thread_keys_adjust(const f_array_length_t length, f_thread_keys_t *keys) { + #ifndef _di_level_0_parameter_checking_ + if (!keys) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_keys_adjust(length, keys); + } +#endif // _di_f_thread_keys_adjust_ + +#ifndef _di_f_thread_keys_decimate_by_ + f_status_t f_thread_keys_decimate_by(const f_array_length_t amount, f_thread_keys_t *keys) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!keys) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (keys->size - amount > 0) { + return private_f_thread_keys_adjust(keys->size - amount, keys); + } + + return private_f_thread_keys_adjust(0, keys); + } +#endif // _di_f_thread_keys_decimate_by_ + +#ifndef _di_f_thread_keys_decrease_by_ + f_status_t f_thread_keys_decrease_by(const f_array_length_t amount, f_thread_keys_t *keys) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!keys) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (keys->size - amount > 0) { + return private_f_thread_keys_resize(keys->size - amount, keys); + } + + return private_f_thread_keys_resize(0, keys); + } +#endif // _di_f_thread_keys_decrease_by_ + +#ifndef _di_f_thread_keys_increase_ + f_status_t f_thread_keys_increase(f_thread_keys_t *keys) { + #ifndef _di_level_0_parameter_checking_ + if (!keys) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (keys->used + 1 > keys->size) { + f_array_length_t size = keys->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (keys->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_keys_resize(size, keys); + } + + return F_data_not; + } +#endif // _di_f_thread_keys_increase_ + +#ifndef _di_f_thread_keys_increase_by_ + f_status_t f_thread_keys_increase_by(const f_array_length_t amount, f_thread_keys_t *keys) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!keys) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (keys->used + amount > keys->size) { + if (keys->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_thread_keys_resize(keys->used + amount, keys); + } + + return F_data_not; + } +#endif // _di_f_thread_keys_increase_by_ + +#ifndef _di_f_thread_keys_resize_ + f_status_t f_thread_keys_resize(const f_array_length_t length, f_thread_keys_t *keys) { + #ifndef _di_level_0_parameter_checking_ + if (!keys) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_keys_resize(length, keys); + } +#endif // _di_f_thread_keys_resize_ + +#ifndef _di_f_thread_lock_attribute_create_ + f_status_t f_thread_lock_attribute_create(f_thread_lock_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_rwlockattr_init(attribute); + + // @todo figure out the error codes and update accordingly. + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ENOMEM) return F_status_set_error(F_memory_not); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_lock_attribute_create_ + +#ifndef _di_f_thread_lock_attribute_delete_ + f_status_t f_thread_lock_attribute_delete(f_thread_lock_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_lock_attribute_delete(attribute); + } +#endif // _di_f_thread_lock_attribute_delete_ + +#ifndef _di_f_thread_lock_attribute_shared_get_ + f_status_t f_thread_lock_attribute_shared_get(const f_thread_lock_attribute_t *attribute, int *shared) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + if (!shared) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (pthread_rwlockattr_getpshared(attribute, shared)) { + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_lock_attribute_shared_get_ + +#ifndef _di_f_thread_lock_attribute_shared_set_ + f_status_t f_thread_lock_attribute_shared_set(const int shared, f_thread_lock_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_rwlockattr_setpshared(attribute, shared); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_lock_attribute_shared_set_ + +#ifndef _di_f_thread_lock_attributes_adjust_ + f_status_t f_thread_lock_attributes_adjust(const f_array_length_t length, f_thread_lock_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_lock_attributes_adjust(length, attributes); + } +#endif // _di_f_thread_lock_attributes_adjust_ + +#ifndef _di_f_thread_lock_attributes_decimate_by_ + f_status_t f_thread_lock_attributes_decimate_by(const f_array_length_t amount, f_thread_lock_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->size - amount > 0) { + return private_f_thread_lock_attributes_adjust(attributes->size - amount, attributes); + } + + return private_f_thread_lock_attributes_adjust(0, attributes); + } +#endif // _di_f_thread_lock_attributes_decimate_by_ + +#ifndef _di_f_thread_lock_attributes_decrease_by_ + f_status_t f_thread_lock_attributes_decrease_by(const f_array_length_t amount, f_thread_lock_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->size - amount > 0) { + return private_f_thread_lock_attributes_resize(attributes->size - amount, attributes); + } + + return private_f_thread_lock_attributes_resize(0, attributes); + } +#endif // _di_f_thread_lock_attributes_decrease_by_ + +#ifndef _di_f_thread_lock_attributes_increase_ + f_status_t f_thread_lock_attributes_increase(f_thread_lock_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->used + 1 > attributes->size) { + f_array_length_t size = attributes->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (attributes->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_lock_attributes_resize(size, attributes); + } + + return F_data_not; + } +#endif // _di_f_thread_lock_attributes_increase_ + +#ifndef _di_f_thread_lock_attributes_increase_by_ + f_status_t f_thread_lock_attributes_increase_by(const f_array_length_t amount, f_thread_lock_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->used + amount > attributes->size) { + if (attributes->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_thread_lock_attributes_resize(attributes->used + amount, attributes); + } + + return F_data_not; + } +#endif // _di_f_thread_lock_attributes_increase_by_ + +#ifndef _di_f_thread_lock_attributes_resize_ + f_status_t f_thread_lock_attributes_resize(const f_array_length_t length, f_thread_lock_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_lock_attributes_resize(length, attributes); + } +#endif // _di_f_thread_lock_attributes_resize_ + +#ifndef _di_f_thread_lock_create_ + f_status_t f_thread_lock_create(const f_thread_lock_attribute_t *attribute, f_thread_lock_t *lock) { + #ifndef _di_level_0_parameter_checking_ + if (!lock) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_rwlock_init(lock, attribute); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == ENOMEM) return F_status_set_error(F_memory_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_lock_create_ + +#ifndef _di_f_thread_lock_delete_ + f_status_t f_thread_lock_delete(f_thread_lock_t *lock) { + #ifndef _di_level_0_parameter_checking_ + if (!lock) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_lock_delete(lock); + } +#endif // _di_f_thread_lock_delete_ + +#ifndef _di_f_thread_lock_read_ + f_status_t f_thread_lock_read(f_thread_lock_t *lock) { + #ifndef _di_level_0_parameter_checking_ + if (!lock) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_rwlock_rdlock(lock); + + if (error) { + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ETIMEDOUT) return F_time; + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_lock_read_ + +#ifndef _di_f_thread_lock_read_timed_ + f_status_t f_thread_lock_read_timed(const struct timespec *timeout, f_thread_lock_t *lock) { + #ifndef _di_level_0_parameter_checking_ + if (!timeout) return F_status_set_error(F_parameter); + if (!lock) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_rwlock_timedrdlock(lock, timeout); + + if (error) { + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ETIMEDOUT) return F_time; + + return F_status_set_error(F_failure); + } return F_none; } -#endif // _di_f_thread_condition_wait_timed_ +#endif // _di_f_thread_lock_read_timed_ -#ifndef _di_f_thread_conditions_adjust_ - f_status_t f_thread_conditions_adjust(const f_array_length_t length, f_thread_conditions_t *conditions) { +#ifndef _di_f_thread_lock_read_try_ + f_status_t f_thread_lock_read_try(f_thread_lock_t *lock) { #ifndef _di_level_0_parameter_checking_ - if (!conditions) return F_status_set_error(F_parameter); + if (!lock) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - return private_f_thread_conditions_adjust(length, conditions); + const int error = pthread_rwlock_tryrdlock(lock); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EBUSY) return F_busy; + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; } -#endif // _di_f_thread_conditions_adjust_ +#endif // _di_f_thread_lock_read_try_ -#ifndef _di_f_thread_conditions_decimate_by_ - f_status_t f_thread_conditions_decimate_by(const f_array_length_t amount, f_thread_conditions_t *conditions) { +#ifndef _di_f_thread_lock_write_ + f_status_t f_thread_lock_write(f_thread_lock_t *lock) { + #ifndef _di_level_0_parameter_checking_ + if (!lock) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_rwlock_wrlock(lock); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_lock_write_ + +#ifndef _di_f_thread_lock_write_timed_ + f_status_t f_thread_lock_write_timed(const struct timespec *timeout, f_thread_lock_t *lock) { + #ifndef _di_level_0_parameter_checking_ + if (!timeout) return F_status_set_error(F_parameter); + if (!lock) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_rwlock_timedwrlock(lock, timeout); + + if (error) { + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ETIMEDOUT) return F_time; + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_lock_write_timed_ + +#ifndef _di_f_thread_lock_write_try_ + f_status_t f_thread_lock_write_try(f_thread_lock_t *lock) { + #ifndef _di_level_0_parameter_checking_ + if (!lock) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_rwlock_trywrlock(lock); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EBUSY) return F_busy; + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_lock_write_try_ + +#ifndef _di_f_thread_locks_adjust_ + f_status_t f_thread_locks_adjust(const f_array_length_t length, f_thread_locks_t *locks) { + #ifndef _di_level_0_parameter_checking_ + if (!locks) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_locks_adjust(length, locks); + } +#endif // _di_f_thread_locks_adjust_ + +#ifndef _di_f_thread_locks_decimate_by_ + f_status_t f_thread_locks_decimate_by(const f_array_length_t amount, f_thread_locks_t *locks) { #ifndef _di_level_0_parameter_checking_ if (!amount) return F_status_set_error(F_parameter); - if (!conditions) return F_status_set_error(F_parameter); + if (!locks) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (conditions->size - amount > 0) { - return private_f_thread_conditions_adjust(conditions->size - amount, conditions); + if (locks->size - amount > 0) { + return private_f_thread_locks_adjust(locks->size - amount, locks); } - return private_f_thread_conditions_adjust(0, conditions); + return private_f_thread_locks_adjust(0, locks); } -#endif // _di_f_thread_conditions_decimate_by_ +#endif // _di_f_thread_locks_decimate_by_ -#ifndef _di_f_thread_conditions_decrease_by_ - f_status_t f_thread_conditions_decrease_by(const f_array_length_t amount, f_thread_conditions_t *conditions) { +#ifndef _di_f_thread_locks_decrease_by_ + f_status_t f_thread_locks_decrease_by(const f_array_length_t amount, f_thread_locks_t *locks) { #ifndef _di_level_0_parameter_checking_ if (!amount) return F_status_set_error(F_parameter); - if (!conditions) return F_status_set_error(F_parameter); + if (!locks) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (conditions->size - amount > 0) { - return private_f_thread_conditions_resize(conditions->size - amount, conditions); + if (locks->size - amount > 0) { + return private_f_thread_locks_resize(locks->size - amount, locks); } - return private_f_thread_conditions_resize(0, conditions); + return private_f_thread_locks_resize(0, locks); } -#endif // _di_f_thread_conditions_decrease_by_ +#endif // _di_f_thread_locks_decrease_by_ -#ifndef _di_f_thread_conditions_increase_ - f_status_t f_thread_conditions_increase(f_thread_conditions_t *conditions) { +#ifndef _di_f_thread_locks_increase_ + f_status_t f_thread_locks_increase(f_thread_locks_t *locks) { #ifndef _di_level_0_parameter_checking_ - if (!conditions) return F_status_set_error(F_parameter); + if (!locks) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (conditions->used + 1 > conditions->size) { - f_array_length_t size = conditions->used + f_memory_default_allocation_step; + if (locks->used + 1 > locks->size) { + f_array_length_t size = locks->used + f_memory_default_allocation_step; if (size > f_array_length_t_size) { - if (conditions->used + 1 > f_array_length_t_size) { + if (locks->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_conditions_resize(size, conditions); + return private_f_thread_locks_resize(size, locks); } return F_data_not; } -#endif // _di_f_thread_conditions_increase_ +#endif // _di_f_thread_locks_increase_ -#ifndef _di_f_thread_conditions_increase_by_ - f_status_t f_thread_conditions_increase_by(const f_array_length_t amount, f_thread_conditions_t *conditions) { +#ifndef _di_f_thread_locks_increase_by_ + f_status_t f_thread_locks_increase_by(const f_array_length_t amount, f_thread_locks_t *locks) { #ifndef _di_level_0_parameter_checking_ if (!amount) return F_status_set_error(F_parameter); - if (!conditions) return F_status_set_error(F_parameter); + if (!locks) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (conditions->used + amount > conditions->size) { - if (conditions->used + amount > f_array_length_t_size) { + if (locks->used + amount > locks->size) { + if (locks->used + amount > f_array_length_t_size) { return F_status_set_error(F_array_too_large); } - return private_f_thread_conditions_resize(conditions->used + amount, conditions); + return private_f_thread_locks_resize(locks->used + amount, locks); } return F_data_not; } -#endif // _di_f_thread_conditions_increase_by_ +#endif // _di_f_thread_locks_increase_by_ -#ifndef _di_f_thread_conditions_resize_ - f_status_t f_thread_conditions_resize(const f_array_length_t length, f_thread_conditions_t *conditions) { +#ifndef _di_f_thread_locks_resize_ + f_status_t f_thread_locks_resize(const f_array_length_t length, f_thread_locks_t *locks) { #ifndef _di_level_0_parameter_checking_ - if (!conditions) return F_status_set_error(F_parameter); + if (!locks) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - return private_f_thread_conditions_resize(length, conditions); + return private_f_thread_locks_resize(length, locks); } -#endif // _di_f_thread_conditions_resize_ +#endif // _di_f_thread_locks_resize_ -#ifndef _di_f_thread_create_ - f_status_t f_thread_create(const f_thread_attribute_t *attribute, f_thread_id_t *id, void *(*routine) (void *), void *argument) { +#ifndef _di_f_thread_mutex_attribute_create_ + f_status_t f_thread_mutex_attribute_create(f_thread_mutex_attribute_t *attribute) { #ifndef _di_level_0_parameter_checking_ - if (!id) return F_status_set_error(F_parameter); - if (!routine) return F_status_set_error(F_parameter); + if (!attribute) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_create(id, attribute, routine, argument); + const int error = pthread_mutexattr_init(attribute); + // @todo figure out the error codes and update accordingly. if (error) { if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EBUSY) return F_status_set_error(F_busy); if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ENOMEM) return F_status_set_error(F_memory_not); if (error == EPERM) return F_status_set_error(F_prohibited); return F_status_set_error(F_failure); @@ -900,116 +1962,112 @@ extern "C" { return F_none; } -#endif // _di_f_thread_create_ +#endif // _di_f_thread_mutex_attribute_create_ -#ifndef _di_f_thread_exit_ - f_status_t f_thread_exit(int *result) { +#ifndef _di_f_thread_mutex_attribute_delete_ + f_status_t f_thread_mutex_attribute_delete(f_thread_mutex_attribute_t *attribute) { #ifndef _di_level_0_parameter_checking_ - if (!result) return F_status_set_error(F_parameter); + if (!attribute) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - pthread_exit(result); - - return F_none; + return private_f_thread_mutex_attribute_delete(attribute); } -#endif // _di_f_thread_exit_ +#endif // _di_f_thread_mutex_attribute_delete_ -#ifndef _di_f_thread_join_ - f_status_t f_thread_join(const f_thread_id_t id, void **result) { +#ifndef _di_f_thread_mutex_attribute_priority_ceiling_get_ + f_status_t f_thread_mutex_attribute_priority_ceiling_get(const f_thread_mutex_attribute_t *attribute, int *ceiling) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + if (!ceiling) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ - const int error = pthread_join(id, result); + const int error = pthread_mutexattr_getprioceiling(attribute, ceiling); if (error) { - if (error == EDEADLK) return F_status_set_error(F_deadlock); if (error == EINVAL) return F_status_set_error(F_parameter); - if (error == EPERM) return F_status_set_error(F_supported_not); - if (error == ESRCH) return F_status_set_error(F_found_not); + if (error == EPERM) return F_status_set_error(F_prohibited); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_join_ +#endif // _di_f_thread_mutex_attribute_priority_ceiling_get_ -#ifndef _di_f_thread_join_try_ - f_status_t f_thread_join_try(const f_thread_id_t id, void **result) { +#ifndef _di_f_thread_mutex_attribute_priority_ceiling_set_ + f_status_t f_thread_mutex_attribute_priority_ceiling_set(const int ceiling, f_thread_mutex_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ - const int error = pthread_tryjoin_np(id, result); + const int error = pthread_mutexattr_setprioceiling(attribute, ceiling); if (error) { - if (error == EBUSY) return F_busy; - if (error == EDEADLK) return F_status_set_error(F_deadlock); if (error == EINVAL) return F_status_set_error(F_parameter); - if (error == EPERM) return F_status_set_error(F_supported_not); - if (error == ESRCH) return F_status_set_error(F_found_not); + if (error == EPERM) return F_status_set_error(F_prohibited); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_join_try_ - -#ifndef _di_f_thread_join_timed_ - f_status_t f_thread_join_timed(const f_thread_id_t id, const struct timespec wait, void **result) { - - const int error = pthread_timedjoin_np(id, result, &wait); +#endif // _di_f_thread_mutex_attribute_priority_ceiling_set_ - if (error) { - if (error == EBUSY) return F_busy; - if (error == EDEADLK) return F_status_set_error(F_deadlock); - if (error == EINVAL) return F_status_set_error(F_parameter); - if (error == EPERM) return F_status_set_error(F_supported_not); - if (error == ESRCH) return F_status_set_error(F_found_not); - if (error == ETIMEDOUT) return F_time; +#ifndef _di_f_thread_mutex_attribute_shared_get_ + f_status_t f_thread_mutex_attribute_shared_get(const f_thread_mutex_attribute_t *attribute, int *shared) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + if (!shared) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + if (pthread_mutexattr_getpshared(attribute, shared)) { return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_join_timed_ +#endif // _di_f_thread_mutex_attribute_shared_get_ -#ifndef _di_f_thread_key_create_ - f_status_t f_thread_key_create(void (*routine) (void *), f_thread_key_t *key) { +#ifndef _di_f_thread_mutex_attribute_shared_set_ + f_status_t f_thread_mutex_attribute_shared_set(const int shared, f_thread_mutex_attribute_t *attribute) { #ifndef _di_level_0_parameter_checking_ - if (!routine) return F_status_set_error(F_parameter); - if (!key) return F_status_set_error(F_parameter); + if (!attribute) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_key_create(key, routine); + const int error = pthread_mutexattr_setpshared(attribute, shared); if (error) { - if (error == EAGAIN) return F_status_set_error(F_resource_not); - if (error == ENOMEM) return F_status_set_error(F_memory_not); + if (error == EINVAL) return F_status_set_error(F_parameter); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_key_create_ +#endif // _di_f_thread_mutex_attribute_shared_set_ -#ifndef _di_f_thread_key_get_ - f_status_t f_thread_key_get(const f_thread_key_t key, void **value) { +#ifndef _di_f_thread_mutex_attribute_type_get_ + f_status_t f_thread_mutex_attribute_type_get(const f_thread_mutex_attribute_t *attribute, int *type) { #ifndef _di_level_0_parameter_checking_ - if (!value) return F_status_set_error(F_parameter); + if (!attribute) return F_status_set_error(F_parameter); + if (!type) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - *value = pthread_getspecific(key); + if (pthread_mutexattr_gettype(attribute, type)) { + return F_status_set_error(F_failure); + } return F_none; } -#endif // _di_f_thread_key_get_ +#endif // _di_f_thread_mutex_attribute_type_get_ -#ifndef _di_f_thread_key_set_ - f_status_t f_thread_key_set(const f_thread_key_t key, const void *value) { +#ifndef _di_f_thread_mutex_attribute_type_set_ + f_status_t f_thread_mutex_attribute_type_set(const int type, f_thread_mutex_attribute_t *attribute) { #ifndef _di_level_0_parameter_checking_ - if (!value) return F_status_set_error(F_parameter); + if (!attribute) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_setspecific(key, value); + const int error = pthread_mutexattr_settype(attribute, type); if (error) { if (error == EINVAL) return F_status_set_error(F_parameter); @@ -1019,47 +2077,47 @@ extern "C" { return F_none; } -#endif // _di_f_thread_key_set_ +#endif // _di_f_thread_mutex_attribute_type_set_ -#ifndef _di_f_thread_lock_ - f_status_t f_thread_lock(f_thread_lock_t *lock) { +#ifndef _di_f_thread_mutex_attribute_protocol_get_ + f_status_t f_thread_mutex_attribute_protocol_get(const f_thread_mutex_attribute_t *attribute, int *protocol) { #ifndef _di_level_0_parameter_checking_ - if (!lock) return F_status_set_error(F_parameter); + if (!attribute) return F_status_set_error(F_parameter); + if (!protocol) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_rwlock_rdlock(lock); + const int error = pthread_mutexattr_getprotocol(attribute, protocol); if (error) { - if (error == EAGAIN) return F_status_set_error(F_resource_not); - if (error == EDEADLK) return F_status_set_error(F_deadlock); if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_lock_ +#endif // _di_f_thread_mutex_attribute_protocol_get_ -#ifndef _di_f_thread_lock_try_ - f_status_t f_thread_lock_try(f_thread_lock_t *lock) { +#ifndef _di_f_thread_mutex_attribute_protocol_set_ + f_status_t f_thread_mutex_attribute_protocol_set(const int protocol, f_thread_mutex_attribute_t *attribute) { #ifndef _di_level_0_parameter_checking_ - if (!lock) return F_status_set_error(F_parameter); + if (!attribute) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_rwlock_tryrdlock(lock); + const int error = pthread_mutexattr_setprotocol(attribute, protocol); if (error) { - if (error == EAGAIN) return F_status_set_error(F_resource_not); - if (error == EBUSY) return F_busy; if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); + if (error == ENOTSUP) return F_status_set_error(F_supported_not); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_lock_try_ +#endif // _di_f_thread_mutex_attribute_protocol_set_ #ifndef _di_f_thread_mutex_attributes_adjust_ f_status_t f_thread_mutex_attributes_adjust(const f_array_length_t length, f_thread_mutex_attributes_t *attributes) { @@ -1072,67 +2130,34 @@ extern "C" { #endif // _di_f_thread_mutex_attributes_adjust_ #ifndef _di_f_thread_mutex_attributes_decimate_by_ - f_status_t f_thread_mutex_attributes_decimate_by(const f_array_length_t amount, f_thread_mutex_attributes_t *attributes) { - #ifndef _di_level_0_parameter_checking_ - if (!amount) return F_status_set_error(F_parameter); - if (!attributes) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - if (attributes->size - amount > 0) { - return private_f_thread_mutex_attributes_adjust(attributes->size - amount, attributes); - } - - return private_f_thread_mutex_attributes_adjust(0, attributes); - } -#endif // _di_f_thread_mutex_attributes_decimate_by_ - -#ifndef _di_f_thread_mutex_attributes_decrease_by_ - f_status_t f_thread_mutex_attributes_decrease_by(const f_array_length_t amount, f_thread_mutex_attributes_t *attributes) { - #ifndef _di_level_0_parameter_checking_ - if (!amount) return F_status_set_error(F_parameter); - if (!attributes) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - if (attributes->size - amount > 0) { - return private_f_thread_mutex_attributes_resize(attributes->size - amount, attributes); - } - - return private_f_thread_mutex_attributes_resize(0, attributes); - } -#endif // _di_f_thread_mutex_attributes_decrease_by_ - -#ifndef _di_f_thread_mutex_attribute_create_ - f_status_t f_thread_mutex_attribute_create(f_thread_mutex_attribute_t *attribute) { - #ifndef _di_level_0_parameter_checking_ - if (!attribute) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ - - const int error = pthread_mutexattr_init(attribute); - - // @todo figure out the error codes and update accordingly. - if (error) { - if (error == EAGAIN) return F_status_set_error(F_resource_not); - if (error == EBUSY) return F_status_set_error(F_busy); - if (error == EINVAL) return F_status_set_error(F_parameter); - if (error == ENOMEM) return F_status_set_error(F_memory_not); - if (error == EPERM) return F_status_set_error(F_prohibited); + f_status_t f_thread_mutex_attributes_decimate_by(const f_array_length_t amount, f_thread_mutex_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ - return F_status_set_error(F_failure); + if (attributes->size - amount > 0) { + return private_f_thread_mutex_attributes_adjust(attributes->size - amount, attributes); } - return F_none; + return private_f_thread_mutex_attributes_adjust(0, attributes); } -#endif // _di_f_thread_mutex_attribute_create_ +#endif // _di_f_thread_mutex_attributes_decimate_by_ -#ifndef _di_f_thread_mutex_attribute_delete_ - f_status_t f_thread_mutex_attribute_delete(f_thread_mutex_attribute_t *attribute) { +#ifndef _di_f_thread_mutex_attributes_decrease_by_ + f_status_t f_thread_mutex_attributes_decrease_by(const f_array_length_t amount, f_thread_mutex_attributes_t *attributes) { #ifndef _di_level_0_parameter_checking_ - if (!attribute) return F_status_set_error(F_parameter); + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - return private_f_thread_mutex_attribute_delete(attribute); + if (attributes->size - amount > 0) { + return private_f_thread_mutex_attributes_resize(attributes->size - amount, attributes); + } + + return private_f_thread_mutex_attributes_resize(0, attributes); } -#endif // _di_f_thread_mutex_attribute_delete_ +#endif // _di_f_thread_mutex_attributes_decrease_by_ #ifndef _di_f_thread_mutex_attributes_increase_ f_status_t f_thread_mutex_attributes_increase(f_thread_mutex_attributes_t *attributes) { @@ -1239,6 +2264,30 @@ extern "C" { } #endif // _di_f_thread_mutex_lock_ +#ifndef _di_f_thread_mutex_lock_timed_ + f_status_t f_thread_mutex_lock_timed(const struct timespec *timeout, f_thread_mutex_t *mutex) { + #ifndef _di_level_0_parameter_checking_ + if (!timeout) return F_status_set_error(F_parameter); + if (!mutex) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_mutex_timedlock(mutex, timeout); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ENOTRECOVERABLE) return F_status_set_error(F_recover_not); + if (error == EOWNERDEAD) return F_status_set_error(F_thread_not); + if (error == ETIMEDOUT) return F_time; + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_mutex_lock_timed_ + #ifndef _di_f_thread_mutex_lock_try_ f_status_t f_thread_mutex_lock_try(f_thread_mutex_t *mutex) { #ifndef _di_level_0_parameter_checking_ @@ -1259,6 +2308,49 @@ extern "C" { } #endif // _di_f_thread_mutex_lock_try_ +#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_ + if (!mutex) return F_status_set_error(F_parameter); + if (!ceiling) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_mutex_getprioceiling(mutex, ceiling); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_mutex_priority_ceiling_get_ + +#ifndef _di_f_thread_mutex_priority_ceiling_set_ + f_status_t f_thread_mutex_priority_ceiling_set(const int ceiling, f_thread_mutex_t *mutex, int *previous) { + #ifndef _di_level_0_parameter_checking_ + if (!mutex) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_mutex_setprioceiling(mutex, ceiling, previous); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ENOTRECOVERABLE) return F_status_set_error(F_recover_not); + if (error == EOWNERDEAD) return F_status_set_error(F_thread_not); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_mutex_priority_ceiling_set_ + #ifndef _di_f_thread_mutex_unlock_ f_status_t f_thread_mutex_unlock(f_thread_mutex_t *mutex) { #ifndef _di_level_0_parameter_checking_ @@ -1392,6 +2484,62 @@ extern "C" { } #endif // _di_f_thread_once_ +#ifndef _di_f_thread_scheduler_parameter_get_ + f_status_t f_thread_scheduler_parameter_get(const f_thread_id_t id, int *policy, struct sched_param *parameter) { + #ifndef _di_level_0_parameter_checking_ + if (!policy) return F_status_set_error(F_parameter); + if (!parameter) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_getschedparam(id, policy, parameter); + + if (error) { + if (error == ENOTSUP) return F_status_set_error(F_supported_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_scheduler_parameter_get_ + +#ifndef _di_f_thread_scheduler_parameter_set_ + f_status_t f_thread_scheduler_parameter_set(const f_thread_id_t id, const int policy, const struct sched_param *parameter) { + #ifndef _di_level_0_parameter_checking_ + if (!policy) return F_status_set_error(F_parameter); + if (!parameter) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_setschedparam(id, policy, parameter); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_scheduler_parameter_set_ + +#ifndef _di_f_thread_scheduler_priority_set_ + f_status_t f_thread_scheduler_priority_set(const f_thread_id_t id, const int priority) { + + const int error = pthread_setschedprio(id, priority); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); + if (error == ESRCH) return F_status_set_error(F_found_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_scheduler_priority_set_ + #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_ @@ -1545,6 +2693,210 @@ extern "C" { } #endif // _di_f_thread_signal_queue_ +#ifndef _di_f_thread_spin_create_ + f_status_t f_thread_spin_create(const int shared, f_thread_spin_t *spin) { + #ifndef _di_level_0_parameter_checking_ + if (!spin) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_spin_init(spin, shared); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == ENOMEM) return F_status_set_error(F_memory_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_spin_create_ + +#ifndef _di_f_thread_spin_delete_ + f_status_t f_thread_spin_delete(f_thread_spin_t *spin) { + #ifndef _di_level_0_parameter_checking_ + if (!spin) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_spin_delete(spin); + } +#endif // _di_f_thread_spin_delete_ + +#ifndef _di_f_thread_spin_lock_ + f_status_t f_thread_spin_lock(f_thread_spin_t *spin) { + #ifndef _di_level_0_parameter_checking_ + if (!spin) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_spin_lock(spin); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EDEADLK) return F_status_set_error(F_deadlock); + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_spin_lock_ + +#ifndef _di_f_thread_spin_lock_try_ + f_status_t f_thread_spin_lock_try(f_thread_spin_t *spin) { + #ifndef _di_level_0_parameter_checking_ + if (!spin) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_spin_trylock(spin); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EBUSY) return F_busy; + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_spin_lock_try_ + +#ifndef _di_f_thread_spin_unlock_ + f_status_t f_thread_spin_unlock(f_thread_spin_t *spin) { + #ifndef _di_level_0_parameter_checking_ + if (!spin) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_spin_unlock(spin); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_spin_unlock_ + +#ifndef _di_f_thread_spins_adjust_ + f_status_t f_thread_spins_adjust(const f_array_length_t length, f_thread_spins_t *spins) { + #ifndef _di_level_0_parameter_checking_ + if (!spins) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_spins_adjust(length, spins); + } +#endif // _di_f_thread_spins_adjust_ + +#ifndef _di_f_thread_spins_decimate_by_ + f_status_t f_thread_spins_decimate_by(const f_array_length_t amount, f_thread_spins_t *spins) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!spins) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (spins->size - amount > 0) { + return private_f_thread_spins_adjust(spins->size - amount, spins); + } + + return private_f_thread_spins_adjust(0, spins); + } +#endif // _di_f_thread_spins_decimate_by_ + +#ifndef _di_f_thread_spins_decrease_by_ + f_status_t f_thread_spins_decrease_by(const f_array_length_t amount, f_thread_spins_t *spins) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!spins) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (spins->size - amount > 0) { + return private_f_thread_spins_resize(spins->size - amount, spins); + } + + return private_f_thread_spins_resize(0, spins); + } +#endif // _di_f_thread_spins_decrease_by_ + +#ifndef _di_f_thread_spins_increase_ + f_status_t f_thread_spins_increase(f_thread_spins_t *spins) { + #ifndef _di_level_0_parameter_checking_ + if (!spins) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (spins->used + 1 > spins->size) { + f_array_length_t size = spins->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (spins->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_spins_resize(size, spins); + } + + return F_data_not; + } +#endif // _di_f_thread_spins_increase_ + +#ifndef _di_f_thread_spins_increase_by_ + f_status_t f_thread_spins_increase_by(const f_array_length_t amount, f_thread_spins_t *spins) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!spins) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (spins->used + amount > spins->size) { + if (spins->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_thread_spins_resize(spins->used + amount, spins); + } + + return F_data_not; + } +#endif // _di_f_thread_spins_increase_by_ + +#ifndef _di_f_thread_spins_resize_ + f_status_t f_thread_spins_resize(const f_array_length_t length, f_thread_spins_t *spins) { + #ifndef _di_level_0_parameter_checking_ + if (!spins) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_spins_resize(length, spins); + } +#endif // _di_f_thread_spins_resize_ + +#ifndef _di_f_thread_unlock_ + f_status_t f_thread_unlock(f_thread_lock_t *lock) { + #ifndef _di_level_0_parameter_checking_ + if (!lock) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_rwlock_unlock(lock); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_unlock_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_0/f_thread/c/thread.h b/level_0/f_thread/c/thread.h index 35a9c06..51239a1 100644 --- a/level_0/f_thread/c/thread.h +++ b/level_0/f_thread/c/thread.h @@ -10,47 +10,6 @@ #ifndef _F_thread_h #define _F_thread_h -// @todo pthread_attr_getstackaddr() -// @todo pthread_attr_getstacksize() -// @todo pthread_attr_setstackaddr() -// @todo pthread_attr_setstacksize() -// @todo pthread_barrier_destroy -// @todo pthread_barrier_init -// @todo pthread_barrier_wait -// @todo pthread_barrierattr_destroy -// @todo pthread_barrierattr_getpshared -// @todo pthread_barrierattr_init -// @todo pthread_barrierattr_setpshared -// @todo pthread_condattr_getclock -// @todo pthread_condattr_getpshared -// @todo pthread_condattr_setclock -// @todo pthread_condattr_setpshared -// @todo pthread_getconcurrency -// @todo pthread_getschedparam -// @todo pthread_key_delete -// @todo pthread_mutex_getprioceiling -// @todo pthread_mutex_setprioceiling -// @todo pthread_mutex_timedlock -// @todo pthread_mutexattr_getprioceiling -// @todo pthread_mutexattr_getprotocol -// @todo pthread_mutexattr_getpshared -// @todo pthread_mutexattr_gettype -// @todo pthread_mutexattr_setprioceiling -// @todo pthread_mutexattr_setprotocol -// @todo pthread_mutexattr_setpshared -// @todo pthread_mutexattr_settype -// @todo pthread_rwlock_destroy -// @todo pthread_rwlock_init -// @todo pthread_rwlock_timedrdlock -// @todo pthread_rwlock_timedwrlock -// @todo pthread_rwlock_trywrlock -// @todo pthread_rwlock_unlock -// @todo pthread_rwlock_wrlock -// @todo pthread_rwlockattr_destroy -// @todo pthread_rwlockattr_getpshared -// @todo pthread_rwlockattr_init -// @todo pthread_rwlockattr_setpshared - // include pre-requirements #define _GNU_SOURCE @@ -142,6 +101,86 @@ extern "C" { #endif // _di_f_thread_attribute_affinity_set_ /** + * Get the clock selection thread condition attribute. + * + * @param attribute + * The thread condition attribute. + * @param id + * The clock ID. + * + * @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 pthread_condattr_getclock() + */ +#ifndef _di_f_thread_attribute_clock_get_ + extern f_status_t f_thread_attribute_clock_get(const f_thread_condition_attribute_t *attribute, clockid_t *id); +#endif // _di_f_thread_attribute_clock_get_ + +/** + * Set the clock selection thread condition attribute. + * + * @param id + * The clock ID. + * @param attribute + * The thread condition attribute. + * + * @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 pthread_condattr_setclock() + */ +#ifndef _di_f_thread_attribute_clock_set_ + extern f_status_t f_thread_attribute_clock_set(const clockid_t id, f_thread_condition_attribute_t *attribute); +#endif // _di_f_thread_attribute_clock_set_ + +/** + * Get the process shared thread condition attribute. + * + * @param attribute + * The thread condition attribute. + * @param shared + * The process shared attribute 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 pthread_condattr_getpshared() + */ +#ifndef _di_f_thread_attribute_condition_shared_get_ + extern f_status_t f_thread_attribute_condition_shared_get(const f_thread_condition_attribute_t *attribute, int *shared); +#endif // _di_f_thread_attribute_condition_shared_get_ + +/** + * Set the process shared thread condition attribute. + * + * @param shared + * The process shared attribute value. + * @param attribute + * The thread condition attribute. + * + * @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 pthread_condattr_setpshared() + */ +#ifndef _di_f_thread_attribute_condition_shared_set_ + extern f_status_t f_thread_attribute_condition_shared_set(const int shared, f_thread_condition_attribute_t *attribute); +#endif // _di_f_thread_attribute_condition_shared_set_ + +/** * Create (initialize) a thread attribute structure. * * @param attribute @@ -489,7 +528,7 @@ extern "C" { * Set the stack of the thread attribute. * * @param stack_size - * The size of the stack_set. + * The size of the stack. * @param stack * The stack to assign. * @param attribute @@ -509,7 +548,47 @@ extern "C" { #endif // _di_f_thread_attribute_stack_set_ /** - * Resize the string attributes array. + * Get the stack size of the thread attribute. + * + * @param attribute + * The thread attributes to process. + * @param stack_size + * The assigned size of the stack. + * + * @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 pthread_attr_getstacksize() + */ +#ifndef _di_f_thread_attribute_stack_size_get_ + extern f_status_t f_thread_attribute_stack_size_get(const f_thread_attribute_t attribute, size_t *stack_size); +#endif // _di_f_thread_attribute_stack_size_get_ + +/** + * Set the stack size of the thread attribute. + * + * @param stack_size + * The size of the stack. + * @param attribute + * The thread attributes to update. + * + * @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 pthread_attr_setstacksize() + */ +#ifndef _di_f_thread_attribute_stack_size_set_ + extern f_status_t f_thread_attribute_stack_size_set(const size_t stack_size, f_thread_attribute_t *attribute); +#endif // _di_f_thread_attribute_stack_size_set_ + +/** + * Resize the thread attributes array. * * @param length * The new size to use. @@ -527,7 +606,7 @@ extern "C" { #endif // _di_f_thread_attributes_adjust_ /** - * Resize the string attributes array to a smaller size. + * Resize the thread attributes 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. @@ -549,7 +628,7 @@ extern "C" { #endif // _di_f_thread_attributes_decimate_by_ /** - * Resize the string attributes array to a smaller size. + * Resize the thread attributes 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. @@ -571,7 +650,7 @@ extern "C" { #endif // _di_f_thread_attributes_decrease_by_ /** - * Increase the size of the string attributes array, but only if necessary. + * Increase the size of the thread attributes 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. @@ -592,9 +671,9 @@ extern "C" { #endif // _di_f_thread_attributes_increase_ /** - * Resize the string attributes array to a larger size. + * Resize the thread attributes array to a larger size. * - * This will resize making the string larger based on the given length. + * 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. * @@ -616,7 +695,7 @@ extern "C" { #endif // _di_f_thread_attributes_increase_by_ /** - * Resize the string attributes array. + * Resize the thread attributes array. * * @param length * The new size to use. @@ -634,81 +713,35 @@ extern "C" { #endif // _di_f_thread_attributes_resize_ /** - * Get the ID of the calling thread. - * - * @return - * ID of the calling thread - * - * @see pthread_self() - */ -#ifndef _di_f_thread_caller_ - extern f_thread_id_t f_thread_caller(); -#endif // _di_f_thread_caller_ - -/** - * Cancel a thread. - * - * @param id - * The thread to cancel. - * - * @return - * 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() - */ -#ifndef _di_f_thread_cancel_ - extern f_status_t f_thread_cancel(const f_thread_id_t id); -#endif // _di_f_thread_cancel_ - -/** - * Assign a cancellation state. + * Create (initialize) a thread barrier attribute structure. * - * @param state - * The cancellation state to assign. - * @param previous - * (optional) The previously assigned cancellation state. - * Set to NULL to not use. - * (Note: Linux allows this to be optional/NULL but POSIX does not explicitly defined this and there may be portability issues.) + * @param attribute + * (optional) The attribute to set. + * Set to NULL to not use (in which case the default attribute is used). * * @return * F_none on success. * * 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_setcancelstate() + * @see pthread_barrierattr_init() */ -#ifndef _di_f_thread_cancel_state_set_ - extern f_status_t f_thread_cancel_state_set(const int state, int *previous); -#endif // _di_f_thread_cancel_state_set_ +#ifndef _di_f_thread_barrier_attribute_create_ + extern f_status_t f_thread_barrier_attribute_create(f_thread_barrier_attribute_t *attribute); +#endif // _di_f_thread_barrier_attribute_create_ /** - * Force any pending thread cancellation to be processed. - * - * If there is no pending thread cancel, nothing happens. - * If there is a pending thread cancel, the thread cancels and this function never returns. + * Delete a thread barrier attribute structure. * - * @return - * F_none on success. + * On successfully delete, the pointer address is set to 0. * - * @see pthread_testcancel() - */ -#ifndef _di_f_thread_cancel_test_ - extern f_status_t f_thread_cancel_test(); -#endif // _di_f_thread_cancel_test_ - -/** - * Assign a cancellation type. + * The pthread_barrierattr_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 type - * The cancellation type to assign. - * @param previous - * (optional) The previously assigned cancellation type. - * Set to NULL to not use. - * (Note: Linux allows this to be optional/NULL but POSIX does not explicitly defined this and there may be portability issues.) + * @param attribute + * The thread barrier_attributes to delete. * * @return * F_none on success. @@ -716,55 +749,19 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_failure (with error bit) on any other error. * - * @see pthread_setcanceltype() - */ -#ifndef _di_f_thread_cancel_type_set_ - extern f_status_t f_thread_cancel_type_set(const int type, int *previous); -#endif // _di_f_thread_cancel_type_set_ - -/** - * Get the clock ID for the given thread. - * - * @param id_thread - * The ID of the thread to use. - * @param id_clock - * The retrieved clock ID. - * - * @return - * F_none on success. - * - * 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() - */ -#ifndef _di_f_thread_clock_get_id_ - extern f_status_t f_thread_clock_get_id(const f_thread_id_t id_thread, clockid_t *id_clock); -#endif // _di_f_thread_clock_get_id_ - -/** - * Compare two different thread IDs. - * - * POSIX designates that the thread id (pthread_t) to be loosely defined and can be anything from an integer to a structure. - * For portability purposes, calling pthread_equal() is the only safe way to compare two thread ids. - * - * @return - * F_equal_to if the two thread IDs are the same. - * F_equal_to_not if the two thread IDs are different. - * - * @see pthread_equal() + * @see pthread_barrierattr_destroy() */ -#ifndef _di_f_thread_compare_ - extern f_status_t f_thread_compare(const f_thread_id_t id1, const f_thread_id_t id2); -#endif // _di_f_thread_compare_ +#ifndef _di_f_thread_barrier_attribute_delete_ + extern f_status_t f_thread_barrier_attribute_delete(f_thread_barrier_attribute_t *attribute); +#endif // _di_f_thread_barrier_attribute_delete_ /** - * Initialize a attribute. + * Get the barrier process shared thread attribute. * * @param attribute - * The attribute to set. - * This assigns the default to the attribute. + * The barrier thread attribute. + * @param shared + * The process shared attribute value. * * @return * F_none on success. @@ -772,41 +769,39 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_failure (with error bit) on any other error. * - * @see pthread_condattr_init() + * @see pthread_barrierattr_getpshared() */ -#ifndef _di_f_thread_condition_attribute_create_ - extern f_status_t f_thread_condition_attribute_create(f_thread_condition_attribute_t *attribute); -#endif // _di_f_thread_condition_attribute_create_ +#ifndef _di_f_thread_barrier_attribute_shared_get_ + extern f_status_t f_thread_barrier_attribute_shared_get(const f_thread_barrier_attribute_t *attribute, int *shared); +#endif // _di_f_thread_barrier_attribute_shared_get_ /** - * Delete a thread attribute. - * - * The pthread_condattr_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. + * Set the barrier process shared thread attribute. * + * @param shared + * The process shared attribute value. * @param attribute - * The attribute to delete. + * The barrier thread attribute. * * @return * F_none on success. * - * 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() + * @see pthread_barrierattr_setpshared() */ -#ifndef _di_f_thread_condition_attribute_delete_ - extern f_status_t f_thread_condition_attribute_delete(f_thread_condition_attribute_t *attribute); -#endif // _di_f_thread_condition_attribute_delete_ +#ifndef _di_f_thread_barrier_attribute_shared_set_ + extern f_status_t f_thread_barrier_attribute_shared_set(const int shared, f_thread_barrier_attribute_t *attribute); +#endif // _di_f_thread_barrier_attribute_shared_set_ /** - * Resize the string attributes array. + * Resize the thread barrier attributes array. * * @param length * The new size to use. * @param attributes - * The string attributes array to resize. + * The thread attributes array to resize. * * @return * F_none on success. @@ -814,12 +809,12 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_condition_attributes_adjust_ - extern f_status_t f_thread_condition_attributes_adjust(const f_array_length_t length, f_thread_condition_attributes_t *attributes); -#endif // _di_f_thread_condition_attributes_adjust_ +#ifndef _di_f_thread_barrier_attributes_adjust_ + extern f_status_t f_thread_barrier_attributes_adjust(const f_array_length_t length, f_thread_barrier_attributes_t *attributes); +#endif // _di_f_thread_barrier_attributes_adjust_ /** - * Resize the string attributes array to a smaller size. + * Resize the thread barrier attributes 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. @@ -828,7 +823,7 @@ extern "C" { * @param amount * A positive number representing how much to decimate the size by. * @param attributes - * The string attributes array to resize. + * The thread attributes array to resize. * * @return * F_none on success. @@ -836,12 +831,12 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_condition_attributes_decimate_by_ - extern f_status_t f_thread_condition_attributes_decimate_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes); -#endif // _di_f_thread_condition_attributes_decimate_by_ +#ifndef _di_f_thread_barrier_attributes_decimate_by_ + extern f_status_t f_thread_barrier_attributes_decimate_by(const f_array_length_t amount, f_thread_barrier_attributes_t *attributes); +#endif // _di_f_thread_barrier_attributes_decimate_by_ /** - * Resize the string attributes array to a smaller size. + * Resize the thread barrier attributes 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. @@ -850,7 +845,7 @@ extern "C" { * @param amount * A positive number representing how much to decrease the size by. * @param attributes - * The string attributes array to resize. + * The thread attributes array to resize. * * @return * F_none on success. @@ -858,18 +853,18 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_condition_attributes_decrease_by_ - extern f_status_t f_thread_condition_attributes_decrease_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes); -#endif // _di_f_thread_condition_attributes_decrease_by_ +#ifndef _di_f_thread_barrier_attributes_decrease_by_ + extern f_status_t f_thread_barrier_attributes_decrease_by(const f_array_length_t amount, f_thread_barrier_attributes_t *attributes); +#endif // _di_f_thread_barrier_attributes_decrease_by_ /** - * Increase the size of the string attributes array, but only if necessary. + * Increase the size of the thread barrier attributes 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 attributes - * The string attributes array to resize. + * The thread attributes array to resize. * * @return * F_none on success. @@ -879,21 +874,21 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_condition_attributes_increase_ - extern f_status_t f_thread_condition_attributes_increase(f_thread_condition_attributes_t *attributes); -#endif // _di_f_thread_condition_attributes_increase_ +#ifndef _di_f_thread_barrier_attributes_increase_ + extern f_status_t f_thread_barrier_attributes_increase(f_thread_barrier_attributes_t *attributes); +#endif // _di_f_thread_barrier_attributes_increase_ /** - * Resize the string attributes array to a larger size. + * Resize the thread barrier attributes array to a larger size. * - * This will resize making the string larger based on the given length. + * 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 attributes - * The string attributes array to resize. + * The thread attributes array to resize. * * @return * F_none on success. @@ -903,17 +898,17 @@ extern "C" { * 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); -#endif // _di_f_thread_condition_attributes_increase_by_ +#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); +#endif // _di_f_thread_barrier_attributes_increase_by_ /** - * Resize the string attributes array. + * Resize the thread barrier attributes array. * * @param length * The new size to use. * @param attributes - * The string attributes array to adjust. + * The thread attributes array to adjust. * * @return * F_none on success. @@ -921,76 +916,1205 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_condition_attributes_resize_ - extern f_status_t f_thread_condition_attributes_resize(const f_array_length_t length, f_thread_condition_attributes_t *attributes); -#endif // _di_f_thread_condition_attributes_resize_ +#ifndef _di_f_thread_barrier_attributes_resize_ + extern f_status_t f_thread_barrier_attributes_resize(const f_array_length_t length, f_thread_barrier_attributes_t *attributes); +#endif // _di_f_thread_barrier_attributes_resize_ /** - * Initialize a condition. + * Create (initialize) a thread barrier structure. * - * @param attribute - * (optional) The attribute to set. - * Set to NULL to not use (in which case the default attribute is used). - * @param condition - * The condition to wait on. + * @param barrier + * (optional) The barrier to set. + * Set to NULL to not use (in which case the default barrier is used). * * @return * F_none on success. * * 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_cond_init() + * @see pthread_barrier_init() */ -#ifndef _di_f_thread_condition_create_ - extern f_status_t f_thread_condition_create(const f_thread_condition_attribute_t *attribute, f_thread_condition_t *condition); -#endif // _di_f_thread_condition_create_ +#ifndef _di_f_thread_barrier_create_ + extern f_status_t f_thread_barrier_create(const unsigned int count, f_thread_barrier_attribute_t * const attribute, f_thread_barrier_t *barrier); +#endif // _di_f_thread_barrier_create_ /** - * Delete a thread condition. + * Delete a thread barrier structure. * - * The pthread_cond_destroy() function has no distinction like the *_destroy() and the *_delete() used by the FLL project. + * On successfully delete, the pointer address is set to 0. + * + * The pthread_barrier_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 condition - * The condition to delete. + * @param barrier + * The thread barriers to delete. * * @return * F_none on success. * - * F_busy (with error bit) if the condition is busy. * F_parameter (with error bit) if a parameter is invalid. * F_failure (with error bit) on any other error. * - * @see pthread_cond_destroy() + * @see pthread_barrier_destroy() */ -#ifndef _di_f_thread_condition_delete_ - extern f_status_t f_thread_condition_delete(f_thread_condition_t *condition); -#endif // _di_f_thread_condition_delete_ +#ifndef _di_f_thread_barrier_delete_ + extern f_status_t f_thread_barrier_delete(f_thread_barrier_t *barrier); +#endif // _di_f_thread_barrier_delete_ /** - * Unblock all threads waiting on a condition. + * Wait on a barrier, effectively synchronizing multiple threads with some barrier. * - * @param condition - * The condition to broadcast the unblock signal to. + * @param barrier + * The barrier to wait on. + * @param result + * (optional) the return value, which will be PTHREAD_BARRIER_SERIAL_THREAD for one thread and 0 for others. + * Set to NULL to not use. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * @see pthread_barrier_wait() + */ +#ifndef _di_f_thread_barrier_wait_ + extern f_status_t f_thread_barrier_wait(f_thread_barrier_t *barrier, int *result); +#endif // _di_f_thread_barrier_wait_ + +/** + * Resize the thread barriers array. + * + * @param length + * The new size to use. + * @param barriers + * The thread barriers 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_barriers_adjust_ + extern f_status_t f_thread_barriers_adjust(const f_array_length_t length, f_thread_barriers_t *barriers); +#endif // _di_f_thread_barriers_adjust_ + +/** + * Resize the thread barriers 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 barriers + * The thread barriers 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_barriers_decimate_by_ + extern f_status_t f_thread_barriers_decimate_by(const f_array_length_t amount, f_thread_barriers_t *barriers); +#endif // _di_f_thread_barriers_decimate_by_ + +/** + * Resize the thread barriers 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 barriers + * The thread barriers 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_barriers_decrease_by_ + extern f_status_t f_thread_barriers_decrease_by(const f_array_length_t amount, f_thread_barriers_t *barriers); +#endif // _di_f_thread_barriers_decrease_by_ + +/** + * Increase the size of the thread barriers 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 barriers + * The thread barriers 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_barriers_increase_ + extern f_status_t f_thread_barriers_increase(f_thread_barriers_t *barriers); +#endif // _di_f_thread_barriers_increase_ + +/** + * Resize the thread barriers 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 barriers + * The thread barriers 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_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); +#endif // _di_f_thread_barriers_increase_by_ + +/** + * Resize the thread barriers array. + * + * @param length + * The new size to use. + * @param barriers + * The thread barriers 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_barriers_resize_ + extern f_status_t f_thread_barriers_resize(const f_array_length_t length, f_thread_barriers_t *barriers); +#endif // _di_f_thread_barriers_resize_ + +/** + * Get the ID of the calling thread. + * + * @return + * ID of the calling thread + * + * @see pthread_self() + */ +#ifndef _di_f_thread_caller_ + extern f_thread_id_t f_thread_caller(); +#endif // _di_f_thread_caller_ + +/** + * Cancel a thread. + * + * @param id + * The thread to cancel. + * + * @return + * 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() + */ +#ifndef _di_f_thread_cancel_ + extern f_status_t f_thread_cancel(const f_thread_id_t id); +#endif // _di_f_thread_cancel_ + +/** + * Assign a cancellation state. + * + * @param state + * The cancellation state to assign. + * @param previous + * (optional) The previously assigned cancellation state. + * Set to NULL to not use. + * (Note: Linux allows this to be optional/NULL but POSIX does not explicitly defined this and there may be portability issues.) + * + * @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 pthread_setcancelstate() + */ +#ifndef _di_f_thread_cancel_state_set_ + extern f_status_t f_thread_cancel_state_set(const int state, int *previous); +#endif // _di_f_thread_cancel_state_set_ + +/** + * Force any pending thread cancellation to be processed. + * + * If there is no pending thread cancel, nothing happens. + * If there is a pending thread cancel, the thread cancels and this function never returns. + * + * @return + * F_none on success. + * + * @see pthread_testcancel() + */ +#ifndef _di_f_thread_cancel_test_ + extern f_status_t f_thread_cancel_test(); +#endif // _di_f_thread_cancel_test_ + +/** + * Assign a cancellation type. + * + * @param type + * The cancellation type to assign. + * @param previous + * (optional) The previously assigned cancellation type. + * Set to NULL to not use. + * (Note: Linux allows this to be optional/NULL but POSIX does not explicitly defined this and there may be portability issues.) + * + * @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 pthread_setcanceltype() + */ +#ifndef _di_f_thread_cancel_type_set_ + extern f_status_t f_thread_cancel_type_set(const int type, int *previous); +#endif // _di_f_thread_cancel_type_set_ + +/** + * Get the clock ID for the given thread. + * + * @param id_thread + * The ID of the thread to use. + * @param id_clock + * The retrieved clock ID. + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_clock_get_id_ + extern f_status_t f_thread_clock_get_id(const f_thread_id_t id_thread, clockid_t *id_clock); +#endif // _di_f_thread_clock_get_id_ + +/** + * Compare two different thread IDs. + * + * POSIX designates that the thread id (pthread_t) to be loosely defined and can be anything from an integer to a structure. + * For portability purposes, calling pthread_equal() is the only safe way to compare two thread ids. + * + * @return + * F_equal_to if the two thread IDs are the same. + * F_equal_to_not if the two thread IDs are different. + * + * @see pthread_equal() + */ +#ifndef _di_f_thread_compare_ + extern f_status_t f_thread_compare(const f_thread_id_t id1, const f_thread_id_t id2); +#endif // _di_f_thread_compare_ + +/** + * Get the level of concurrency. + * + * A level of 0 designates the system to automatically choose concurrency level. + * Any non-zero level is considered a hint and will be followed at the systems discretion. + * + * @param level + * The concurrency level. + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_attribute_concurrency_get_ + extern f_status_t f_thread_attribute_concurrency_get(int *level); +#endif // _di_f_thread_attribute_concurrency_get_ + +/** + * Set the level of concurrency. + * + * A level of 0 designates the system to automatically choose concurrency level. + * Any non-zero level is considered a hint and will be followed at the systems discretion. + * + * @param level + * The concurrency level. + * + * @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 pthread_setconcurrency() + */ +#ifndef _di_f_thread_attribute_concurrency_set_ + extern f_status_t f_thread_attribute_concurrency_set(const int level); +#endif // _di_f_thread_attribute_concurrency_set_ + +/** + * Initialize a attribute. + * + * @param attribute + * The attribute to set. + * This assigns the default to the attribute. + * + * @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 pthread_condattr_init() + */ +#ifndef _di_f_thread_condition_attribute_create_ + extern f_status_t f_thread_condition_attribute_create(f_thread_condition_attribute_t *attribute); +#endif // _di_f_thread_condition_attribute_create_ + +/** + * Delete a thread attribute. + * + * The pthread_condattr_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 attribute + * The attribute to delete. + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_condition_attribute_delete_ + extern f_status_t f_thread_condition_attribute_delete(f_thread_condition_attribute_t *attribute); +#endif // _di_f_thread_condition_attribute_delete_ + +/** + * Resize the thread attributes array. + * + * @param length + * The new size to use. + * @param attributes + * The string attributes 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_condition_attributes_adjust_ + extern f_status_t f_thread_condition_attributes_adjust(const f_array_length_t length, f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_adjust_ + +/** + * Resize the thread attributes 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 attributes + * The string attributes 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_condition_attributes_decimate_by_ + extern f_status_t f_thread_condition_attributes_decimate_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_decimate_by_ + +/** + * Resize the thread attributes 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 attributes + * The string attributes 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_condition_attributes_decrease_by_ + extern f_status_t f_thread_condition_attributes_decrease_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_decrease_by_ + +/** + * Increase the size of the thread attributes 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 attributes + * The string attributes 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_condition_attributes_increase_ + extern f_status_t f_thread_condition_attributes_increase(f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_increase_ + +/** + * Resize the thread attributes 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 attributes + * The string attributes 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_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); +#endif // _di_f_thread_condition_attributes_increase_by_ + +/** + * Resize the thread attributes array. + * + * @param length + * The new size to use. + * @param attributes + * The string attributes 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_condition_attributes_resize_ + extern f_status_t f_thread_condition_attributes_resize(const f_array_length_t length, f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_resize_ + +/** + * Initialize a condition. + * + * @param attribute + * (optional) The attribute to set. + * Set to NULL to not use (in which case the default attribute is used). + * @param condition + * The condition to wait on. + * + * @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 pthread_cond_init() + */ +#ifndef _di_f_thread_condition_create_ + extern f_status_t f_thread_condition_create(const f_thread_condition_attribute_t *attribute, f_thread_condition_t *condition); +#endif // _di_f_thread_condition_create_ + +/** + * Delete a thread condition. + * + * The pthread_cond_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 condition + * The condition to delete. + * + * @return + * F_none on success. + * + * F_busy (with error bit) if the condition is busy. + * F_parameter (with error bit) if a parameter is invalid. + * F_failure (with error bit) on any other error. + * + * @see pthread_cond_destroy() + */ +#ifndef _di_f_thread_condition_delete_ + extern f_status_t f_thread_condition_delete(f_thread_condition_t *condition); +#endif // _di_f_thread_condition_delete_ + +/** + * Unblock all threads waiting on a condition. + * + * @param condition + * The condition to broadcast the unblock signal to. + * + * @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 pthread_cond_broadcast() + */ +#ifndef _di_f_thread_condition_unblock_all_ + extern f_status_t f_thread_condition_unblock_all(f_thread_condition_t *condition); +#endif // _di_f_thread_condition_unblock_all_ + +/** + * Unblock all threads waiting on a condition. + * + * @param condition + * The condition to broadcast the unblock signal to. + * + * @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 pthread_cond_signal() + */ +#ifndef _di_f_thread_condition_unblock_any_ + extern f_status_t f_thread_condition_unblock_any(f_thread_condition_t *condition); +#endif // _di_f_thread_condition_unblock_any_ + +/** + * Wait until condition is triggered. + * + * This is a blocking operation. + * + * @param condition + * The condition to wait on. + * @param mutex + * The mutex to use for waiting on condition. + * + * @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 pthread_cond_wait() + */ +#ifndef _di_f_thread_condition_wait_ + extern f_status_t f_thread_condition_wait(f_thread_condition_t *condition, f_thread_mutex_t *mutex); +#endif // _di_f_thread_condition_wait_ + +/** + * Wait until condition is triggered, blocking until the timeout expires. + * + * This is a semi-blocking operation. + * This will block until timeout and then no longer block. + * + * @param wait + * The amount of time to wait for. + * The wait time is relative to the clock, so consider calling clock_gettime() and then adding the amount of wait time. + * @param condition + * The condition to wait on. + * @param mutex + * The mutex to use for waiting on condition. + * + * @return + * F_none on success. + * F_time on success, and wait timeout was reached before condition was triggered. + * + * 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() + */ +#ifndef _di_f_thread_condition_wait_timed_ + extern f_status_t f_thread_condition_wait_timed(const struct timespec *wait, f_thread_condition_t *condition, f_thread_mutex_t *mutex); +#endif // _di_f_thread_condition_wait_timed_ + +/** + * Resize the thread conditions array. + * + * @param length + * The new size to use. + * @param conditions + * The string conditions 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_conditions_adjust_ + extern f_status_t f_thread_conditions_adjust(const f_array_length_t length, f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_adjust_ + +/** + * Resize the thread conditions 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 conditions + * The string conditions 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_conditions_decimate_by_ + extern f_status_t f_thread_conditions_decimate_by(const f_array_length_t amount, f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_decimate_by_ + +/** + * Resize the thread conditions 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 conditions + * The string conditions 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_conditions_decrease_by_ + extern f_status_t f_thread_conditions_decrease_by(const f_array_length_t amount, f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_decrease_by_ + +/** + * Increase the size of the thread conditions 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 conditions + * The string conditions 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_conditions_increase_ + extern f_status_t f_thread_conditions_increase(f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_increase_ + +/** + * Resize the thread conditions 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 conditions + * The string conditions 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_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); +#endif // _di_f_thread_conditions_increase_by_ + +/** + * Resize the thread conditions array. + * + * @param length + * The new size to use. + * @param conditions + * The string conditions 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_conditions_resize_ + extern f_status_t f_thread_conditions_resize(const f_array_length_t length, f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_resize_ + +/** + * Create a thread. + * + * @param attribute + * (optional) The thread attributes. + * Set to NULL to use default attributes. + * @param id + * The thread ID. + * This gets populated with the created thread ID (aka: the "child" thread). + * @param routine + * The function to execute. + * @param argument + * (optional) The structure containing all arguments to pass to the routine. + * Set to NULL to not pass an argument. + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_create_ + extern f_status_t f_thread_create(const f_thread_attribute_t *attribute, f_thread_id_t *id, void *(*routine) (void *), void *argument); +#endif // _di_f_thread_create_ + +/** + * Detatch the given thread. + * + * When a detached thread exits, the resources will automatically be returned to the system without needing another thread to join with it. + * + * Only joinable, undetached, threads are detachable. + * + * Once a thread is detached, it can no longer be joined. + * + * @param id + * The ID of the thread to detach. + * + * @return + * F_none on success. + * + * 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 + * + * + * @see pthread_detach() + */ +#ifndef _di_f_thread_detach_ + extern f_status_t f_thread_detach(const f_thread_id_t id); +#endif // _di_f_thread_detach_ + +/** + * Have the current thread exit. + * + * @param result + * The code returned by the exited thread. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * @see pthread_exit() + */ +#ifndef _di_f_thread_exit_ + extern f_status_t f_thread_exit(int *result); +#endif // _di_f_thread_exit_ + +/** + * Wait until the given thread exits and then join it to the current thread. + * + * This is a blocking operation. + * + * @param id + * The ID of the thread to wait for. + * @param result + * (optional) The data returned by the terminated thread (usually the exist status). + * If the terminated thread is cancelled, then this holds PTHREAD_CANCELED. + * Set to NULL to not use. + * + * @return + * F_none on success. + * + * 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 + * + * + * @see pthread_join() + */ +#ifndef _di_f_thread_join_ + extern f_status_t f_thread_join(const f_thread_id_t id, void **result); +#endif // _di_f_thread_join_ + +/** + * Try to join the given thread to the current thread. + * + * This is a non-blocking operation. + * + * @param id + * The ID of the thread to wait for. + * @param result + * (optional) The data returned by the terminated thread (usually the exist status). + * If the terminated thread is cancelled, then this holds PTHREAD_CANCELED. + * Set to NULL to not use. + * + * @return + * F_none on success. + * F_busy on success, but thread could not be joined because it has not yet exited. + * + * 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 + * + * + * @see pthread_tryjoin_np() + */ +#ifndef _di_f_thread_join_try_ + extern f_status_t f_thread_join_try(const f_thread_id_t id, void **result); +#endif // _di_f_thread_join_try_ + +/** + * Try to join the given thread to the current thread, blocking until the timeout expires. + * + * This is a semi-blocking operation. + * This will block until timeout and then no longer block. + * + * @param id + * The ID of the thread to wait for. + * @param wait + * The amount of time to wait for. + * The wait time is relative to the clock, so consider calling clock_gettime() and then adding the amount of wait time. + * @param result + * (optional) The data returned by the terminated thread (usually the exist status). + * If the terminated thread is cancelled, then this holds PTHREAD_CANCELED. + * Set to NULL to not use. + * + * @return + * F_none on success. + * F_busy on success, but thread could not be joined because it has not yet exited. + * F_time on success, but thread could not be joined because it has not yet exited and the wait timeout was reached. + * + * F_deadlock (with error bit) if operation would cause a deadlock. + * 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 thread. + * + * + * @see pthread_timedjoin_np() + */ +#ifndef _di_f_thread_join_timed_ + extern f_status_t f_thread_join_timed(const f_thread_id_t id, const struct timespec wait, void **result); +#endif // _di_f_thread_join_timed_ + +/** + * Create a thread key. + * + * @param routine + * The function to execute for deallocation/deleting. + * @param key + * The thread key. + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_key_create_ + extern f_status_t f_thread_key_create(void (*routine) (void *), f_thread_key_t *key); +#endif // _di_f_thread_key_create_ + +/** + * Delete a thread key. + * + * The pthread_key_delete() 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 key + * The key 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. + * + * @see pthread_key_delete() + */ +#ifndef _di_f_thread_key_delete_ + extern f_status_t f_thread_key_delete(f_thread_key_t *key); +#endif // _di_f_thread_key_delete_ + +/** + * Get the value of a thread key. + * + * @param key + * The thread key. + * @param value + * The assigned thread key value. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * @see pthread_getspecific() + */ +#ifndef _di_f_thread_key_get_ + extern f_status_t f_thread_key_get(const f_thread_key_t key, void **value); +#endif // _di_f_thread_key_get_ + +/** + * Get the value of a thread key. + * + * @param key + * The thread key. + * @param value + * The thread key value to assign. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * + * @see pthread_setspecific() + */ +#ifndef _di_f_thread_key_set_ + extern f_status_t f_thread_key_set(const f_thread_key_t key, const void *value); +#endif // _di_f_thread_key_set_ + +/** + * Resize the thread keys array. + * + * @param length + * The new size to use. + * @param keys + * The string keys 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_keys_adjust_ + extern f_status_t f_thread_keys_adjust(const f_array_length_t length, f_thread_keys_t *keys); +#endif // _di_f_thread_keys_adjust_ + +/** + * Resize the thread keys 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 keys + * The string keys 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_keys_decimate_by_ + extern f_status_t f_thread_keys_decimate_by(const f_array_length_t amount, f_thread_keys_t *keys); +#endif // _di_f_thread_keys_decimate_by_ + +/** + * Resize the thread keys 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 keys + * The string keys 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_keys_decrease_by_ + extern f_status_t f_thread_keys_decrease_by(const f_array_length_t amount, f_thread_keys_t *keys); +#endif // _di_f_thread_keys_decrease_by_ + +/** + * Increase the size of the thread keys 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 keys + * The string keys 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_keys_increase_ + extern f_status_t f_thread_keys_increase(f_thread_keys_t *keys); +#endif // _di_f_thread_keys_increase_ + +/** + * Resize the thread keys 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 keys + * The string keys 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_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); +#endif // _di_f_thread_keys_increase_by_ + +/** + * Resize the thread keys array. + * + * @param length + * The new size to use. + * @param keys + * The string keys 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_keys_resize_ + extern f_status_t f_thread_keys_resize(const f_array_length_t length, f_thread_keys_t *keys); +#endif // _di_f_thread_keys_resize_ + +/** + * Create a thread lock attribute. + * + * @param attribute + * The lock attributes to create. + * + * @return + * F_none on success. + * + * F_busy (with error bit) if the lock is busy. + * 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 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() + */ +#ifndef _di_f_thread_lock_attribute_create_ + extern f_status_t f_thread_lock_attribute_create(f_thread_lock_attribute_t *attribute); +#endif // _di_f_thread_lock_attribute_create_ + +/** + * Delete a thread lock attribute. + * + * The pthread_lockattr_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 attribute + * The attribute to delete. * * @return * F_none on success. * + * 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_cond_broadcast() + * @see pthread_rwlockattr_destroy() */ -#ifndef _di_f_thread_condition_unblock_all_ - extern f_status_t f_thread_condition_unblock_all(f_thread_condition_t *condition); -#endif // _di_f_thread_condition_unblock_all_ +#ifndef _di_f_thread_lock_attribute_delete_ + extern f_status_t f_thread_lock_attribute_delete(f_thread_lock_attribute_t *attribute); +#endif // _di_f_thread_lock_attribute_delete_ /** - * Unblock all threads waiting on a condition. + * Get the lock attribute process shared thread attribute. * - * @param condition - * The condition to broadcast the unblock signal to. + * @param attribute + * The lock attribute. + * @param shared + * The lock shared attribute value. * * @return * F_none on success. @@ -998,69 +2122,345 @@ extern "C" { * F_parameter (with error bit) if a parameter is invalid. * F_failure (with error bit) on any other error. * - * @see pthread_cond_signal() + * @see pthread_rwlockattr_getpshared() */ -#ifndef _di_f_thread_condition_unblock_any_ - extern f_status_t f_thread_condition_unblock_any(f_thread_condition_t *condition); -#endif // _di_f_thread_condition_unblock_any_ +#ifndef _di_f_thread_lock_attribute_shared_get_ + extern f_status_t f_thread_lock_attribute_shared_get(const f_thread_lock_attribute_t *attribute, int *shared); +#endif // _di_f_thread_lock_attribute_shared_get_ /** - * Wait until condition is triggered. + * Set the lock attribute process shared thread attribute. * - * This is a blocking operation. + * @param attribute + * The lock attribute. + * @param shared + * The lock shared attribute value. * - * @param condition - * The condition to wait on. - * @param mutex - * The mutex to use for waiting on condition. + * @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 pthread_rwlockattr_setpshared() + */ +#ifndef _di_f_thread_lock_attribute_shared_set_ + extern f_status_t f_thread_lock_attribute_shared_set(const int shared, f_thread_lock_attribute_t *attribute); +#endif // _di_f_thread_lock_attribute_shared_set_ + +/** + * Resize the thread attributes array. + * + * @param length + * The new size to use. + * @param attributes + * The string attributes 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_lock_attributes_adjust_ + extern f_status_t f_thread_lock_attributes_adjust(const f_array_length_t length, f_thread_lock_attributes_t *attributes); +#endif // _di_f_thread_lock_attributes_adjust_ + +/** + * Resize the thread attributes 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 attributes + * The string attributes 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_lock_attributes_decimate_by_ + extern f_status_t f_thread_lock_attributes_decimate_by(const f_array_length_t amount, f_thread_lock_attributes_t *attributes); +#endif // _di_f_thread_lock_attributes_decimate_by_ + +/** + * Resize the thread attributes 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 attributes + * The string attributes 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_lock_attributes_decrease_by_ + extern f_status_t f_thread_lock_attributes_decrease_by(const f_array_length_t amount, f_thread_lock_attributes_t *attributes); +#endif // _di_f_thread_lock_attributes_decrease_by_ + +/** + * Increase the size of the thread attributes 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 attributes + * The string attributes 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_lock_attributes_increase_ + extern f_status_t f_thread_lock_attributes_increase(f_thread_lock_attributes_t *attributes); +#endif // _di_f_thread_lock_attributes_increase_ + +/** + * Resize the thread attributes 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 attributes + * The string attributes 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_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); +#endif // _di_f_thread_lock_attributes_increase_by_ + +/** + * Resize the thread attributes array. + * + * @param length + * The new size to use. + * @param attributes + * The string attributes 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_lock_attributes_resize_ + extern f_status_t f_thread_lock_attributes_resize(const f_array_length_t length, f_thread_lock_attributes_t *attributes); +#endif // _di_f_thread_lock_attributes_resize_ + +/** + * Create a thread read/write lock. + * + * @param attribute + * The lock attribute. + * @param lock + * The lock to create. + * + * @return + * F_none on success. + * + * 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_cond_wait() + * @see pthread_rwlock_init() */ -#ifndef _di_f_thread_condition_wait_ - extern f_status_t f_thread_condition_wait(f_thread_condition_t *condition, f_thread_mutex_t *mutex); -#endif // _di_f_thread_condition_wait_ +#ifndef _di_f_thread_lock_create_ + extern f_status_t f_thread_lock_create(const f_thread_lock_attribute_t *attribute, f_thread_lock_t *lock); +#endif // _di_f_thread_lock_create_ /** - * Wait until condition is triggered, blocking until the timeout expires. + * Delete a thread read/write lock. * - * This is a semi-blocking operation. - * This will block until timeout and then no longer block. + * The pthread_lock_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 wait - * The amount of time to wait for. - * The wait time is relative to the clock, so consider calling clock_gettime() and then adding the amount of wait time. - * @param condition - * The condition to wait on. - * @param mutex - * The mutex to use for waiting on condition. + * @param lock + * The lock to delete. * * @return * F_none on success. - * F_time on success, and wait timeout was reached before condition was triggered. * + * F_busy (with error bit) if the lock is busy. * 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() + * @see pthread_rwlock_destroy() */ -#ifndef _di_f_thread_condition_wait_timed_ - extern f_status_t f_thread_condition_wait_timed(const struct timespec *wait, f_thread_condition_t *condition, f_thread_mutex_t *mutex); -#endif // _di_f_thread_condition_wait_timed_ +#ifndef _di_f_thread_lock_delete_ + extern f_status_t f_thread_lock_delete(f_thread_lock_t *lock); +#endif // _di_f_thread_lock_delete_ + +/** + * Lock the read part of a read/write lock. + * + * This is a blocking function. + * + * @param lock + * The thread lock. + * + * @return + * F_none on success. + * + * F_deadlock (with error bit) if operation would cause a deadlock. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see pthread_rwlock_rdlock() + */ +#ifndef _di_f_thread_lock_read_ + extern f_status_t f_thread_lock_read(f_thread_lock_t *lock); +#endif // _di_f_thread_lock_read_ + +/** + * Lock the read part of a read/write lock, waiting for a set period of time to get the lock if already locked. + * + * If the read part of the read/write lock 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 lock + * The read/write lock. + * + * @return + * F_none on success. + * F_time if the timeout was reached before obtaining the lock. + * + * F_deadlock (with error bit) if operation would cause a deadlock. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see pthread_rwlock_timedrdlock() + */ +#ifndef _di_f_thread_lock_read_timed_ + extern f_status_t f_thread_lock_read_timed(const struct timespec *timeout, f_thread_lock_t *lock); +#endif // _di_f_thread_lock_read_timed_ + +/** + * Try to lock the read part of a read/write lock. + * + * If lock is already locked, return immediately. + * + * This is a non-blocking function. + * + * @param lock + * The thread lock. + * + * @return + * F_none on success. + * F_busy on success, but the lock is already locked. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_resource_not (with error bit) if max locks is reached. + * + * @see pthread_rwlock_tryrdlock() + */ +#ifndef _di_f_thread_lock_read_try_ + extern f_status_t f_thread_lock_read_try(f_thread_lock_t *lock); +#endif // _di_f_thread_lock_read_try_ + +/** + * Lock the write part of a read/write lock. + * + * This is a blocking function. + * + * @param lock + * The thread lock. + * + * @return + * F_none on success. + * + * F_deadlock (with error bit) if operation would cause a deadlock. + * F_parameter (with error bit) if a parameter is invalid. + * F_resource_not (with error bit) if max locks is reached. + * + * @see pthread_rwlock_wrlock() + */ +#ifndef _di_f_thread_lock_write_ + extern f_status_t f_thread_lock_write(f_thread_lock_t *lock); +#endif // _di_f_thread_lock_write_ + +/** + * Lock the write part of a read/write lock, waiting for a set period of time to get the lock if already locked. + * + * If the write part of the read/write lock 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 lock + * The read/write lock. + * + * @return + * F_none on success. + * F_time if the timeout was reached before obtaining the lock. + * + * F_deadlock (with error bit) if operation would cause a deadlock. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see pthread_rwlock_timedwrlock() + */ +#ifndef _di_f_thread_lock_write_timed_ + extern f_status_t f_thread_lock_write_timed(const struct timespec *timeout, f_thread_lock_t *lock); +#endif // _di_f_thread_lock_write_timed_ + +/** + * Try to lock the read part of a read/write lock. + * + * If lock is already locked, return immediately. + * + * This is a non-blocking function. + * + * @param lock + * The thread lock. + * + * @return + * F_none on success. + * F_busy on success, but the lock is already locked. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_resource_not (with error bit) if max locks is reached. + * + * @see pthread_rwlock_trywrlock() + */ +#ifndef _di_f_thread_lock_write_try_ + extern f_status_t f_thread_lock_write_try(f_thread_lock_t *lock); +#endif // _di_f_thread_lock_write_try_ /** - * Resize the string conditions array. + * Resize the read/write locks array. * * @param length * The new size to use. - * @param conditions - * The string conditions array to resize. + * @param locks + * The string locks array to resize. * * @return * F_none on success. @@ -1068,12 +2468,12 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_conditions_adjust_ - extern f_status_t f_thread_conditions_adjust(const f_array_length_t length, f_thread_conditions_t *conditions); -#endif // _di_f_thread_conditions_adjust_ +#ifndef _di_f_thread_locks_adjust_ + extern f_status_t f_thread_locks_adjust(const f_array_length_t length, f_thread_locks_t *locks); +#endif // _di_f_thread_locks_adjust_ /** - * Resize the string conditions array to a smaller size. + * Resize the read/write locks 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. @@ -1081,8 +2481,8 @@ extern "C" { * * @param amount * A positive number representing how much to decimate the size by. - * @param conditions - * The string conditions array to resize. + * @param locks + * The string locks array to resize. * * @return * F_none on success. @@ -1090,12 +2490,12 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_conditions_decimate_by_ - extern f_status_t f_thread_conditions_decimate_by(const f_array_length_t amount, f_thread_conditions_t *conditions); -#endif // _di_f_thread_conditions_decimate_by_ +#ifndef _di_f_thread_locks_decimate_by_ + extern f_status_t f_thread_locks_decimate_by(const f_array_length_t amount, f_thread_locks_t *locks); +#endif // _di_f_thread_locks_decimate_by_ /** - * Resize the string conditions array to a smaller size. + * Resize the read/write locks 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. @@ -1103,8 +2503,8 @@ extern "C" { * * @param amount * A positive number representing how much to decrease the size by. - * @param conditions - * The string conditions array to resize. + * @param locks + * The string locks array to resize. * * @return * F_none on success. @@ -1112,18 +2512,18 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_conditions_decrease_by_ - extern f_status_t f_thread_conditions_decrease_by(const f_array_length_t amount, f_thread_conditions_t *conditions); -#endif // _di_f_thread_conditions_decrease_by_ +#ifndef _di_f_thread_locks_decrease_by_ + extern f_status_t f_thread_locks_decrease_by(const f_array_length_t amount, f_thread_locks_t *locks); +#endif // _di_f_thread_locks_decrease_by_ /** - * Increase the size of the string conditions array, but only if necessary. + * Increase the size of the read/write 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 conditions - * The string conditions array to resize. + * @param locks + * The string locks array to resize. * * @return * F_none on success. @@ -1133,21 +2533,21 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_conditions_increase_ - extern f_status_t f_thread_conditions_increase(f_thread_conditions_t *conditions); -#endif // _di_f_thread_conditions_increase_ +#ifndef _di_f_thread_locks_increase_ + extern f_status_t f_thread_locks_increase(f_thread_locks_t *locks); +#endif // _di_f_thread_locks_increase_ /** - * Resize the string conditions array to a larger size. + * Resize the read/write locks array to a larger size. * - * This will resize making the string larger based on the given length. + * 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 conditions - * The string conditions array to resize. + * @param locks + * The string locks array to resize. * * @return * F_none on success. @@ -1157,17 +2557,17 @@ extern "C" { * 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); -#endif // _di_f_thread_conditions_increase_by_ +#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); +#endif // _di_f_thread_locks_increase_by_ /** - * Resize the string conditions array. + * Resize the read/write locks array. * * @param length * The new size to use. - * @param conditions - * The string conditions array to adjust. + * @param locks + * The string locks array to adjust. * * @return * F_none on success. @@ -1175,271 +2575,217 @@ extern "C" { * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. */ -#ifndef _di_f_thread_conditions_resize_ - extern f_status_t f_thread_conditions_resize(const f_array_length_t length, f_thread_conditions_t *conditions); -#endif // _di_f_thread_conditions_resize_ +#ifndef _di_f_thread_locks_resize_ + extern f_status_t f_thread_locks_resize(const f_array_length_t length, f_thread_locks_t *locks); +#endif // _di_f_thread_locks_resize_ /** - * Create a thread. + * Create a thread mutex attribute. * * @param attribute - * (optional) The thread attributes. - * Set to NULL to use default attributes. - * @param id - * The thread ID. - * This gets populated with the created thread ID (aka: the "child" thread). - * @param routine - * The function to execute. - * @param argument - * (optional) The structure containing all arguments to pass to the routine. - * Set to NULL to not pass an argument. + * The mutex attributes to create. * * @return * F_none on success. * + * F_busy (with error bit) if the mutex is busy. + * 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_resource_not (with error bit) if there are not enough resources to create another thread. + * 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_create() + * @see pthread_mutexattr_init() */ -#ifndef _di_f_thread_create_ - extern f_status_t f_thread_create(const f_thread_attribute_t *attribute, f_thread_id_t *id, void *(*routine) (void *), void *argument); -#endif // _di_f_thread_create_ +#ifndef _di_f_thread_mutex_attribute_create_ + extern f_status_t f_thread_mutex_attribute_create(f_thread_mutex_attribute_t *attribute); +#endif // _di_f_thread_mutex_attribute_create_ /** - * Detatch the given thread. - * - * When a detached thread exits, the resources will automatically be returned to the system without needing another thread to join with it. - * - * Only joinable, undetached, threads are detachable. - * - * Once a thread is detached, it can no longer be joined. - * - * @param id - * The ID of the thread to detach. - * - * @return - * F_none on success. - * - * 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 - * + * Delete a thread mutex attribute. * - * @see pthread_detach() - */ -#ifndef _di_f_thread_detach_ - extern f_status_t f_thread_detach(const f_thread_id_t id); -#endif // _di_f_thread_detach_ - -/** - * Have the current thread exit. + * The pthread_mutexattr_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 result - * The code returned by the exited thread. + * @param attribute + * The attribute to delete. * * @return * F_none on success. * + * 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_exit() + * @see pthread_mutexattr_destroy() */ -#ifndef _di_f_thread_exit_ - extern f_status_t f_thread_exit(int *result); -#endif // _di_f_thread_exit_ +#ifndef _di_f_thread_mutex_attribute_delete_ + extern f_status_t f_thread_mutex_attribute_delete(f_thread_mutex_attribute_t *attribute); +#endif // _di_f_thread_mutex_attribute_delete_ /** - * Wait until the given thread exits and then join it to the current thread. - * - * This is a blocking operation. + * Get the mutex attribute priority ceiling. * - * @param id - * The ID of the thread to wait for. - * @param result - * (optional) The data returned by the terminated thread (usually the exist status). - * If the terminated thread is cancelled, then this holds PTHREAD_CANCELED. - * Set to NULL to not use. + * @param attribute + * The thread mutex attribute. + * @param ceiling + * The priority ceiling. * * @return * F_none on success. * - * 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_prohibited (with error bit) if not allowed to perform the operation. * - * @see pthread_join() + * @see pthread_mutexattr_getprioceiling() */ -#ifndef _di_f_thread_join_ - extern f_status_t f_thread_join(const f_thread_id_t id, void **result); -#endif // _di_f_thread_join_ +#ifndef _di_f_thread_mutex_attribute_priority_ceiling_get_ + extern f_status_t f_thread_mutex_attribute_priority_ceiling_get(const f_thread_mutex_attribute_t *attribute, int *ceiling); +#endif // _di_f_thread_mutex_attribute_priority_ceiling_get_ /** - * Try to join the given thread to the current thread. + * Set the mutex attribute priority ceiling. * - * This is a non-blocking operation. - * - * @param id - * The ID of the thread to wait for. - * @param result - * (optional) The data returned by the terminated thread (usually the exist status). - * If the terminated thread is cancelled, then this holds PTHREAD_CANCELED. - * Set to NULL to not use. + * @param ceiling + * The priority ceiling. + * @param attribute + * The thread mutex attribute. * * @return * F_none on success. - * F_busy on success, but thread could not be joined because it has not yet exited. * - * 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_prohibited (with error bit) if not allowed to perform the operation. * - * @see pthread_tryjoin_np() + * @see pthread_mutexattr_setprioceiling() */ -#ifndef _di_f_thread_join_try_ - extern f_status_t f_thread_join_try(const f_thread_id_t id, void **result); -#endif // _di_f_thread_join_try_ +#ifndef _di_f_thread_mutex_attribute_priority_ceiling_set_ + extern f_status_t f_thread_mutex_attribute_priority_ceiling_set(const int ceiling, f_thread_mutex_attribute_t *attribute); +#endif // _di_f_thread_mutex_attribute_priority_ceiling_set_ /** - * Try to join the given thread to the current thread, blocking until the timeout expires. + * Get the mutex attribute process shared thread attribute. * - * This is a semi-blocking operation. - * This will block until timeout and then no longer block. - * - * @param id - * The ID of the thread to wait for. - * @param wait - * The amount of time to wait for. - * The wait time is relative to the clock, so consider calling clock_gettime() and then adding the amount of wait time. - * @param result - * (optional) The data returned by the terminated thread (usually the exist status). - * If the terminated thread is cancelled, then this holds PTHREAD_CANCELED. - * Set to NULL to not use. + * @param attribute + * The mutex attribute. + * @param shared + * The mutex shared attribute value. * * @return * F_none on success. - * F_busy on success, but thread could not be joined because it has not yet exited. - * F_time on success, but thread could not be joined because it has not yet exited and the wait timeout was reached. * - * F_deadlock (with error bit) if operation would cause a deadlock. - * 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 thread. - * + * F_failure (with error bit) on any other error. * - * @see pthread_timedjoin_np() + * @see pthread_mutexattr_getpshared() */ -#ifndef _di_f_thread_join_timed_ - extern f_status_t f_thread_join_timed(const f_thread_id_t id, const struct timespec wait, void **result); -#endif // _di_f_thread_join_timed_ +#ifndef _di_f_thread_mutex_attribute_shared_get_ + extern f_status_t f_thread_mutex_attribute_shared_get(const f_thread_mutex_attribute_t *attribute, int *shared); +#endif // _di_f_thread_mutex_attribute_shared_get_ /** - * Create a thread key. + * Set the mutex attribute process shared thread attribute. * - * @param routine - * The function to execute for deallocation/deleting. - * @param key - * The thread key. + * @param attribute + * The mutex attribute. + * @param shared + * The mutex shared attribute value. * * @return * F_none on success. * - * 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() + * @see pthread_mutexattr_setpshared() */ -#ifndef _di_f_thread_key_create_ - extern f_status_t f_thread_key_create(void (*routine) (void *), f_thread_key_t *key); -#endif // _di_f_thread_key_create_ +#ifndef _di_f_thread_mutex_attribute_shared_set_ + extern f_status_t f_thread_mutex_attribute_shared_set(const int shared, f_thread_mutex_attribute_t *attribute); +#endif // _di_f_thread_mutex_attribute_shared_set_ /** - * Get the value of a thread key. + * Get the mutex attribute type. * - * @param key - * The thread key. - * @param value - * The assigned thread key value. + * @param attribute + * The mutex attribute. + * @param type + * The type. * * @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 pthread_getspecific() + * @see pthread_mutexattr_gettype() */ -#ifndef _di_f_thread_key_get_ - extern f_status_t f_thread_key_get(const f_thread_key_t key, void **value); -#endif // _di_f_thread_key_get_ +#ifndef _di_f_thread_mutex_attribute_type_get_ + extern f_status_t f_thread_mutex_attribute_type_get(const f_thread_mutex_attribute_t *attribute, int *type); +#endif // _di_f_thread_mutex_attribute_type_get_ /** - * Get the value of a thread key. + * Set the mutex attribute process shared thread attribute. * - * @param key - * The thread key. - * @param value - * The thread key value to assign. + * @param type + * The type. + * @param attribute + * The mutex attribute. * * @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 pthread_setspecific() + * @see pthread_mutexattr_settype() */ -#ifndef _di_f_thread_key_set_ - extern f_status_t f_thread_key_set(const f_thread_key_t key, const void *value); -#endif // _di_f_thread_key_set_ +#ifndef _di_f_thread_mutex_attribute_type_set_ + extern f_status_t f_thread_mutex_attribute_type_set(const int type, f_thread_mutex_attribute_t *attribute); +#endif // _di_f_thread_mutex_attribute_type_set_ /** - * Make a read lock on the read/write lock. + * Get the mutex attribute protocol. * - * @param lock - * The read/write lock. + * @param attribute + * The thread mutex attribute. + * @param protocol + * The protocol. * * @return * F_none on success. * - * F_deadlock (with error bit) if operation would cause a deadlock. * F_parameter (with error bit) if a parameter is invalid. - * F_resource_not (with error bit) if max read/write locks is reached. + * F_prohibited (with error bit) if not allowed to perform the operation. * - * @see pthread_rwlock_rdlock() + * @see pthread_mutexattr_getprotocol() */ -#ifndef _di_f_thread_lock_ - extern f_status_t f_thread_lock(f_thread_lock_t *lock); -#endif // _di_f_thread_lock_ +#ifndef _di_f_thread_mutex_attribute_protocol_get_ + extern f_status_t f_thread_mutex_attribute_protocol_get(const f_thread_mutex_attribute_t *attribute, int *protocol); +#endif // _di_f_thread_mutex_attribute_protocol_get_ /** - * Try to make a read lock on the read/write lock. + * Set the mutex attribute protocol. * - * @param lock - * The read/write lock. + * @param protocol + * The protocol. + * @param attribute + * The thread mutex attribute. * * @return * F_none on success. - * F_busy on success, but the read/write lock is already locked. * * F_parameter (with error bit) if a parameter is invalid. - * F_resource_not (with error bit) if max read/write locks is reached. + * F_prohibited (with error bit) if not allowed to perform the operation. + * F_supported_not (with error bit) if the protocol is not supported. * - * @see pthread_rwlock_tryrdlock() + * @see pthread_mutexattr_setprotocol() */ -#ifndef _di_f_thread_lock_try_ - extern f_status_t f_thread_lock_try(f_thread_lock_t *lock); -#endif // _di_f_thread_lock_try_ +#ifndef _di_f_thread_mutex_attribute_protocol_set_ + extern f_status_t f_thread_mutex_attribute_protocol_set(const int protocol, f_thread_mutex_attribute_t *attribute); +#endif // _di_f_thread_mutex_attribute_protocol_set_ /** - * Resize the string attributes array. + * Resize the thread attributes array. * * @param length * The new size to use. @@ -1457,7 +2803,7 @@ extern "C" { #endif // _di_f_thread_mutex_attributes_adjust_ /** - * Resize the string attributes array to a smaller size. + * Resize the thread attributes 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. @@ -1479,7 +2825,7 @@ extern "C" { #endif // _di_f_thread_mutex_attributes_decimate_by_ /** - * Resize the string attributes array to a smaller size. + * Resize the thread attributes 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. @@ -1494,58 +2840,14 @@ extern "C" { * 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_mutex_attributes_decrease_by_ - extern f_status_t f_thread_mutex_attributes_decrease_by(const f_array_length_t amount, f_thread_mutex_attributes_t *attributes); -#endif // _di_f_thread_mutex_attributes_decrease_by_ - -/** - * Create a thread mutex attribute. - * - * @param attribute - * The mutex attributes to create. - * - * @return - * F_none on success. - * - * F_busy (with error bit) if the mutex is busy. - * 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 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_mutexattr_init() - */ -#ifndef _di_f_thread_mutex_attribute_create_ - extern f_status_t f_thread_mutex_attribute_create(f_thread_mutex_attribute_t *attribute); -#endif // _di_f_thread_mutex_attribute_create_ - -/** - * Delete a thread mutex attribute. - * - * The pthread_mutexattr_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 attribute - * The attribute to delete. - * - * @return - * F_none on success. - * - * 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_mutexattr_destroy() - */ -#ifndef _di_f_thread_mutex_attribute_delete_ - extern f_status_t f_thread_mutex_attribute_delete(f_thread_mutex_attribute_t *attribute); -#endif // _di_f_thread_mutex_attribute_delete_ + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_mutex_attributes_decrease_by_ + extern f_status_t f_thread_mutex_attributes_decrease_by(const f_array_length_t amount, f_thread_mutex_attributes_t *attributes); +#endif // _di_f_thread_mutex_attributes_decrease_by_ /** - * Increase the size of the string attributes array, but only if necessary. + * Increase the size of the thread attributes 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. @@ -1566,9 +2868,9 @@ extern "C" { #endif // _di_f_thread_mutex_attributes_increase_ /** - * Resize the string attributes array to a larger size. + * Resize the thread attributes array to a larger size. * - * This will resize making the string larger based on the given length. + * 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. * @@ -1590,7 +2892,7 @@ extern "C" { #endif // _di_f_thread_mutex_attributes_increase_by_ /** - * Resize the string attributes array. + * Resize the thread attributes array. * * @param length * The new size to use. @@ -1607,7 +2909,6 @@ extern "C" { extern f_status_t f_thread_mutex_attributes_resize(const f_array_length_t length, f_thread_mutex_attributes_t *attributes); #endif // _di_f_thread_mutex_attributes_resize_ - /** * Create a thread mutex. * @@ -1677,6 +2978,35 @@ extern "C" { #endif // _di_f_thread_mutex_lock_ /** + * Lock the mutex, waiting for a set period of time to get the lock if already locked. + * + * If the mutex 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 mutex + * The thread mutex. + * + * @return + * F_none on success. + * F_time if the timeout was reached before obtaining the lock. + * + * F_deadlock (with error bit) if operation would cause a deadlock. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if not allowed to perform the operation. + * F_recover_not (with error bit) if the state protected by the mutex is not recoverable. + * 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). + * + * @see pthread_mutex_timedlock() + */ +#ifndef _di_f_thread_mutex_lock_timed_ + extern f_status_t f_thread_mutex_lock_timed(const struct timespec *timeout, f_thread_mutex_t *mutex); +#endif // _di_f_thread_mutex_lock_timed_ + +/** * Try to lock the mutex. * * If mutex is already locked, return immediately. @@ -1700,6 +3030,53 @@ extern "C" { #endif // _di_f_thread_mutex_lock_try_ /** + * Get the mutex priority ceiling. + * + * @param mutex + * The thread mutex. + * @param ceiling + * The priority ceiling. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if not allowed to perform the operation. + * + * @see pthread_mutex_getprioceiling() + */ +#ifndef _di_f_thread_mutex_priority_ceiling_get_ + extern f_status_t f_thread_mutex_priority_ceiling_get(f_thread_mutex_t *mutex, int *ceiling); +#endif // _di_f_thread_mutex_priority_ceiling_get_ + +/** + * Set the mutex priority ceiling. + * + * @param ceiling + * The priority ceiling. + * @param mutex + * The thread mutex. + * @param previous + * (optional) The previous priority ceiling. + * Set to NULL to not use. + * + * @return + * F_none on success. + * + * F_deadlock (with error bit) if operation would cause a deadlock. + * F_parameter (with error bit) if a parameter is invalid. + * F_prohibited (with error bit) if not allowed to perform the operation. + * F_recover_not (with error bit) if the state protected by the mutex is not recoverable (for a "robust" mutex). + * 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). + * + * @see pthread_mutex_setprioceiling() + */ +#ifndef _di_f_thread_mutex_priority_ceiling_set_ + extern f_status_t f_thread_mutex_priority_ceiling_set(const int ceiling, f_thread_mutex_t *mutex, int *previous); +#endif // _di_f_thread_mutex_priority_ceiling_set_ + +/** * Unlock the mutex. * * @param mutex @@ -1719,7 +3096,7 @@ extern "C" { #endif // _di_f_thread_mutex_unlock_ /** - * Resize the string mutexs array. + * Resize the thread mutexs array. * * @param length * The new size to use. @@ -1737,7 +3114,7 @@ extern "C" { #endif // _di_f_thread_mutexs_adjust_ /** - * Resize the string mutexs array to a smaller size. + * Resize the thread mutexs 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. @@ -1759,7 +3136,7 @@ extern "C" { #endif // _di_f_thread_mutexs_decimate_by_ /** - * Resize the string mutexs array to a smaller size. + * Resize the thread mutexs 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. @@ -1781,7 +3158,7 @@ extern "C" { #endif // _di_f_thread_mutexs_decrease_by_ /** - * Increase the size of the string mutexs array, but only if necessary. + * Increase the size of the thread mutexs 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. @@ -1802,9 +3179,9 @@ extern "C" { #endif // _di_f_thread_mutexs_increase_ /** - * Resize the string mutexs array to a larger size. + * Resize the thread mutexs array to a larger size. * - * This will resize making the string larger based on the given length. + * 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. * @@ -1826,7 +3203,7 @@ extern "C" { #endif // _di_f_thread_mutexs_increase_by_ /** - * Resize the string mutexs array. + * Resize the thread mutexs array. * * @param length * The new size to use. @@ -1863,7 +3240,75 @@ extern "C" { #endif // _di_f_thread_once_ /** - * Resize the string sets array. + * Get the thread scheduler parameter. + * + * @param id + * The thread ID. + * @param policy + * The scheduler policy + * @param parameter + * The scheduler parameter + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_scheduler_parameter_get_ + extern f_status_t f_thread_scheduler_parameter_get(const f_thread_id_t id, int *policy, struct sched_param *parameter); +#endif // _di_f_thread_scheduler_parameter_get_ + +/** + * Set the thread scheduler parameter. + * + * @param id + * The thread ID. + * @param policy + * The scheduler policy + * @param parameter + * The scheduler parameter + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_scheduler_parameter_set_ + extern f_status_t f_thread_scheduler_parameter_set(const f_thread_id_t id, const int policy, const struct sched_param *parameter); +#endif // _di_f_thread_scheduler_parameter_set_ + +/** + * Set the thread scheduler priority. + * + * @param id + * The thread ID. + * @param priority + * The scheduler priority. + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_scheduler_priority_set_ + extern f_status_t f_thread_scheduler_priority_set(const f_thread_id_t id, const int priority); +#endif // _di_f_thread_scheduler_priority_set_ + +/** + * Resize the thread sets array. * * @param length * The new size to use. @@ -1881,7 +3326,7 @@ extern "C" { #endif // _di_f_thread_sets_adjust_ /** - * Resize the string sets array to a smaller size. + * Resize the thread sets 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. @@ -1903,7 +3348,7 @@ extern "C" { #endif // _di_f_thread_sets_decimate_by_ /** - * Resize the string sets array to a smaller size. + * Resize the thread sets 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. @@ -1925,7 +3370,7 @@ extern "C" { #endif // _di_f_thread_sets_decrease_by_ /** - * Increase the size of the string sets array, but only if necessary. + * Increase the size of the thread sets 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. @@ -1946,9 +3391,9 @@ extern "C" { #endif // _di_f_thread_sets_increase_ /** - * Resize the string sets array to a larger size. + * Resize the thread sets array to a larger size. * - * This will resize making the string larger based on the given length. + * 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. * @@ -1970,7 +3415,7 @@ extern "C" { #endif // _di_f_thread_sets_increase_by_ /** - * Resize the string sets array. + * Resize the thread sets array. * * @param length * The new size to use. @@ -2062,6 +3507,257 @@ extern "C" { extern f_status_t f_thread_signal_queue(const f_thread_id_t id, const int signal, const union sigval value); #endif // _di_f_thread_signal_queue_ +/** + * Create a thread spin lock. + * + * @param shared + * The shared process setting. + * @param spin + * The spin to create. + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_spin_create_ + extern f_status_t f_thread_spin_create(const int shared, f_thread_spin_t *spin); +#endif // _di_f_thread_spin_create_ + +/** + * Delete a thread spin lock. + * + * The pthread_spin_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 spin + * The spin to delete. + * + * @return + * F_none on success. + * + * 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() + */ +#ifndef _di_f_thread_spin_delete_ + extern f_status_t f_thread_spin_delete(f_thread_spin_t *spin); +#endif // _di_f_thread_spin_delete_ + +/** + * Lock the spin lock. + * + * This is a blocking function. + * + * @param spin + * The thread spin. + * + * @return + * F_none on success. + * + * F_deadlock (with error bit) if operation would cause a deadlock. + * F_parameter (with error bit) if a parameter is invalid. + * F_resource_not (with error bit) if max spin locks is reached. + * + * @see pthread_spin_lock() + */ +#ifndef _di_f_thread_spin_lock_ + extern f_status_t f_thread_spin_lock(f_thread_spin_t *spin); +#endif // _di_f_thread_spin_lock_ + +/** + * Try to lock the spin lock. + * + * If spin is already locked, return immediately. + * + * This is a non-blocking function. + * + * @param spin + * The thread spin. + * + * @return + * F_none on success. + * F_busy on success, but the spin is already locked. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_resource_not (with error bit) if max spin locks is reached. + * + * @see pthread_spin_trylock() + */ +#ifndef _di_f_thread_spin_lock_try_ + extern f_status_t f_thread_spin_lock_try(f_thread_spin_t *spin); +#endif // _di_f_thread_spin_lock_try_ + +/** + * Unlock the spin lock. + * + * @param spin + * The thread spin. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * 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. + * + * @see pthread_spin_unlock() + */ +#ifndef _di_f_thread_spin_unlock_ + extern f_status_t f_thread_spin_unlock(f_thread_spin_t *spin); +#endif // _di_f_thread_spin_unlock_ + +/** + * Resize the thread spin locks array. + * + * @param length + * The new size to use. + * @param spins + * The string spins 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_spins_adjust_ + extern f_status_t f_thread_spins_adjust(const f_array_length_t length, f_thread_spins_t *spins); +#endif // _di_f_thread_spins_adjust_ + +/** + * Resize the thread spin locks 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 spins + * The string spins 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_spins_decimate_by_ + extern f_status_t f_thread_spins_decimate_by(const f_array_length_t amount, f_thread_spins_t *spins); +#endif // _di_f_thread_spins_decimate_by_ + +/** + * Resize the thread spin locks 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 spins + * The string spins 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_spins_decrease_by_ + extern f_status_t f_thread_spins_decrease_by(const f_array_length_t amount, f_thread_spins_t *spins); +#endif // _di_f_thread_spins_decrease_by_ + +/** + * Increase the size of the thread spin locks 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 spins + * The string spins 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_spins_increase_ + extern f_status_t f_thread_spins_increase(f_thread_spins_t *spins); +#endif // _di_f_thread_spins_increase_ + +/** + * Resize the thread spin locks 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 spins + * The string spins 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_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); +#endif // _di_f_thread_spins_increase_by_ + +/** + * Resize the thread spin locks array. + * + * @param length + * The new size to use. + * @param spins + * The string spins 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_spins_resize_ + extern f_status_t f_thread_spins_resize(const f_array_length_t length, f_thread_spins_t *spins); +#endif // _di_f_thread_spins_resize_ + +/** + * Unlock the read/write lock. + * + * @param lock + * The thread lock. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * 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. + * + * @see pthread_rwlock_unlock() + */ +#ifndef _di_f_thread_unlock_ + extern f_status_t f_thread_unlock(f_thread_lock_t *lock); +#endif // _di_f_thread_unlock_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_1/fl_status/c/status.c b/level_1/fl_status/c/status.c index 8b906a1..2731bf8 100644 --- a/level_1/fl_status/c/status.c +++ b/level_1/fl_status/c/status.c @@ -524,6 +524,12 @@ extern "C" { case F_ready_not: *string = FL_status_string_ready_not; break; + case F_recover: + *string = FL_status_string_recover; + break; + case F_recover_not: + *string = FL_status_string_recover_not; + break; case F_recurse: *string = FL_status_string_recurse; break; diff --git a/level_1/fl_status/c/status.h b/level_1/fl_status/c/status.h index d2e7b85..98b8c15 100644 --- a/level_1/fl_status/c/status.h +++ b/level_1/fl_status/c/status.h @@ -269,6 +269,8 @@ extern "C" { #define FL_status_string_read_only "F_read_only" #define FL_status_string_ready "F_ready" #define FL_status_string_ready_not "F_ready_not" + #define FL_status_string_recover "F_recover" + #define FL_status_string_recover_not "F_recover_not" #define FL_status_string_recurse "F_recurse" #define FL_status_string_recurse_not "F_recurse_not" #define FL_status_string_relative "F_relative" @@ -422,6 +424,8 @@ extern "C" { #define FL_status_string_read_only_length 11 #define FL_status_string_ready_length 7 #define FL_status_string_ready_not_length 11 + #define FL_status_string_recover_length 9 + #define FL_status_string_recover_not_length 13 #define FL_status_string_recurse_length 9 #define FL_status_string_recurse_not_length 13 #define FL_status_string_relative_length 10 diff --git a/level_2/fll_status/c/status.c b/level_2/fll_status/c/status.c index bc6e381..18f7729 100644 --- a/level_2/fll_status/c/status.c +++ b/level_2/fll_status/c/status.c @@ -886,6 +886,16 @@ extern "C" { return F_none; } + if (fl_string_compare(string, FL_status_string_recover, length, FL_status_string_recover_length) == F_equal_to) { + *code = F_recover; + return F_none; + } + + if (fl_string_compare(string, FL_status_string_recover_not, length, FL_status_string_recover_not_length) == F_equal_to) { + *code = F_recover_not; + return F_none; + } + if (fl_string_compare(string, FL_status_string_recurse, length, FL_status_string_recurse_length) == F_equal_to) { *code = F_recurse; return F_none; -- 1.8.3.1