Realtime System Fundamentals : Scheduling B. Ramamurthy 5/28/2016

advertisement
Realtime System Fundamentals :
Scheduling
B. Ramamurthy
Page 1
5/28/2016
Realtime scheduling
•
We discussed realtime system scheduling:
– Earliest deadline scheduling (EDS)
• Starting deadline
• Completion deadline
• Dynamic priority scheduling
– Rate monotonic scheduling (RMS)
• Periodic tasks are prioritized by the frequency of repetition
(high priority to tasks with shorter periods)
• Preemptive scheduling
• Fixed priority scheduling
• Schedulability according to RMS
Σ(Ci/Ti) <= n(21/n-1)
– Cyclic executives (pre-scheduled) (later: next class?)
• Concepts of cycle, slot and frame
• Repeated execution
• times
Page 2
5/28/2016
Critical sections and Semaphores
• When multiples tasks are executing there
may be sections where only one task could
execute at a given time: critical region or
critical section
• There may be resources which can be
accessed only be one of the processes:
critical resource
• Semaphores can be used to ensure mutual
exclusion to critical sections and critical
resources
Page 3
5/28/2016
Semaphores
See semaphore.h of xinu
Page 4
5/28/2016
Semaphores in exinu
•
•
#include <kernel.h>
#include <queue.h>
•
•
•
/* Semaphore state definitions */
#define SFREE 0x01
/**< this semaphore is free
#define SUSED 0x02
/**< this semaphore is used
•
•
/* type definition of "semaphore" */
typedef ulong semaphore;
•
•
•
•
•
•
•
/* Semaphore table entry */
struct sentry
{
char state;
/**< the state SFREE or SUSED
short count;
/**< count for this semaphore
queue queue;
/**< requires q.h.
};
5
/**< queue.h must define # of sem queues */
*/
*/
*/
*/
*/
Semaphores in exinu (contd.)
•
extern struct sentry semtab[];
•
•
•
•
•
•
/**
* isbadsem - check validity of reqested semaphore id and state
* @param s id number to test; NSEM is declared to be 100 in kernel.h
A system typically has a predetermined limited number of semaphores
*/
#define isbadsem(s) (((ushort)(s) >= NSEM) || (SFREE == semtab[s].state))
•
•
•
•
•
•
•
/* Semaphore function declarations */
syscall wait(semaphore);
syscall signal(semaphore);
syscall signaln(semaphore, short);
semaphore newsem(short);
syscall freesem(semaphore);
syscall scount(semaphore);
6
Definition of Semaphores
functions
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
static semaphore allocsem(void);
/**
* newsem - allocate and initialize a new semaphore.
* @param count - number of resources available without waiting.
* example: count = 1 for mutual exclusion lock
* @return new semaphore id on success, SYSERR on failure
*/
semaphore newsem(short count)
{
irqmask ps;
semaphore sem;
ps = disable();
/* disable interrupts */
sem = allocsem();
/* request new semaphore */
if ( sem != SYSERR && count >= 0 ) /* safety check
*/
{
semtab[sem].count = count;
/* initialize count
*/
restore(ps);
/* restore interrupts */
return sem;
/* return semaphore id */
}
restore(ps);
7
}
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Semaphore: newsem contd.
/**
* allocsem - allocate an unused semaphore and return its index.
* Scan the global semaphore table for a free entry, mark the entry
* used, and return the new semaphore
* @return available semaphore id on success, SYSERR on failure
*/
static semaphore allocsem(void)
{
int i = 0;
while(i < NSEM)
/* loop through semaphore table */
{
/* to find SFREE semaphore
*/
if( semtab[i].state == SFREE )
{
semtab[i].state = SUSED;
return i;
}
i++;
}
8
return SYSERR; }
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
Semaphore: wait(…)
/**
* wait - make current process wait on a semaphore
* @param sem semaphore for which to wait
* @return OK on success, SYSERR on failure
*/
syscall wait(semaphore sem)
{
irqmask ps;
struct sentry *psem;
pcb *ppcb;
ps = disable();
/* disable interrupts
*/
if ( isbadsem(sem) )
/* safety check
*/
{
restore(ps);
return SYSERR;
}
ppcb = &proctab[currpid]; /* retrieve pcb from process table
*/
psem = &semtab[sem];
/* retrieve semaphore entry
*/
if( --(psem->count) < 0 ) /* if requested resource is unavailable */
{
ppcb->state = PRWAIT; /* set process state to PRWAIT*/
9
Semaphore: wait()
•
•
•
•
•
•
•
ppcb->sem = sem; /* record semaphore id in pcb */
enqueue(currpid, psem->queue);
resched();
/* place in wait queue and reschedule */
}
restore(ps);
/* restore interrupts
*/
return OK;
}
10
Semaphore: signal()
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
/*signal - signal a semaphore, releasing one waiting process, and block
* @param sem id of semaphore to signal
* @return OK on success, SYSERR on failure
*/
syscall signal(semaphore sem)
{
irqmask ps;
register struct sentry *psem;
}
11
ps = disable();
/* disable interrupts
*/
if ( isbadsem(sem) )
/* safety check
*/
{
restore(ps);
return SYSERR;
}
psem = &semtab[sem];
/* retrieve semaphore entry
*/
if ( (psem->count++) < 0 )
/* release one process from wait queue */
{ ready(dequeue(psem->queue), RESCHED_YES); }
restore(ps);
/* restore interrupts
*/
return OK;
Semaphore: usage
• Problem 1:
– Create 3 tasks that each sleep for a random time
and update a counter.
– Counter is the critical resources shared among the
processes.
– Only one task can update the counter at a time so
that counter value is correct.
• Problem 2:
– Create 3 tasks; task 1 updates the counter by 1
and then signal task 2 that updates the counter by
2 and then signals task 3 to update the counter by
3.
12
Problem 1
#include <..>
//declare semaphore
semaphore mutex1 = newsem(1);
int counter = 0;
//declare functions: proc1,proc1, proc3
ready(create((void *)proc1, INITSTK, INITPRIO,
“PROC1",, 2, 0, NULL), RESCHED_NO);
ready(create((void *)proc2, INITSTK, INITPRIO,
“PROC2",, 2, 0, NULL), RESCHED_NO);
ready(create((void *)proc3, INITSTK, INITPRIO,
“PROC3",, 2, 0, NULL), RESCHED_NO);
13
Problem 1: multi-tasks
void proc1()
{ while (1) {
sleep (rand()%10);
wait(mutex1);
counter++;
signal(mutex1);
}}
void proc2()
{ while (1) {
sleep (rand()%10);
wait(mutex1);
counter++;
signal(mutex1);
}}
//similarly proc3
Simulation of this;
14
Problem 1
Task 1
Counter1
Task 3
15
Task 2
Problem 2
semaphore synch12 = newsem(0);
semaphore synch23 = newsem(0);
semaphore synch31 = newsem(0);
ready(create((void *)proc1, INITSTK, INITPRIO,
“PROC1",, 2, 0, NULL), RESCHED_NO);
ready(create((void *)proc2, INITSTK, INITPRIO,
“PROC2",, 2, 0, NULL), RESCHED_NO);
ready(create((void *)proc3, INITSTK, INITPRIO,
“PROC3",, 2, 0, NULL), RESCHED_NO);
signal(synch31);
16
Task flow
void proc1()
void proc2()
void proc3()
•{
•while (1) {
•sleep (rand()%10);
•wait(synch31);
•counter++;
•signal(synch12);
•} }
•{
•while (1) {
•sleep (rand()%10);
•wait(synch12);
•counter++;
•signal(synch23);
•} }
•{
•while (1) {
•sleep(rand()%10);
•wait(synch23);
•counter++;
•signal(synch31); } }
17
Priority Inversion
• When we allow concurrent task to
execute and with semaphore and
mailboxes and other synchronization
primitives, it is possible that a low
priority task may come to block a high
priority task. This situation is known as
priority inversion.
Page 18
5/28/2016
Priority inversion
(Priority: t1>t2>t3)
blocked
task1
task2
Critical
section
task3
0
1
Page 19
2
3
4
5
6
7
8
time
9
10
5/28/2016
Problem: Priority inversion
Solution1: Priority Inheritance
blocked
task1
Task 2 delayed
task2
Critical
section
task3
0
1
Page 20
2
Priority of t1
inherited
Priority reverted
To t3
3
4
5
6
7
8
time
9
10
5/28/2016
Solution2:Priority Ceiling
Protocol
Acquire S1
CS
Used
by
Priority
Ceiling
S1
t1,t2
P(t1)
S2
t1,t2,t3
P(t1)
S3
t3
P(t3)
Release S1
task1
Attempt to
Acquire S1
No way
task2
Acquire S1
Acquire S2
Release S2
Critical
section
task3
0
1
Page 21
2
Acquire S2
3
4
5
6
7
8
time
9
10
5/28/2016
Download