kernel/semaphore: add macros for sem_get/setprotocol()
authorHeesub Shin <heesub.shin@samsung.com>
Thu, 6 Apr 2017 01:11:40 +0000 (10:11 +0900)
committerHeesub Shin <heesub.shin@samsung.com>
Tue, 18 Apr 2017 03:02:11 +0000 (12:02 +0900)
Provide macros for sem_setprotocol() and sem_getprotocol() if priority
inheritance is not enabled. More SEM_PRIO_* definitions to
include/tinyara/semaphore.h.

All credits should go to Gregory Nutt who wrote the original patch.

Change-Id: Id0f931210629e5b15db5c659b914794662f04adc
Signed-off-by: Gregory Nutt <gnutt@nuttx.org>
[Shin: backported 97bf82ee from NuttX]
Signed-off-by: Heesub Shin <heesub.shin@samsung.com>
os/include/pthread.h
os/include/semaphore.h
os/include/tinyara/semaphore.h
os/kernel/semaphore/sem_setprotocol.c

index 4506a84..1530a58 100644 (file)
  * 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
index d9594af..3ab6263 100644 (file)
 #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
@@ -160,6 +147,14 @@ typedef struct sem_s sem_t;
  * Public Variables
  ****************************************************************************/
 
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
index 3f25428..733a286 100644 (file)
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* Values for protocol attribute */
+
+#define SEM_PRIO_NONE          0
+#define SEM_PRIO_INHERIT       1
+#define SEM_PRIO_PROTECT       2
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -158,6 +164,8 @@ int sem_reset(FAR sem_t *sem, int16_t count);
 
 #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
 
 /****************************************************************************
@@ -166,6 +174,25 @@ int sem_getprotocol(FAR sem_t *sem, FAR int *protocol);
  * 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
@@ -179,6 +206,8 @@ int sem_getprotocol(FAR sem_t *sem, FAR int *protocol);
 
 #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
index 127cf11..85ba240 100644 (file)
  * 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