<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "- //OASIS//DTD DocBook XML V4.1.2//EN"
	"/usr/share/sgml/docbook/dtd/xml/4.1.2/docbookx.dtd"
        [<!ENTITY biblio SYSTEM "biblio.xml">] >

<book>
  <bookinfo>
    <title>CBS implementation in RTLinux </title>
    <authorgroup>
      <author>
	<firstname>Pau</firstname>
	<surname>Mendoza</surname>
	<affiliation>
	  <orgname>DISCA, Universidad Politecnica de Valencia</orgname>
	  <address>e-mail: <email>pabmench@disca.upv.es</email></address>
	</affiliation>
      </author>
      <author>
	<firstname>Patricia</firstname>
	<surname>Balbastre</surname>
	<affiliation>
	  <orgname>DISCA, Universidad Politecnica de Valencia</orgname>
	  <address>e-mail: <email>patricia@disca.upv.es</email></address>
	</affiliation>
      </author>
    </authorgroup>
    
    <pubdate>January 2002</pubdate>
    <copyright>
      <year>2002</year>
      <holder>OCERA Consortium</holder>
    </copyright>
  </bookinfo>

  <chapter>
  <title>Constant Bandwith Server in RTLinux</title>
  
  <!-- ================================ Summary ============== -->
  <section>
    <title>Summary</title>
    
      <variablelist>
	<varlistentry>
	  <term>Name</term>
	  <listitem>
	    <para>
	      Native CBS implementation based in RTLinux.
	    </para>
	  </listitem>
	</varlistentry>
	
	<varlistentry>
	  <term>Description</term>
	  <listitem>
	    <para>
	      This component implements the CBS scheduling policy for RTLinux 
	      threads. The Constant Bandwidth Server (CBS) was developed to 
	      efficiently handle soft real-time requests with a variable or unknown execution 
	      behaviour under EDF scheduling policy. 
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>Authors</term>
	  <listitem>
	    <para>
	      Pau Mendoza and Patricia Balbastre.
	    </para>
	  </listitem>
	</varlistentry>
	
	<varlistentry>
	  <term>Reviewer</term>
	  <listitem>
	    <para>
	      Alfons Crespo.
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>Layer</term>
	  <listitem>
	    <para>
	      Low level RTLinux.
	    </para>
	  </listitem>
	</varlistentry>
	
	<varlistentry>
	  <term>Version</term>
	  <listitem>
	    <para>
	      0.1
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>Status</term>
	  <listitem>
	    <para>
	      Stable
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>Dependencies</term>
	  <listitem>
	    <para>
	      EDF scheduler for RTLinux.
	    </para>
	  </listitem>
	</varlistentry>
	<varlistentry>
	  <term>Release Date</term>
	  <listitem>
	    <para>
	      M2
	    </para>
	  </listitem>
	</varlistentry>
      </variablelist>
      
    </section>
    
    
    <section>
      <title>Descritpion</title>
      <para>
	The problem of integrating flexible Quality of Service (QoS) 
	guarantees in real-time systems has been widely studied in the 
	last years, resulting in some interesting proposals. Probably, 
	the most important theoretical result that emerged in this work 
	is the idea that in order to provide a predictable QoS to different 
	applications running on the same system, the OS kernel must provide 
	temporal isolation between different applications or tasks. Temporal 
	isolation (also known as temporal protection), requires that the 
	temporal behaviour of a task is not influenced by the temporal behaviour 
	of other tasks in the system. Based on classical real-time scheduling 
	(EDF or RM priority assignment), it is possible to implement a reservation 
	guarantee by simply enabling a task to execute as a real-time task (scheduled, 
	for example, by EDF or RM) for the reserved time Q, and then blocking it 
	(or scheduling it in background as a non real-time task) until the next 
	reservation period. One of the most interesting resource reservation protocols 
	is the Constant Bandwidth Server (CBS).
      </para>
      
      <para>
	The Constant Bandwidth Server (CBS) 
	<citation><xref linkend="bib.abeni98"></xref></citation> was developed to 
	efficiently handle soft real-time requests with a variable or unknown execution 
	behaviour under EDF scheduling policy. To avoid unpredictable delays on hard 
	real-time tasks, soft tasks are isolated through a bandwidth reservation mechanism, 
	according to wich each soft task is assigned a fraction of the CPU and it is 
	scheduled in such a way that it will never demand more than its reserved bandwidth, 
	independently of its actual requests. This is achieved by assigning each soft task a 
	deadline, computed as a function of the reserved bandwidth and its actual requests. If 
	a task requires to execute more than its expected computation time, its deadline is 
	postponed so that its reserved bandwidth is not exceeded. As a consequence, overruns 
	ocurring on a served task will only delay that task, without compromising the bandwidth 
	assigned to other tasks. By isolating the effects of task overloads, hard tasks can be 
	guaranteed using classical schedulability analysis.
      </para>
      
      <para>
	In more detail, as stated in <citation><xref linkend="bib.abeni98"></xref></citation> 
	CBS can be defined as follows:
      </para>
      
      <itemizedlist>
	<listitem>
	  <para>
	    A CBS server is characterized by a budget c<subscript>s</subscript> and by the 
	    server bandwidth U<subscript>s</subscript>=Q<subscript>s</subscript>/T<subscript>
	      s</subscript>. Where Q<subscript>s</subscript> is the maximum budget and 
	    T<subscript>s</subscript> is the period of the server.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Initially, the server is assigned the deadline d<subscript>s</subscript>=0
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Each served job, is assigned the deadline of the server.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    Whenever the server task executes, the budget c<subscript>s</subscript> is 
	    decreased by the same amount.
	  </para> 
	</listitem>
	<listitem>
	  <para>
	    When c<subscript>s</subscript>=0 the server budget is recharged to the maximum 
	    value C<subscript>s</subscript> and a new server deadline is generated as 
	    d<subscript>s,k+1</subscript>=d<subscript>s,k</subscript>+T<subscript>s</subscript>.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    When a job J<subscript>i,j</subscript> arrives and the server is idle 
	    (there are no pending jobs), if c<subscript>s</subscript> &ge; (d<subscript>s,
	      k</subscript>-r<subscript>i,j</subscript>)U<subscript>s</subscript> the server 
	    generates a new deadline d<subscript>s,k+1</subscript>=r<subscript>i,j</subscript>+
	    T<subscript>s</subscript> and c<subscript>s</subscript> is recharged to the 
	    maximum value Q<subscript>s</subscript>
	  </para>
	</listitem>
	<listitem>
	  
	  <para>
	    When a job finishes, the next pending job is served using the current budget and deadline.
	  </para>
	</listitem>
      </itemizedlist>
      
      <para>
	In <citation><xref linkend="bib.caccamo01"></xref></citation> the CBS algorithm is 
	extended to deal with shared resources, specifically, it is integrated with the Stack 
	Resource Policy (SRP) <citation><xref linkend="bib.baker91"></xref></citation>.
      </para>   
      
      <para>
	This component implemetns the CBS scheduling policy for RTLinux threads, that is, when the CBS thread is the highest priority one, it can execute Linux task. How linux processes are scheduled is not related with this component. 
      </para>
      
    </section>
    
    <section>
      <title>Layer</title>
      <para>
	This is a low-level RTLinux and low-level Linux component, since it modifies 
	both RTLinux and Linux kernel. Thus, the distribution of this component comes 
	in the form of two patches, one for RTLinux 
	(<filename>rtlinux-3.2pre1-rtlcbs.patch</filename>) and the 
	other for Linux (<filename>linux-2.4.18-rtlcbs.patch</filename>).
      </para>
    </section>
    
    <section>
      <title>API / Compatibility</title>
      <para>
	To initialise CBS threads, new API functions have been 
	defined. Specifically: 
      </para>
      
      <funcsynopsis>
	<funcprototype>
	  <funcdef>extern inline int <function>pthread_attr_set_initbudget_np</function></funcdef>
	  <paramdef>pthread_t <parameter>thread</parameter></paramdef>
	  <paramdef>hrtime_t <parameter>initbudget</parameter></paramdef>
	</funcprototype>
	<funcprototype>
	  <funcdef>extern inline int <function>pthread_attr_get_initbudget_np</function></funcdef>
	  <paramdef>const pthread_t <parameter>thread</parameter></paramdef>
	  <paramdef>hrtime_t *<parameter>initbudget</parameter></paramdef>
	</funcprototype>
	<funcprototype>
	  <funcdef>extern inline int <function>pthread_setinitbudget_np</function></funcdef>
	  <paramdef>pthread_t <parameter>thread</parameter></paramdef>
	  <paramdef>hrtime_t <parameter>initbudget</parameter></paramdef>
	</funcprototype>
	<funcprototype>
	  <funcdef>extern inline int <function>pthread_getinitbudget_np</function></funcdef>
	  <paramdef>pthread_t <parameter>thread</parameter></paramdef>
	  <paramdef>hrtime_t *<parameter>initbudget</parameter></paramdef>
	</funcprototype>
	<funcprototype>
	  <funcdef>extern inline int <function>pthread_initcbs_np</function></funcdef>
	  <paramdef>pthread_t <parameter>thread</parameter></paramdef>
	  <paramdef>hrtime_t <parameter>period</parameter></paramdef>  
	</funcprototype>
	<funcprototype>
	  <funcdef>void <function>make_linux_task_cbs_server</function></funcdef>
	  <paramdef>hrtime_t <parameter>start</parameter></paramdef>
	  <paramdef>hrtime_t <parameter>deadline</parameter></paramdef>
	  <paramdef>hrtime_t <parameter>period</parameter></paramdef>
	  <paramdef>int <parameter>priority</parameter></paramdef>
	</funcprototype>
      </funcsynopsis>

     
    </section>
    
    <section>
      <title>Dependencies</title>
      <para>
	CBS depends on EDF scheduler, since aperiodic events are scheduled with EDF 
	scheduling policy. V1 API support has not to be selected when configuring RTLinux installation.
      </para>
    </section>

    <section>
      <title>Status</title>
      <para>
	This is a stable version. Some bugs have been already fixed from the beta version.
      </para>
      
    </section>


    <section>
      <title>Implementation issues</title>
      <para>The implementation work consists of modifications to two 
	files: <filename>rtl_sched.h</filename> and <filename>rtl_sched.c</filename>. The 
	modifications are mainly in the scheduler function <function>rtl_schedule()</function>, 
	apart from the new functions and parameters added. A new scheduling policy is defined 
	(<constant>SCHED_CBS_NP</constant>), for those threads working as CBS servers.
      </para>
     
      <para>
	All the modifications done to the RTLinux code have been enclosed 
	by macros (CONFIG_OC_RTLCBS) that can be toggled from the RTLinux configuration tool.
      </para>

      <para>
	Each CBS server thread must have two parameters:
      </para>
      <itemizedlist>
	<listitem>
	  <para>
	    The maximum budget Q<subscript>s</subscript>. It has been added to 
	    the <structname>rtl_sched_param</structname> struct, because usually 
	    params belonging to this struct are initialized once, and after this, 
	    they do not change its value. The parameter has been called 
	    <structfield>sched_cbs_init_budget</structfield>:
	  </para>
	  <programlisting>
