From 3b1306078b57c5f6fa6141ecd3d80e4847c0b981 Mon Sep 17 00:00:00 2001
From: Gregory Nutt <gnutt@nuttx.org>
Date: Thu, 23 Jul 2015 15:08:41 -0600
Subject: [PATCH] Sporadic Scheduler:  Ensure that the replenishment period is
 greater than or equal to the budget period

---
 sched/pthread/pthread_create.c   | 46 +++++++++++++++++++------
 sched/sched/sched_setparam.c     | 59 ++++++++++++++++++++++----------
 sched/sched/sched_setscheduler.c | 39 ++++++++++++---------
 3 files changed, 100 insertions(+), 44 deletions(-)

diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c
index 86e3dd8d8d..9cea2af0e8 100644
--- a/sched/pthread/pthread_create.c
+++ b/sched/pthread/pthread_create.c
@@ -227,9 +227,6 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
 {
   FAR struct pthread_tcb_s *ptcb;
   FAR struct join_s *pjoin;
-#ifdef CONFIG_SCHED_SPORADIC
-  int ticks;
-#endif
   int priority;
   int policy;
   int errcode;
@@ -308,6 +305,9 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
   if (attr->inheritsched == PTHREAD_INHERIT_SCHED)
     {
       struct sched_param param;
+#ifdef CONFIG_SCHED_SPORADIC
+      int ticks;
+#endif
 
       /* Get the priority (and any other scheduling parameters) for this
        * thread.
@@ -352,16 +352,42 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
       policy   = attr->policy;
 
 #ifdef CONFIG_SCHED_SPORADIC
-      /* Save the sporadic scheduling parameters */
+      if (policy == SCHED_SPORADIC)
+        {
+          int repl_ticks;
+          int budget_ticks;
 
-      ptcb->cmn.low_priority = attr->low_priority;
-      ptcb->cmn.max_repl     = attr->max_repl;
+          /* Convert timespec values to system clock ticks */
 
-      (void)clock_time2ticks(&attr->repl_period, &ticks);
-      ptcb->cmn.repl_period  = ticks;
+          (void)clock_time2ticks(&attr->repl_period, &repl_ticks);
+          (void)clock_time2ticks(&attr->budget, &budget_ticks);
 
-      (void)clock_time2ticks(&attr->budget, &ticks);
-      ptcb->cmn.budget       = ticks;
+          /* The replenishment period must be greater than or equal to the
+           * budget period.
+           */
+
+          if (repl_ticks < budget_ticks)
+            {
+              errcode = EINVAL;
+              goto errout_with_join;
+            }
+
+          /* Save the sporadic scheduling parameters */
+
+          ptcb->cmn.low_priority = attr->low_priority;
+          ptcb->cmn.max_repl     = attr->max_repl;
+          ptcb->cmn.repl_period  = repl_ticks;
+          ptcb->cmn.budget       = budget_ticks;
+        }
+      else
+        {
+          /* Ignore sporadic scheduling parameters */
+
+          ptcb->cmn.low_priority = 0;
+          ptcb->cmn.max_repl     = 0;
+          ptcb->cmn.repl_period  = 0;
+          ptcb->cmn.budget       = 0;
+        }
 #endif
     }
 
diff --git a/sched/sched/sched_setparam.c b/sched/sched/sched_setparam.c
index e75980c3b5..f7f193cdcf 100644
--- a/sched/sched/sched_setparam.c
+++ b/sched/sched/sched_setparam.c
@@ -86,14 +86,15 @@ int sched_setparam(pid_t pid, FAR const struct sched_param *param)
 {
   FAR struct tcb_s *rtcb;
   FAR struct tcb_s *tcb;
+  int errcode;
   int ret;
 
   /* Verify that the requested priority is in the valid range */
 
   if (!param)
     {
-      set_errno(EINVAL);
-      return ERROR;
+      errcode = EINVAL;
+      goto errout_with_errcode;
     }
 
   /* Prohibit modifications to the head of the ready-to-run task
@@ -110,18 +111,17 @@ int sched_setparam(pid_t pid, FAR const struct sched_param *param)
       tcb = rtcb;
     }
 
-  /* The pid is not the calling task, we will have to search for it */
+  /* The PID is not the calling task, we will have to search for it */
 
   else
     {
       tcb = sched_gettcb(pid);
       if (!tcb)
         {
-          /* No task with this pid was found */
+          /* No task with this PID was found */
 
-          set_errno(ESRCH);
-          sched_unlock();
-          return ERROR;
+          errcode = ESRCH;
+          goto errout_with_lock;
         }
     }
 
@@ -130,20 +130,34 @@ int sched_setparam(pid_t pid, FAR const struct sched_param *param)
 
   if ((rtcb->flags & TCB_FLAG_POLICY_MASK) == TCB_FLAG_SCHED_SPORADIC)
     {
-      int ticks;
+      int repl_ticks;
+      int budget_ticks;
 
       DEBUGASSERT(param->sched_ss_max_repl <= UINT8_MAX);
 
+      /* Convert timespec values to system clock ticks */
+
+      (void)clock_time2ticks(&param->sched_ss_repl_period, &repl_ticks);
+      (void)clock_time2ticks(&param->sched_ss_init_budget, &budget_ticks);
+
+      /* The replenishment period must be greater than or equal to the
+       * budget period.
+       */
+
+      if (repl_ticks < budget_ticks)
+        {
+          errcode = EINVAL;
+          goto errout_with_lock;
+        }
+
+      /* Save the sporadic scheduling parameters */
+
       tcb->flags       |= TCB_FLAG_SCHED_SPORADIC;
       tcb->timeslice    = MSEC2TICK(CONFIG_RR_INTERVAL);
       tcb->low_priority = param->sched_ss_low_priority;
       tcb->max_repl     = param->sched_ss_max_repl;
-
-      (void)clock_time2ticks(&param->sched_ss_repl_period, &ticks);
-      tcb->repl_period  = ticks;
-
-      (void)clock_time2ticks(&param->sched_ss_init_budget, &ticks);
-      tcb->budget       = ticks;
+      tcb->repl_period  = repl_ticks;
+      tcb->budget       = budget_ticks;
     }
   else
     {
@@ -154,9 +168,18 @@ int sched_setparam(pid_t pid, FAR const struct sched_param *param)
     }
 #endif
 
- /* Then perform the reprioritization */
+  /* Then perform the reprioritization */
+
+  ret = sched_reprioritize(tcb, param->sched_priority);
+  sched_unlock();
+  return ret;
+
+errout_with_lock:
+  set_errno(errcode);
+  sched_unlock();
+  return ERROR;
 
- ret = sched_reprioritize(tcb, param->sched_priority);
- sched_unlock();
- return ret;
+errout_with_errcode:
+  set_errno(errcode);
+  return ERROR;
 }
diff --git a/sched/sched/sched_setscheduler.c b/sched/sched/sched_setscheduler.c
index f05fb39bc7..0c3c6a6f94 100644
--- a/sched/sched/sched_setscheduler.c
+++ b/sched/sched/sched_setscheduler.c
@@ -166,20 +166,35 @@ int sched_setscheduler(pid_t pid, int policy,
 #ifdef CONFIG_SCHED_SPORADIC
       case SCHED_SPORADIC:
         {
-          int ticks;
+          int repl_ticks;
+          int budget_ticks;
 
           DEBUGASSERT(param->sched_ss_max_repl <= UINT8_MAX);
 
+          /* Convert timespec values to system clock ticks */
+
+          (void)clock_time2ticks(&param->sched_ss_repl_period, &repl_ticks);
+          (void)clock_time2ticks(&param->sched_ss_init_budget, &budget_ticks);
+
+          /* The replenishment period must be greater than or equal to the
+           * budget period.
+           */
+
+          if (repl_ticks < budget_ticks)
+            {
+              set_errno(EINVAL);
+              sched_unlock();
+              return ERROR;
+            }
+
+          /* Save the sporadic scheduling parameters */
+
           tcb->flags       |= TCB_FLAG_SCHED_SPORADIC;
           tcb->timeslice    = MSEC2TICK(CONFIG_RR_INTERVAL);
           tcb->low_priority = param->sched_ss_low_priority;
           tcb->max_repl     = param->sched_ss_max_repl;
-
-          (void)clock_time2ticks(&param->sched_ss_repl_period, &ticks);
-          tcb->repl_period  = ticks;
-
-          (void)clock_time2ticks(&param->sched_ss_init_budget, &ticks);
-          tcb->budget       = ticks;
+          tcb->repl_period  = repl_ticks;
+          tcb->budget       = budget_ticks;
         }
         break;
 #endif
@@ -197,13 +212,5 @@ int sched_setscheduler(pid_t pid, int policy,
 
   ret = sched_reprioritize(tcb, param->sched_priority);
   sched_unlock();
-
-  if (ret != OK)
-    {
-      return ERROR;
-    }
-  else
-    {
-      return OK;
-    }
+  return (ret >= 0) ? OK : ERROR;
 }
-- 
GitLab