[linux-audio-dev] new realtime scheduling policy

rm async at cc.gatech.edu
Tue Mar 18 02:55:01 UTC 2003


hi all, 

     so i've tried to make a new scheduling policy for linux.  i've
called it SCHED_USERFIFO.  the intent is basically to allow a process
ask for x amount of processor time out of every y jiffies.  (the user
part is in the hope that the administrator can set rlimits on the
amount of percentage of time requested and allow non-priviledged users
to use this policy without being able to complete hang the box).

    it works just like SCHED_FIFO as long as the process doesn't take
more than the amount of time it asked for.  if it does try to take
more time, it is allowed to be preempted until the period is over.

    i hacked this up quickly, and tested it with the program below.  i
was able to get a process in a while (1) loop to take up >99.4% of
processor while still being able to kill it from the console (although
trying to do anything interactive was excruciatingly slow during this
time).  when i allowed the process to take up 100% of the period, the
system hung (with respect to other processes) as expected.  (tested in
vmware, btw).

    this patch is against 2.4.20+lowlatency.  it's intended mostly
for people to look at and give feedback.  it probably won't work on
systems that use APIC's, it doesn't do any sanity checking, and it
doesn't handle jiffy rollover.

    (mostly i'm just sending a mail because i'm pleased with myself
and want to share and get feedback; hopefully this sort of does what i
say it does too).

	 thanks, 
	  rob


    here is the test program, note the two new fields in sched_param:

  param.period_reserved
  param.period_length

these are specified in system ticks.  below i give the program
49 out of every 50 ticks.



------------- testprogram.c ----------------
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
//#include <sched.h>
// import these directly 
#include <sys/time.h>
#include <sys/poll.h>


#define SCHED_OTHER		0
#define SCHED_FIFO		1
#define SCHED_RR		2
#define SCHED_USERFIFO          3

struct sched_param {
  int sched_priority;
  /* user fifo stuff */
  unsigned long period_length; 
  unsigned long period_reserved;
};


/* return -1 on failure */
int
set_realtime(void)
{
  int r;
  struct sched_param param;
  pid_t pid;
  
  pid = getpid();

  param.sched_priority = 50;
  param.period_length = 50;
  param.period_reserved = 49;
  return sched_setscheduler(pid, SCHED_USERFIFO, &param);

}

void
waste_time(void)
{
  struct timeval tv, tv_old, tv_tmp, tv_timeout;
  struct pollfd ufds;
  int res; 
  int i = 0; 
  ufds.fd = 2;
  ufds.events = POLLPRI;
  
  tv_timeout.tv_sec = 0; 
  tv_timeout.tv_usec = 600; 
  i = 0;
  while (i<40000000L) { 
    printf("unf\n");
    i++;
  }
}

int
main(int argc, char ** argv)
{
  int i = 0; 
  if (set_realtime() < 0) { 
    fprintf(stderr, "couldn't set scheduler to SCHED_USERFIFO\n");
    return -1; 
  }
  waste_time();
  return 0;
}

---------------------------------------------

here is the kernel patch.

--- pristine/linux-2.4.20/kernel/sched.c	2003-03-17 23:24:02.000000000 -0500
+++ linux/kernel/sched.c	2003-03-17 22:11:13.000000000 -0500
@@ -188,7 +188,42 @@
 	 * runqueue (taking priorities within processes
 	 * into account).
 	 */
+
+	if (p->policy == SCHED_USERFIFO) { 
+	  
+	  /*
+	   *   check if we are in the right time period
+	   *
+	   *   XXX if it burns though it's entire period and
+	   *       into the next ? 
+	   *     
+	   */
+	  if (jiffies >= p->t_period_end) { 
+	    /* no, start over from now */
+	    p->t_period_start = jiffies;
+	    p->t_period_end = p->t_period_length + p->t_period_start;
+	    p->t_period_remain = p->t_period_reserved; 
+	  }
+
+	  /*
+	   *  is there any remaining time ? 
+	   *  
+	   */
+
+	  if (p->t_period_remain > 0) { 
+	    weight = 1000 + p->rt_priority;	    
+	  }  else { 
+	    /* redundent, for clarity */
+	    weight = -1; 
+	  }
+	  goto out;
+	}
+
+	/* normal RT case */
+
 	weight = 1000 + p->rt_priority;
+
+
 out:
 	return weight;
 }
@@ -939,8 +974,8 @@
 	else {
 		retval = -EINVAL;
 		if (policy != SCHED_FIFO && policy != SCHED_RR &&
-				policy != SCHED_OTHER)
-			goto out_unlock;
+		    policy != SCHED_OTHER && policy != SCHED_USERFIFO)
+		  goto out_unlock;
 	}
 	
 	/*
@@ -964,6 +999,15 @@
 	retval = 0;
 	p->policy = policy;
 	p->rt_priority = lp.sched_priority;
+	
+	if (policy == SCHED_USERFIFO) { 
+	  /* FIXME: no checks, doesn't handle jiffy rollover */
+	  p->t_period_length = lp.period_length; 
+	  p->t_period_reserved = lp.period_reserved;
+	  p->t_period_start = jiffies;
+	  p->t_period_end = p->t_period_length + p->t_period_start;
+	  p->t_period_remain = p->t_period_reserved; 
+	}
 
 	current->need_resched = 1;
 
--- pristine/linux-2.4.20/include/linux/sched.h	2003-03-17 23:24:02.000000000 -0500
+++ linux/include/linux/sched.h	2003-03-17 21:55:04.000000000 -0500
@@ -119,7 +119,7 @@
 #define SCHED_OTHER		0
 #define SCHED_FIFO		1
 #define SCHED_RR		2
-
+#define SCHED_USERFIFO          3
 /*
  * This is an additional bit set when we want to
  * yield the CPU for one re-schedule..
@@ -127,7 +127,10 @@
 #define SCHED_YIELD		0x10
 
 struct sched_param {
-	int sched_priority;
+  int sched_priority;
+  /* user fifo stuff */
+  unsigned long period_length; 
+  unsigned long period_reserved;
 };
 
 struct completion;
@@ -419,6 +422,15 @@
 
 /* journalling filesystem info */
 	void *journal_info;
+
+
+  /* our extra stuff */ 
+
+  unsigned long t_period_end; 
+  unsigned long t_period_start; 
+  unsigned long t_period_remain;
+  unsigned long t_period_length;
+  unsigned long t_period_reserved;
 };
 
 /*
--- pristine/linux-2.4.20/kernel/timer.c	2002-11-28 18:53:15.000000000 -0500
+++ linux/kernel/timer.c	2003-03-17 22:42:52.000000000 -0500
@@ -610,6 +610,15 @@
 				p->need_resched = 1;
 			}
 		}
+		if (p->policy == SCHED_USERFIFO) { 
+
+		  if (p->t_period_remain == 0) { 
+		    p->need_resched = 1;
+		  } else { 
+		    p->t_period_remain--;
+		  }
+		}
+
 		if (p->nice > 0)
 			kstat.per_cpu_nice[cpu] += user_tick;
 		else

-------------------- end -------------------------------

----
Robert Melby
Georgia Institute of Technology, Atlanta Georgia, 30332
uucp:     ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt4255a
Internet: async at cc.gatech.edu



More information about the Linux-audio-dev mailing list