struct rtl_sched_param {
  int sched_priority;
  hrtime_t sched_deadline;
#ifdef CONFIG_RTL_CBS
  hrtime_t sched_cbs_init_budget;
#define RTL_INIT_BUDGET(th) ((th)->sched_param.sched_cbs_init_budget)
#endif
};
</programlisting>
	</listitem>
	<listitem>
	  <para>
	    The current budget c<subscript>s</subscript>. This param decreases 
	    and it is recharged as time goes by. So, it is more suitable to 
	    include it in the <structname>rtl_thread_struct</structname> struct:
	  </para>
	  <programlisting>
struct rtl_thread_struct {
        ... fields of original RTLinux ...
#ifdef CONFIG_RTL_EDF 
        hrtime_t current_deadline;
        int policy;
#ifdef CONFIG_RTL_CBS
        hrtime_t sched_cbs_current_budget;
#endif
#endif
};
	  </programlisting>
	</listitem>
      </itemizedlist>
      
     
      
      <para>
	When an aperiodic event arrives, depending on wether the CBS thread is idle 
	or not, a new deadline for the CBS thread is calculated. This deadline is assigned 
	to the thread associated with the aperiodic event. The implementation has been 
	done in such a way that the user can choose between two options: 
      </para>

     
	<itemizedlist>
	  <listitem>
	    <para>
	      The aperiodic events are interrupts, and the thread associated with these events 
	      is the linux task. When an interrupts arrives (for example, a network interrupt), 
	      linux executes until it schedules the idle task. In this implementation, there is 
	      no need to implement queues of pending jobs. As an example, let's suppose that two 
	      interrupts arrive at the same time. In the first interrupt arrival, if the CBS server 
	      is idle, a new deadline is calculated for the linux task. Linux task will recover 
	      its original state (as the background thread) when it schedules the idle task. So, 
	      the second interrupt will be already treated. If not, linux do not schedule the idle 
	      task until all tasks are finished.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
	      The user can customize CBS. Therefore, events have to be defined by the user, and 
	      the same CBS thread attends the execution of events. When the event processing finishes, 
	      the CBS thread suspends itself. In this option, the user must implement the queues of 
	      pending jobs.
	    </para>
	  </listitem>
	</itemizedlist>
    

      <para>
	From now on, the CBS thread will refer to the linux task or the CBS thread itself, 
	depending on the option chosen.
      </para>
      <para>
	In the first option, when a network interrupt arrives, the linux task must execute with 
	the priority (static and dynamic) of the CBS server thread associated with the 
	interrupt. This way of inheritance between the linux task and the CBS thread is made in 
	the interrupt handler, through the <function>make_linux_task_cbs_server</function> 
	function. In this function, the CBS thread parameters (initbudget, deadline, period and priority)
	are attached to the linux task. Then, a new deadline is calculated in the 
	<function>rtl_cbs_reset_deadline</function> function. The code of both functions is 
	listed below:
      </para>
      <programlisting>
