* Included Files
********************************************************************************/
-#include <tinyara/config.h> /* Default settings */
+#include <tinyara/config.h> /* Default settings */
#include <tinyara/compiler.h> /* Compiler settings, noreturn_function */
-#include <sys/types.h> /* Needed for general types */
-#include <sys/prctl.h> /* Needed by pthread_[set|get]name_np */
+#include <sys/types.h> /* Needed for general types */
+#include <sys/prctl.h> /* Needed by pthread_[set|get]name_np */
-#include <stdint.h> /* C99 fixed width integer types */
-#include <stdbool.h> /* C99 boolean types */
-#include <unistd.h> /* For getpid */
-#include <semaphore.h> /* Needed for sem_t */
-#include <signal.h> /* Needed for sigset_t */
-#include <time.h> /* Needed for struct timespec */
+#include <stdint.h> /* C99 fixed width integer types */
+#include <stdbool.h> /* C99 boolean types */
+#include <unistd.h> /* For getpid */
+#include <signal.h> /* Needed for sigset_t */
+#include <time.h> /* Needed for struct timespec */
+
+#include <tinyara/semaphore.h> /* For sem_t and SEM_PRIO_* defines */
/********************************************************************************
* Pre-processor Definitions
#define PTHREAD_INHERIT_SCHED 0
#define PTHREAD_EXPLICIT_SCHED 1
-#define PTHREAD_PRIO_NONE 0
-#define PTHREAD_PRIO_INHERIT 1
-#define PTHREAD_PRIO_PROTECT 2
+/* Default priority */
#define PTHREAD_DEFAULT_PRIORITY 100
#define PTHREAD_BARRIER_SERIAL_THREAD 0x1000
-/* Values for protocol attribute */
+/* Values for protocol mutex attribute */
#define PTHREAD_PRIO_NONE SEM_PRIO_NONE
#define PTHREAD_PRIO_INHERIT SEM_PRIO_INHERIT
#include <stdint.h>
#include <limits.h>
-#ifdef __cplusplus
-#define EXTERN extern "C"
-extern "C" {
-#else
-#define EXTERN extern
-#endif
-
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-/* Values for protocol attribute */
-
-#define SEM_PRIO_NONE 0
-#define SEM_PRIO_INHERIT 1
-#define SEM_PRIO_PROTECT 2
-
/* Bit definitions for the struct sem_s flags field */
#define PRIOINHERIT_FLAGS_DISABLE (1 << 0) /* Bit 0: Priority inheritance
* Public Variables
****************************************************************************/
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
* Pre-processor Definitions
****************************************************************************/
+/* Values for protocol attribute */
+
+#define SEM_PRIO_NONE 0
+#define SEM_PRIO_INHERIT 1
+#define SEM_PRIO_PROTECT 2
+
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef CONFIG_PRIORITY_INHERITANCE
int sem_getprotocol(FAR sem_t *sem, FAR int *protocol);
+#else
+#define sem_getprotocol(s,p) do { *(p) == SEM_PRIO_NONE); } while (0)
#endif
/****************************************************************************
* Description:
* Set semaphore protocol attribute.
*
+ * One particularly important use of this function is when a semaphore
+ * is used for inter-task communication like:
+ *
+ * TASK A TASK B
+ * sem_init(sem, 0, 0);
+ * sem_wait(sem);
+ * sem_post(sem);
+ * Awakens as holder
+ *
+ * In this case priority inheritance can interfere with the operation of
+ * the semaphore. The problem is that when TASK A is restarted it is a
+ * holder of the semaphore. However, it never calls sem_post(sem) so it
+ * becomes *permanently* a holder of the semaphore and may have its
+ * priority boosted when any other task tries to acquire the semaphore.
+ *
+ * The fix is to call sem_setprotocol(SEM_PRIO_NONE) immediately after
+ * the sem_init() call so that there will be no priority inheritance
+ * operations on this semaphore.
+ *
* Parameters:
* sem - A pointer to the semaphore whose attributes are to be
* modified
#ifdef CONFIG_PRIORITY_INHERITANCE
int sem_setprotocol(FAR sem_t *sem, int protocol);
+#else
+#define sem_setprotocol(s,p) DEBUGASSERT((p) == SEM_PRIO_NONE);
#endif
#undef EXTERN
* Description:
* Set semaphore protocol attribute.
*
+ * One particularly important use of this furnction is when a semaphore
+ * is used for inter-task communication like:
+ *
+ * TASK A TASK B
+ * sem_init(sem, 0, 0);
+ * sem_wait(sem);
+ * sem_post(sem);
+ * Awakens as holder
+ *
+ * In this case priority inheritance can interfere with the operation of
+ * the semaphore. The problem is that when TASK A is restarted it is a
+ * holder of the semaphore. However, it never calls sem_post(sem) so it
+ * becomes *permanently* a holder of the semaphore and may have its
+ * priority boosted when any other task tries to acquire the semaphore.
+ *
+ * The fix is to call sem_setprotocol(SEM_PRIO_NONE) immediately after
+ * the sem_init() call so that there will be no priority inheritance
+ * operations on this semaphore.
+ *
* Parameters:
* sem - A pointer to the semaphore whose attributes are to be
* modified