]> Kevux Git Server - fll/commitdiff
Update: add pthread semaphore support and correct comments.
authorKevin Day <thekevinday@gmail.com>
Wed, 7 Apr 2021 04:52:43 +0000 (23:52 -0500)
committerKevin Day <thekevinday@gmail.com>
Wed, 7 Apr 2021 04:57:31 +0000 (23:57 -0500)
This includes named semaphores, using the words "semaphore_file".

Fix several problems with the comments.

level_0/f_thread/c/private-thread.c
level_0/f_thread/c/private-thread.h
level_0/f_thread/c/thread-common.h
level_0/f_thread/c/thread.c
level_0/f_thread/c/thread.h
level_0/f_thread/data/build/dependencies
level_0/f_thread/data/build/settings

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