<![CDATA[extern void make_linux_task_cbs_server(hrtime_t start, hrtime_t initbudget, 
                    hrtime_t deadline, hrtime_t period, int priority){
	hrtime_t now;
	int cpu_id = rtl_getcpuid();
	pthread_t linux_task = rtl_get_linux_thread(cpu_id);
	schedule_t *sched;

	if (linux_task->policy != SCHED_CBS_NP) {
	    sched = &rtl_sched[cpu_id];
	    now = sched->clock->gethrtime(sched->clock);

	    RTL_INIT_BUDGET(linux_task) = initbudget;
	    linux_task->sched_param.sched_deadline = deadline;
	    linux_task->period = period;
	    linux_task->sched_param.sched_priority = priority;
	    linux_task->policy = SCHED_CBS_NP;

	    linux_task->sched_cbs_current_budget = 0;
	    if (linux_task->current_deadline < now)
	        linux_task->current_deadline = now;
	    cbs_linux_idle = 1;

	    rtl_cbs_reset_deadline(linux_task);

	    rtl_reschedule_thread(linux_task);

	};
	return;
}]]>
      </programlisting>

      <programlisting>
<![CDATA[static inline void rtl_cbs_reset_deadline(pthread_t t){
        hrtime_t now;
	rtl_irqstate_t flags;
	int cpu_id = rtl_getcpuid();
	schedule_t *sched;
	rtl_no_interrupts(flags);
	sched = &rtl_sched[cpu_id];
        if ((t->policy == SCHED_CBS_NP)) {
	         now = sched->clock->gethrtime(sched->clock);
		 if (now + (t->sched_cbs_current_budget/ RTL_INIT_BUDGET(t)) * t->period
                       >= t->current_deadline) {
		          t->current_deadline = now + t->period;
			  t->sched_cbs_current_budget = RTL_INIT_BUDGET(t);
		 }
		 t->resume_time = now;		 
	}
	rtl_restore_interrupts(flags);
}]]>
      </programlisting>

      <para>
	If the second option is chosen, there is no need to use the 
	<function>make_linux_task_cbs_server</function> function, since 
	the CBS thread already has the correct parameters. Simply, the 
	<function>rtl_cbs_reset_deadline</function> function is executed 
	when the CBS thread is woke up. This is made in the 
	<function>pthread_kill</function> function:
      </para>

	<programlisting>
