Semaphores and Mailboxes B. Ramamurthy 1 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 2 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. }; /**< queue.h must define # of sem queues */ */ */ */ */ */ 3 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); 4 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); } 5 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++; } return SYSERR; } 6 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*/ 7 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; } 8 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; 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; } 9 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. 10 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); 11 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; 12 Problem 1 Task 1 Counter1 Task 2 Task 3 13 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); 14 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); } } 15 UART and UART Drivers Inside the system UART Driver Outside Actual UART Buffer (input, output) Registers (Control, status) 16 Reverse Engineer UART read, write and intr (interrupt) Application : UARTRead : UARTIntr : UARTWrite : UART read(buf , 4) wait(isem) read bit by bit signal(isem) copy ibuf to application 17 UART Operation and code (contd.) • We will look at the sequence diagrams for other UART operations and read the code. • Lets look at initialize.c 18