From 5fec9aeb9e63386b829fe924548904366fcffb81 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Fri, 1 Jul 2022 00:32:38 -0500 Subject: [PATCH] Bugfix: Problems exposed by f_thread unit tests. Notable fixes: - Rename f_thread_semaphore_file_create() to f_thread_semaphore_file_open(). - Rename f_thread_semaphore_file_delete() to f_thread_semaphore_file_close(). - Rename f_thread_semaphore_file_destroy() to f_thread_semaphore_file_delete(). - Have f_thread_semaphore_file_open() accept a double pointer for semaphore because sem_open() returns a pointer. - Initializer f_thread_semaphore_t_initialize is on a union which is initialized differently from a normal digit. --- level_0/f_thread/c/thread.c | 359 +++++++++++++++++----------------- level_0/f_thread/c/thread.h | 255 ++++++++++++------------ level_0/f_thread/c/thread/semaphore.h | 2 +- 3 files changed, 305 insertions(+), 311 deletions(-) diff --git a/level_0/f_thread/c/thread.c b/level_0/f_thread/c/thread.c index 6d8b936..204f28c 100644 --- a/level_0/f_thread/c/thread.c +++ b/level_0/f_thread/c/thread.c @@ -1549,174 +1549,178 @@ extern "C" { } #endif // _di_f_thread_mutex_lock_try_ -#ifndef _di_f_thread_semaphore_create_ - f_status_t f_thread_semaphore_create(const bool shared, const unsigned int value, f_thread_semaphore_t * const semaphore) { +#ifndef _di_f_thread_mutex_priority_ceiling_get_ + f_status_t f_thread_mutex_priority_ceiling_get(f_thread_mutex_t * const mutex, int * const ceiling) { #ifndef _di_level_0_parameter_checking_ - if (!semaphore) return F_status_set_error(F_parameter); + if (!mutex) return F_status_set_error(F_parameter); + if (!ceiling) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (sem_init(semaphore, shared, value) == -1) { - if (errno == EINVAL) return F_status_set_error(F_parameter); - if (errno == ENOSYS) return F_status_set_error(F_supported_not); + 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_semaphore_create_ +#endif // _di_f_thread_mutex_priority_ceiling_get_ -#ifndef _di_f_thread_semaphore_delete_ - f_status_t f_thread_semaphore_delete(f_thread_semaphore_t *semaphore) { +#ifndef _di_f_thread_mutex_priority_ceiling_set_ + f_status_t f_thread_mutex_priority_ceiling_set(const int ceiling, f_thread_mutex_t * const mutex, int * const previous) { #ifndef _di_level_0_parameter_checking_ - if (!semaphore) return F_status_set_error(F_parameter); + if (!mutex) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - return private_f_thread_semaphore_delete(semaphore); + 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_dead); + if (error == EPERM) return F_status_set_error(F_prohibited); + + return F_status_set_error(F_failure); + } + + return F_none; } -#endif // _di_f_thread_semaphore_delete_ +#endif // _di_f_thread_mutex_priority_ceiling_set_ -#ifndef _di_f_thread_semaphore_file_create_ - f_status_t f_thread_semaphore_file_create(const f_string_static_t name, const int flag, mode_t mode, unsigned int value, f_thread_semaphore_t *semaphore) { +#ifndef _di_f_thread_mutex_unlock_ + f_status_t f_thread_mutex_unlock(f_thread_mutex_t * const mutex) { #ifndef _di_level_0_parameter_checking_ - if (!semaphore) return F_status_set_error(F_parameter); + if (!mutex) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (flag & O_CREAT) { - semaphore = sem_open(name.string, flag, mode, value); - } - else { - semaphore = sem_open(name.string, flag); - } + const int error = pthread_mutex_unlock(mutex); - if (semaphore == SEM_FAILED) { - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == EEXIST) return F_status_set_error(F_file_found); - if (errno == EINVAL) return F_status_set_error(F_parameter); - if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max); - if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not); - if (errno == ENFILE) return F_status_set_error(F_file_open_max); - if (errno == ENOENT) return F_status_set_error(F_file_found_not); - if (errno == ENOMEM) return F_status_set_error(F_memory_not); + 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_semaphore_file_create_ +#endif // _di_f_thread_mutex_unlock_ -#ifndef _di_f_thread_semaphore_file_delete_ - f_status_t f_thread_semaphore_file_delete(f_thread_semaphore_t *semaphore) { +#ifndef _di_f_thread_once_ + f_status_t f_thread_once(void (*routine) (void), f_thread_once_t * const once) { #ifndef _di_level_0_parameter_checking_ - if (!semaphore) return F_status_set_error(F_parameter); + if (!routine) return F_status_set_error(F_parameter); + if (!once) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (sem_close(semaphore) == -1) { - if (errno == EINVAL) return F_status_set_error(F_parameter); + const int error = pthread_once(once, routine); + + 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_semaphore_file_delete_ +#endif // _di_f_thread_once_ -#ifndef _di_f_thread_semaphore_file_destroy_ - f_status_t f_thread_semaphore_file_destroy(const f_string_static_t name) { +#ifndef _di_f_thread_scheduler_parameter_get_ + f_status_t f_thread_scheduler_parameter_get(const f_thread_id_t id, int * const policy, struct sched_param * const 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_ - if (sem_unlink(name.string) == -1) { - if (errno == EACCES) return F_status_set_error(F_access_denied); - if (errno == EINVAL) return F_status_set_error(F_parameter); - if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not); - if (errno == ENOENT) return F_file_found_not; + 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_semaphore_file_destroy_ +#endif // _di_f_thread_scheduler_parameter_get_ -#ifndef _di_f_thread_semaphore_lock_ - f_status_t f_thread_semaphore_lock(f_thread_semaphore_t * const semaphore) { +#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 * const parameter) { #ifndef _di_level_0_parameter_checking_ - if (!semaphore) return F_status_set_error(F_parameter); + if (!parameter) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (sem_wait(semaphore) == -1) { - if (errno == EINTR) return F_status_set_error(F_interrupt); - if (errno == EINVAL) return F_status_set_error(F_parameter); + 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_semaphore_lock_ +#endif // _di_f_thread_scheduler_parameter_set_ -#ifndef _di_f_thread_semaphore_lock_timed_ - f_status_t f_thread_semaphore_lock_timed(const struct timespec * const timeout, f_thread_semaphore_t * const semaphore) { - #ifndef _di_level_0_parameter_checking_ - if (!timeout) return F_status_set_error(F_parameter); - if (!semaphore) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ +#ifndef _di_f_thread_scheduler_priority_set_ + f_status_t f_thread_scheduler_priority_set(const f_thread_id_t id, const int priority) { - if (sem_timedwait(semaphore, timeout) == -1) { - if (errno == EINTR) return F_status_set_error(F_interrupt); - if (errno == EINVAL) return F_status_set_error(F_parameter); - if (errno == ETIMEDOUT) return F_time; + 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_semaphore_lock_timed_ +#endif // _di_f_thread_scheduler_priority_set_ -#ifndef _di_f_thread_semaphore_lock_try_ - f_status_t f_thread_semaphore_lock_try(f_thread_semaphore_t * const semaphore) { +#ifndef _di_f_thread_semaphore_create_ + f_status_t f_thread_semaphore_create(const bool shared, const unsigned int value, f_thread_semaphore_t * const semaphore) { #ifndef _di_level_0_parameter_checking_ if (!semaphore) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (sem_trywait(semaphore) == -1) { - if (errno == EAGAIN) return F_status_set_error(F_resource_not); - if (errno == EINTR) return F_status_set_error(F_interrupt); + if (sem_init(semaphore, shared, value) == -1) { if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ENOSYS) return F_status_set_error(F_supported_not); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_semaphore_lock_try_ +#endif // _di_f_thread_semaphore_create_ -#ifndef _di_f_thread_semaphore_unlock_ - f_status_t f_thread_semaphore_unlock(f_thread_semaphore_t * const semaphore) { +#ifndef _di_f_thread_semaphore_delete_ + f_status_t f_thread_semaphore_delete(f_thread_semaphore_t *semaphore) { #ifndef _di_level_0_parameter_checking_ if (!semaphore) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (sem_post(semaphore) == -1) { - if (errno == EOVERFLOW) return F_status_set_error(F_number_overflow); - if (errno == EINVAL) return F_status_set_error(F_parameter); - - return F_status_set_error(F_failure); - } - - return F_none; + return private_f_thread_semaphore_delete(semaphore); } -#endif // _di_f_thread_semaphore_unlock_ +#endif // _di_f_thread_semaphore_delete_ -#ifndef _di_f_thread_semaphore_value_get_ - f_status_t f_thread_semaphore_value_get(f_thread_semaphore_t * const semaphore, int * const value) { +#ifndef _di_f_thread_semaphore_file_close_ + f_status_t f_thread_semaphore_file_close(f_thread_semaphore_t *semaphore) { #ifndef _di_level_0_parameter_checking_ if (!semaphore) return F_status_set_error(F_parameter); - if (!value) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - if (sem_getvalue(semaphore, value) == -1) { + if (sem_close(semaphore) == -1) { if (errno == EINVAL) return F_status_set_error(F_parameter); return F_status_set_error(F_failure); @@ -1724,146 +1728,141 @@ extern "C" { return F_none; } -#endif // _di_f_thread_semaphore_value_get_ - -#ifndef _di_f_thread_mutex_priority_ceiling_get_ - f_status_t f_thread_mutex_priority_ceiling_get(f_thread_mutex_t * const mutex, int * const 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_ +#endif // _di_f_thread_semaphore_file_close_ - const int error = pthread_mutex_getprioceiling(mutex, ceiling); +#ifndef _di_f_thread_semaphore_file_delete_ + f_status_t f_thread_semaphore_file_delete(const f_string_static_t name) { - if (error) { - if (error == EINVAL) return F_status_set_error(F_parameter); - if (error == EPERM) return F_status_set_error(F_prohibited); + if (sem_unlink(name.string) == -1) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not); + if (errno == ENOENT) return F_file_found_not; return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_mutex_priority_ceiling_get_ +#endif // _di_f_thread_semaphore_file_delete_ -#ifndef _di_f_thread_mutex_priority_ceiling_set_ - f_status_t f_thread_mutex_priority_ceiling_set(const int ceiling, f_thread_mutex_t * const mutex, int * const previous) { +#ifndef _di_f_thread_semaphore_file_open_ + f_status_t f_thread_semaphore_file_open(const f_string_static_t name, const int flag, const mode_t mode, unsigned int value, f_thread_semaphore_t **semaphore) { #ifndef _di_level_0_parameter_checking_ - if (!mutex) return F_status_set_error(F_parameter); + if (!semaphore) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_mutex_setprioceiling(mutex, ceiling, previous); + if (flag & O_CREAT) { + *semaphore = sem_open(name.string, flag, mode, value); + } + else { + *semaphore = sem_open(name.string, flag); + } - 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_dead); - if (error == EPERM) return F_status_set_error(F_prohibited); + if (*semaphore == SEM_FAILED) { + if (errno == EACCES) return F_status_set_error(F_access_denied); + if (errno == EEXIST) return F_status_set_error(F_file_found); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == EMFILE) return F_status_set_error(F_file_descriptor_max); + if (errno == ENAMETOOLONG) return F_status_set_error(F_name_not); + if (errno == ENFILE) return F_status_set_error(F_file_open_max); + if (errno == ENOENT) return F_status_set_error(F_file_found_not); + if (errno == ENOMEM) return F_status_set_error(F_memory_not); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_mutex_priority_ceiling_set_ +#endif // _di_f_thread_semaphore_file_open_ -#ifndef _di_f_thread_mutex_unlock_ - f_status_t f_thread_mutex_unlock(f_thread_mutex_t * const mutex) { +#ifndef _di_f_thread_semaphore_lock_ + f_status_t f_thread_semaphore_lock(f_thread_semaphore_t * const semaphore) { #ifndef _di_level_0_parameter_checking_ - if (!mutex) return F_status_set_error(F_parameter); + if (!semaphore) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_mutex_unlock(mutex); - - 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); + if (sem_wait(semaphore) == -1) { + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_mutex_unlock_ +#endif // _di_f_thread_semaphore_lock_ -#ifndef _di_f_thread_once_ - f_status_t f_thread_once(void (*routine) (void), f_thread_once_t * const once) { +#ifndef _di_f_thread_semaphore_lock_timed_ + f_status_t f_thread_semaphore_lock_timed(const struct timespec * const timeout, f_thread_semaphore_t * const semaphore) { #ifndef _di_level_0_parameter_checking_ - if (!routine) return F_status_set_error(F_parameter); - if (!once) return F_status_set_error(F_parameter); + if (!timeout) return F_status_set_error(F_parameter); + if (!semaphore) return F_status_set_error(F_parameter); #endif // _di_level_0_parameter_checking_ - const int error = pthread_once(once, routine); - - if (error) { - if (error == EINVAL) return F_status_set_error(F_parameter); + if (sem_timedwait(semaphore, timeout) == -1) { + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); + if (errno == ETIMEDOUT) return F_time; return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_once_ +#endif // _di_f_thread_semaphore_lock_timed_ -#ifndef _di_f_thread_scheduler_parameter_get_ - f_status_t f_thread_scheduler_parameter_get(const f_thread_id_t id, int * const policy, struct sched_param * const parameter) { +#ifndef _di_f_thread_semaphore_lock_try_ + f_status_t f_thread_semaphore_lock_try(f_thread_semaphore_t * const semaphore) { #ifndef _di_level_0_parameter_checking_ - if (!policy) return F_status_set_error(F_parameter); - if (!parameter) return F_status_set_error(F_parameter); + if (!semaphore) 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); + if (sem_trywait(semaphore) == -1) { + if (errno == EAGAIN) return F_status_set_error(F_resource_not); + if (errno == EINTR) return F_status_set_error(F_interrupt); + if (errno == EINVAL) return F_status_set_error(F_parameter); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_scheduler_parameter_get_ +#endif // _di_f_thread_semaphore_lock_try_ -#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 * const parameter) { +#ifndef _di_f_thread_semaphore_unlock_ + f_status_t f_thread_semaphore_unlock(f_thread_semaphore_t * const semaphore) { #ifndef _di_level_0_parameter_checking_ - if (!policy) return F_status_set_error(F_parameter); - if (!parameter) return F_status_set_error(F_parameter); + if (!semaphore) 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); + if (sem_post(semaphore) == -1) { + if (errno == EOVERFLOW) return F_status_set_error(F_number_overflow); + if (errno == EINVAL) return F_status_set_error(F_parameter); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_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) { +#endif // _di_f_thread_semaphore_unlock_ - const int error = pthread_setschedprio(id, priority); +#ifndef _di_f_thread_semaphore_value_get_ + f_status_t f_thread_semaphore_value_get(f_thread_semaphore_t * const semaphore, int * const value) { + #ifndef _di_level_0_parameter_checking_ + if (!semaphore) return F_status_set_error(F_parameter); + if (!value) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ - if (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); + if (sem_getvalue(semaphore, value) == -1) { + if (errno == EINVAL) return F_status_set_error(F_parameter); return F_status_set_error(F_failure); } return F_none; } -#endif // _di_f_thread_scheduler_priority_set_ +#endif // _di_f_thread_semaphore_value_get_ #ifndef _di_f_thread_signal_mask_ f_status_t f_thread_signal_mask(const int how, const sigset_t *next, sigset_t * const current) { @@ -1884,6 +1883,29 @@ extern "C" { } #endif // _di_f_thread_signal_mask_ +#if defined(_pthread_sigqueue_unsupported_) && !defined(_di_f_thread_signal_queue_) + f_status_t f_thread_signal_queue(const f_thread_id_t id, const int signal, const union sigval value) { + + return F_status_set_error(F_implemented_not); + } +#elif !defined(_di_f_thread_signal_queue_) + f_status_t f_thread_signal_queue(const f_thread_id_t id, const int signal, const union sigval value) { + + const int error = pthread_sigqueue(id, signal, value); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == ENOSYS) return F_status_set_error(F_supported_not); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ESRCH) return F_status_set_error(F_found_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // defined(_pthread_sigqueue_unsupported_) && !defined(_di_f_thread_signal_queue_) + #ifndef _di_f_thread_signal_write_ f_status_t f_thread_signal_write(const f_thread_id_t id, const int signal) { @@ -1909,29 +1931,6 @@ extern "C" { } #endif // _di_f_thread_signal_write_ -#if defined(_pthread_sigqueue_unsupported_) && !defined(_di_f_thread_signal_queue_) - f_status_t f_thread_signal_queue(const f_thread_id_t id, const int signal, const union sigval value) { - - return F_status_set_error(F_implemented_not); - } -#elif !defined(_di_f_thread_signal_queue_) - f_status_t f_thread_signal_queue(const f_thread_id_t id, const int signal, const union sigval value) { - - const int error = pthread_sigqueue(id, signal, value); - - if (error) { - if (error == EAGAIN) return F_status_set_error(F_resource_not); - if (error == ENOSYS) return F_status_set_error(F_supported_not); - if (error == EINVAL) return F_status_set_error(F_parameter); - if (error == ESRCH) return F_status_set_error(F_found_not); - - return F_status_set_error(F_failure); - } - - return F_none; - } -#endif // defined(_pthread_sigqueue_unsupported_) && !defined(_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 * const spin) { #ifndef _di_level_0_parameter_checking_ diff --git a/level_0/f_thread/c/thread.h b/level_0/f_thread/c/thread.h index e1f4d8f..d5dda08 100644 --- a/level_0/f_thread/c/thread.h +++ b/level_0/f_thread/c/thread.h @@ -1120,7 +1120,7 @@ extern "C" { * 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. + * This blocks until timeout and then no longer block. * * @param wait * The amount of time to wait for. @@ -1281,7 +1281,7 @@ extern "C" { * 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. + * This blocks until timeout and then no longer block. * * @param id * The ID of the thread to wait for. @@ -1944,155 +1944,155 @@ extern "C" { #endif // _di_f_thread_mutex_delete_ /** - * Lock the mutex. - * - * This is a blocking function. + * Get the mutex priority ceiling. * * @param mutex * The thread mutex. + * @param ceiling + * The priority ceiling. * * @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 mutex locks is reached. + * F_prohibited (with error bit) if not allowed to perform the operation. * * F_failure (with error bit) on any other error. * - * @see pthread_mutex_lock() + * @see pthread_mutex_getprioceiling() */ -#ifndef _di_f_thread_mutex_lock_ - extern f_status_t f_thread_mutex_lock(f_thread_mutex_t * const mutex); -#endif // _di_f_thread_mutex_lock_ +#ifndef _di_f_thread_mutex_priority_ceiling_get_ + extern f_status_t f_thread_mutex_priority_ceiling_get(f_thread_mutex_t * const mutex, int * const ceiling); +#endif // _di_f_thread_mutex_priority_ceiling_get_ /** - * 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). + * Set the mutex priority ceiling. * - * @param timeout - * The timeout. + * @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_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_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_dead (with error bit) if the owning thread terminated while holding the mutex lock (thread is dead). * * F_failure (with error bit) on any other error. * - * @see pthread_mutex_timedlock() + * @see pthread_mutex_setprioceiling() */ -#ifndef _di_f_thread_mutex_lock_timed_ - extern f_status_t f_thread_mutex_lock_timed(const struct timespec * const timeout, f_thread_mutex_t * const mutex); -#endif // _di_f_thread_mutex_lock_timed_ +#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 * const mutex, int * const previous); +#endif // _di_f_thread_mutex_priority_ceiling_set_ /** - * Try to lock the mutex. - * - * If mutex is already locked, return immediately. - * - * This is a non-blocking function. + * Unlock the mutex. * * @param mutex * The thread mutex. * * @return * F_none on success. - * F_busy on success, but the mutex is already locked. * * 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_resource_not (with error bit) if max mutex locks is reached. * * F_failure (with error bit) on any other error. * - * @see pthread_mutex_trylock() + * @see pthread_mutex_unlock() */ -#ifndef _di_f_thread_mutex_lock_try_ - extern f_status_t f_thread_mutex_lock_try(f_thread_mutex_t * const mutex); -#endif // _di_f_thread_mutex_lock_try_ +#ifndef _di_f_thread_mutex_unlock_ + extern f_status_t f_thread_mutex_unlock(f_thread_mutex_t * const mutex); +#endif // _di_f_thread_mutex_unlock_ /** - * Get the mutex priority ceiling. + * Lock the mutex. + * + * This is a blocking function. * * @param mutex * The thread mutex. - * @param ceiling - * The priority ceiling. * * @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_resource_not (with error bit) if max mutex locks is reached. * * F_failure (with error bit) on any other error. * - * @see pthread_mutex_getprioceiling() + * @see pthread_mutex_lock() */ -#ifndef _di_f_thread_mutex_priority_ceiling_get_ - extern f_status_t f_thread_mutex_priority_ceiling_get(f_thread_mutex_t * const mutex, int * const ceiling); -#endif // _di_f_thread_mutex_priority_ceiling_get_ +#ifndef _di_f_thread_mutex_lock_ + extern f_status_t f_thread_mutex_lock(f_thread_mutex_t * const mutex); +#endif // _di_f_thread_mutex_lock_ /** - * Set the mutex priority ceiling. + * Lock the mutex, waiting for a set period of time to get the lock if already locked. * - * @param ceiling - * The priority ceiling. + * 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. - * @param previous - * (optional) The previous priority ceiling. - * Set to NULL to not use. * * @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 (for a "robust" mutex). + * 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_dead (with error bit) if the owning thread terminated while holding the mutex lock (thread is dead). * * F_failure (with error bit) on any other error. * - * @see pthread_mutex_setprioceiling() + * @see pthread_mutex_timedlock() */ -#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 * const mutex, int * const previous); -#endif // _di_f_thread_mutex_priority_ceiling_set_ +#ifndef _di_f_thread_mutex_lock_timed_ + extern f_status_t f_thread_mutex_lock_timed(const struct timespec * const timeout, f_thread_mutex_t * const mutex); +#endif // _di_f_thread_mutex_lock_timed_ /** - * Unlock the mutex. + * Try to lock the mutex. + * + * If mutex is already locked, return immediately. + * + * This is a non-blocking function. * * @param mutex * The thread mutex. * * @return * F_none on success. + * F_busy on success, but the mutex is already locked. * * 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_resource_not (with error bit) if max mutex locks is reached. * * F_failure (with error bit) on any other error. * - * @see pthread_mutex_unlock() + * @see pthread_mutex_trylock() */ -#ifndef _di_f_thread_mutex_unlock_ - extern f_status_t f_thread_mutex_unlock(f_thread_mutex_t * const mutex); -#endif // _di_f_thread_mutex_unlock_ +#ifndef _di_f_thread_mutex_lock_try_ + extern f_status_t f_thread_mutex_lock_try(f_thread_mutex_t * const mutex); +#endif // _di_f_thread_mutex_lock_try_ /** * Call the given routine only one time and never again. @@ -2236,96 +2236,91 @@ extern "C" { #endif // _di_f_thread_semaphore_delete_ /** - * Create a thread (named) semaphore. + * Close a thread (named) semaphore file. + * + * A named semaphore should be deleted with f_thread_semephore_file_destroy(). * - * @param name - * The semaphore file name to create. - * @param flag - * The file create/open flags. - * @param mode - * (optional) The file permissions to assign the semaphore. - * Ignored if O_CREAT is not used in flag. - * Ignored if the named semaphore already exists. - * @param value - * (optional) The value to initially assign the semaphore on creation. - * Ignored if O_CREAT is not used in flag. - * Ignored if the named semaphore already exists. * @param semaphore - * The thread semaphore. + * The semaphore to delete. * * @return * F_none on success. * - * F_access_denied (with error bit) on access denied. - * F_file_descriptor_max (with error bit) if max file descrriptors was reached. - * F_file_found (with error bit) if the file was found and both the O_CREAT and O_EXCL flags are set. - * F_file_open_max (with error bit) too many open files. - * F_file_found_not (with error bit) if the file was not found and the O_CREAT is not set. - * F_name_not (with error bit) if file name is too long. * F_parameter (with error bit) if a parameter is invalid. - * F_supported_not (with error bit) if the system does not support the process shared semaphore (shared == true). - * F_memory_not (with error bit) if out of memory. * * F_failure (with error bit) on any other error. * - * @see sem_open() + * A named semaphore should be deleted with this function or with f_thread_semephore_file_destroy(). + * + * @see sem_close() */ -#ifndef _di_f_thread_semaphore_file_create_ - extern f_status_t f_thread_semaphore_file_create(const f_string_static_t name, const int flag, mode_t mode, unsigned int value, f_thread_semaphore_t *semaphore); -#endif // _di_f_thread_semaphore_file_create_ +#ifndef _di_f_thread_semaphore_file_close_ + extern f_status_t f_thread_semaphore_file_close(f_thread_semaphore_t *semaphore); +#endif // _di_f_thread_semaphore_file_close_ /** * Delete a thread (named) semaphore. * - * A named semaphore should be deleted with this function or with f_thread_semephore_file_destroy(). + * This deletes the semaphore file and all processes holding this semaphore will be forcibly closed. * - * @param semaphore - * The semaphore to delete. + * @param name + * The semaphore name to delete. * * @return * F_none on success. + * F_file_found_not the named file was not found. * + * F_access_denied (with error bit) on access denied. + * F_name_not (with error bit) if file name is too long. * F_parameter (with error bit) if a parameter is invalid. * * F_failure (with error bit) on any other error. * - * A named semaphore should be deleted with this function or with f_thread_semephore_file_destroy(). - * - * @see sem_close() - * - * @see f_thread_semaphore_file_destroy() + * @see sem_unlink() */ #ifndef _di_f_thread_semaphore_file_delete_ - extern f_status_t f_thread_semaphore_file_delete(f_thread_semaphore_t *semaphore); + extern f_status_t f_thread_semaphore_file_delete(const f_string_static_t name); #endif // _di_f_thread_semaphore_file_delete_ /** - * Destroy a thread (named) semaphore. - * - * This will immediately delete the semaphore file and all processes holding this semaphore will be forced to close. - * - * A named semaphore should be deleted with this function or with f_thread_semephore_file_delete(). + * Open or create a thread (named) semaphore file. * * @param name - * The semaphore name to delete. + * The semaphore file name to create. + * @param flag + * The file create/open flags. + * Pass the O_CREATE flag to create the semaphore file. + * @param mode + * (optional) The file permissions to assign the semaphore. + * Ignored if O_CREAT is not used in flag. + * Ignored if the named semaphore already exists. + * @param value + * (optional) The value to initially assign the semaphore on creation. + * Ignored if O_CREAT is not used in flag. + * Ignored if the named semaphore already exists. + * @param semaphore + * The thread semaphore. * * @return * F_none on success. - * F_file_found_not the named file was not found. * * F_access_denied (with error bit) on access denied. + * F_file_descriptor_max (with error bit) if max file descrriptors was reached. + * F_file_found (with error bit) if the file was found and both the O_CREAT and O_EXCL flags are set. + * F_file_open_max (with error bit) too many open files. + * F_file_found_not (with error bit) if the file was not found and the O_CREAT is not set. * F_name_not (with error bit) if file name is too long. * F_parameter (with error bit) if a parameter is invalid. + * F_supported_not (with error bit) if the system does not support the process shared semaphore (shared == true). + * F_memory_not (with error bit) if out of memory. * * F_failure (with error bit) on any other error. * - * @see sem_unlink() - * - * @see f_thread_semaphore_file_delete() + * @see sem_open() */ -#ifndef _di_f_thread_semaphore_file_destroy_ - extern f_status_t f_thread_semaphore_file_destroy(const f_string_static_t name); -#endif // _di_f_thread_semaphore_file_destroy_ +#ifndef _di_f_thread_semaphore_file_open_ + extern f_status_t f_thread_semaphore_file_open(const f_string_static_t name, const int flag, const mode_t mode, unsigned int value, f_thread_semaphore_t **semaphore); +#endif // _di_f_thread_semaphore_file_open_ /** * Lock the semaphore. @@ -2471,29 +2466,6 @@ extern "C" { #endif // _di_f_thread_signal_mask_ /** - * Send a signal to the given thread. - * - * @param id - * The ID of the thread to signal. - * @param signal - * The signal to send to the thread. - * If 0 is used instead of a valid signal, then instead check to see if the thread exists. - * - * @return - * F_none on success and signal is not 0. - * F_found on success, signal is 0, and the thread by the given ID does exist. - * - * F_found_not on success, signal is 0, and the thread by the given ID does not exist. - * F_found_not (with error bit) if no thread by the given ID was found (and signal is not 0). - * F_parameter (with error bit) if a parameter is invalid. - * - * @see pthread_kill() - */ -#ifndef _di_f_thread_signal_write_ - extern f_status_t f_thread_signal_write(const f_thread_id_t id, const int signal); -#endif // _di_f_thread_signal_write_ - -/** * Send the signal and value to the given thread. * * @param id @@ -2520,6 +2492,29 @@ extern "C" { #endif // _di_f_thread_signal_queue_ /** + * Send a signal to the given thread. + * + * @param id + * The ID of the thread to signal. + * @param signal + * The signal to send to the thread. + * If 0 is used instead of a valid signal, then instead check to see if the thread exists. + * + * @return + * F_none on success and signal is not 0. + * F_found on success, signal is 0, and the thread by the given ID does exist. + * + * F_found_not on success, signal is 0, and the thread by the given ID does not exist. + * F_found_not (with error bit) if no thread by the given ID was found (and signal is not 0). + * F_parameter (with error bit) if a parameter is invalid. + * + * @see pthread_kill() + */ +#ifndef _di_f_thread_signal_write_ + extern f_status_t f_thread_signal_write(const f_thread_id_t id, const int signal); +#endif // _di_f_thread_signal_write_ + +/** * Create a thread spin lock. * * @param shared diff --git a/level_0/f_thread/c/thread/semaphore.h b/level_0/f_thread/c/thread/semaphore.h index 61e4b4b..c1b79a1 100644 --- a/level_0/f_thread/c/thread/semaphore.h +++ b/level_0/f_thread/c/thread/semaphore.h @@ -26,7 +26,7 @@ extern "C" { #ifndef _di_f_thread_semaphore_t_ typedef sem_t f_thread_semaphore_t; - #define f_thread_semaphore_t_initialize 0 + #define f_thread_semaphore_t_initialize { (long) 0 } #define macro_f_thread_semaphore_t_initialize(semaphore) semaphore -- 1.8.3.1