<![CDATA[int pthread_kill(pthread_t thread, int signal){
	... Original RTLinux code ...
#ifdef CONFIG_RTL_CBS
			if ((unsigned) signal == RTL_SIGNAL_WAKEUP)
			        rtl_cbs_reset_deadline(thread);
#endif
	... Original RTLinux code ...
}]]></programlisting>


      <para>
	Then, the CBS thread will execute when its new deadline is the 
	nearest of all active threads. It is important to note that if 
	another interrupt arrives, the<function> rtl_cbs_reset_deadline</function> 
	function will not execute, since the thread is already active. By definition 
	of CBS, if a job arrives and the server is active the request is enqueued, 
	so it will execute with the current deadline. 
      </para>
      <para>
	When the CBS thread is chosen by the scheduler as the highest priority thread, 
	two situations can stop the thread execution:
      </para>
      <itemizedlist>
	<listitem>
	  <para>
	    A higher priority thread becomes active in the future, but before the 
	    CBS thread finishes its execution. This is solved in the 
	    <function>find_preemptor</function> function in the original RTLinux code.
	  </para>
	</listitem>
	<listitem>
	  <para>
	    The budget is exhausted, so it must be recharged and a new deadline is assigned. 
	  </para>
	</listitem>
      </itemizedlist>
      <para>
	In the original RTLinux code, the last situation is not taken into account, 
	so if the thread is not preempted, the timer is programmed to ten miliseconds 
	after. Now, the timer must be programmed to the nearest time of the previous 
	cases commented: a higher thread activation, or the actual time plus the current 
	budget. The code is:
      </para>
      <programlisting>
<![CDATA[if ((sched->clock->mode == RTL_CLOCK_MODE_ONESHOT && !test_bit (RTL_SCHED_TIMER_OK, 
    &sched->sched_flags)) || (new_task->policy == SCHED_CBS_NP)) {
	if ( (preemptor = find_preemptor(sched,new_task))) {
#ifdef CONFIG_OC_RTLCBS
           if (new_task->policy == SCHED_CBS_NP) {
	      if (( preemptor->resume_time - now) > (new_task->sched_cbs_current_budget)){
	          (sched->clock)->settimer(sched->clock, new_task->sched_cbs_current_budget);         			
#endif
		                (sched->clock)->settimer(sched->clock, preemptor->resume_time - now);
#ifdef CONFIG_OC_RTLCBS
			}
		} else {
		        (sched->clock)->settimer(sched->clock, preemptor->resume_time - now);
		}
#endif
	} else {
#ifdef CONFIG_OC_RTLCBS
	        if (new_task->policy == SCHED_CBS_NP) {
		                (sched->clock)->settimer(sched->clock, new_task->sched_cbs_current_budget);
		} else
#endif 
		        (sched->clock)->settimer(sched->clock, (HRTICKS_PER_SEC / HZ) / 2);
	}
	set_bit (RTL_SCHED_TIMER_OK, &sched->sched_flags);
}]]></programlisting>

      <para>
	Once the CBS thread is preempted, the scheduler must measure the execution time, 
	in order to decrease the current budget. When the budget is exhausted, it must 
	be recharged and a new deadline is generated, according to CBS rules. This must 
	be checked in the <function>rtl_schedule()</function> function before choosing 
	the new task to execute. However, if the linux threads executes as the CBS server 
	(first option) and it schedules the idle task (which is indicated by the 
	flag <varname>cbs_linux_idle</varname>) then it must recover its original state, 
	that is, as the background thread.
      </para>
      <programlisting>	
