Professional Documents
Culture Documents
Realtime systems
This timeliness factor which distinguishes realtime software from normal application software targeted at desktop computers. In realtime software, we have to ascertain that all deadlines are met before deploying the software. In desktop software, usually ensuring correctness is sufficient. Thus while developing realtime software, we should do Performance Analysis during the design phase.
5
History of RTOS
The so called operating system offers abstraction of the underlying hardware from the application code. In addition, the evolution of OS helped shift the design of software applications from large, monolithic applications to more modular, interconnected applications that could run on top of the operating system environment.
7
History of RTOS
In 60s and 70s, when mid-sized and mainframe computing was in its prime, UNIX was developed to facilitate multi-user access to expensive, limitedavailability computing systems. UNIX allowed to share these large and costly computers. Multi-user access was very efficient. UNIX was also ported to all types of machines from microcomputer to supercomputers. In 80s Windows operating system, targeted for personal computing environment through Graphical User Interface helped residential and business users interact with the PCs.
8
RTOS
An RTOS is not usually such a complex piece of software when compared to the mammoth size OSes currently available. Though current RTOSes provide a huge variety of features, a basic RTOS is just small enough to provide some scheduling, memory management and a decent level of hardware abstraction.
9
Similarities between a Real Time Operating System and General Purpose Operating System
Some level of multitasking, Software and hardware resource management Providing OS services to applications Abstracting the hardware from the software applications.
10
OS vs RTOS
A desktop OS is usually huge in size. It is not uncommon to see the OS using 300-500 MB just for their installation. But, in embedded systems, even 8-16MB of memory is considered to be luxury. A desktop OS has huge libraries for UI management, support for networking protocols and fancy features like Plug n Play. They also implement complex policies for network communication and facilities for binary reusability such as DLLs, COM/DCOM, .NET, etc.
11
Kernel
In some applications, an RTOS consists only a kernel, which is the core supervisory software that provides minimal logic, scheduling and resource management algorithms. Every RTOS has a kernel. An RTOS can be a combination of various modules, including the kernel, a file system, networking protocol stacks and other components needed for a particular application.
13
Some of the common elements of the heart of an RTOS the kernel are:
Scheduler A set of algorithms that determines which task executes when. Objects Useful for developers to create applications for real-time embedded systems. Common kernel objects are tasks, semaphores and message queues. Services Operations that the kernel performs on an object. Eg timing, interrupt handling and resource management.
14
Desktop vs RTOS
In a desktop development environment, a programmer opens his IDE and types his code. Then he builds it using his compiler and then executes his program. Here OS is running already and it loads the executable program. The program makes uses of the OS services. The OS takes care of scheduling it. When the program completes, it exits. The OS can run other programs even while our program is running. Programs have a definite exit point and programs that contain infinite loop are considered bad.
16
BSP
But this is not the case in most of the embedded systems. Usually there will be no dedicated OS already running on the target to load our programs. In an embedded system the software written bus us, the RTOS (usually in the form of some library) and a special component called the Board Support Package (BSP) is bundled into a single executable file. This executable is burnt into a Boot-ROM or Flash. Sometimes, the code is obtained over a network on being powered up. Usually embedded systems cannot afford the luxury of having hard disks. Thus there is no OS during the startup. Here BSP is part of OS code in the sense that it is used by the OS to talk to different hardware in the board. In fact ,we write the software that is going to run on the target board.
17
Concurrency
Concurrency design requires developers to decompose an application into small, schedulable, and sequential program units. When done correctly, concurrent design allows system multitasking to meet the performance and timing requirements for real-time system.
21
Task
It consists of the following: Task Creation, Task Scheduling and Task Deletion. A Task is the atomic unit of execution that can be scheduled by an RTOS to use the system resources. Thus a task is an independent thread of execution that can compete with other concurrent tasks for processor execution time. When we say that a task is an atomic unit, any other entity smaller than a task cannot compete for system resources. The resources such as CPU, memory, input / output devices, etc are called system resources.
22
Task Creation
A task first need to be created. A task is characterized by the parameters and supporting data structures: 1) A task name 2) Priority 3) Stack Size and 4) OS specific options. These parameters can be used to create a task. A typical call might look like as follows: result = task_create(TxTask, 100, 0x4000, OS_PREEMPTABLE); if result = = OS_SUCCESS) { // task created} At this stage, the code is in an embryonic state (Dormant). It still does not have the code to execute. But by now, a task control block (TCB) would have been created by the RTOS.
23
System tasks
When a kernel first starts, it creates its own set of system tasks and allocates the appropriate priority for each from a set of reserved priority levels. An application should avoid using these priority levels for its tasks because running application tasks at such level may affect the overall system performance or behavior. The system priorities are not be modified. Eg. initialization or startup task, idle task, logging task, exception-handling task and debug agent task (allows debugging with a host debugger).
24
Control Blocks
The use of control blocks is not limited to a task. There are control blocks for memory, synchronization, etc. The control blocks are internal to RTOS. There is absolutely no need for a programmer to access these blocks. But, a programmer need to know how these control blocks are used by the RTOS.
25
TCB
An RTOS usually reserves a portion of available memory for itself during startup. This chunk of memory is used to maintain structures such as TCB. The TCB will usually consists of the state of the task. ie the value of registers when the task was preempted earlier, its priority and its RTOS specific parameters (say scheduling policy). When a task is blocked, the value of the registers is saved in its context in TCB. When a task is scheduled again, the system registers are restored with these saved values, so that the task will know even if it was pre-empted. An RTOS uses the TCB of a task to store all the relevant information regarding the task. 26
Task states
A task can be in one of the following states: 1) Dormant 2) Ready 3) Running and 4) Blocked. Dormant When the task is created, but not added to RTOS for scheduling. Ready When a task is added to the RTOS for scheduling, it usually arrives in the ready state. But it cannot do so currently if a higher priority task is being executed. Running The task is currently using the CPU. When a task is running and if another higher priority task becomes ready, the task that is running is pre-empted and the highest priority task is scheduled for execution. Blocked During course of execution of a task, it may require a resource or input. In this case, if the resource / input is not immediately available, the task gets blocked.
27
Granular states
Some commercial kernel such as the VxWorks kernel, define other, granular states such as suspended, pended and delayed. Pended and delayed are sub-states of blocked state. A pended task is waiting for a resource that it needs to be freed. A delayed task is waiting for a timing delay to end. The suspended state exists for debugging purposes.
28
29
Ready State
When a task is first created and made ready to run, the kernel puts it into the ready state. Here the task actively competes with all other ready task for the processors execution time. The tasks in this state cannot move directly to the blocked state. But it can move to the running state. Because many tasks might be in the ready state, the kernals scheduler uses the priority of each task to determine which task to move to the running state.
30
Ready state
Many kernals support more than one task per priority level, allowing many more tasks in an application. Then the scheduling algorithm is quite complicated and involves maintaining a taskready list. Some kernals maintain a separate task-ready list for each priority level; others have one combined list. A kernel uses this list to move tasks from the ready state to the running state.
31
Running State
In a single-processor system, only one task can run at a time. When a task is moved to the running state, the processor loads its registers with this tasks context. The processor can then execute the tasks instructions and manipulate the associated stack. When a pre-empted task is put in the appropriate, priority-based location in the task-ready list, and the higher priority task is moved from the ready state to the running state. This state can move to the blocked state .
32
Blocked state
The possibility of blocked states is very important in real-time systems because without blocked states, lower priority tasks could not run. If higher priority tasks are not designed to block, CPU starvation can result. CPU starvation occurs when a higher priority task use all the CPU execution time and lower priority tasks do not get to run. When a task becomes unblocked, the task might move from the blocked state to the ready state if it is not the highest priority task. The task is then put into the task-ready list at the appropriate priority based location. However, if the unblocked state is the highest priority task, the task moves directly into the running state (without going to ready state) and preempts the currently running task. The preempted task is moved to the ready state and put into the appropriate priority-based location in the task-ready list. 33
Idle task
What happens if no task is ready to run and all of them are blocked? The RTOS will be in trouble. So, an RTOS will usually execute a task called idle task. An idle task does nothing. void IdleTask (void) { while(1); } This has no system calls. It has no code except an infinite loop. In RTOS, the idle task has the lowest priority. Many RTOS reserve a few lowest and highest priority tasks for themselves. For example, if an RTOS can provide 256 tasks, it may reserve the lowest 10 and the highest 10, leaving the user with 236 tasks of priorities in the range (10-246).
34
CPU loading
Though an idle task does nothing, we can use it to determine the CPU loading the average utilization ratio of the CPU. This can be done by making the idle task writing the system clock in some memory location whenever it gets scheduled. Is an ISR also a task? No. A task is a standalone executable entity. An ISR is a routine that is called by system in response to an interrupt event. But some new RTOSes model ISR as high priority threads.
35
Process
A Process is a program or part of it, in execution. Multiple instances of the same program can execute simultaneously. A process needs various system resources like CPU for executing the process, memory for storing the code corresponding to the process and associated variables, I/O devices for information exchange, etc. A process is sequential in execution.
37
Structure of a process
The concept of Process leads to concurrent execution of tasks and the efficient utilization of the CPU and other system resources. A process mimics a processor in properties and holds a set of registers, process status, a Program Counter (PC) to point to the next executable instruction of the process, a stack for holding the local variables associated with the process and the code corresponding to the process.
38
39
Virtual Processor
A process which inherits all the properties of the CPU can be considered as a virtual processor, awaiting its turn to have its properties switched into the physical processor. When the process gets its turn, its registers and the program counter register becomes mapped to the physical registers of the CPU. The memory occupied by the process is segmented into 3 regions, namely, Stack memory, Data Memory and Code memory.
40
Virtual processor
The stack memory holds all temporary data such as variables local to the process. Data memory holds all the global data for the process. The code memory contains the program code corresponding to the process. On loading a process into the main memory, a specific area of memory is allocated for the process.
41
42
Process Management
Process management deals with the creation of a process, setting up the memory space for the process, loading the processs code into the memory space, allocating system resources, setting up a Process Control Block for the process and process termination / deletion.
43
Threads
A thread is the primitive that can execute code. A thread is a single sequential flow of control within a process. Thread is also known as light weight process. A process can have many threads of execution. Different threads, which are part of a process, share the same address space; Meaning they share the data memory, code memory and heap memory area. Threads maintain their own thread status (CPU register values), Program Counter (PC) and stack.
44
45
Multithreading
A process / task in embedded application may be a complex or lengthy one and it may contain various sub operations like getting input form I/O devices connected to the processor, performing some internal calculations / operations, updating some I/O devices etc. If all the sub functions of a task are executed in sequence, the CPU utilization may not be efficient. For example, if the process is waiting for a user input, the CPU enters the wait state for the event, and the process execution also enters a wait state.
46
Multithreading
Instead of this single sequential execution of the whole process, if the task / process is split into different threads carrying out the different sub functionalities of the process, the CPU can be effectively utilized and when the thread corresponding to the I/O operation enters the wait state, another thread which do not require the I/O event for their operation can be switched into execution. This leads to speedy execution of the process and the efficient utilization of the processor time and resources. The multithreaded architecture of a process can be visualized with the thread-process diagram as shown below.
47
48
Advantages of Multithreading
If the process is split into multiple threads, which executes a portion of the process, there will be a main thread and rest of the threads will be created within the main thread. The advantages of multithreading are: Better memory utilization. Multiple threads of the same process share the address space for data memory. This also reduces the complexity of inter thread communication since variables can be shared across the threads. Since the process is split into different threads, when one thread enters a wait state, the CPU can be utilized by other threads of the process that do not require the event, while the other thread is waiting, for processing. This speeds up the execution of the process. Efficient CPU utilization. The CPU is engaged all time.
49
50
Context switching
In a multitasking environment, when task / process switching happens, the virtual processor gets its properties converted into that of the physical processor. The switching of the virtual processor to physical processor is controlled by the scheduler of the OS kernel. During CPU switching, current context of execution are saved and used later when the CPU executes the process again. This is known as context switching. The act of saving the context is called as Context Saving. The process of retrieving the saved context is called as Context Retrieval.
52
Toss Juggling
The skilful object manipulation game is a real world example for multitasking illusion. The juggler uses a number of objects (balls, rings, etc) and throws them up and catches them. At any point of time, he throws only one ball and catches only one per hand. However, the speed at which he is switching the balls for throwing and catching creates the illusion, he is throwing and catching multiple balls to spectators.
53
Co-operative Multitasking
There are various types of multitasking existing in the operating systems context. Co-operative Multitasking It is the most primitive form of multitasking in which a task/process gets a chance to execute only when the currently executing task / process voluntarily relinquishes the CPU. Here any task / process can hold the CPU as much time as it wants. It involves the mercy of the tasks for getting the CPU time for execution, it is known as co-operative multitasking. If the currently executing task is non-cooperative, the other tasks may have to wait for a long time to get the CPU.
54
Preemptive multitasking
It ensures that every task / process gets a chance to execute. When and how much time a process gets is dependent on the implementation of the preemptive scheduling. Here the currently running task/ process is preempted to give a chance to other tasks / processes to execute. The preemption of task may be based on time slots or task / process priority.
55
Non-preemptive multitasking
Here, the process / task which is currently given the CPU time, is allowed to execute until it terminates or enters the Blocked / Wait state, waiting for an I/O system resource. The co-operative and non-preemptive multitasking differs in their behavior when they are in the Blocked / Wait state. In the co-operative multitasking, the currently executing task / process need not relinquish the CPU when it enters the Blocked / Wait state, waiting for an I/O, or a shared resource access or an event to occur whereas in non-preemptive mutli tasking the currently executing task relinquishes the CPU when it waits for an I/O or system resource or an event to occur.
56
Scheduler
There should be some mechanism in place to share the CPU among the different tasks and to decide which process / task is to be executed at a given point of time. Determining which task / process is to be executed at a given point of time is known as task / process scheduling. The scheduling polices are implemented in an algorithm and it is run by the kernel as a service. The kernel service / application which implements the scheduling algorithm, is known as Scheduler.
57
59
Time slicing
Here the CPU time is shared between all the tasks. Each task gets a fraction of CPU time. There is no notion of priority here. This scheduling is also known as round robin scheduling. It is not used in its original form. It can be used in conjunction with pre-emptive scheduling. In a pre-emptive system, if two or more tasks have same priority, we can make the scheduler use time slicing for those tasks with the same priority. Pros: No need of complex analysis of the system. This kind of kernel is easy to implement. The pre-emption time of a task is deterministic ie if a task is pre-empted, we will know exactly the time after which the task will be scheduled (if the number of tasks in the system do not vary in time). Cons: This is a very rigid scheduling policy ie there is no 63 notion of priority.
Fairness Scheduling
Here every task is given an opportunity to execute. Unlike pre-emptive scheduling, in which a lower priority task may not get an opportunity to execute, here every task will be given a fair chance to execute. Though some kind of priority mechanism could be incorporated here, it is not strict. Priority of a task, which has not executed for some period will gradually be increased by the RTOS and will finally get a chance to execute.
64
65
Non-preemptive Scheduling
Here the currently executing task / process is allowed to run until it terminates or enters the wait state waiting for an I/O or system resource. The various types of nonpreemptive scheduling algorithms are: First-Come-First Server (FCFS) / FIFO scheduling Here the algorithm allocated CPU time to the processes based on the order in which they enter the Ready queue. The first entered process is serviced first. It is same as any real world application where queue systems are used. Eg Ticketing reservation system where people need to stand in a queue and the first person standing in the queue is serviced first. FCFS is also known as First In First Out (FIFO).
66
Drawback of FCFS
The major drawback here is that it favors monopoly of process. A process, which does not contain any I/O operation, continues it execution until it finishes its task. If the process contains any I/O operation, the CPU is relinquished by the process. In general, FCFS favors CPU bound processes and I/O bound processes may have to wait until the completion of the CPU bound process, if the currently executing process is a CPU bound process. This leads to poor device utilization. The average waiting time is not minimal for FCFS scheduling algorithm.
67
LCFS / LIFO
The Last Come First Served scheduling algorithm also allocates CPU time to the processes based on the order in which they are entered in the Ready state queue. The last entered process is serviced first. LCFS scheduling is also known as LIFO where the process, which is put last into the Ready queue is serviced first. It is also not optimal and possesses the same drawback as that of FCFS algorithm.
68
Drawback of SJF
The average waiting time for a given set of process is minimal in SJF scheduling and so it is optimal compared to other non-preemptive scheduling like FCFS. The main drawback of SJF algorithm is that a process whose estimated execution completion time is high may not get a chance to execute if more and more processes with least estimated execution time enters Ready queue before the process with longest estimated execution time started its execution (in pre-emptive SJF). This condition is known as Starvation. Another drawback of SJF is that it is difficult to know in advance the next shortest process in the Ready queue for scheduling since new processes with different estimated execution time keep entering the Ready queue at any point of time.
70
Priority in Windows CE
Another way of priority assigning is associating a priority to the task / process at the time of creation of the task / process. Windows CE supports 256 levels or priority, while creating a task. Here 0 indicates highest priority and 255 indicates the lowest priority. The non-preemptive priority based scheduler sorts the Ready state queue based on priority and picks the process with the highest level of priority for execution.
72
Aging
Similar to SJF scheduling algorithm, non-preemptive priority based algorithm also possess the drawback of Starvation where a process whose priority is low may not get a chance to execute if more and more processes with higher priorities enter the Ready queue before the process with lower priority started its execution. Starvation can be tackled in priority based nonpreemptive scheduling by dynamically raising the priority of the low priority task which is under starvation. This technique is known as Aging.
73
Preemptive Scheduling
In preemptive scheduling, every task in the Ready state gets a chance to execute. When and how often each process gets a chance to execute (gets the CPU time) is dependent on the type of preemptive scheduling algorithm used for scheduling the processes. Here the scheduler can pre-empt (stop temporarily) the currently executing task and select another task from the Ready queue for execution. When to pre-empt a task and which task is to be picked up from the Ready queue for execution after preempting the current task is purely dependent on the scheduling algorithm. A task which is preempted by the scheduler is moved to the Ready queue. The act of moving a Running process into the Ready queue by the scheduler, without the processes requesting for it is known as Preemption. Two important approaches used in preemptive scheduling are 74 time-based and priority based preemption.
RR drawbacks
Once each process in the Ready queue is executed for the pre-defined time period, the scheduler comes back and picks the first process in the Ready queue again for execution. The sequence is repeated. Round Robin scheduling is similar to FCFS scheduling and the only difference is that a time slice based preemption is added to switch the execution between the processes in the Ready queue. The Ready queue can be considered as a circular queue in which the scheduler picks up the first process for execution and moves to the next till the end of the queue and then comes back to the beginning of the queue to pick up the first process.
78
81
Task Synchronization
So far we talked about many tasks executing in the RTOS. In all but trivial systems, these tasks need to interact with each other. ie they must synchronize and communicate with each other. Let us explain this with a real-time example. When the tasks are independent ie there is no communication between the tasks, they do not share any resources between them. This can be compared with two roads that run parallel to each other and hence do not meet.
82
Task synchronization
Vehicles can ply on these roads safely without colliding with ones in the parallel road. But the case becomes difficult when we have two intersecting roads. Here we need an explicit mechanism like a traffic signal to make sure that the vehicles ply without getting into any mishaps. This situation is different, because, there is a shared region between the roads. So the traffic on the two roads need explicit synchronization. The traffic signal is needed only at the region of intersection. There is no need for this synchronization either before or after this region. 83
Mutex
The solution to this problem is that one of the tasks can acquire the printer resource, use it and then release it. To implement this solution, we need to use a mutex short name for Mutual Exclusion. It is a mechanism to exclude other tasks to use a resource when a specific task has acquired it. For example, task A can be coded as: // Task A code // . Mutex_acquire (printer_mutex); print (1); print (2); print (3) ; mutex_release (printer_mutex) ; 85
More on mutex
Similarly, task B can be coded as : // Task B code // Mutex_acquire (printer_mutex); print (A); print (B) ; print (C) ; mutex_release (printer_mutex) ; At any point of time if both the tasks want to use the printer, they first try to acquire the mutex. Since, we are considering only a single processor model, the task, which makes the first attempt will acquire it.
86
Mutex
// Task B code // mutex_acquire (printer_mutex); --- Blocked here print (A); print (B); The task B will be blocked now. Ie we say B is blocked on resource. Since task B is blocked, task A gets to resume again and completes its printing. It then releases the mutex. Now, task B can resume and continue with its printing. We should remember that if task B is a higher priority task, the execution would shift to task B immediately after task A releases the mutex.
88
More on mutex
Consider the following code of task A: // print (3); mutex_release (printer_mutex); my_foo( ); //some other function called from task A In a truly pre-emptive system, the execution will be transferred to task B immediately after execution of mutex_release. Statement my_foo will be executed only after task A is scheduled again.
89
Race conditions
Mutexes are also required when two tasks share data using global variables. Let us consider a case where two tasks are writing into contiguous memory locations and another task uses these values produced by the tasks. In concurrent programming language, the first two tasks that generate the values are called producers and the one that uses these values is called the consumer. A task can be a producer and a consumer at the same time.
91
Race conditions
Let us use a pointer ptr to write into the list. To write, we can use *prt = 8; Assume that ptr points to memory location 0x4000. ptr is a global variable and both the tasks P1 and P2 can access it. Consider the following situation: P1 reads the value of ptr. After P1 reads the value of ptr from the memory, it gets pre-empted by P2 that writes say ptr = 12; Now, the contents of memory location 0x4000 will be changed to 12.
92
Race conditions
Before P2 increments the pointer, task P1 is scheduled again. Now the contents of P2 are lost when P1 writes 8 into same memory location. This condition where data consistency is lost because of lack of synchronization of the component tasks of a system is called a race condition. This belongs to one of the worst categories of bugs nonrepeatable bugs. To avoid this problem, shared global variables must be used only with synchronization.
93
Priority inversion
It is one of the issues that must be addressed during the analysis and design of realtime systems. In a pre-emptive system, at any point of time, only the task with the highest priority executes. But due to some reasons, if a higher priority task is blocked because of some lower priority task, then a Priority Inversion is said to have occurred. It can happen in two ways: Bounded priority inversion and Unbounded priority inversion.
94
Example
Consider an RTOS where 1 is the highest priority. Let 10 tasks, with priorities 1-10 execute in the system. Let us consider that the tasks with priority 2 and 7 share a resource R. Let T7 (lower priority) acquire the shared resource R and get pre-empted by task T5 before releasing it. Later, let T2 get scheduled and get blocked for the resource R. Immediately priority of T7 is boosted to 2. Now, T7 with boosted priority will be able to complete its critical section and release the mutex. Once the mutex is released, its previous priority is restored so that the actual high priority task can continue its execution and enter its critical section.
101
104