250 likes | 446 Views
Embedded Xinu Kernel Programming. bina@buffalo.edu Bina Ramamurthy. How to analyze the kernel code?. Review the Makefile to understand the various modules involved Cross compiling done by specifying appropriate compile option. In this case –march= mips
E N D
Embedded Xinu Kernel Programming bina@buffalo.edu Bina Ramamurthy Amrita-UB-MSES-2013-11
How to analyze the kernel code? Review the Makefile to understand the various modules involved Cross compiling done by specifying appropriate compile option. In this case –march=mips Another example : -march=athlon64 In general it defines various symbols; Various targets, dependencies, and commands Target: dependencies command1 command2 … Sometime commands are implied by the file extension of the dependencies Amrita-UB-MSES-2013-11
Include and lib directory Include directory All the header file… lets go through some of them clock.hgpio.hmemory.hproc.hshell.hstring.hvararg.h ctype.hinterrupt.hmips.hqueue.hstdio.htty.hxc.h device.hkernel.hplatform.hsemaphore.hstdlib.huart.h Load library: primarily c library Loader : usually written in assemble, responsible for loading the OS. Amrita-UB-MSES-2013-11
System Directory clockinit.cfreemem.cinitialize.ckprintf.cread.csend.cwrite.c clockintr.cfreesem.cinsert.cmain.cready.csignal.cxdone.c close.cgetc.cinsertd.cnewsem.creceive.csignaln.cxtrap.c control.cgetmem.cioerr.copen.cresched.csleep.c create.cgetpid.cionull.cputc.cscount.cwait.c devtable.cgetstk.ckill.cqueue.cseek.cwakeup.c Amrita-UB-MSES-2013-11
create(…) tid_typ create(void *procaddr, uintssize, int priority, char *name, intnargs, ...) • Creates a thread, similar to pthread_create. • Returns the thread ID. • Takes in the function to be executed, stack size, priority, name of the thread, number of arguments for the function, argument 1, argument 2, … • Reference link Amrita-UB-MSES-2013-11
ready(…) int ready(tid_typtid, boolresch) • Makes a thread (with thread ID == tid) eligible for CPU service. • Takes in the thread ID, and resch = {RESCHED_YES, RESCHED_NO} • Inserts the thread ID into the readylist, which is a FIFO queue. • Calls resched() if resch == RESCHED_YES. Reference link Amrita-UB-MSES-2013-11
resched(…) intresched(void) • Reschedules processor to the highest priority-ready thread. • Dequeues the thread with the highest priority from the readylist and changes its state to THRCURR. • This thread will run next. • Reference link Amrita-UB-MSES-2013-11
yield(…) intyield(void) • A safe way of calling resched() • First disables the interrupt request mask and calls resched(). • Reference link Amrita-UB-MSES-2013-11
semaphore.h • Header file: sempaphore.h • Usage: semaphore s1; // sem_t s1; s1 = semcreate(1); // sem_init(&s1, 0, 1); wait(s1); // sem_wait(&s1); signal(s1); // sem_post(&s1); • Check out test/test_semaphore.c Amrita-UB-MSES-2013-11
sleep(…) syscall sleep(uintms) • Put the calling thread to sleep for ms milliseconds. • Reference link Amrita-UB-MSES-2013-11
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” Amrita-UB-MSES-2013-11
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 Amrita-UB-MSES-2013-11
Semaphores See semaphore.h of xinu Amrita-UB-MSES-2013-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; } Amrita-UB-MSES-2013-11
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; • } Amrita-UB-MSES-2013-11
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. Amrita-UB-MSES-2013-11
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); Amrita-UB-MSES-2013-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 Amrita-UB-MSES-2013-11
Problem 1 Task 1 Task 2 Counter1 Task 3 Amrita-UB-MSES-2013-11
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); Amrita-UB-MSES-2013-11
Task flow Amrita-UB-MSES-2013-11
Shell Shell provides the interface to the kernel from the nexos.cse.buffalo.edu “front-end” server The wrt54gl are called “back-end” servers Look at the shell commands : shell.h, shell.c Each of the command is implemented in xsh_name.c Lets review some of them. Amrita-UB-MSES-2013-11
TTY device The specification for tty is in include in tty.h The function in tty.h are defined in the directory tty devcallttyInit(device *); devcallttyOpen(device *, va_list); devcallttyClose(device *); devcallttyRead(device *, char *, ushort); devcallttyWrite(device *, uchar *, ushort); devcallttyGetChar(device *); devcallttyPutChar(device *, uchar); devcallttyControl(device *, uchar, uchar, uchar); Amrita-UB-MSES-2013-11
UART This is an abstraction of the actual device uart.h is in include devcalluartInit(device *); devcalluartRead(device *, unsigned char *, int); devcalluartWrite(device *, unsigned char *, int); devcalluartGetChar(device *); devcalluartPutChar(device *, unsigned char); devcalluartControl(device *, int, unsigned char, unsigned char); interrupt uartIntr(void); Amrita-UB-MSES-2013-11
Summary We looked the embedded xinu kernel. Read it again to get a better in-depth understanding of the kernel. Now we will capture the whole picture of all the hardware and software combined in a class diagram. Amrita-UB-MSES-2013-11