<![CDATA[elapsed_time = now - rtl_prev_sched_time;
rtl_prev_sched_time = now;

if (sched->rtl_current->policy == SCHED_CBS_NP) {
  if (sched->rtl_current->sched_cbs_current_budget >= elapsed_time){
	sched->rtl_current->sched_cbs_current_budget -= elapsed_time;
	} else {
	        sched->rtl_current->sched_cbs_current_budget = RTL_INIT_BUDGET(sched->rtl_current);
	        sched->rtl_current->current_deadline += sched->rtl_current->period;
	        sched->rtl_current->resume_time = now;
	  }
  if (sched->rtl_current == &sched->rtl_linux_task) {
          if (cbs_linux_idle == 0) {
	          sched->rtl_linux_task.sched_param.sched_priority = -1;
#ifdef CONFIG_RTL_EDF
		  sched->rtl_linux_task.sched_param.sched_deadline = 0;
		  sched->rtl_linux_task.current_deadline =           0;
#endif
		  sched->rtl_linux_task.sched_cbs_current_budget = 0;
		  RTL_INIT_BUDGET(&sched->rtl_linux_task) = 0;
		  sched->rtl_linux_task.period = HRTIME_INFINITY;
		  sched->rtl_linux_task.policy = SCHED_OTHER;
	  }
  }
}]]>
</programlisting>
   
  
      <para>
	The only point to solve now is to detect wether the linux task schedules 
	the idle task. To do this, the linux code must be modified, specifically 
	the <filename>kernel/sched.c</filename>, which is where the linux scheduler 
	is implemented. The flag <varname>cbs_linux_idle</varname> is defined as 
	<emphasis>extern</emphasis> in the <filename>include/sched.h</filename> 
	file. It has the value 0 whenever the idle task is scheduled, and 1 
	otherwise. Then, simply, before the context switch in the <function>schedule()</function> 
	function, it is added the following code:
      </para>
      
      <programlisting>
	<![CDATA[if(next == idle_task(this_cpu)){
	cbs_linux_idle = 0;
	}]]></programlisting>
          
    </section>
    
    
    <section>
      <title>Tests and Validation Criteria</title>
      
      <section>
	<title>Validation criteria</title>
	
	<para>
	  The CBS implementation in RTLinux must have the following behavior:
	</para>
	<itemizedlist>
	  <listitem>
	    <para>
	      If the served tasks have the same period as the CBS server, 
	      then the CBS algorithm behaves as plain EDF.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
	      The CBS server must reclaim any spare time caused by early completions.
	    </para>
	  </listitem>
	</itemizedlist>
	<para>
	  Regarding context switches,
	  the CBS server must call the scheduler at most every
	  <emphasis>budget</emphasis> units of time. Therefore, no more
	  of (<emphasis>task computation/server budget</emphasis>)
	  context switches must be introduced by the new implementation
	  of CBS. 
	</para>  
      <para> 
	  Also, a low overhead have been assured, since there is no need
	  to implement queues of pending aperiodic arrivals. 
	</para>    
      </section>
      
      <section>
	
	<title>Tests</title>
	<para>
	  Four tests have been implemented to validate the correct behaviour 
	  of the system. These tests can also be used as examples for the user, since it creates 
	  CBS threads to validate the correct behavior. The target system was a Pentium 133 MHz.
	</para>
	<para>
	  For every test developed, it has been used the same workload, that is, 
	  threads scheduled under EDF are the same in all tests. The parameters of 
	  the EDF periodic threads are listed in <xref linkend="Table1"></xref>. CBS 
	  parameters will be presented when explaining the specific tests.
	</para>
	
	<table id="Table1">
	  <title>Thread parameters (in miliseconds)</title>
	  <tgroup cols="5" align="center">
	    <thead>
	      <row>
		<entry>Task id</entry>
		<entry>Compute</entry>
		<entry>Deadline</entry>
		<entry>Period</entry>
		<entry>Prio level</entry>
	      </row>
	    </thead>
          
	  <tbody valign="middle">
          
	    <row>
	      <entry>T1</entry>
	      <entry>0.8</entry>
	      <entry>6</entry>
	      <entry>6</entry>
	      <entry>10</entry>
            </row>

	    <row>
	      <entry>T2</entry>
	      <entry>2.4</entry>
	      <entry>10</entry>
	      <entry>10</entry>
	      <entry>10</entry>
            </row>            

	    <row>
	      <entry>T3</entry>
	      <entry>3</entry>
	      <entry>11</entry>
	      <entry>11</entry>
	      <entry>10</entry>
            </row>

	    <row>
	      <entry>T4</entry>
	      <entry>3.5</entry>
	      <entry>19</entry>
	      <entry>19</entry>
	      <entry>10</entry>
            </row>

	  </tbody>
	</tgroup>
	    
      </table>
      
      <para>
	The structure of the tests is made up, basically, of two 
	files: <filename>rt_process.c</filename> and <filename>CBS_app.c</filename>. The 
	former contains the module that creates the four threads plus the CBS threads. The 
	latter contains the code that generates the aperiodic events. The code to implement 
	the four periodic threads is listed below:
      </para>

      <programlisting>
