180 likes | 362 Views
Semaphores and Mailboxes. B. Ramamurthy. 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
E N D
Semaphores and Mailboxes B. Ramamurthy
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
Semaphores in exinu • #include <kernel.h> • #include <queue.h> /**< queue.h must define # of sem queues */ • /* Semaphore state definitions */ • #define SFREE 0x01 /**< this semaphore is free */ • #define SUSED 0x02 /**< this semaphore is used */ • /* type definition of "semaphore" */ • typedefulong semaphore; • /* Semaphore table entry */ • struct sentry • { • char state; /**< the state SFREE or SUSED */ • short count; /**< count for this semaphore */ • queue queue; /**< requires q.h. */ • };
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); • syscallsignaln(semaphore, short); • semaphore newsem(short); • syscallfreesem(semaphore); • syscallscount(semaphore);
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); • }
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; }
Semaphore: wait(…) • /** • * wait - make current process wait on a semaphore • * @paramsem semaphore for which to wait • * @return OK on success, SYSERR on failure • */ • syscall wait(semaphore sem) • { • irqmaskps; • 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*/
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; • }
Semaphore: signal() • /*signal - signal a semaphore, releasing one waiting process, and block • * @paramsem id of semaphore to signal • * @return OK on success, SYSERR on failure • */ • syscall signal(semaphore sem) • { • irqmaskps; • 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; • }
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.
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);
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;
Problem 1 Task 1 Task 2 Counter1 Task 3
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);
UART and UART Drivers Inside the system Outside Actual UART Buffer (input, output) Registers (Control, status) UART Driver
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