Realtime System Fundamentals Scheduling and Prioritybased scheduling B
Realtime System Fundamentals : Scheduling and Priority-based scheduling B. Ramamurthy Page 1 1/26/2022
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 1/26/2022
Task State Diagram Task admitted New Resources allocated Ready rr t en v E cu c o Blocked Page 3 Dis pat c ed hed ; cpu allo cat ed Waiting for event k Tas Run 1/26/2022 exit
Resources & Critical Resources • Shared resources: need mutual • • • exclusion Tasks cooperating to complete a job Tasks contending to access a resource Tasks synchronizing Critical resources and critical region A important synchronization and mutual exclusion primitive / resource is “semaphore” Page 4 1/26/2022
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 5 1/26/2022
Semaphores See semaphore. h of xinu Page 6 1/26/2022
Semaphores in exinu • • #include <kernel. h> #include <queue. h> • • • /* Semaphore state definitions */ #define SFREE 0 x 01 /**< this semaphore is free #define SUSED 0 x 02 /**< 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; /**< requires q. h. }; 7 /**< 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 signaln(semaphore, short); semaphore newsem(short); syscall freesem(semaphore); syscall scount(semaphore); 8
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); 9 }
• • • • • 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++; } 10 return SYSERR; }
• • • • • • Semaphore: wait(…) /** * wait - make current process wait on a semaphore * @param 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*/ 11
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; } 12
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; } 13 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. 14
Problem 1 #include <. . > //declare semaphore mutex 1 = newsem(1); int counter = 0; //declare functions: proc 1, proc 3 ready(create((void *)proc 1, INITSTK, INITPRIO, “PROC 1", , 2, 0, NULL), RESCHED_NO); ready(create((void *)proc 2, INITSTK, INITPRIO, “PROC 2", , 2, 0, NULL), RESCHED_NO); ready(create((void *)proc 3, INITSTK, INITPRIO, “PROC 3", , 2, 0, NULL), RESCHED_NO); 15
Problem 1: multi-tasks void proc 1() { while (1) { sleep (rand()%10); wait(mutex 1); counter++; signal(mutex 1); }} void proc 2() { while (1) { sleep (rand()%10); wait(mutex 1); counter++; signal(mutex 1); }} //similarly proc 3 16
Problem 1 Task 1 Counter 1 Task 3 17 Task 2
Problem 2 semaphore synch 12 = newsem(0); semaphore synch 23 = newsem(0); semaphore synch 31 = newsem(0); ready(create((void *)proc 1, INITSTK, INITPRIO, “PROC 1", , 2, 0, NULL), RESCHED_NO); ready(create((void *)proc 2, INITSTK, INITPRIO, “PROC 2", , 2, 0, NULL), RESCHED_NO); ready(create((void *)proc 3, INITSTK, INITPRIO, “PROC 3", , 2, 0, NULL), RESCHED_NO); signal(synch 31); 18
Task flow void proc 1() void proc 2() void proc 3() • { • while (1) { • sleep (rand()%10); • wait(synch 31); • counter++; • signal(synch 12); • } } • { • while (1) { • sleep (rand()%10); • wait(synch 12); • counter++; • signal(synch 23); • } } • { • while (1) { • sleep(rand()%10); • wait(synch 23); • counter++; • signal(synch 31); } } 19
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 20 1/26/2022
Priority inversion (Priority: t 1>t 2>t 3) blocked task 1 task 2 Critical section task 3 0 1 Page 21 2 3 4 5 6 7 8 time 9 10 1/26/2022
Problem: Priority inversion Solution 1: Priority Inheritance blocked task 1 Task 2 delayed task 2 Critical section task 3 0 1 Page 22 2 Priority of t 1 inherited Priority reverted To t 3 3 4 5 6 7 8 time 9 10 1/26/2022
Solution 2: Priority Ceiling Protocol Acquire S 1 CS Used by Priority Ceiling S 1 t 1, t 2 P(t 1) S 2 t 1, t 2, t 3 P(t 1) S 3 t 3 P(t 3) Release S 1 task 1 Attempt to Acquire S 1 No way task 2 Acquire S 1 Acquire S 2 Release S 2 Critical section task 3 0 1 Page 23 2 Acquire S 2 3 4 5 6 7 8 time 9 10 1/26/2022
- Slides: 23