<![CDATA[pthread_attr_t attrib;
struct {
    int id;
    int compute;
    int period;
    hrtime_t deadline;
    hrtime_t budget;
    struct sched_param params;
} sched_attrib[6];
...
for (x=0; x<NTASKS; x++) {
      pthread_attr_init(&attrib);
      pthread_attr_setschedparam(&attrib, &sched_attrib[x].params);
      pthread_attr_setdeadline_np(&attrib, sched_attrib[x].deadline);
      pthread_attr_setschedpolicy(&attrib, SCHED_EDF_NP);
      pthread_create(&(tasks[x]), &attrib, fun, (void *)x);
      pthread_attr_destroy(&attrib);
}]]>
      </programlisting>


      <para>
	While implementing these tests, some debugging code was also included. That 
	feature was used to obtain the execution chronogram of the threads for each 
	test. The debugging can be made selecting the option CONFIG_RTL_EDF_DEBUG in 
	the config menu of RTLinux install. This way, it is obtained a trace via the rtf0 
	where the scheduler writes the thread identifier, initial and final execution times 
	and activations of the thread, in a text file. This file is the input 
	data to a X window application "crono" that represents the chronogram of the execution.
      </para>


<section>
	<title>Test 1. CBS thread serves aperiodic jobs </title>
	<para>This test has five threads: the four threads shown in <xref linkend="Table1"></xref>, plus the CBS thread. Parameters for the CBS thread are presented in  <xref linkend="Table2"></xref></para>

	<table id="Table2">
	  <title>CBS thread parameters for test 1 (in miliseconds)</title>
	  <tgroup cols="6" align="center">
	    <thead>
	      <row>
		<entry>Task id</entry>
		<entry>Compute</entry>
		<entry>Deadline</entry>
		<entry>Period</entry>
		<entry>Prio level</entry>
		<entry>Max. budget</entry>
	      </row>
	    </thead>
	    
	    <tbody valign="middle">
	      
	      <row>
		<entry>CBS1</entry>
		<entry>1.2</entry>
		<entry>3</entry>
		<entry>3.1</entry>
		<entry>10</entry>
		<entry>0.15</entry>
	      </row>
	    </tbody>
	  </tgroup>	 
	</table>


<para> The code implemented to create the CBS thread is the following:</para>

	<programlisting>
<![CDATA[for (x=0; x<N_CBSs; x++) {
	pthread_attr_init(&attrib);
	pthread_attr_setschedparam(&attrib, &sched_attrib[NTASKS+x].params);
	pthread_attr_setschedpolicy(&attrib, SCHED_CBS_NP);
	pthread_attr_setinitbudget_np(&attrib, sched_attrib[NTASKS+x].budget);
	pthread_create(&cbs_task,&attrib, cbs_code,(void *)x + NTASKS);
	pthread_attr_destroy(&attrib);
}]]></programlisting>

<para>This thread also executes the code of aperiodic events. These events are generated by a user application by writing on a rt_fifo. Following, is the code of the user application (CBS_app):</para>

	<programlisting>
<![CDATA[#define RTF_IN_1           "/dev/rtf1"

int main(){
  int event=1; 
  int ret_out=0;
  int fd;
  if ((fd = open(RTF_IN_1, O_WRONLY)) < 0) {
    fprintf(stderr, "Error opening /dev/rtf\n");
    exit(1);
  }
  
  fprintf(stderr, "%d\n",event);
  ret_out = write(fd,&event,sizeof(event));
  fprintf(stderr, "%d\n",event);
  close(fd);

  return 0;
}]]></programlisting>

	<para>As it shows the previous code, the user application generates two aperiodic events. The first event wakes up the CBS server (by means of the rt_fifo handler), that executes a dummy loop to consume its computation time. Afterwards, the thread suspends itself until the arrival of the second event. The code that executes the CBS server is:</para>

	<programlisting>
