Home

www.cis.ksu.edu - People - Kansas State University

image

Contents

1. thread_end instance 18 Figure 2 3 Context switches due to the activation of thread B by a call of thread_make_ready by a lower priority thread A 1 thread_end_instance 19 Chapter 3 Kernels ERIKA currently provides two kernels FP Fixed Priority scheduling with Pre emption Thresholds and SRP protocols and SRPT Earliest deadline scheduling with Preemption Thresholds and SRP protocols 3 1 FP Kernel The scheduling algorithm used by the FP Kernel is the Fixed Priority with Pre emption Threshold Scheduling Algorithm Each thread in the system has a priority called ready priority that is used to enqueue threads in the ready queue When a task becomes the running task its priority is raised to another priority level called dispatch priority that usually is greater than the ready priority Lower priority threads do not execute until there are no higher priority threads ready for execution so at any instant of time the thread with the highest priority is the running thread Threads can share resources and mutexes are used to enforce mutual exclusion Stack Resource Policy 2Stack Resource Policy with Preemption Threshold Scheduling 20 between them Each mutex has assigned a ceiling that is the maximum ready priority of the threads that use that mutex When a mutex is locked the priority of the task is raised to the mutex ceiling The protocol just showed avoids deadlocks chained blocking an
2. c gt first th_next lc gt first 280 if m gt first NIL the monitor queue is not empty th_neat m gt last tempthread else the monitor queue is empty m gt first tempthread m gt last tempthread th_next tempthread NIL 290 The task state switch from BLOCKED TO STACKED th_status tempthread STACKED if defined _ FP__ check if there is to schedule a ready thread or pop a preempted thread A if rq queryfirstO NIL 300 sys_ceiling gt th_ready_prio rq_queryfirst else check if there is to schedule a ready thread or pop a preempted one th_absdline stk_queryfirst lt th_absdline rq_queryfirst O see also src srpt thendin c if rq queryfirstO NIL this test work also for the dummy task stk_queryfirst NIL S signed th_absdline stk_queryfirst 67 th_absdline rq_queryfirst lt 0 310 sys_ceiling gt th_ready_prio rq_queryfirst Aendif we have to schedule an interrupted thread that is on the top of its stack the state is already STACKED hal_stkchange stk_queryfirst 320 else we have to schedule a ready thread that is not yet on the stack th_status rq_queryfirst STACKED sys_ceiling th_dispatch_prio rq_queryfirst 0 hal_ready2stacked rq2stk_exchange O hal_end_primitive A 6 signalall c 330 Monitors for ERIKA Embedded
3. gt e Stacked Mutex 1 Queue System Ceiling Ready saved by the mutex Queue becomes the running task the system ceiling is raised to at least the threshold of the running task Threads can share resources and mutexes are used to enforce mutual exclusion between them Each mutex has assigned a ceiling which is the maximum preemp tion level of the threads that use that mutex When a mutex is locked the system ceiling is raised at least to the mutex ceiling At any instant of time a thread can become the running thread only if it has the earliest deadline and its preemption level is greater than the system ceiling The protocol just showed avoids deadlocks chained blocking and priority in version Moreover all the threads can share the same stack and dispatch priorities 23 can be used to reduce the preemption between threads in a controlled way further reducing the overall stack space needed 24 Chapter 4 HAL Internals One of the main design issues in the design of a Kernel Layer is the code portability in the sense of the ability of reusing all the Kernel Layer source code in more than one architecture For that reason all the code of the Kernel Layer is standard C code whereas all the architecture dependent issues are hidden under the HAL Layer interface Note that applications never call HAL functions directly They can only call the primitives provided by the Kernel Layer independent of their implementation
4. 3 Every thread can have its private stack or it can share it with other threads This allows the Kernel Layer to use scheduling algorithms that could block threads in synchronization primitives as for example a fixed priority scheduler with semaphores or for arbitrary reasons as for example a classical round robin scheduler Note that this model can also adapt to architectures that support memory protection since every thread stack must stay in different address spaces Please note that the mono stack HAL behavior can be viewed as a particular case of the multi stack HAL behavior where all tasks shares the same stack The main differences between the two versions are the execution time and memory required to perform the context switches the mono stack HAL should be in general preferred if possible Finally the HAL besides introducing the thread abstraction offer a general abstraction of the peripherals provided by a particular architecture This generally includes a set of functions that allow the application to interact with a particular interface together with the definition of a user handler to be associated with each interrupt 1 6 System Modules One of the objectives when designing an embedded application for systems that need a reduced memory footprint is to precisely tune which parts of the OS should be included in the final system and which not In this way both execution performance and memory footprint can be
5. It is the address of the first instruction of the internal st10_thread_endinstance function Automatic variables It is the space used by the compiler to allocate the automatic variables of a thread Prim call This is the return address that is pushed on stack only if the thread was preempted after a call to some primitive ex thread_activate it is not present if the thread was preempted by an interrupt PSW IP These values are pushed on the stack by a primitive or by the CPU interrupt response 39 MDC MDL MDH These are a copy of the ST10s multiply registers and they need to be saved every time a thread is preempted CP This is the St10 s context pointer used by the thread This is saved every time a thread is preempted and it is restored every time preemption level to which the preempted thread belongs to 5 2 3 Stack Implementation To be compatible with the C compiler the multi stack HAL has to switch the user stack at each thread change To allow maximum performance the system stack is used for parameter passing and the system stack of each thread is mapped in different location of the global system stack No overflow check is done on the system stack A typical stack configuration can be depicted as shown in the Figure 5 2 Figure 5 2 A typical stack configuration 1 Global System Stack st10 thread tos stack tos thread 1 System thread 2 Stack 1 thread 3 System Stack 2 st10_ active tos
6. a check that is used to guarantee that the highest priority always preempt lower priority threads The Figure 2 1 summarizes all the possible state changes and the kernel primitives that cause them In the following paragraphs the kernel primitives are detailed void thread_activate TID thread This primitive activates the thread whose index is passed as parameter As a result the activated thread is put into the ready state if the running thread has higher 12 priority If not the activated thread becomes the running thread preempting the thread that called the primitive If the activated thread is already active its state is not changed and a pending activation is accounted for it void thread_make_ready TID thread TYPENACT nact This primitive tells the kernel that the thread passed as first argument will when possible execute for nact instances This primitive never blocks the running thread it simply increments the pending activation counter An activated thread with priority higher than the running thread will execute after the next preemp tion check void sys_scheduler void This primitive simply execute a preemption check to see if the highest priority thread is in the ready queue has higher priority than the running thread In that case the higher priority thread in the ready queue preempts the running thread void thread_end_instance void This primitive is called to terminate the current instance of a thre
7. of the HAL primitives can be expanded inline Multi Stack HAL This is another HAL that is similar to the mono stack HAL except that it supports multiple stacks allowing the usage of blocking primitives We will look into details of this HAL since it is the simplest efficient and sufficient for most of the real time applications Segmented Multi Stack HAL This HAL is the slowest one because it uses the Large Memory model and the user stack for function calls It is useful only when the application source code is big and there is a need of using all the available 35 CPU memory Table 5 1 Characteristics of the ST10 HALs 1 Feature Segmented Multi Stack Speed Slow Single Stack No Blocking Primitives Allowed Yes Memory Model Tiny Tiny Large Functions store return values into user stack No No Yes Typical ROM Footprint XXX bytes YYY bytes ZZZ bytes 5 1 Peculiarities of the ST10 Implementation This section contains some notes about the implementation details that you can find in the source code Compiler and configuration files The tool chain used to compile the project is the TASKING tool chain for ST10 The make file is done in a way that 1t will build all the source files of the Kernel into the out directory under the current application directory System stack and user stack The ST10 architecture supports two stacks a system stack and a user stack The system stack is stored in the internal chip memory and it is for t
8. Even though its priority is greater than the priority of Thread 1 it is not greater than the current system ceiling hence it goes in the ready queue 5 Thread 4 arrives and become the running thread 6 Thread 5 arrives and since it belongs to the same nonpreemption group of Thread 4 and Thread 4 is still active then it goes into the ready queue Finally suppose that all the threads share the same system stack After these events the configuration of the kernel data structures is shown in the Figure 3 1 3 2 SRPT Kernel The scheduling algorithm used by the SRPT Kernel is the Stack Resource Policy with Preemption Threshold Scheduling Algorithm This algorithm is very similar to the one used in the FP Kernel except that it uses Earliest Deadline First EDF scheduling instead of a Fixed Priority assignment Each thread in the system has a deadline that is used to enqueue threads in the ready queue Moreover each thread has a preemption level that is chosen proportional to the inverse of its period and a threshold The system maintains a system ceiling which stores the thresholds of the stacked threads When a task 22 Figure 3 1 Kernel Data structures snapshot after the events listed 1 Empty Stack Th qasj EES Thread N Status Nact Next Thread 1 74t s Ki 1 0 k N Thread O nnrir ang 1 LJ Y ie The Stack i A 2 Y KA System j j 1 0 1 0 1 1 Ceiling 4 The p pepepepop
9. directly call the kernel primitives to get services provided by the kernel The following kernel primitives can be used in an application Table 2 1 Kernel primitives that can be used in an application 1 Thread Management thread_make_ready thread_activate sys_scheduler thread_end_instance Thread Management into Interrupt Drivers I RQ_make_ready IRQ_end_instance set_handler Shared Resource Management mutex_lock mutex_unlock Utility Functions sys_gettime sys_panic sys_reboot sys_idle 11 2 1 Thread management Each thread in the system owns a flag that contains information about its state Recall that a thread can be in one of the following four states stacked ready idle or blocked In general the transition of a thread from a state to another one is triggered by the execution of a kernel primitive e Thread Activation Some primitives can activate a thread In this case the activated thread jumps in the ready state waiting the availability of its execution If the activated thread is already in the ready or stacked state its current state is not changed and the activation is stored in a pending activation counter e Thread Wakeup Some primitives can wake up a thread that is already activated and that was not executing for some reason For example a thread could be waiting for a synchronization point e Preemption Check Most of the kernel primitives include in their behavior
10. from a frame to another frame that is already saved The function saves the context of the current thread and prepares the system to switch to the context of the new thread t passed as an argument TID rq2stk_exchange void This function extracts the first task from the ready queue and inserts the extracted task on the top of the stack The function returns TID of the extracted task void hal_ready2stacked TID t This function is called when a context of a thread have to be saved The context of the thread t is saved on its user stack and the thread t starts execution from the starting instruction once the function is returned void sys_scheduler void 53 This primitive simply executes a preemption check to see if the highest priority thread in the ready queue has higher priority than the running thread In that case the highest priority thread in the ready queue preempts the running thread Otherwise nothing happens 54 Chapter 8 Monitor Interface The primitives described in this section cover the monitor mechanism interface that can be used by ERIKA applications These primitives can be used both for process synchronization and mutual exclusion There is no limit on the number of monitors the application can create Note Monitor primitives can only be used with a multi stack HAL because these primitives are blocking To use a monitor the user must include the header file mon h in their appli cation which is in t
11. in the HAL layer There are two reasons why a user can not call directly the implementation provided by a kernel Every architecture has its own methods for calling a primitive and a Kernel implementation should only implement the behavior of a particular primitive without relying on nothing else than the standard C HAL interface Some CPU architectures allow an efficient implementation of some primi tives For example the mutex_lock primitive can be implemented using ATOMIC instruction under ST10 giving an inline implementation that is as 25 fast as a simple function call 4 1 HAL Interface HAL Layer is a software layer that is used to abstract a particular implementation from the underlying hardware HAL interface offers the following services e Thread Abstraction A thread is identified by the HAL by a C function and by the information that is stored in ROM and RAM such as the stack space it occupies when it is stacked the copy of CPU registers if needed and other implementation dependent information e Context Handling The HAL implements a limited set of functions that can be used to implement context switching between tasks e Interrupt Handling The HAL implements the entire interface needed to properly handle interrupts e Utility Functions Finally some functions for time idle time and reboot handling are provided All these services are not used directly by the application but they ar
12. stack sharing can only be exploited if a proper scheduling algorithm is used In general that scheduling algorithm must ensure that once a task is started and its frame is allocated on the stack none of the tasks with lower priority and with which the task shares the stack can be executed An example of this algorithm is for example the Stack Resource Policy that allows resource and task sharing and prevents deadlocks Depending on the scheduling algorithm used by the kernel a proper HAL should be used For example if a Kernel Layer that allows tasks to block e g providing blocking semaphores for synchronization the HAL not only has to allow stack sharing but also allows different tasks to execute concurrently on different stacks in an interleaved way Supporting a model that allows the use of more than one stack can lead to a degradation in performance for those applications that do not need different stacks and where all the threads share the same stack For that reason the ERIKA Project provides more than one HAL for each architecture where each HAL is optimized for a particular usage i e for mono and multi stack applications Mono Stack HALs 2 All the threads and the interrupts share the same stack This kind of HAL can only be used if the scheduling algorithm used by the Kernel Layer guarantees that a preempted thread cannot execute again before all the preempted threads have finished their instances Multi Stack HALs
13. Interrupt Stack 40 The important data structures are described in the following paragraphs iram UINT16 st10_thread_tos This is an array that stores for each thread the addresses of the stack data structures In the Figure 5 2 three threads are showed thread 1 and thread 3 share the same stack When a context change occurs the HAL needs sometimes to know about the stacks of the threads For this reason the HAL interface is hacked adding a structure stack pointer iram struct struct_tos stack_tos This array stores the information about each couple of stacks Since each thread needs a system and a user stack they are grouped in a structure called struct_tos that contains the pointer to the top of the stack tos for a system stack and a user stack tram WORD st10_active_tos This variable stores the stack used by the running thread This variable must be used by the interrupt handler to save the tos before switching to the interrupt stack In this way the interrupt handler can rely only on the HAL implementation Global system stack The Figure 5 2 shows how the system stack is divided in slices The situation shows how the three threads allocate its stack frames on their stacks and shows also an empty interrupt stack which starts and ends empty User stacks Finally the Figure 5 2 shows the user stacks typically located in the external memory of the ST10 5 2 4 Performance The performance metrics of the Multi Stack ST10 HAL a
14. It must be the last function call of the interrupt handler 28 void hal_IRQ_stacked TID t It has the same meaning of the hal_IRQ_ready except that it does not create the context for the thread t but it assumes that it is present on top of the stack void hal_stkchange TID t This function is implemented only by the multistack HALs It changes the running thread to another thread that is already on the top of another stack This function always change the current context This function is used by the kernel to implement the synchronization points for the blocking primitives 4 3 Kernel Primitive Definition void hal_begin_primitive void This function must be called as the first instruction of every primitive to prepare the environment for the kernel void hal_end_primitive void This function must be called as the last instruction of every primitive to restore the environment of the calling thread Note that it is implementation defined if this function returns to the kernel primitive or to the calling thread void hal_IRQ_begin_primitive void This function must be called as the first instruction of every primitive used in an interrupt handler to prepare the environment for the kernel 29 void hal_IRQ_end_primitive void This function must be called as the last instruction of every primitive used in an interrupt handler to restore the environment of the calling thread Note that it is implementation define
15. KERNEL IMPLEMENTATION OF MONITORS FOR ERIKA by SATHISH KUMAR D YENNA B Tech Jawaharlal Nehru Technological University India 2001 A THESIS submitted in partial fulfillment of the requirements for the degree MASTER OF SCIENCE Department of Computing and Information Sciences College of Engineering KANSAS STATE UNIVERSITY Manhattan Kansas 2003 Approved By Major Professor Mitchell L Neilsen Copyright c 2003 Sathish Kumar R Yenna Permission is granted to copy distribute and or modify this document under the terms of the GNU Free Docu mentation License Version 1 1 or any later version published by the Free Software Foundation with no Invariant Sections with no FrontCover Texts and with no BackCover Texts This document is prepared using TRX ABSTRACT ERIKA Embedded Real me Kernel Architecture is a research project on micro kernel architectures for embedded systems Users can develop embedded applications on ERIKA without worrying about the underlying architectural and implementation details Monitors are program modules that provide a structured approach for process synchronization and can be implemented as efficiently as semaphores ERIKA presently supports basic mutual exclusion primitives and semaphores for thread synchronization It does not support monitors which pro vide an efficient data abstraction mechanism This thesis is about implementing monitors for ERIKA using the available kernel primitiv
16. Real tIme Kernel Architecture Author Sathish Kumar R Yenna lt sathish AT ksu edu gt Dept of Computing and Information Systems Kansas State University ae include lt config h gt include lt kernel h gt include lt mon mon h gt 340 void mon_signalall MON m CONDVAR xc TID tempthread hal_begin_primitive while c gt first NIL the conditional variable delay queue is not empty 350 Move the task from front of delay queue to rear of entry queue tempthread c gt first c gt first th_next c first if m gt first NIL 68 the monitor queue is not empty th_next m last tempthread else the monitor queue is empty m gt first tempthread 360 m gt last tempthread th_next tempthread NIL The task state switch from BLOCKED TO STACKED th_status tempthread STACKED if defined _ FP__ 370 check if there is to schedule a ready thread or pop a preempted thread A if rq queryfirstO NIL sys_ceiling gt th_ready_prio rq_queryfirst else check if there is to schedule a ready thread or pop a preempted one th_absdline stk_queryfirst lt th_absdline rq_queryfirst O 1 see also src srpt thendin c if rq queryfirstO NIL this test work also for the dummy task 380 stk_queryfirst NIL S signed th_absdline stk_queryfirst th_absdline rq_queryfirst lt 0 sys_ceilin
17. ad This must be the last call in the thread and it must be called at the same level as the and C symbols that delimit the thread body If the thread body does not end with this call results can be unpredictable Context change scenarios due to the activation of a thread that has higher prior ity with respect to the running thread using thread_activate and thread_make_ready are shown in the Figures 2 2 and 2 3 13 2 2 Thread Management in Interrupt Handlers An interrupt handler is a routine written by the user and executed to handle the arrival of an interrupt Interrupt handlers are executed in special contexts that can be different from the context of the running thread that the handler inter rupted For that reason an interrupt handler can only call the primitives of this class These primitives are architecture dependent though the names are same void IRQ_make_ready TID thread TYPENACT nact This function works as thread_make_ready primitive void IRQ_end_instance void This primitive must be called as the last instruction of an interrupt handler The behavior of this function is the termination of the routine Usually this function also does the preemption check 2 3 Shared Resource Handling The kernel layer provides a set of functions that can be used to enforce mutual exclusion between threads These functions manages mutexes that are basically binary semaphores statically defined and initial
18. ain layers compose the ERIKA kernel Kernel Layer This layer is the software layer that exports all of the system primitives to the application It is written using the C programming language in a way independent from the underlying architecture This layer uses the services offered by the HAL for thread and hardware interface handling Hardware Abstraction Layer HAL HAL is the software layer used by the Kernel Layer to abstract from a particular architecture This is the only nonportable part of the system and it isolates all the peculiarities of the underlying architecture from the implementation of the behavior of the primitives All HAL primitives are related to low level aspects like context switching and interrupt handling All other levels use the primitives provided by the HAL Porting the ERIKA kernel to another architecture requires only modification of the HAL Figure 1 1 Layers of ERIKA Application Layer user tasks Kernel Layer hardware independent routines Hardware Abstraction Layer hardware dependent routines 1 5 1 The Kernel Layer The functions provided by the Kernel Layer can be grouped in Queue Handling The kernel uses some queue data structures to keep track of the state of all threads in an application The functions for queue manage ment cannot be called directly by the application but only from inside the 5 kernel The queues are usually ordered Scheduling The kernel uses some extra func
19. ast CONDVAR Aifndef _ PRIVATE_MON_ENTER__ void mon_enter MON m Aendif ifndef _PRIVATE_MON_EXIT__ void mon_exit MON m Aendif Aifndef _ PRIVATE_MON_WAIT_ void mon_wait MON zsm CONDVAR zc Aendif Aifndef _PRIVATE_MON_SIGNAL__ void mon_signal MON m CONDVAR xc Aendif ifndef _PRIVATE MON SIGNALALL _ void mon_signalall MON zm CONDVAR c Aendif Aendif A 2 enter c Monitors for ERIKA Embedded Real tIme Kernel Architecture Author Sathish Kumar R Yenna lt sathish AT ksu edu gt Dept of Computing and Information Systems Kansas State University Ka include lt config h gt include lt kernel h gt include lt mon mon h gt 62 void mon_enter MON m TID current hal_begin_primitive if m lock The running task blocks 80 It must be removed from the stacked queue and then it must be inserted at the end of the monitor entry queue get the running task current stk_queryfirstO extract the task from the stk data structure stk_getfirst 90 The task state switch from STACKED TO BLOCKED th_status currentl BLOCKED reset the thread priority bit in the system_ceiling sys_ceiling amp th_dispatch_prio current if m gt first NIL the monitor queue is not empty th_next m gt last current else 100 the monitor queue is empty m gt first current m gt last cu
20. ation and the idle loop The dummy thread is always the lowest priority thread in the system it does not have a TID and it never ends It is always active and for that reason it can not be activated It is used for System initialization The dummy thread should initialize all peripher als Thread activation It should also manage the initial thread activations through the use of the thread_make_ready primitive Preemption The dummy function usually calls the sys_scheduler or thread_activate primitive to execute a preemption check Otherwise no other thread is activated and the system will be in the infinite idle loop Idle loop The dummy function should execute an infinte idle loop Dur ing the idle loop any kind of background code can be executed if no code to be executed the sys_idle primitive should be called 16 Figure 2 1 Thread Transition Diagram 1 Suyiem atem wes qsod wes uondw aad g 7 e ue r AJ a0Uue3sur pus peaty 2 _ 20 SC 4oyedsip aduezsurt pus pee1uyz apo Tan zen 7 ae o lt qoeu ya aouez3sur pus Oar ee qeatTqoe DES Jo fre z Tnpeyos sds 7 2 10 peez yew OXI 03RATJON pees s0ueqsut pues DES 10 o 30eu ya pes1 seu Dar sa uondulsa1d 17 Figure 2 2 Context changes due to the activation of thread B that has higher priority with respect to the running thread A 1 thread_abtivate TID_B
21. be called with interrupts disabled Note that hal_set_handler only set the function that have to be called when an interrupt arrives The peripherals that raise the interrupts must be configured directly by the application 5 2 Multi Stack HAL Under the multi stack HAL the system is composed by a set of threads Each thread has a stack a context and a body The thread stacks and context may be shared 5 2 1 Internal data structures defined by the user iram ADDR st10_thread_body This array stores the thread body pointer for each thread in the system because when a thread activation occurs the HAL needs to know which is the body function to execute These body pointers are stored in the HAL because the HAL interface only exports the concept of TID so the kernel never needs to know about body functions iram ADDR st10_thread_cp This vector stores the register bank addresses that are used by the HAL for each thread 38 iram UINT16 st10_user_stack This vector is the user stack The dimen sion of this vector should be enough to store all the user stack of the system 5 2 2 Context Layout Typical stack layout is as shown in the following figure Figure 5 1 Typical Stack layout of a preempted thread 1 CP 2 bytes 2 bytes MDC 2 bytes IP 2 bytes PSW 2 bytes prim call automatic variables ENDINSTANCE ENDINSTANCE This is the return address which the CPU jumps to when a thread instance ends
22. ce A process can access the variables in a monitor only by calling one of the monitor procedures Mutual exclusion is provided by ensuring that execution of procedures in the same monitor is not overlapped Condition synchronization in monitors is provided by a low level mechanism called condition variables 4 When monitors are used for synchronization a concurrent program contains two kinds of modules active processes and passive monitors Assuming all the shared variables are within monitors two processes can interact only by calling procedures in the same monitor The resulting modularization has two benefits First a process that calls a monitor procedure can ignore how the procedure is im 43 plemented all that matters are the visible effects of calling the procedure Second the programmer of a monitor can ignore how or where the monitors procedures are used Once a monitor is implemented correctly it remains correct independent of the number of processes that use it Also the programmer of a monitor is free to change the way in which the monitor is implemented so long as the visible proce dures and their effects are not changed Together these benefits make it possible to design each process and monitor relatively independently This in turn makes a concurrent program easier to develop and understand 4 6 1 Programming Using Monitors A monitor places a strict boundary around both the variables and the procedures that im
23. ciated with some condition variable c are awakened by means of signal statements If c s delay queue is not empty execution of signal c awakens the process at the front of the delay queue and removes it from the queue That process executes at some time in the future when it can acquire exclusive access to the monitor If c s delay queue is empty execution of signal has no effect Independent of whether a delayed process is awakened the process execut ing signal retains exclusive access of the monitor thus it can continue executing Programmer has to take care of inserting wait and signal operations at the appropriate locations to avoid permanent blocking of processes A process wait ing on some condition variable must be awakened by some other process when its boolean condition is satisfied There is one more operation Broadcast Signal available on condition variables 46 It is used if more than one delayed process can proceed or if the signaling process doesn t know which delayed process might be able to proceed Execution of signal_all c awakens all the processes waiting on the condition variable c In particular its effect is the same as executing signal c n number of times where n is the number of processes in the delayed queue 6 3 Implementation Using a Kernel Monitors can be implemented directly by a kernel The implementation of monitors using a kernel is more efficient than the implementation usin
24. d if this function returns to the kernel primitive or to the calling thread 4 4 Interrupt Handling void hal_enableIRQ void It enables all the interrupt sources It can only be called in a thread void hal_disableIRQ void It disables all the interrupt sources It can only be called in a thread void hal_IRQenableIR Q void It enables all the interrupt sources It can only be called in an interrupt handler void hal_IRQdisableIRQ void It disables all the interrupt sources It can only be called in an interrupt handler 4 5 Utility Functions void hal_gettime TIME t It returns the value of the system timer Note that this function is only available if the user defines the _TIME_SUPPORT__ symbol in the ERIKA makefile void hal_panic void 30 It is called by sys_panic to put the system to a meaningful state It usually resets the system or it hangs the system signaling an abnormal termination to the external world void hal_reboot void This function is called by sys_reboot to reset the system void hal_idle void This function is called by sys_idle to put the CPU in an idle low power state CPU does nothing except waiting for an interrupt 31 Figure 4 1 Interaction between the kernel layer primitives and the HAL functions for context handling 1 kernel layer hardware abstraction layer 3 hal endcycle ready thread end instance 2 hal endcycle stacked hal_r
25. d priority in version Moreover all the threads can share the same stack and dispatch priorities can be used to reduce the preemption between threads in a controlled way further reducing the overall stack space needed 3 1 1 An Example As an example in this section we depict a typical situation that explains the internal mechanisms of the kernel Suppose to have the thread set depicted in Table 3 1 with the corresponding initialization values The thread set is composed of six threads each with different priority there is a non preemption group composed by thread 4 and 5 they have the same dispatch priority and there is a shared resource used by threads 1 and 3 through a mutex The system ceiling has a starting value of 0x01 because the thread 1 starts on the stack Table 3 1 The example thread set 1 Thread Ready Dispatch Initial Values After the events Number Priority Priority Status Pend Act next Status Pend Act next STACKED NIL STACKED 0 READY NIL READY STACKED READY 3As there are only 6 threads in this example only the first 8 bits are showed the MSB is considered equal to 0x00 21 Then suppose that these events happen in the system 1 System start Thread 0 is activated so it starts in the STACKED state 2 Thread 1 arrives and preempts Thread 0 since it has a higher priority 3 Thread 1 locks the mutex therefore the system ceiling is updated to 0x0B 4 Thread 3 arrives
26. der to allow portability and re usability of application software 1 1 Architecture The following paragraphs describe the architecture of the ERIKA from a functional point of view A Kernel represents the core of a Real Time Operating System which is a software layer that directly interacts with the hardware on which the application program runs The main purpose of the Kernel is to give the application an inter face capable to handle a set of entities that tries to abstract from the peculiarities of the underlying hardware The ERIKA kernel is able to Handle threads a thread is a function which is executed concurrently with other entities in the system Handle synchronization between threads threads can share information by communicating with each other Handle interrupts an interrupt is a mechanism used to signal a running thread asynchronously 1 2 Thread Handling A multiprogramming environment provides entities that can execute concurrently These entities are called threads processes and tasks The term process is usually used to identify an address space with one or more threads executing within that address space The term thread can be thought as a single flow of control within a process The term task is used in the real time literature with different meanings ERIKA does not support any kind of memory protection so we can say that the ERIKA kernel can handle a set of threads The ERIKA Operating Syste
27. e By contrast condition synchronization must be explicitly programmed since different programmers require different synchronization conditions Based on these considerations mutual exclusion in monitors is implicitly pro vided and condition synchronization is explicitly programmed using mechanisms called condition variables Since execution within a monitor is mutually exclusive processes cannot interfere with each other when accessing permanent monitor vari ables A condition variable is used to delay a process that cannot safely continue 45 executing until the monitor s state satisfies some boolean condition It is also used to awaken a delayed process when the condition becomes true A condition variable is declared in the form var c cond The value of c is a queue of delayed processes but this value is not visible to the programmer The boolean delay condition is implicitly associated with the condition variable by the programmer Since the condition variables are used to synchronize processes within monitors they may be declared and used only within monitors To delay on a condition variable c a process executes wait c Execution of wait causes the executing process to delay at the rear of c s queue So that some other process can eventually enter the monitor to awaken the delayed process execution of wait also causes the process relinquish exclusive access to the monitor Processes waiting on some boolean condition asso
28. e O 160 if m gt first NIL wake up blocked thread newthread m gt first if m gt first th_next newthread1 NIL m gt last NIL 64 check for preemption if defined __FP__ if sys_ceiling lt th_ready_prio newthread else if stk_queryfirst NIL dummy task signed th_absdline stk_queryfirstQ th_absdline newthread gt 0 amp amp sys_ceiling lt th_ready_prio newthread lendif we have to schedule the blocked thread th_status newthread STACKED sys_ceiling th_dispatch_prio newthread insert the extracted task on the top of the stack th_next newthread stk_queryfirst stkfirst newthread hal_stkchange newthread else th_status newthread READY rq_insert newthread Insert in the Ready Queue th_status newthread READY rq_insert newthread else m gt lock 0 Call the dispatcher sys_scheduler O hal_end_primitive A AJ wait c Monitors for ERIKA Embedded Real tIme Kernel Architecture Author Sathish Kumar R Yenna lt sathish AT ksu edu gt Dept of Computing and Information Systems Kansas State University or include lt config h gt include lt kernel h gt 65 170 190 200 210 include lt mon mon h gt void mon_wait MON m CONDVAR c TID current hal_begin_primitive O 220 A 5 The runn
29. e ae a ee a eke 5 2 3 Stack Implementation ada a a a ee 5 2 4 Performanc eet gab ee eS Big ees Bia Sees Monitors 6 1 Programming Using Monitors a 8 ca te eka det ert ode ar 6 2 Synchronization in Monitors 6 3 Implementation Using a Kernel il 20 20 21 22 25 26 28 29 30 30 35 36 38 38 39 40 41 7 Implementation of Monitors 50 CE D ta Str ctures se tt doe dd ey og es a E BS NS Soke 50 7 1 1 Monitor Descriptor aoaaa 50 7 1 2 Condition Variable Descriptor ge peta pete e 51 7 2 Kernel Primitives A ad ea ta E Bose en EA 52 8 Monitor Interface 55 8 1 Monitor Condition Variable Initialization 55 8 2 Another Exampl saec eere he a a ea a EE 56 Bre The EE A EE EE 56 9 Conclusion 59 Bibliography 60 Appendix 61 A Source Code 61 EE EE EE 61 MAD SETI OE ne he a A he Bake Go ie he Bale ee EE 62 A e Sekt e ee e hb hele Bole aac Boker Ba E he ee gl 64 MCE EE Bag eh et ee S 65 AD A AI A E EN 66 bo sicnalalls einer te Delle a le 68 111 1 1 2 1 2 2 2 3 3 1 4 1 4 2 4 3 5 1 5 2 6 1 LIST OF FIGURES avers ol ERIKA s 8 AE SEA a pa A AR Thread Transition Diagram 1 oeste Context changes due to the activation of thread B that has higher priority with respect to the running thread A fl Context switches due to the activation of thread B by a call of thread_make_ready by a lower priority thread A 1 Kernel Data structures snaps
30. e called through the services exported by the Kernel Layer The HAL interface is implemented by the HAL Layer In general HAL layer can be developed following two different paradigms which in the following para graphs we highlighted as monostack HAL and multistack HAL Mono Stack HAL Following this model all the threads share the same stack This implicitly assumes that a preempted thread can not execute again until all the threads and interrupts handlers that preempted it have finished Note that it is not possible to implement any kind of blocking primitive with this paradigm 26 Table 4 1 The Basic HAL Interface 1 Context Handling Primitive Definition Interrupt Handling Utility Functions hal_endcycle_ready hal_endcycle_stacked hal_ready2stacked hal_IRQ_ready hal_IRQ_stacked hal_stkchange hal_begin_primitive hal_end_primitive hal_IRQ_begin_primitive hal_IRQ_end_primitive hal_enableIRQ hal_disableIRQ hal_IRQ_enableIRQ hal_IRQ_disableIRQ hal_gettime hal_reboot hal_panic hal_idle Multi Stack HAL This model HAL handles more than one stack In partic ular stack sharing is limited by assigning a set of thread to a particular stack As a limit all the threads use a private stack and no stack sharing is exploited at all Note that the assignment of threads to stacks is usually done statically All the HAL implementations should guarantee a thread that has been in terrupt
31. eady2stacked e sys_scheduler A Primitive used into a thread kernel layer hardware abstraction layer hal IRQ ready IRQ end instance hal IRQ stacked Oh Primitive used into a driver 32 Figure 4 2 Context change due to the activation of a thread B at higher priority 1 with respect to the running thread A Y GIL peyoeqs apToAopue Tey ar San a sk Sas tal a a lyk et A Sk g GIL pexyoeqszApesaz Tey auloy a0uezsur pua DES a dIL 23PATJOP DES pea d Dell y 33 Figure 4 3 Context change caused by the activation of two higher priority threads 1 with respect to the running thread TWH ao0uezsur pua peryg 9 dIL pegx sie pesxyp A oe A T a1 Apeda sien pesay Pealuro Dout g Io Ueox Doll vu 34 Chapter 5 ST10 HAL Internals This chapter describes some implementation details that can be useful to under stand the architectural choices made to implement the ST10 C167 HALs The ERIKA project provides three kinds of HALs for the ST10 platform Each HAL has different requirements in terms of the underlying memory models and in terms of memory usage Moreover each HAL provide different performance in terms of execution time of the primitives Mono Stack HAL This is the simplest and fastest HAL available for ST10 It supports only functions built for the system stack and it is so simple that most
32. ed will start again form the same point where it was interrupted As for the Kernel Layer the application should define and initialize the HAL data struc tures These data structures heavily depend on the architecture The initialization 27 of these data structures can be statically done in the variable initializers or can be done in the dummy function 4 2 Context Handling void hal_endcycle_ready TID t This function is called as the last function in primitives such as thread_end_instance It destroys the context allocated by the thread that is just ended and creates the context of the thread t passed as parameter Then the thread t is executed In case of a multi stack HAL this function can change the current stack void hal_endcycle_stacked TID t This function destroys the context allocated by the thread that is just ended and then executes the thread t whose context is supposed to be on top of a stack that in a multi stack HAL may not be the current stack void hal_ready2stacked TID t This function is used to dispatch a ready task This function suspends the running thread saving its context on its stack then it creates the thread t on its stack and finally it executes the body of the thread t In case of a multi stack HAL this function can change the current stack void hal_IRQ_ready TID t It has the same meaning of hal_endcycle_ready but it is called only at the end of the last nested interrupt handler
33. efined in the files fp kern h or srpt kern h Using the m first and th_next the second thread can be found The second thread is th_next m first In the same way the list can be traversed Finally th_next m last is NULL to specify the end of the list 7 1 2 Condition Variable Descriptor typedef struct TID first TID last CONDVAR The other structure CONDVAR is used to define the condition variables in a monitor In practice each condition variable is part of a monitor Since each monitor can have a variable number of condition variables there are two ways of implementing condition variables A monitor can have a linked list of condition variables or a new structure can be declared to define the condition variables In the later case user has to keep track of the condition variables belonging to each monitor In the implementation described a new structure is declared to define the condition variables Each condition variable has two member variables first and last which are used to maintain the list of threads waiting on the condition variable Both are set to NULL if there is no thread waiting on the condition variable Otherwise first is the first thread waiting and last is the last thread waiting 51 7 2 Kernel Primitives Below is a list of the additional kernel primitives used in the implementation of monitor primitives void hal_begin_primitive void This function is called as the first instruction in all t
34. es This implementation enables users to directly declare define and use monitors in their applications TABLE OF CONTENTS ABSTRACT ACKNOWLEDGEMENTS Introduction to ERIKA 1 1 Architecture E ser Ah ah a 1 2 Thread Handle uds A ee ds Ls ea e 1 3 Thread Synchronization Age o e ae Ee A e A Sc PM 4 1 4 Interrupt Handling yea a E ls E Tyo Layers sida ek Ee Ee A Se ee ld a Se kt 1 5 1 The Kernel Layer eos le UA Ace ee A 1 5 2 The Hardware Abstraction Layer 1 6 System Modules i bares e E a Gee eC ne eee aie bere SEN 1 7 G de Portability a t a amp ES es Ge ee A e da i Kernel API 2 1 Thread management ig 2 ate os II Be ee eS be 2 2 Thread Management in Interrupt Handlers 2 2 3 Shared Resource Handling caciones e vi 2A Utility e e epa LR se se ey Bue Se Ee Ee eS ee 2 5 The dummy thread ea a ee eS EE Kernels S EP Kernel a a sera EE EE a aA Bree AS R gl th G Adal An Example La a Lat AAA a Ea de SRPT Kernel nesa of Deg Ee e hee HAL Internals gek RK rc Ae card pe E BO Aber ee rA 4 2 Context EE EE EH 4 3 Kernel Primitive Definition 4 4 Interrupt Handling eta eh ts dd Be EE ANG Utility ECMO 1 rs eae Et oe Se Ke Se ora ahah cae ee 4 ST10 HAL Internals 5 1 Peculiarities of the ST10 Implementation 5 2 Multiestack HAI Zu a O ee oe as ee ea 5 2 1 Internal data structures defined by the user 5 2 2 Context Layout oc deg by d
35. g gt th_ready prio rq queryfirst 1 Aendif 390 we have to schedule an interrupted thread that is on the top of its stack the state is already STACKED hal_stkchange stk_queryfirst else we have to schedule a ready thread that is not yet on the stack th_status rq_queryfirst STACKED sys_ceiling th_dispatch_prio rq_queryfirst hal_ready2stacked rq2stk_exchange O 400 hal_end_primitive 69
36. g semaphores The following implementation is described in 4 We assume that each process has a descriptor and the descriptors of processes that are to execute are linked together on a ready queue Also to implement monitors we add primitives for monitor entry exit and each of the operations on the condition variables Primitives are also needed to create descriptors for each monitor and each condition variable These are nothing but defining and initializing the descriptors for each monitor and each condition variable Each monitor descriptor contains a lock and an entry queue of descriptors of processes waiting to enter the monitor The lock is used to ensure mutual exclusion When the lock is set exactly one process is executing in the monitor otherwise no process is executing in the monitor The descriptor of a condition variable contains the head of a queue of de scriptors of processes waiting on that condition variable Thus every process descriptor except those of executing processes is linked to either the ready list a monitor entry queue or a condition variable delay queue The monitor entry primitive enter name finds the descriptor for monitor name AT then either sets the monitor lock and allows the executing process to proceed or blocks the process on the monitor entry queue The monitor exit primitive exit name either moves one process from the entry queue to the ready list or clears the monitor lock The wait c sta
37. he directory include mon mon h 8 1 Monitor Condition Variable Initialization A monitor can be defined and initialized as shown in the example below MON mon1 0 NIL NIL In this example mon is initialized to zero which means no task is running in the monitor and is free The other two fields initialize the list of the tasks waiting to enter the monitor to be NULL A condition variable can be defined and initialized as shown below CONDVAR condvar NIL NIL The list of tasks waiting on the condition variable condvar is initialized to NULL 59 8 2 Another Example This example describes a thread that uses a monitor to access a critical section MON mon 0 NIL NIL CONDVAR oktoread NIL NIL void thread_example void The task enters a critical section protected by a mon monitor mon_enter amp mon while nw gt 0 mon_wait amp mon amp oktoread nr nr 1 mon_erit amp mon The task leaves the critical section allowing other tasks to enter the monitor 8 3 The Functions void mon_enter MON mon This function is used to lock the monitor by setting the lock variable associated with the monitor mon If the lock value is already one then the calling task does not return from the call to mon_wait until it has been set to zero by another thread calling mon_exit The task has to call this function every time it enters 56 the monitor This function makes the monitor busy and w
38. he primitives to prepare the environment for the kernel The function disables all the interrupts and the kernel primitive is executed as an indivisible unit void hal_end_primitive void This function is called as the last instruction of every primitive to restore the environment of the calling thread Note that it is implementation defined if this function returns to the kernel primitive or to the calling thread The function enables all the interrupts TID rq_queryfirst void This function is used to get the first ready task in the ready queue without ex tracting it TID stk_queryfirst void This function is used to get the first stacked task running task queue without extracting it void stk_getfirst void This function is used to extract the running task from the stack The second task on the stack becomes the first one 52 void rq_insert TID t The function inserts a task thread t into the ready queue The thread t is in serted at its position in the ready queue depending on its priority The function varies depending on the kernel used The ERIKA supports two kernels namely FP Kernel and SRPT Kernel The scheduling algorithm used by the FP Kernel is Fixed Priority with Preemption Threshold Scheduling Algorithm The scheduling algorithm used by the SRPT Kernel is the Stack Resource Policy with Preemption Threshold Scheduling Algorithm void hal_stkchange TID t This function is called when we need to switch
39. his reason fastest stack on machine Unfortunately its size is limited so often the applications simulates a stack using the RO register The mono and multi stack HALs for reasons of speed do not support the use of the user stack for storing the return address of the functions In other words functions are called using the couple of assembler instructions CALL RET The multi stack kernel need to address more than one system stack For that 36 reason the various system stacks are re mapped in different places of the real system stack Note that in this way there is no protection for system stack overflows The different stacks are implemented saving at each stack switch the top of the user stack and of the system stack in a private HAL variable CP register and register banks To speed up the kernel a register bank is used accessible through the CP register for each preemption level Every time there is a context change the CP value is saved on the stack and is then restored Function calls primitives and __NOPT__ primtives can be thought as simple functions that disable the interrupts as their first operation Interrupt disabling is a typical way of ensuring that the kernel and HAL data structures are accessed in mutual exclusion A particular attention must be reserved to the end of a thread In practice a thread ends when it reaches the trailing of its function definition The RET instruction inserted by the compiler at the end of
40. hot after the events listed 1 Interaction between the kernel layer primitives and the HAL func tions for context handling 1 Context change due to the activation of a thread B at higher priority with respect to the running thread A 1 Context change caused by the activation of two higher priority threads with respect to the running thread 1 Typical Stack layout of a preempted thread 1 A typical stack configuration lll 444645 4 es tra o 4 Monitor Kernel Primitives 4 00 heces ple 2 1 3 1 4 1 5 1 5 2 LIST OF TABLES Kernel primitives that can be used in an application 1 11 The example thread set lll 2 3242224 Gob 4 64844 2064 21 The Basic HAL Interface EE 27 Characteristics of the ST10 HALs lo osas re A 36 Performance metrics of the multi stack ST10 kernel 1 42 ACKNOWLEDGEMENTS First of all I would like to thank my major professor Dr Mitch Neilsen for allowing me to do this thesis under his guidance I am grateful to him for all the advice encouragement and support he provided me with I wish to thank him for believing in me and providing me the opportunity to work with him as a Graduate Research Assistant Next I would like to thank Dr Masaaki Mizuno for being a continual source of inspiration and encouragement and Dr Gurdip Singh for kindly consenting to be on my committee Also I want to thank m
41. ing task blocks It must be removed from the stacked queue and then it must be inserted at the end of the condition variable delay queue get the running task current stk_queryfirstO extract the task from the stk data structure 230 stk_getfirst The task state switch from STACKED TO BLOCKED th_status current BLOCKED reset the thread priority bit in the system_ceiling sys_ceiling amp th_dispatch_prio current if c gt first NIL the conditional variable delay queue is not empty 240 th_neaxt c gt last current else the conditional variable delay queue is empty c gt first current c gt last current th_next current NIL Call the monitor exit primitive mon_exit m 250 No need of calling the hal_end_primitive as it is called in mon_exit hal_end_primitive signal c Monitors for ERIKA Embedded Real tIme Kernel Architecture Author Sathish Kumar R Yenna lt sathish AT ksu edu gt Dept of Computing and Information Systems 66 Kansas State University 260 include lt config h gt include lt kernel h gt include lt mon mon h gt void mon_signal MON sm CONDVAR c TID tempthread 270 hal_begin_primitive if c gt first NIL the conditional variable delay queue is not empty Move the task from front of delay queue to rear of entry queue tempthread c gt first
42. ized The kernel layer provides two functions for managing mutexes that are mutezx_lock and mutex_unlock Every critical section that use mutexes must start locking a mutex and must end unlocking it void mutex_lock MUTEX mutex_id This primitive locks a mutex not already locked by another thread Nested locks 14 of the same mutex in the same thread are prohibited void mutex_unlock MUTEX mutex_id This primitive frees a mutex that was previously locked by the same thread The unlocking of the mutex usually provokes a preemption check 2 4 Utility Functions This section shortly describes a few functions that can be used in the application void sys_panic void This function is invoked in case of an abnormal state of the application Typically this function should reset the system and or signal a system fault void sys_reboot void This primitive resets the system void sys_idle void This function is the function that should be used into the idle loop in the dummy function This function does nothing void sys_gettime TIME t This function returns the timer value that is currently used as system clock This function is only available if the user defines the symbol _TIME_SUPPORT__ 15 2 5 The dummy thread The startup point of an application is a function called dummy whith the pro totype void dummy void The dummy thread can be thought as the thread that is responsible for system initializ
43. m can be thought as a single process with many threads executing within the same address space The ERIKA kernel provides only the basic features for thread handling it implements a real time scheduling algorithm a thread activation service and all of the underlying context switching functions Each thread owns a set of attributes body function priority user stack reg isters etc that identify the state of the thread Each thread is associated with a status word which describes the state of the thread with respect to the scheduling algorithm In ERIKA a thread can be in one of the following four states Stacked The thread t started its execution and its frame is currently allo cated on its stack that is t is the running thread or t has been preempted by another thread Ready The task has been activated and is ready to execute All ready tasks are queued in a data structure called ready queue Idle The last instance of thread t has terminated and t is not queued on the ready queue Moreover t does not have any memory allocated on its stack A task in the idle state is usually is waiting for activation Blocked This state is used when a task is blocked on a synchronizing con dition Note that this state is meaningful only in a multi stack HAL where a thread can be blocked without interrupting others 1 3 Thread Synchronization The ERIKA kernel supports some synchronization mechanisms that can be used t
44. ming Principles and Practice Addison Wesley Publishing Company 1991 Hoare C A R Monitors an operating system structuring concept Comm ACM 17 10 October 1974 Brian W Kernighan and Dennis M Ritchie The C Programming Lan guage Pentice Hall 1988 SIEMENS AG Instruction Set Manual for the C166 Family Version 1 2 12 97 1997 60 Appendix A Source Code The following sections show the files that were added in implementing the monitors for ERIKA mon h is put in the folder include mon The other files are put in the folder src mon A l mon h Monitors for ERIKA Embedded Real tIme Kernel Architecture Author Sathish Kumar R Yenna lt sathish AT ksu edu gt Dept of Computing and Information Systems Kansas State University ifndef INCLUDE MON_MON_H__ define _INCLUDE_MON_MON_H__ 10 Monitors This file declares the E R I K A monitors and conditional variables A monitor is contained in a data structure called MON and a condition variable is contained in a data structure called CONDVAR That structure can be initialized statically recommended or dynamically using the macro mon_init 20 These functions can ONLY be used with a multistack HAL or similar because these monitor primitives are BLOCKING primitives Z 61 The monitor descriptor typedef struct UINTS lock TID first TID last MON The conditional variable typedef struct TID first TID l
45. o guarantee that some critical code sections are executed in mutual exclusion and other synchronization mechanisms that can be used for thread communication ERIKA system provides a type MUTEX and two mutex primitives mutez_lock and mutex_unlock that can be used to set the boundaries of critical regions There are also blocking primitives implemented such as classic semaphores and Cyclical Asynchronous Buffers CABs The ERIKA distribution does not support monitors which is the main topic of this document 1 4 Interrupt Handling The ERIKA kernel can be configured to directly interact with the underlying hardware architecture In particular it can handle the interrupts that are raised by the I O interfaces timers and so on in a clean way In fact it provides an interface that allows linking a handler written by the user into an interrupt vector That interface also provides proper handling of eventual interrupt controllers that may be present in a particular architecture The handler can be considered a special function that can call a subset of the primitives These primitives can be used to interact with the operating system for example activating a thread that will terminate the interaction with the hardware interface In this way urgent pieces of code can be put directly into the handler On the other hand less urgent tasks can be processed in a separated thread without interfering the high priority tasks 1 5 Layers Two m
46. on t allow other tasks to enter the monitor void mon_exit MON mon This function is used by the tasks to exit the monitor It checks to see whether there is any other task waiting to enter the monitor If there is a task waiting to enter the monitor then it wakes up the task and compares the priorities of the woke up task and the calling task to find out which one is to be scheduled The function schedules the highest priority task If there is no task on the monitor list then it clears the lock associated with the monitor enabling others to know that the monitor is free and call the dispatcher to schedule the highest priority task void mon_wait MON mon CONDVAR cond This function is called by the tasks to wait on a condition variable cond associated with the monitor mon The calling task is blocked and is added to the end of the list of tasks waiting on the condition variable Since the calling function is blocked it must leave the monitor mon_exit mon is called as the last instruction in the function void mon_signal MON mon CONDVAR cond This function is used to signal a task waiting on a condition variable cond It checks to see if the list associated with the condition variable is empty or not If its empty it does nothing except scheduling a highest priority task If it is not empty then it moves the task from the front of the delay queue associated with the condition variable cond to the rear of the entry queue as
47. only a subset of the CPU registers that is the minimum set of registers that can reproduce the status of a thread without any problem In practice the HAL offers support for thread execution Using the HAL in terface threads can be executed or stopped and their context saved The Kernel Layer internally only refers to a thread using some identifier called a Thread Den tifier TID This allows the implementation of various scheduling algorithms in a way independent of the particular hardware architecture The thread execution model is one shot in that model the body function simply represents an instance of a thread Every time a thread is activated the body function is called when the body function finishes the thread instance is terminated Note that when an instance terminates the end of the body function automatically clean up the stack frame of the thread Typically the end of a body function jumps to a HAL Kernel Layer function that is responsible for choosing the next thread to execute The memory model supported by the HAL is a shared memory model where the whole address space is shared among all threads in the system This assumption that reflects in fact the typical hardware architecture of most microcontrollers that typically do not support memory protection usually they do not have a MMU The interface exported by the HAL and the one shot thread model allow in general different threads to share the same stack Anyway
48. optimized The design of ERIKA helps the process of optimizing the memory foot print because each part of the system can be thought as a module that can be included or not in the final image file The entire Kernel is in fact compiled and linked together with the application reducing every possible overhead In particular the user can choose the following options at compile time The hardware architecture on which the application will execute The HAL to be used mono stack or multi stack The scheduling algorithm used by the application Other external modules for example semaphores mailboxes and so on Finally the application will define the initialization of the HAL and kernel data Operating System structures that are application dependent for example the number of threads and their priority 1 7 Code Portability The division of the RTOS in two layers eases the porting of the Kernel Layer on top of different architectures The use of a common interface for handling operating system calls also ease the migration from one scheduling algorithm to another one Moreover the interaction between the application and the operating system is done using the syntax of a high level programming language which allows the specification of the constraints in a programming environment independent of the architecture 10 Chapter 2 Kernel API Kernel Layer provides an interface for the application An application can
49. plement a shared resource A monitor declaration has the form Monitor MonitorName Declarations of shared variables initialization code Procedure operation formal parameters Body of operation End Procedure operationN formal parameters Body of operationN End End The permanent variables describe the state of the resource The procedures 44 implement the operations on the resource A monitor has three properties which make it an abstract data type First only the procedure names are visible outside the monitor they provide the only gates through the monitor boundary To alter the state a process must call one of the available procedures The second property is that the procedures within a monitor may access only the permanent variables and the local variables They may not access the variables declared outside the monitor Third permanent variables are initialized before any procedure body is executed Processes executing in monitors may require mutual exclusion to avoid inter ference and may require condition synchronization to delay until the monitor state is conducive to continued execution We will now look at how processes synchronize within monitors 6 2 Synchronization in Monitors Synchronization is easiest to understand and hence to program if mutual exclu sion and condition synchronization are provided in different ways 4 It is best if mutual exclusion is implicitly provided since this precludes interferenc
50. re presented in the Table 5 2 More observations are skipped for brevity 41 Table 5 2 Performance metrics of the multi stack ST10 kernel 1 Kernel Data Not inlined code Test Application Timer Handler Total image of the sample application ROM Footprint RAM Footprint System Stack Usage Mutexes Activate End instance Interrupt Latency 250 bytes RAM RAM Initialization ROM 794 bytes 132 bytes 176 bytes 1352 bytes system stack register banks and initialization not included 970 bytes 10 bytes for each thread 2 bytes for each SRP Mutex 8 bytes global variables 4 bytes for each thread 32 for each priority level 2 for each SRP Mutex 4 for each stack System Stack User Stack 16 bytes for each priority level iterrupt frames lock 1 4 microseconds unlock from 3 6 to 10 8 microseconds from 2 8 to 9 6 microseconds from 8 8 to 12 4 microseconds 6 microseconds 42 Chapter 6 Monitors Monitors 5 are program modules that provide a structured approach for pro cess synchronization and can be implemented as efficiently as semaphores First and foremost monitors are a data abstraction mechanism they encapsulate the representations of abstract resources and provide a set of operations that are the only means by which the representation is manipulated In particular a monitor contains variables that store the resource s state and procedures that implement operations on the resour
51. riptor of executing at the end of the delay queue executing 0 call exit name end procedure signal name monitor_index cname condvar_index find descriptor for monitor name find descriptor for condition variable cname if delay queue not empty move process descriptor from front of delay queue to rear of entry queue fi call dispatcher end 49 Chapter 7 Implementation of Monitors 7 1 Data Structures The following two structures are the only data structures added to the existing kernel These structures are defined in the file include mon mon h 7 1 1 Monitor Descriptor typedef struct 4 UINTS lock TID first TID last MON The MON is for the application user to declare and define monitor in their application at the user level The first field lock determines whether the monitor is locked or not That is it determines whether there is a thread running in the monitor The lock is set to 7 before a thread enters the monitor and it is set to 0 once the thread leaves the monitor A thread t can enter a monitor m if and only if the m lock is O zero The other member variables first and last are used to maintain the list of threads waiting for their chance to enter the monitor The data type TID is nothing 50 but an integer type The variable m first specifies the first thread waiting It is NULL when there is no thread waiting to enter the monitor The list is maintained using another variable th_nezt d
52. rrent th_next current NIL if defined _ FP__ check if there is to schedule a ready thread or pop a preempted thread 110 if rq_queryfirst NIL sys_ceiling gt th_ready_prio rq_queryfirst else check if there is to schedule a ready thread or pop a preempted th_absdline stk_queryfirst 1 lt th_absdline rq_queryfirst O see also src srpt thendin c if rq queryfirstO NIL this test work also for the dummy task stk_queryfirst NIL S signed th_absdline stk_queryfirstO 1 120 th_absdline rq_queryfirst lt 0 63 sys_ceiling gt th_ready prio rq_queryfirst Aendif we have to schedule an interrupted thread that is on the top of its stack the state is already STACKED hal_stkchange stk_queryfirstO 130 else we have to schedule a ready thread that is not yet on the stack th_status rq_queryfirst STACKED sys_ceiling th_dispatch_prio rq_queryfirst hal_ready2stacked rq2stk_exchange O else m gt lock 1 140 hal_end_primitive A 2 exit c Monitors for ERIKA Embedded Real tIme Kernel Architecture Author Sathish Kumar R Yenna lt sathish AT ksu edu gt Dept of Computing and Information Systems Kansas State University 150 include lt config h gt include lt kernel h gt include lt mon mon h gt void mon_exit MON m TID newthread hal_begin_primitiv
53. sociated with the monitor mon and schedules the highest priority task 97 void mon_signalall MON mon CONDVAR cond This function is similar to the mon_signal except that it moves all the tasks form the delay queue to the rear of the entry queue It makes the delay queue associated with the condition variable empty Finally it checks the priorities of the tasks and schedules the highest priority task 58 Chapter 9 Conclusion Monitors are program modules that provide a strcutured approach for process synchronization Assuming all shared variables are within monitors two processes can interact only by calling procedures in the same monitor Monitors makes a concurrent program easier to develop and understand 4 The distribution of ERIKA doesn t provide monitors for the applications It only provides mutual exclusion primitives and semaphore primitives This docu ment provides a structured approach for implementing monitors for ERIKA which enables the users to declare define and use monitors in their applications Using this monitor module real time concurrent aaplications can be developed easily 59 Bibliography Paolo Gai and Alessandro Colantonio ERIKA User Manual draft ver sion RETIS Lab Pisa ITALY 2002 Paolo Gai ERIKA Mono Stack Documetation Notes RETIS Lab Pisa ITALY 2000 Paolo Gai ERIKA Multi Stack Documetation Notes RETIS Lab Pisa ITALY 2000 Gregory R Andrews Concurrent Program
54. tement is implemented by invoking the kernel primitive wait name cname and the signal c statement is implemented by invoking the kernel primitive signal name cname In both primitives name is the name of the monitor descriptor and cname is the name of the condition variable descriptor Execution of wait delays the executing process on the specified condition variable queue and then either awakens some process on the monitor entry queue or clears the monitor lock Execution of signal checks the condition variable queue If it is empty the primitive simply returns otherwise the descriptor at the front of the condition variable queue is moved to the of the monitor entry queue Since a process that calls wait exits the monitor the wait primitive simply calls the exit primitive after blocking the executing process 48 Figure 6 1 Monitor Kernel Primitives 4 procedure enter name monitor_index find descriptor for monitor name if lock 1 insert descriptor of executing at the end of entry queue executing 0 lock 0 lock 1 fi call dispatcher end procedure exit name monitor_index find descriptor for monitor name if entry queue not empty move process descriptor form front of the entry queue to rear of ready list entry queue empty lock 0 clear the lock fi call dispatcher end procedure wait name monitor_index cname condvar_index find descriptor for the condition variable cname insert desc
55. the function jumps to the internal function called st10_thread_endinstance This function cleans the stack and then depending on the priority and number of instances of the thread st10_thread_endinstance executes the right instructions to change the running thread accordingly to the kernel choice This way of implementing the end of a thread can be selected with the option _ NOPT_ in the ERIKAOPT variable in the make file However note that the instructions that are needed to change the context are often only a few For this reason the HALs support a way of ending the instance of a thread using an optimized inline substitution The advantage of the first approach is that the code produced by the compiler can be used straight without modification allowing an easy extension of the Kernel Layer If the maximum efficiency is needed an the correspondent optimized version is available the second approach can be used reducing code size and enhancing 37 the performance of the system Timers and thread activations The ST10 architecture has a lot of nice features including in particular a lot of timers and CAPCOMs The ERIKA implementation uses a free running timer timer T8 to have a coherent timing reference and the related CAPCOMs to raise the periodic interrupts in a coherent way Interrupt Handlers Interrupt handlers are defined using the hal_set_handler macro that is responsible to link an interrupt source to a user function that will
56. tions to schedule the threads in the system These functions use the HAL interface and the queue handling functions These functions are not directly accessible to the user User Interface This is the part of the kernel that exports the constants types data and primitives the user can use The user interface in particular covers all system services that are handled by the kernel The kernel layer internally uses some extra information about the tasks In particular it defines for each thread the status the priorities and the pending activations Moreover it defines the mechanisms for mutual exclusion and the available resources 1 5 2 The Hardware Abstraction Layer The main objective of the Hardware Abstraction Layer is to export to the Kernel Layer the abstraction of thread In general each thread is characterized by A body which is a C function that implements the control flow of the thread This function is called by the HAL with interrupts enabled each time a particular thread becomes the running thread A context which is the CPU status of the thread at a particular instant in time The real composition of the context varies from architecture to architecture The context can be thought as a copy of the CPU registers that is made each time the running thread is preempted or interrupted for some reason In any case the application can not rely on the composition of a context in general a particular HAL can save
57. y parents for always believing in me and for allowing me to take chances and I thank my friends for their invaluable support and for their warm wishes Finally I thank God for giving me the oppportunity to pursue a dream and for always being there for me when I needed vi DEDICATION To My Parents Chapter 1 Introduction to ERIKA ERIKA Embedded Real tIme Kernel Architecture 1 is a research project on micro kernel architectures for embedded systems ERIKA is composed of a set of kernels and a set of tools ascheduling simulator that can be used to simulate the scheduling behavior of the system a set of optimized algorithms which help the designer to find an optimal assignment of scheduling parameters that minimize the RAM usage while maintaining the schedulability of the system ERIKA Kernels consist of two layers the Kernel Layer and the Hardware Abstrac tion Layer HAL The Kernel Layer contains a set of modules that implement task management and real time scheduling policies The Hardware Abstraction Layer contains the hardware dependent code that handles context switches and interrupt handling Currently there are HALs for the Seimens ST10 C167 architecture and for the ARM7TDMI architecture It is easy to port ERIKA to a new processor family in a very short time by writing the HAL routines for the new architecture The interface is identical for all the implementations of the operating system in or

Download Pdf Manuals

image

Related Search

Related Contents

Provider Portal User Guide - Early Learning Coalition of Broward  PRODUCT SERVICE MANUAL SERIES 110H & 210H  Fujitsu ESPRIMO Mobile U Series MOB U9210  Xtech XTC-329 SATA cable  Sony VGN-CR290EAP User's Manual  Optoma Technology 1080p User's Manual  STATIVWAAGE 7830/7831 - Soehnle Professional  DSTS-5A/2C User`s Manual - Electronic Devices, Inc.  取扱説明書 GSS-1002N 保証期間 1 ヵ年  

Copyright © All rights reserved.
Failed to retrieve file