From f5880ee5d5559d45771e4a626c54309c88f437e7 Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Fri, 1 Jul 2016 09:51:32 +0900
Subject: Change API of chopstx_setpriority

---
 ChangeLog               |  4 ++++
 chopstx.c               | 39 ++++++++++++++++++++++++---------------
 chopstx.h               |  2 +-
 example-fs-bb48/touch.c |  6 ++++++
 4 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 2c4b0b5..3e1e1e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2016-07-01  NIIBE Yutaka  <gniibe@fsij.org>
+
+	* chopstx.c (chopstx_setpriority): Change the API.
+
 2016-06-30  NIIBE Yutaka  <gniibe@fsij.org>
 
 	* example-cdc/usb-cdc.c (tty_recv, tty_main): Follow the change of
diff --git a/chopstx.c b/chopstx.c
index 4aa9d75..6d9de04 100644
--- a/chopstx.c
+++ b/chopstx.c
@@ -1868,6 +1868,7 @@ chopstx_poll (uint32_t *usec_p, int n, struct chx_poll_head *pd_array[])
  * @prio: priority
  *
  * Change the schedule priority with @prio.
+ * Returns the old priority.
  *
  * In general, it is not recommended to use this function because
  * dynamically changing schedule priorities complicates the system.
@@ -1875,25 +1876,33 @@ chopstx_poll (uint32_t *usec_p, int n, struct chx_poll_head *pd_array[])
  * which starts its execution with priority of CHX_PRIO_MAIN_INIT, and
  * let it change its priority after initialization of other threads.
  */
-void
-chopstx_setpriority (chopstx_prio_t prio)
+chopstx_prio_t
+chopstx_setpriority (chopstx_prio_t prio_new)
 {
   struct chx_thread *tp = running;
+  chopstx_prio_t prio_orig, prio_cur;
 
-  if (tp->prio < CHOPSTX_PRIO_INHIBIT_PREEMPTION
-      && prio >= CHOPSTX_PRIO_INHIBIT_PREEMPTION)
-    {
-      chx_cpu_sched_lock ();
-      tp->prio = tp->prio_orig = prio;
-    }
-  else if (tp->prio >= CHOPSTX_PRIO_INHIBIT_PREEMPTION
-      && prio < CHOPSTX_PRIO_INHIBIT_PREEMPTION)
-    {
-      tp->prio = tp->prio_orig = prio;
-      chx_cpu_sched_unlock ();
-    }
+  chx_cpu_sched_lock ();
+  prio_orig = tp->prio_orig;
+  prio_cur = tp->prio;
+
+  tp->prio_orig = prio_new;
+  if (prio_cur == prio_orig)
+    /* No priority inheritance is active.  */
+    tp->prio = prio_new;
   else
-    tp->prio = tp->prio_orig = prio;
+    /* Priority inheritance is active.  */
+    /* In this case, only when new priority is greater, change the
+       priority of this thread.  */
+    if (prio_new > prio_cur)
+      tp->prio = prio_new;
+
+  if (tp->prio < prio_cur)
+    chx_sched (CHX_YIELD);
+  else if (tp->prio < CHOPSTX_PRIO_INHIBIT_PREEMPTION)
+    chx_cpu_sched_unlock ();
+
+  return prio_orig;
 }
 
 /*
diff --git a/chopstx.h b/chopstx.h
index b8daa0e..54153e6 100644
--- a/chopstx.h
+++ b/chopstx.h
@@ -113,7 +113,7 @@ typedef struct chx_cleanup {
 void chopstx_cleanup_push (chopstx_cleanup_t *clp);
 void chopstx_cleanup_pop (int execute);
 
-void chopstx_setpriority (chopstx_prio_t);
+chopstx_prio_t chopstx_setpriority (chopstx_prio_t);
 
 enum {
   CHOPSTX_POLL_COND = 0,
diff --git a/example-fs-bb48/touch.c b/example-fs-bb48/touch.c
index 127be23..960692e 100644
--- a/example-fs-bb48/touch.c
+++ b/example-fs-bb48/touch.c
@@ -27,6 +27,10 @@ static chopstx_intr_t tpm1_intr;
 uint16_t
 touch_get (void)
 {
+  chopstx_prio_t prio_old;
+
+  prio_old = chopstx_setpriority (CHOPSTX_PRIO_INHIBIT_PREEMPTION);
+
   /* Assert LOW.  */ 
   PORTB->PCR1 = (1<<8) /* GPIO                  */
               | (0<<6) /* DriveStrengthEnable=0 */
@@ -51,6 +55,8 @@ touch_get (void)
               | (0<<0) /* puddselect= 0         */
               ;
 
+  chopstx_setpriority (prio_old);
+
   chopstx_intr_wait (&tpm1_intr);
   /* Clear overflow and CH1 capture.  */
   TPM1->STATUS = 0x102;
-- 
cgit v1.2.3