<![CDATA[void * cbs_code(void *arg){
    int id = (int)arg;
    int compute = sched_attrib[id].compute;
    int my_loop;

    pthread_initcbs_np(pthread_self(), sched_attrib[id].period);
    while(1) {
        pthread_suspend_np(pthread_self());
	for (my_loop=0; my_loop < compute ; my_loop++) {
	    rtl_delay(DELAY);
	}
    }
    ...
}]]></programlisting>
	
	<para>Note that the CBS thread is not make periodic, that is, the new function <function>pthread_initcbs_np</function> is used instead of <function>pthread_make_periodic_np</function>. If the latter function is used, the CBS thread would be woke up in every period. This behaviour is not correct for a CBS server, since it must be woke up only when an aperiodic job arrives. Following is the chronogram (<xref linkend="fig1"></xref>) of the execution:</para>
	
	<figure id="fig1"><title>Chronogram execution for test 1</title>
	  <graphic fileref="img/rtlcbs_test1.png" format="PNG" srccredit="Chronogram execution for test 1" align="center" scale="40"/>
	</figure>

	<para>The chronogram generated by the execution shows the four periodic tasks plus the CBS server (task 5 in the chronogram) and the linux thread (task 0). In the first three replenishments CBS executes without interferences (since its deadline is shorter than others), but in the fourth it is preempted by task 1, and later by task 2. This is because in each replenishment the deadline is increased by the period.</para>

     </section>

      <section>
	<title>Test 2. CBS thread serves aperiodic jobs</title>
	<para>It is possible that when the CBS thread wakes up and executes, no other threads are active. In this situation, several replenishments can occur before other threads become active. Therefore, CBS deadline becomes greater, and at the end it behaves as the background thread. To increase the system utilization, this test is made up of the four periodic threads in <xref linkend="Table1"></xref> and two CBS threads. This way, CBS and periodic threads will alternate their executions whenever a replenishment occurs. Parameters for the CBS threads are presented in <xref linkend="Table3"></xref>.</para>

	<table id="Table3">
	  <title>CBS thread parameters for test 2 (in miliseconds)</title>
	  <tgroup cols="6" align="center">
	    <thead>
	      <row>
		<entry>Task id</entry>
		<entry>Compute</entry>
		<entry>Deadline</entry>
		<entry>Period</entry>
		<entry>Prio level</entry>
		<entry>Max. budget</entry>
	      </row>
	    </thead>
	    
	    <tbody valign="middle">
	      
	      <row>
		<entry>CBS1</entry>
		<entry>0.6</entry>
		<entry>3</entry>
		<entry>3</entry>
		<entry>10</entry>
		<entry>0.2</entry>
	      </row>

	      <row>
		<entry>CBS2</entry>
		<entry>0.84</entry>
		<entry>5</entry>
		<entry>6</entry>
		<entry>10</entry>
		<entry>0.3</entry>
	      </row>	   
	    </tbody>
	  </tgroup>	 
	</table>
	
<para>Regardin the implementation details, an periodic auxiliary thread is created to wake up CBS threads when the user application writes on a rt_fifo. This auxiliary thread wakes up all CBS threads, so they compete for the processor control. The code is following:</para>

	<programlisting>
<![CDATA[void *fun_aux(void *arg){
    int j;
    int end = 5;

    while (end != 0) {
	pthread_suspend_np(pthread_self());
	for (j = 0; j < N_CBSs; j++) {
	    pthread_wakeup_np(cbs_tasks[j]);
	}
	end--;
    }
    pthread_exit(0);
    return (void *) 0;
}]]></programlisting>


	<para>The chronogram is shown in <xref linkend="fig2"></xref>. Again, tasks 1 to 4 are the periodic threads, tasks 5 and 6 are the CBS ones and task 7 is the auxiliary thread. The figure shows how the CBS thread with the shorter deadline wakes up  and executes after the execution of the auxiliary thread. In its first replenishment, its deadline becomes greater than the other CBS thread, so CBS2 executes. CBS1 and CBS2 executions are alternating until periodic threads with shorter deadlines become active.</para>

	<figure id="fig2"><title>Chronogram execution for test 2</title>
	  <graphic fileref="img/rtlcbs_test2.png" format="PNG" align="center" scale="40"/>
	</figure>
      </section>

      <section>
	<title>Test 3. Linux thread serves aperiodic jobs</title>
	<para>Tests 3 and 4 shows how to associate linux task to serve aperiodic events. Is is considered that the aperiodic job has been served when linux schedules the idle task, and new events arrive when an interrupt is forwarded to linux. In test 3, aperiodic events are generated as in the previous test, that is, by means of the user aplication that writes on a fifo. The fifo handler now do not wake up the CBS server, since in this test is linux who serves events. Instead, linux executes as a CBS thread with its properties. This is made in the <function>make_linux_task_cbs_server</function> function:</para>

	<programlisting>
<![CDATA[int my_handler(unsigned int fifo){
    int err, event;

    while ((err = rtf_get(AUX_FIFO, &event, sizeof(event))) 
            == sizeof(event)) {

	make_linux_task_cbs_server(gethrtime(),
				   sched_attrib[4].budget,
				   sched_attrib[4].deadline,
				   sched_attrib[4].period,
				   sched_attrib[4].params.sched_priority);
    }
    if (err != 0) {
	return -EINVAL;
    }
    return 0;
}]]></programlisting>
	
	<para>The parameters of the linux task when executing as CBS server are shown in <xref linkend="Table4"></xref>.</para>

	<table id="Table4">
	  <title>CBS thread parameters for test 4 (in miliseconds)</title>
	  <tgroup cols="5" align="center">
	    <thead>
	      <row>
		<entry>Task id</entry>
		<entry>Deadline</entry>
		<entry>Period</entry>
		<entry>Prio level</entry>
		<entry>Max. budget</entry>
	      </row>
	    </thead>
	    
	    <tbody valign="middle">
	      
	      <row>
		<entry>Linux CBS</entry>
		<entry>3</entry>
		<entry>3</entry>
		<entry>10</entry>
		<entry>0.2</entry>
	      </row>

	    
	    </tbody>
	  </tgroup>	 
	</table>


	<para>The chronogram is presented in <xref linkend="fig3"></xref>. The chronogram generated by the execution draws the Linux task in a different position depending on wether it is scheduled as the task in background (task 0), or as a CBS thread (task 5).</para>

	<figure id="fig3"><title>Chronogram execution for test 3</title>
	  <graphic fileref="img/rtlcbs_test3.png" format="PNG" srccredit="Chronogram execution for test 4" scale="40"/>
	</figure>

      </section>

      <section>
	<title>Test 4. Linux thread serves aperiodic jobs</title>
	<para>This test is similar to the previous one, it only changes the way of detecting aperiodic events. Now, aperiodic events are parametrized interrupts. Therefore, there is no user application file (CBS_app). By default, the interrupt detected is the keyboard, but network interrupts or other kind of interrupts can be easily detected, with small modifications of the code. When an keyboard interrupt occurs, the interrupt handler attach CBS properties to the linux task by means of the <function>make_linux_task_cbs_server</function> function:</para>

	<programlisting>
