From 588eb39ded2a6bf1b4083dfd3261cce8904b1460 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 12 Aug 2025 21:13:51 -0500 Subject: [PATCH] Feature: Add missing mutex consistent and robust mutex attribute functions. Add the following functions: - `f_thread_mutex_attribute_robust_get()` - `f_thread_mutex_attribute_robust_set()` - `f_thread_mutex_consistent()` Add the new thread mutex group: - `f_thread_mutex_d` Add the following status codes: - `F_consistent` - `F_consistent_not` - `F_robust` - `F_robust_not` Add appropriate unit tests. --- build/disable/level_0/f_thread.h | 4 ++ build/stand_alone/byte_dump.config.h | 4 ++ build/stand_alone/example.config.h | 4 ++ build/stand_alone/fake.config.h | 4 ++ build/stand_alone/firewall.config.h | 4 ++ build/stand_alone/utf8.config.h | 4 ++ level_0/f_status/c/status.h | 4 ++ level_0/f_status_string/c/status_string.c | 44 ++++++++++--- level_0/f_status_string/c/status_string.h | 12 ++++ .../tests/unit/c/test-status_string-to.c | 10 ++- level_0/f_thread/c/thread.c | 53 ++++++++++++++++ level_0/f_thread/c/thread.h | 74 ++++++++++++++++++++++ level_0/f_thread/c/thread/mutex.h | 12 ++++ level_0/f_thread/data/build/settings-mocks | 3 + level_0/f_thread/data/build/settings-tests | 2 + level_0/f_thread/tests/unit/c/mock-thread.c | 33 ++++++++++ level_0/f_thread/tests/unit/c/mock-thread.h | 3 + .../c/test-thread-mutex_attribute_robust_get.c | 72 +++++++++++++++++++++ .../c/test-thread-mutex_attribute_robust_get.h | 34 ++++++++++ .../c/test-thread-mutex_attribute_robust_set.c | 61 ++++++++++++++++++ .../c/test-thread-mutex_attribute_robust_set.h | 34 ++++++++++ .../tests/unit/c/test-thread-mutex_consistent.c | 57 +++++++++++++++++ .../tests/unit/c/test-thread-mutex_consistent.h | 34 ++++++++++ level_0/f_thread/tests/unit/c/test-thread.c | 13 ++++ level_0/f_thread/tests/unit/c/test-thread.h | 3 + level_1/fl_status_string/c/status_string.c | 24 +++++++ .../tests/unit/c/test-status_string-from.c | 10 ++- 27 files changed, 604 insertions(+), 12 deletions(-) create mode 100644 level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_get.c create mode 100644 level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_get.h create mode 100644 level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_set.c create mode 100644 level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_set.h create mode 100644 level_0/f_thread/tests/unit/c/test-thread-mutex_consistent.c create mode 100644 level_0/f_thread/tests/unit/c/test-thread-mutex_consistent.h diff --git a/build/disable/level_0/f_thread.h b/build/disable/level_0/f_thread.h index 2d23460..176182e 100644 --- a/build/disable/level_0/f_thread.h +++ b/build/disable/level_0/f_thread.h @@ -127,6 +127,8 @@ #define _di_f_thread_mutex_attribute_priority_ceiling_set_ #define _di_f_thread_mutex_attribute_protocol_get_ #define _di_f_thread_mutex_attribute_protocol_set_ +#define _di_f_thread_mutex_attribute_robust_get_ +#define _di_f_thread_mutex_attribute_robust_set_ #define _di_f_thread_mutex_attribute_shared_get_ #define _di_f_thread_mutex_attribute_shared_set_ #define _di_f_thread_mutex_attribute_d_ @@ -138,7 +140,9 @@ #define _di_f_thread_mutex_attributes_t_ #define _di_f_thread_mutex_attributess_delete_callback_ #define _di_f_thread_mutex_attributess_destroy_callback_ +#define _di_f_thread_mutex_consistent_ #define _di_f_thread_mutex_create_ +#define _di_f_thread_mutex_d_ #define _di_f_thread_mutex_delete_ #define _di_f_thread_mutex_lock_ #define _di_f_thread_mutex_lock_timed_ diff --git a/build/stand_alone/byte_dump.config.h b/build/stand_alone/byte_dump.config.h index 53265c6..87c2439 100644 --- a/build/stand_alone/byte_dump.config.h +++ b/build/stand_alone/byte_dump.config.h @@ -1138,6 +1138,8 @@ #define _di_f_thread_mutex_attribute_priority_ceiling_set_ #define _di_f_thread_mutex_attribute_protocol_get_ #define _di_f_thread_mutex_attribute_protocol_set_ +#define _di_f_thread_mutex_attribute_robust_get_ +#define _di_f_thread_mutex_attribute_robust_set_ #define _di_f_thread_mutex_attribute_shared_get_ #define _di_f_thread_mutex_attribute_shared_set_ #define _di_f_thread_mutex_attribute_d_ @@ -1149,7 +1151,9 @@ #define _di_f_thread_mutex_attributes_t_ #define _di_f_thread_mutex_attributess_delete_callback_ #define _di_f_thread_mutex_attributess_destroy_callback_ +#define _di_f_thread_mutex_consistent_ #define _di_f_thread_mutex_create_ +#define _di_f_thread_mutex_d_ #define _di_f_thread_mutex_delete_ #define _di_f_thread_mutex_lock_ #define _di_f_thread_mutex_lock_timed_ diff --git a/build/stand_alone/example.config.h b/build/stand_alone/example.config.h index e96aa97..0ee72a1 100644 --- a/build/stand_alone/example.config.h +++ b/build/stand_alone/example.config.h @@ -1089,6 +1089,8 @@ #define _di_f_thread_mutex_attribute_priority_ceiling_set_ #define _di_f_thread_mutex_attribute_protocol_get_ #define _di_f_thread_mutex_attribute_protocol_set_ +#define _di_f_thread_mutex_attribute_robust_get_ +#define _di_f_thread_mutex_attribute_robust_set_ #define _di_f_thread_mutex_attribute_shared_get_ #define _di_f_thread_mutex_attribute_shared_set_ #define _di_f_thread_mutex_attribute_d_ @@ -1100,7 +1102,9 @@ #define _di_f_thread_mutex_attributes_t_ #define _di_f_thread_mutex_attributess_delete_callback_ #define _di_f_thread_mutex_attributess_destroy_callback_ +#define _di_f_thread_mutex_consistent_ #define _di_f_thread_mutex_create_ +#define _di_f_thread_mutex_d_ #define _di_f_thread_mutex_delete_ #define _di_f_thread_mutex_lock_ #define _di_f_thread_mutex_lock_timed_ diff --git a/build/stand_alone/fake.config.h b/build/stand_alone/fake.config.h index 5484633..df89551 100644 --- a/build/stand_alone/fake.config.h +++ b/build/stand_alone/fake.config.h @@ -1580,6 +1580,8 @@ #define _di_f_thread_mutex_attribute_priority_ceiling_set_ #define _di_f_thread_mutex_attribute_protocol_get_ #define _di_f_thread_mutex_attribute_protocol_set_ +#define _di_f_thread_mutex_attribute_robust_get_ +#define _di_f_thread_mutex_attribute_robust_set_ #define _di_f_thread_mutex_attribute_shared_get_ #define _di_f_thread_mutex_attribute_shared_set_ #define _di_f_thread_mutex_attribute_d_ @@ -1591,7 +1593,9 @@ #define _di_f_thread_mutex_attributes_t_ #define _di_f_thread_mutex_attributess_delete_callback_ #define _di_f_thread_mutex_attributess_destroy_callback_ +#define _di_f_thread_mutex_consistent_ #define _di_f_thread_mutex_create_ +#define _di_f_thread_mutex_d_ #define _di_f_thread_mutex_delete_ #define _di_f_thread_mutex_lock_ #define _di_f_thread_mutex_lock_timed_ diff --git a/build/stand_alone/firewall.config.h b/build/stand_alone/firewall.config.h index 2e3c78b..b288dc4 100644 --- a/build/stand_alone/firewall.config.h +++ b/build/stand_alone/firewall.config.h @@ -1628,6 +1628,8 @@ #define _di_f_thread_mutex_attribute_priority_ceiling_set_ #define _di_f_thread_mutex_attribute_protocol_get_ #define _di_f_thread_mutex_attribute_protocol_set_ +#define _di_f_thread_mutex_attribute_robust_get_ +#define _di_f_thread_mutex_attribute_robust_set_ #define _di_f_thread_mutex_attribute_shared_get_ #define _di_f_thread_mutex_attribute_shared_set_ #define _di_f_thread_mutex_attribute_d_ @@ -1639,7 +1641,9 @@ #define _di_f_thread_mutex_attributes_t_ #define _di_f_thread_mutex_attributess_delete_callback_ #define _di_f_thread_mutex_attributess_destroy_callback_ +#define _di_f_thread_mutex_consistent_ #define _di_f_thread_mutex_create_ +#define _di_f_thread_mutex_d_ #define _di_f_thread_mutex_delete_ #define _di_f_thread_mutex_lock_ #define _di_f_thread_mutex_lock_timed_ diff --git a/build/stand_alone/utf8.config.h b/build/stand_alone/utf8.config.h index 421882f..2ee95ea 100644 --- a/build/stand_alone/utf8.config.h +++ b/build/stand_alone/utf8.config.h @@ -1156,6 +1156,8 @@ #define _di_f_thread_mutex_attribute_priority_ceiling_set_ #define _di_f_thread_mutex_attribute_protocol_get_ #define _di_f_thread_mutex_attribute_protocol_set_ +#define _di_f_thread_mutex_attribute_robust_get_ +#define _di_f_thread_mutex_attribute_robust_set_ #define _di_f_thread_mutex_attribute_shared_get_ #define _di_f_thread_mutex_attribute_shared_set_ #define _di_f_thread_mutex_attribute_d_ @@ -1167,7 +1169,9 @@ #define _di_f_thread_mutex_attributes_t_ #define _di_f_thread_mutex_attributess_delete_callback_ #define _di_f_thread_mutex_attributess_destroy_callback_ +#define _di_f_thread_mutex_consistent_ #define _di_f_thread_mutex_create_ +#define _di_f_thread_mutex_d_ #define _di_f_thread_mutex_delete_ #define _di_f_thread_mutex_lock_ #define _di_f_thread_mutex_lock_timed_ diff --git a/level_0/f_status/c/status.h b/level_0/f_status/c/status.h index a129d88..dba15b6 100644 --- a/level_0/f_status/c/status.h +++ b/level_0/f_status/c/status.h @@ -312,6 +312,8 @@ extern "C" { F_connect_not, F_connect_refuse, F_connect_reset, + F_consistent, + F_consistent_not, F_container, F_container_not, F_content, @@ -705,6 +707,8 @@ extern "C" { F_restore_not, F_revert, F_revert_not, + F_robust, + F_robust_not, F_schedule, F_schedule_not, F_search, diff --git a/level_0/f_status_string/c/status_string.c b/level_0/f_status_string/c/status_string.c index c4374d2..c1af845 100644 --- a/level_0/f_status_string/c/status_string.c +++ b/level_0/f_status_string/c/status_string.c @@ -180,6 +180,8 @@ extern "C" { const f_string_static_t f_status_connect_not_s = macro_f_string_static_t_initialize_1(F_status_connect_not_s, 0, F_status_connect_not_s_length); const f_string_static_t f_status_connect_refuse_s = macro_f_string_static_t_initialize_1(F_status_connect_refuse_s, 0, F_status_connect_refuse_s_length); const f_string_static_t f_status_connect_reset_s = macro_f_string_static_t_initialize_1(F_status_connect_reset_s, 0, F_status_connect_reset_s_length); + const f_string_static_t f_status_consistent_s = macro_f_string_static_t_initialize_1(F_status_consistent_s, 0, F_status_consistent_s_length); + const f_string_static_t f_status_consistent_not_s = macro_f_string_static_t_initialize_1(F_status_consistent_not_s, 0, F_status_consistent_not_s_length); const f_string_static_t f_status_container_s = macro_f_string_static_t_initialize_1(F_status_container_s, 0, F_status_container_s_length); const f_string_static_t f_status_container_not_s = macro_f_string_static_t_initialize_1(F_status_container_not_s, 0, F_status_container_not_s_length); const f_string_static_t f_status_content_s = macro_f_string_static_t_initialize_1(F_status_content_s, 0, F_status_content_s_length); @@ -581,6 +583,8 @@ extern "C" { const f_string_static_t f_status_restore_not_s = macro_f_string_static_t_initialize_1(F_status_restore_not_s, 0, F_status_restore_not_s_length); const f_string_static_t f_status_revert_s = macro_f_string_static_t_initialize_1(F_status_revert_s, 0, F_status_revert_s_length); const f_string_static_t f_status_revert_not_s = macro_f_string_static_t_initialize_1(F_status_revert_not_s, 0, F_status_revert_not_s_length); + const f_string_static_t f_status_robust_s = macro_f_string_static_t_initialize_1(F_status_robust_s, 0, F_status_robust_s_length); + const f_string_static_t f_status_robust_not_s = macro_f_string_static_t_initialize_1(F_status_robust_not_s, 0, F_status_robust_not_s_length); const f_string_static_t f_status_schedule_s = macro_f_string_static_t_initialize_1(F_status_schedule_s, 0, F_status_schedule_s_length); const f_string_static_t f_status_schedule_not_s = macro_f_string_static_t_initialize_1(F_status_schedule_not_s, 0, F_status_schedule_not_s_length); const f_string_static_t f_status_search_s = macro_f_string_static_t_initialize_1(F_status_search_s, 0, F_status_search_s_length); @@ -1570,6 +1574,26 @@ extern "C" { break; + case F_consistent: + *name = f_status_consistent_s; + + break; + + case F_consistent_not: + *name = f_status_consistent_not_s; + + break; + + case F_container: + *name = f_status_container_s; + + break; + + case F_container_not: + *name = f_status_container_not_s; + + break; + case F_content: *name = f_status_content_s; @@ -1590,16 +1614,6 @@ extern "C" { break; - case F_container: - *name = f_status_container_s; - - break; - - case F_container_not: - *name = f_status_container_not_s; - - break; - case F_control: *name = f_status_control_s; @@ -3536,6 +3550,16 @@ extern "C" { break; + case F_robust: + *name = f_status_robust_s; + + break; + + case F_robust_not: + *name = f_status_robust_not_s; + + break; + case F_schedule: *name = f_status_schedule_s; diff --git a/level_0/f_status_string/c/status_string.h b/level_0/f_status_string/c/status_string.h index fbe0b3c..d8f9b3f 100644 --- a/level_0/f_status_string/c/status_string.h +++ b/level_0/f_status_string/c/status_string.h @@ -340,6 +340,8 @@ extern "C" { #define F_status_connect_not_s "F_connect_not" #define F_status_connect_refuse_s "F_connect_refuse" #define F_status_connect_reset_s "F_connect_reset" + #define F_status_consistent_s "F_consistent" + #define F_status_consistent_not_s "F_consistent_not" #define F_status_container_s "F_container" #define F_status_container_not_s "F_container_not" #define F_status_content_s "F_content" @@ -733,6 +735,8 @@ extern "C" { #define F_status_restore_not_s "F_restore_not" #define F_status_revert_s "F_revert" #define F_status_revert_not_s "F_revert_not" + #define F_status_robust_s "F_robust" + #define F_status_robust_not_s "F_robust_not" #define F_status_schedule_s "F_schedule" #define F_status_schedule_not_s "F_schedule_not" #define F_status_search_s "F_search" @@ -942,6 +946,8 @@ extern "C" { #define F_status_connect_not_s_length 13 #define F_status_connect_refuse_s_length 16 #define F_status_connect_reset_s_length 15 + #define F_status_consistent_s_length 12 + #define F_status_consistent_not_s_length 16 #define F_status_container_s_length 11 #define F_status_container_not_s_length 15 #define F_status_content_s_length 9 @@ -1335,6 +1341,8 @@ extern "C" { #define F_status_restore_not_s_length 13 #define F_status_revert_s_length 8 #define F_status_revert_not_s_length 12 + #define F_status_robust_s_length 8 + #define F_status_robust_not_s_length 12 #define F_status_schedule_s_length 10 #define F_status_schedule_not_s_length 14 #define F_status_search_s_length 8 @@ -1544,6 +1552,8 @@ extern "C" { extern const f_string_static_t f_status_connect_not_s; extern const f_string_static_t f_status_connect_refuse_s; extern const f_string_static_t f_status_connect_reset_s; + extern const f_string_static_t f_status_consistent_s; + extern const f_string_static_t f_status_consistent_not_s; extern const f_string_static_t f_status_container_s; extern const f_string_static_t f_status_container_not_s; extern const f_string_static_t f_status_content_s; @@ -1939,6 +1949,8 @@ extern "C" { extern const f_string_static_t f_status_restore_not_s; extern const f_string_static_t f_status_revert_s; extern const f_string_static_t f_status_revert_not_s; + extern const f_string_static_t f_status_robust_s; + extern const f_string_static_t f_status_robust_not_s; extern const f_string_static_t f_status_schedule_s; extern const f_string_static_t f_status_schedule_not_s; extern const f_string_static_t f_status_search_s; diff --git a/level_0/f_status_string/tests/unit/c/test-status_string-to.c b/level_0/f_status_string/tests/unit/c/test-status_string-to.c index 653add9..70360f7 100644 --- a/level_0/f_status_string/tests/unit/c/test-status_string-to.c +++ b/level_0/f_status_string/tests/unit/c/test-status_string-to.c @@ -206,6 +206,8 @@ void test__f_status_string_to__works(void **state) { F_connect_not, F_connect_refuse, F_connect_reset, + F_consistent, + F_consistent_not, F_container, F_container_not, F_content, @@ -599,6 +601,8 @@ void test__f_status_string_to__works(void **state) { F_restore_not, F_revert, F_revert_not, + F_robust, + F_robust_not, F_schedule, F_schedule_not, F_search, @@ -877,6 +881,8 @@ void test__f_status_string_to__works(void **state) { f_status_connect_not_s, f_status_connect_refuse_s, f_status_connect_reset_s, + f_status_consistent_s, + f_status_consistent_not_s, f_status_container_s, f_status_container_not_s, f_status_content_s, @@ -1270,6 +1276,8 @@ void test__f_status_string_to__works(void **state) { f_status_restore_not_s, f_status_revert_s, f_status_revert_not_s, + f_status_robust_s, + f_status_robust_not_s, f_status_schedule_s, f_status_schedule_not_s, f_status_search_s, @@ -1371,7 +1379,7 @@ void test__f_status_string_to__works(void **state) { f_status_status_code_last_s, }; - for (uint16_t i = 0; i < 664; ++i) { + for (uint16_t i = 0; i < 668; ++i) { f_string_static_t result = f_string_static_t_initialize; diff --git a/level_0/f_thread/c/thread.c b/level_0/f_thread/c/thread.c index aeed44b..8ed74b2 100644 --- a/level_0/f_thread/c/thread.c +++ b/level_0/f_thread/c/thread.c @@ -1469,6 +1469,41 @@ extern "C" { } #endif // _di_f_thread_mutex_attribute_protocol_set_ +#ifndef _di_f_thread_mutex_attribute_robust_get_ + f_status_t f_thread_mutex_attribute_robust_get(f_thread_mutex_attribute_t * const attribute, int * const robust) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + if (!robust) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_mutexattr_getrobust(attribute, robust); + + if (error) { + return F_status_set_error(F_failure); + } + + return F_okay; + } +#endif // _di_f_thread_mutex_attribute_robust_get_ + +#ifndef _di_f_thread_mutex_attribute_robust_set_ + f_status_t f_thread_mutex_attribute_robust_set(const int robust, f_thread_mutex_attribute_t * const 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_setrobust(attribute, robust); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_okay; + } +#endif // _di_f_thread_mutex_attribute_robust_set_ + #ifndef _di_f_thread_mutex_attribute_shared_get_ f_status_t f_thread_mutex_attribute_shared_get(const f_thread_mutex_attribute_t * const attribute, int * const shared) { #ifndef _di_level_0_parameter_checking_ @@ -1535,6 +1570,24 @@ extern "C" { } #endif // _di_f_thread_mutex_attribute_type_set_ +#ifndef _di_f_thread_mutex_consistent_ + f_status_t f_thread_mutex_consistent(f_thread_mutex_t * const mutex) { + #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_consistent(mutex); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_robust_not); + + return F_status_set_error(F_failure); + } + + return F_okay; + } +#endif // _di_f_thread_mutex_consistent_ + #ifndef _di_f_thread_mutex_create_ f_status_t f_thread_mutex_create(f_thread_mutex_attribute_t * const attribute, f_thread_mutex_t * const mutex) { #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 334c7cf..58850b0 100644 --- a/level_0/f_thread/c/thread.h +++ b/level_0/f_thread/c/thread.h @@ -1974,6 +1974,54 @@ extern "C" { #endif // _di_f_thread_mutex_attribute_protocol_set_ /** + * Get the robust mutex attribute. + * + * @param attribute + * The mutex attributes to set the value of. + * + * Must not be NULL. + * @param robust + * The value to set to robust attribute to. + * See f_thread_mutex_stalled_d and f_thread_mutex_robust_d. + * + * Must not be NULL. + * + * @return + * F_okay on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_failure (with error bit) on any other error. + * + * @see pthread_mutexattr_setrobust() + */ +#ifndef _di_f_thread_mutex_attribute_robust_get_ + extern f_status_t f_thread_mutex_attribute_robust_get(f_thread_mutex_attribute_t * const attribute, int * const robust); +#endif // _di_f_thread_mutex_attribute_robust_get_ + +/** + * Set the robust mutex attribute. + * + * @param robust + * The value to set to robust attribute to. + * See f_thread_mutex_stalled_d and f_thread_mutex_robust_d. + * @param attribute + * The mutex attributes to set the value of. + * + * Must not be NULL. + * + * @return + * F_okay on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_failure (with error bit) on any other error. + * + * @see pthread_mutexattr_setrobust() + */ +#ifndef _di_f_thread_mutex_attribute_robust_set_ + extern f_status_t f_thread_mutex_attribute_robust_set(const int robust, f_thread_mutex_attribute_t * const attribute); +#endif // _di_f_thread_mutex_attribute_robust_set_ + +/** * Get the mutex attribute process shared thread attribute. * * @param attribute @@ -2070,6 +2118,32 @@ extern "C" { #endif // _di_f_thread_mutex_attribute_type_set_ /** + * Mark a robust mutex as consistent. + * + * Use this to re-mark a mutex that is no longer in a consistent state. + * + * This should be used to address mutex locks that return F_dead when attempting to acquire a lock. + * + * @param mutex + * The thread mutex. + * + * Must not be NULL. + * + * @return + * F_okay on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_robust (with error bit) if mutex is either not robust or it does not protect from an inconsistent state. + * + * F_failure (with error bit) on any other error. + * + * @see pthread_mutex_consistent() + */ +#ifndef _di_f_thread_mutex_consistent_ + extern f_status_t f_thread_mutex_consistent(f_thread_mutex_t * const mutex); +#endif // _di_f_thread_mutex_consistent_ + +/** * Create a thread mutex. * * @param attribute diff --git a/level_0/f_thread/c/thread/mutex.h b/level_0/f_thread/c/thread/mutex.h index f77f17d..094a48c 100644 --- a/level_0/f_thread/c/thread/mutex.h +++ b/level_0/f_thread/c/thread/mutex.h @@ -17,6 +17,18 @@ extern "C" { #endif /** + * Mutex defines. + * + * f_thread_mutex_*_d: + * - robust: The mutex is in a robust state. + * - stalled: The mutex is in a stalled state (non-robust), such as when F_dead is returned on lock attempts. + */ +#ifndef _di_f_thread_mutex_d_ + #define f_thread_mutex_robust_d PTHREAD_MUTEX_ROBUST + #define f_thread_mutex_stalled_d PTHREAD_MUTEX_STALLED +#endif // _di_f_thread_mutex_d_ + +/** * A typedef representing pthread_mutex_t. * * This variable cannot be cleared by setting value to 0, so there is no clear macro provided. diff --git a/level_0/f_thread/data/build/settings-mocks b/level_0/f_thread/data/build/settings-mocks index bcef337..1f7f2f5 100644 --- a/level_0/f_thread/data/build/settings-mocks +++ b/level_0/f_thread/data/build/settings-mocks @@ -128,6 +128,7 @@ flags -Wl,--wrap=pthread_join flags -Wl,--wrap=pthread_key_create flags -Wl,--wrap=pthread_key_delete flags -Wl,--wrap=pthread_kill +flags -Wl,--wrap=pthread_mutex_consistent flags -Wl,--wrap=pthread_mutex_destroy flags -Wl,--wrap=pthread_mutex_getprioceiling flags -Wl,--wrap=pthread_mutex_init @@ -141,10 +142,12 @@ flags -Wl,--wrap=pthread_mutexattr_init flags -Wl,--wrap=pthread_mutexattr_getprioceiling flags -Wl,--wrap=pthread_mutexattr_getprotocol flags -Wl,--wrap=pthread_mutexattr_getpshared +flags -Wl,--wrap=pthread_mutexattr_getrobust flags -Wl,--wrap=pthread_mutexattr_gettype flags -Wl,--wrap=pthread_mutexattr_setprioceiling flags -Wl,--wrap=pthread_mutexattr_setprotocol flags -Wl,--wrap=pthread_mutexattr_setpshared +flags -Wl,--wrap=pthread_mutexattr_setrobust flags -Wl,--wrap=pthread_mutexattr_settype flags -Wl,--wrap=pthread_once flags -Wl,--wrap=pthread_rwlock_destroy diff --git a/level_0/f_thread/data/build/settings-tests b/level_0/f_thread/data/build/settings-tests index c93065a..5954e88 100644 --- a/level_0/f_thread/data/build/settings-tests +++ b/level_0/f_thread/data/build/settings-tests @@ -82,9 +82,11 @@ build_sources_program test-thread-lock_read.c test-thread-lock_read_timed.c test build_sources_program test-thread-lock_write.c test-thread-lock_write_timed.c test-thread-lock_write_try.c build_sources_program test-thread-mutex_attribute_create.c test-thread-mutex_attribute_delete.c build_sources_program test-thread-mutex_attribute_priority_ceiling_get.c test-thread-mutex_attribute_priority_ceiling_set.c +build_sources_program test-thread-mutex_attribute_robust_get.c test-thread-mutex_attribute_robust_set.c build_sources_program test-thread-mutex_attribute_shared_get.c test-thread-mutex_attribute_shared_set.c build_sources_program test-thread-mutex_attribute_type_get.c test-thread-mutex_attribute_type_set.c build_sources_program test-thread-mutex_attribute_protocol_get.c test-thread-mutex_attribute_protocol_set.c +build_sources_program test-thread-mutex_consistent.c build_sources_program test-thread-mutex_create.c test-thread-mutex_delete.c build_sources_program test-thread-mutex_lock.c test-thread-mutex_lock_timed.c test-thread-mutex_lock_try.c build_sources_program test-thread-scheduler_parameter_get.c test-thread-scheduler_parameter_set.c diff --git a/level_0/f_thread/tests/unit/c/mock-thread.c b/level_0/f_thread/tests/unit/c/mock-thread.c index 2935fcf..bab8a3a 100644 --- a/level_0/f_thread/tests/unit/c/mock-thread.c +++ b/level_0/f_thread/tests/unit/c/mock-thread.c @@ -607,6 +607,17 @@ int __wrap_pthread_kill(pthread_t thread, int sig) { return 0; } +int __wrap_pthread_mutex_consistent(pthread_mutex_t *mutex) { + + const bool failure = mock_type(bool); + + if (failure) { + return mock_type(int); + } + + return 0; +} + int __wrap_pthread_mutex_destroy(pthread_mutex_t *mutex) { const bool failure = mock_type(bool); @@ -750,6 +761,28 @@ int __wrap_pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *ps return 0; } +int __wrap_pthread_mutexattr_getrobust(const pthread_mutexattr_t *restrict attr, int *restrict robust) { + + const bool failure = mock_type(bool); + + if (failure) { + return mock_type(int); + } + + return 0; +} + +int __wrap_pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust) { + + const bool failure = mock_type(bool); + + if (failure) { + return mock_type(int); + } + + return 0; +} + int __wrap_pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) { const bool failure = mock_type(bool); diff --git a/level_0/f_thread/tests/unit/c/mock-thread.h b/level_0/f_thread/tests/unit/c/mock-thread.h index 1a59e3b..ff7793d 100644 --- a/level_0/f_thread/tests/unit/c/mock-thread.h +++ b/level_0/f_thread/tests/unit/c/mock-thread.h @@ -87,6 +87,7 @@ extern int __wrap_pthread_join(pthread_t pthread, void **value_ptr); extern int __wrap_pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); extern int __wrap_pthread_key_delete(pthread_key_t key); extern int __wrap_pthread_kill(pthread_t thread, int sig); +extern int __wrap_pthread_mutex_consistent(pthread_mutex_t *mutex); extern int __wrap_pthread_mutex_destroy(pthread_mutex_t *mutex); extern int __wrap_pthread_mutex_getprioceiling(const pthread_mutex_t * restrict mutex, int *prioceiling); extern int __wrap_pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); @@ -100,6 +101,8 @@ extern int __wrap_pthread_mutexattr_init(pthread_mutexattr_t *attr); extern int __wrap_pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *prioceiling); extern int __wrap_pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol); extern int __wrap_pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared); +extern int __wrap_pthread_mutexattr_getrobust(const pthread_mutexattr_t *restrict attr, int *restrict robust); +extern int __wrap_pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust); extern int __wrap_pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind); extern int __wrap_pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling); extern int __wrap_pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol); diff --git a/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_get.c b/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_get.c new file mode 100644 index 0000000..ebb61c7 --- /dev/null +++ b/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_get.c @@ -0,0 +1,72 @@ +#include "test-thread.h" +#include "test-thread-mutex_attribute_robust_get.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_thread_mutex_attribute_robust_get__fails(void **state) { + + f_thread_mutex_attribute_t attribute = f_thread_mutex_attribute_t_initialize; + int robust = 0; + + int errnos[] = { + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_failure, + }; + + for (uint8_t i = 0; i < 1; ++i) { + + will_return(__wrap_pthread_mutexattr_getrobust, true); + will_return(__wrap_pthread_mutexattr_getrobust, errnos[i]); + + const f_status_t status = f_thread_mutex_attribute_robust_get(&attribute, &robust); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for +} + +void test__f_thread_mutex_attribute_robust_get__parameter_checking(void **state) { + + f_thread_mutex_attribute_t attribute = f_thread_mutex_attribute_t_initialize; + int robust = 0; + + { + const f_status_t status = f_thread_mutex_attribute_robust_get(0, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } + + { + const f_status_t status = f_thread_mutex_attribute_robust_get(&attribute, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } + + { + const f_status_t status = f_thread_mutex_attribute_robust_get(0, &robust); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_thread_mutex_attribute_robust_get__works(void **state) { + + f_thread_mutex_attribute_t attribute = f_thread_mutex_attribute_t_initialize; + int robust = 0; + + { + will_return(__wrap_pthread_mutexattr_getrobust, false); + + const f_status_t status = f_thread_mutex_attribute_robust_get(&attribute, &robust); + + assert_int_equal(status, F_okay); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_get.h b/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_get.h new file mode 100644 index 0000000..9465400 --- /dev/null +++ b/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_get.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Thread + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the thread project. + */ +#ifndef _TEST__F_thread__mutex_attribute_robust_get_h +#define _TEST__F_thread__mutex_attribute_robust_get_h + +/** + * Test that function fails. + * + * @see f_thread_mutex_attribute_robust_get() + */ +extern void test__f_thread_mutex_attribute_robust_get__fails(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see f_thread_mutex_attribute_robust_get() + */ +extern void test__f_thread_mutex_attribute_robust_get__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_thread_mutex_attribute_robust_get() + */ +extern void test__f_thread_mutex_attribute_robust_get__works(void **state); + +#endif // _TEST__F_thread__mutex_attribute_robust_get_h diff --git a/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_set.c b/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_set.c new file mode 100644 index 0000000..a54a505 --- /dev/null +++ b/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_set.c @@ -0,0 +1,61 @@ +#include "test-thread.h" +#include "test-thread-mutex_attribute_robust_set.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_thread_mutex_attribute_robust_set__fails(void **state) { + + f_thread_mutex_attribute_t attribute = f_thread_mutex_attribute_t_initialize; + int robust = 0; + + int errnos[] = { + EINVAL, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_parameter, + F_failure, + }; + + for (uint8_t i = 0; i < 2; ++i) { + + will_return(__wrap_pthread_mutexattr_setrobust, true); + will_return(__wrap_pthread_mutexattr_setrobust, errnos[i]); + + const f_status_t status = f_thread_mutex_attribute_robust_set(robust, &attribute); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for +} + +void test__f_thread_mutex_attribute_robust_set__parameter_checking(void **state) { + + int robust = 0; + + { + const f_status_t status = f_thread_mutex_attribute_robust_set(robust, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_thread_mutex_attribute_robust_set__works(void **state) { + + f_thread_mutex_attribute_t attribute = f_thread_mutex_attribute_t_initialize; + int robust = 0; + + { + will_return(__wrap_pthread_mutexattr_setrobust, false); + + const f_status_t status = f_thread_mutex_attribute_robust_set(robust, &attribute); + + assert_int_equal(status, F_okay); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_set.h b/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_set.h new file mode 100644 index 0000000..25bf82e --- /dev/null +++ b/level_0/f_thread/tests/unit/c/test-thread-mutex_attribute_robust_set.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Thread + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the thread project. + */ +#ifndef _TEST__F_thread__mutex_attribute_robust_set_h +#define _TEST__F_thread__mutex_attribute_robust_set_h + +/** + * Test that function fails. + * + * @see f_thread_mutex_attribute_robust_set() + */ +extern void test__f_thread_mutex_attribute_robust_set__fails(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see f_thread_mutex_attribute_robust_set() + */ +extern void test__f_thread_mutex_attribute_robust_set__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_thread_mutex_attribute_robust_set() + */ +extern void test__f_thread_mutex_attribute_robust_set__works(void **state); + +#endif // _TEST__F_thread__mutex_attribute_robust_set_h diff --git a/level_0/f_thread/tests/unit/c/test-thread-mutex_consistent.c b/level_0/f_thread/tests/unit/c/test-thread-mutex_consistent.c new file mode 100644 index 0000000..b253ff2 --- /dev/null +++ b/level_0/f_thread/tests/unit/c/test-thread-mutex_consistent.c @@ -0,0 +1,57 @@ +#include "test-thread.h" +#include "test-thread-mutex_consistent.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__f_thread_mutex_consistent__fails(void **state) { + + f_thread_mutex_t mutex = f_thread_mutex_t_initialize; + + int errnos[] = { + EINVAL, + mock_errno_generic, + }; + + f_status_t statuss[] = { + F_robust_not, + F_failure, + }; + + for (uint8_t i = 0; i < 2; ++i) { + + will_return(__wrap_pthread_mutex_consistent, true); + will_return(__wrap_pthread_mutex_consistent, errnos[i]); + + const f_status_t status = f_thread_mutex_consistent(&mutex); + + assert_int_equal(status, F_status_set_error(statuss[i])); + } // for +} + +void test__f_thread_mutex_consistent__parameter_checking(void **state) { + + { + const f_status_t status = f_thread_mutex_consistent(0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +void test__f_thread_mutex_consistent__works(void **state) { + + f_thread_mutex_t mutex = f_thread_mutex_t_initialize; + + { + will_return(__wrap_pthread_mutex_consistent, false); + + const f_status_t status = f_thread_mutex_consistent(&mutex); + + assert_int_equal(status, F_okay); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_0/f_thread/tests/unit/c/test-thread-mutex_consistent.h b/level_0/f_thread/tests/unit/c/test-thread-mutex_consistent.h new file mode 100644 index 0000000..10c17dd --- /dev/null +++ b/level_0/f_thread/tests/unit/c/test-thread-mutex_consistent.h @@ -0,0 +1,34 @@ +/** + * FLL - Level 0 + * + * Project: Thread + * API Version: 0.7 + * Licenses: lgpl-2.1-or-later + * + * Test the thread project. + */ +#ifndef _TEST__F_thread__mutex_consistent_h +#define _TEST__F_thread__mutex_consistent_h + +/** + * Test that function fails. + * + * @see f_thread_mutex_consistent() + */ +extern void test__f_thread_mutex_consistent__fails(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see f_thread_mutex_consistent() + */ +extern void test__f_thread_mutex_consistent__parameter_checking(void **state); + +/** + * Test that function works. + * + * @see f_thread_mutex_consistent() + */ +extern void test__f_thread_mutex_consistent__works(void **state); + +#endif // _TEST__F_thread__mutex_consistent_h diff --git a/level_0/f_thread/tests/unit/c/test-thread.c b/level_0/f_thread/tests/unit/c/test-thread.c index d0a8813..61208d5 100644 --- a/level_0/f_thread/tests/unit/c/test-thread.c +++ b/level_0/f_thread/tests/unit/c/test-thread.c @@ -301,6 +301,12 @@ int main(void) { cmocka_unit_test(test__f_thread_mutex_attribute_priority_ceiling_set__fails), cmocka_unit_test(test__f_thread_mutex_attribute_priority_ceiling_set__works), + cmocka_unit_test(test__f_thread_mutex_attribute_robust_get__fails), + cmocka_unit_test(test__f_thread_mutex_attribute_robust_get__works), + + cmocka_unit_test(test__f_thread_mutex_attribute_robust_set__fails), + cmocka_unit_test(test__f_thread_mutex_attribute_robust_set__works), + cmocka_unit_test(test__f_thread_mutex_attribute_shared_get__fails), cmocka_unit_test(test__f_thread_mutex_attribute_shared_get__works), @@ -319,6 +325,9 @@ int main(void) { cmocka_unit_test(test__f_thread_mutex_attribute_protocol_set__fails), cmocka_unit_test(test__f_thread_mutex_attribute_protocol_set__works), + cmocka_unit_test(test__f_thread_mutex_consistent__fails), + cmocka_unit_test(test__f_thread_mutex_consistent__works), + cmocka_unit_test(test__f_thread_mutex_create__fails), cmocka_unit_test(test__f_thread_mutex_create__works), @@ -591,6 +600,10 @@ int main(void) { cmocka_unit_test(test__f_thread_mutex_attribute_priority_ceiling_set__parameter_checking), + cmocka_unit_test(test__f_thread_mutex_attribute_robust_get__parameter_checking), + + cmocka_unit_test(test__f_thread_mutex_attribute_robust_set__parameter_checking), + cmocka_unit_test(test__f_thread_mutex_attribute_shared_get__parameter_checking), cmocka_unit_test(test__f_thread_mutex_attribute_shared_set__parameter_checking), diff --git a/level_0/f_thread/tests/unit/c/test-thread.h b/level_0/f_thread/tests/unit/c/test-thread.h index 87f712a..c7d574f 100644 --- a/level_0/f_thread/tests/unit/c/test-thread.h +++ b/level_0/f_thread/tests/unit/c/test-thread.h @@ -131,12 +131,15 @@ #include "test-thread-mutex_attribute_delete.h" #include "test-thread-mutex_attribute_priority_ceiling_get.h" #include "test-thread-mutex_attribute_priority_ceiling_set.h" +#include "test-thread-mutex_attribute_robust_get.h" +#include "test-thread-mutex_attribute_robust_set.h" #include "test-thread-mutex_attribute_shared_get.h" #include "test-thread-mutex_attribute_shared_set.h" #include "test-thread-mutex_attribute_type_get.h" #include "test-thread-mutex_attribute_type_set.h" #include "test-thread-mutex_attribute_protocol_get.h" #include "test-thread-mutex_attribute_protocol_set.h" +#include "test-thread-mutex_consistent.h" #include "test-thread-mutex_create.h" #include "test-thread-mutex_delete.h" #include "test-thread-mutex_lock.h" diff --git a/level_1/fl_status_string/c/status_string.c b/level_1/fl_status_string/c/status_string.c index 8cee174..975931a 100644 --- a/level_1/fl_status_string/c/status_string.c +++ b/level_1/fl_status_string/c/status_string.c @@ -1094,6 +1094,18 @@ extern "C" { return F_okay; } + if (f_compare_dynamic(name, f_status_consistent_s) == F_equal_to) { + *code = F_consistent; + + return F_okay; + } + + if (f_compare_dynamic(name, f_status_consistent_not_s) == F_equal_to) { + *code = F_consistent_not; + + return F_okay; + } + if (f_compare_dynamic(name, f_status_container_s) == F_equal_to) { *code = F_container; @@ -3450,6 +3462,18 @@ extern "C" { return F_okay; } + if (f_compare_dynamic(name, f_status_robust_s) == F_equal_to) { + *code = F_robust; + + return F_okay; + } + + if (f_compare_dynamic(name, f_status_robust_not_s) == F_equal_to) { + *code = F_robust_not; + + return F_okay; + } + if (f_compare_dynamic(name, f_status_schedule_s) == F_equal_to) { *code = F_schedule; diff --git a/level_1/fl_status_string/tests/unit/c/test-status_string-from.c b/level_1/fl_status_string/tests/unit/c/test-status_string-from.c index 13b9e5b..f8142de 100644 --- a/level_1/fl_status_string/tests/unit/c/test-status_string-from.c +++ b/level_1/fl_status_string/tests/unit/c/test-status_string-from.c @@ -222,6 +222,8 @@ void test__fl_status_string_from__works(void **state) { F_connect_not, F_connect_refuse, F_connect_reset, + F_consistent, + F_consistent_not, F_container, F_container_not, F_content, @@ -615,6 +617,8 @@ void test__fl_status_string_from__works(void **state) { F_restore_not, F_revert, F_revert_not, + F_robust, + F_robust_not, F_schedule, F_schedule_not, F_search, @@ -893,6 +897,8 @@ void test__fl_status_string_from__works(void **state) { f_status_connect_not_s, f_status_connect_refuse_s, f_status_connect_reset_s, + f_status_consistent_s, + f_status_consistent_not_s, f_status_container_s, f_status_container_not_s, f_status_content_s, @@ -1286,6 +1292,8 @@ void test__fl_status_string_from__works(void **state) { f_status_restore_not_s, f_status_revert_s, f_status_revert_not_s, + f_status_robust_s, + f_status_robust_not_s, f_status_schedule_s, f_status_schedule_not_s, f_status_search_s, @@ -1387,7 +1395,7 @@ void test__fl_status_string_from__works(void **state) { f_status_status_code_last_s, }; - for (uint16_t i = 0; i < 664; ++i) { + for (uint16_t i = 0; i < 668; ++i) { f_status_t result = F_okay; -- 1.8.3.1