<![CDATA[unsigned my_keyboard_interrupt_handler(unsigned int irq,
				       struct pt_regs *regs){
    make_linux_task_cbs_server(gethrtime(),
			       sched_attrib[4].budget,
			       sched_attrib[4].deadline,
			       sched_attrib[4].period,
			       sched_attrib[4].params.sched_priority);
    rtl_global_pend_irq(KEYBOARD_INTERRUPT);
    return 0;
}]]></programlisting>

	<para>The parameters of the linux task when executing as CBS server are shown in <xref linkend="Table5"></xref>.</para>


	<table id="Table5">
	  <title>CBS thread parameters for test 4 (in miliseconds)</title>
	  <tgroup cols="5" align="center">
	    <thead>
	      <row>
		<entry>Task id</entry>
		<entry>Deadline</entry>
		<entry>Period</entry>
		<entry>Prio level</entry>
		<entry>Max. budget</entry>
	      </row>
	    </thead>
	    
	    <tbody valign="middle">
	      
	      <row>
		<entry>Linux CBS</entry>
		<entry>3</entry>
		<entry>3</entry>
		<entry>10</entry>
		<entry>0.5</entry>
	      </row>

	    
	    </tbody>
	  </tgroup>	 
	</table>


	<para>
	  The chronogram is presented in <xref linkend="fig4"></xref>. The chronogram generated by the execution draws the Linux task in different position depending on wether it is scheduled as the task in background (task 0), or as a CBS thread (task 5).</para>

	<figure id="fig4"><title>Chronogram execution for test 4</title>
	  <graphic fileref="img/rtlcbs_test4.png" format="PNG" srccredit="Chronogram execution for test 3" scale="40"/>
	</figure>
	
      </section>


     </section>
 </section>
    

  <section>
    <title>Installation instructions </title>
      <para>
	To install the cbs scheduling support in rtlinux, you should:
      </para>

      <itemizedlist>
	<listitem>
	  <para>Install the rtlcbs ocera component in your source code:</para>
	  <itemizedlist>
	    <listitem>
	      <para>
		Change directory to the component main one: '<command>cd rtlcbs_directory</command>'
	      </para>
	    </listitem>
	    
	    <listitem>
	      <para>
		Edit the file 'Makefile' and set your rtlinux and linux source directory, 
		for example:
	      </para>
	      <para>"RTLINUX = /usr/src/rtlinux-3.2-pre1"</para>
	      <para>"LINUX  =  /usr/src/linux-2.4.18"</para>
	    </listitem>

	    <listitem>
	      <para> 
		Type<command> make install</command> in the main directory of the rtlcbs component.
	      </para>
	    </listitem>
	  </itemizedlist>

	  <para>	 
	    This will install the component: Copying the documentation, the examples. If necessary,
	    (if it is not installed yet) will install the rtledf features patching your rtlinux with
	    a retailed version. And will patch your source code to support the cbs scheduling.
	  </para>
	</listitem>

	<listitem>
	  <para>
	    After this, you must rebuild your kernel image and your RTLinux modules as usual:
	  </para>

	  <itemizedlist>
	    
	    <listitem>
	      <para>	      Rebuilding the kernel image:</para>
	      <para>		<command>cd /usr/src/linux-2.4.18</command> </para>
	      <para>		<command>make clean dep</command></para>
	      <para>		<command>make {your_image_type}</command></para> 
	      <para>		Install it (i.e. with lilo)</para></listitem>

	    <listitem>
	      <para>	      Rebulding your RTLinux:</para>
	      <para>	<command>cd /usr/src/rtlinux-3.2-pre1</command> </para>
	      <para>	<command>make clean</command></para>
	      <para>	<command>make</command></para>
	      <para>	<command>make modules_install</command></para>
	    </listitem>
	    <listitem>
	      <para>And finally, reboot your system using the new kernel.</para>
	    </listitem>
	  </itemizedlist>
	</listitem>

</itemizedlist>

  </section>  
    &biblio;
    
  </chapter>
</book>