1 / 16

A very simple kernel

A very simple kernel. ITV Multiprogramming and Real-Time Programs Anders P. Ravn May 2009. A kernel specification. /* kernel.h Interface to a lightweight kernel that implements concurrent processes and a release primitive `pause'. Anders P. Ravn, DTU, Denmark 24 April 1998

wendi
Download Presentation

A very simple kernel

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. A very simple kernel ITV Multiprogramming and Real-Time Programs Anders P. Ravn May 2009

  2. A kernel specification /* kernel.h Interface to a lightweight kernel that implements concurrent processes and a release primitive `pause'. Anders P. Ravn, DTU, Denmark 24 April 1998 apr@it.dtu.dk */ typedef void (*Program)(void); /* A program text is a function without parameters*/ typedef void * Thread; /* identifier for a process */ extern Thread create(Program p,unsigned int stacksize); /* creates a process with a stackof the specified size and starts it executing theprogram. If there is insufficientmemory, the result is NULL */ extern void pause(void); /* release the processor */

  3. Multiprogramming #include ”kernel.h” void process() { /* do something */ pause(); /* do something */ } void main() { Thread p1, p2; p1 = create(&process,2000); /* p1 is started */ p2 = create(&process,1000); /* p2 is started */ /* the kernel will see to it that main is left when both p1 and p2 has exited */ }

  4. A kernel implementation I typedef unsigned long Register; typedef struct x {struct x* next; Register esp;} Threaddescriptor; static Threaddescriptor* ready; /* queue of threads linked cyclically; ready points to last, the first is current */ #define current ready->next ready: current esp1 esp2 esp3

  5. A kernel implementation II void pause() { Register sp; __asm__(”pushal movl %%esp,%sp"); /* sp -> |saved registers ... | eip return from call */ DISABLE; /* scheduling */ current->esp = sp; ready = current; sp = current->esp; __asm__(" movl %sp,%%esp popal" ); ENABLE; } stack1 stack2 ready: current esp1 esp2 esp3

  6. A kernel implementation III pause: pushl %ebp movl %esp,%ebp pushal movl %esp,%ecx sp = esp movl ready,%eax movl (%eax),%edx current->esp movl %ecx,4(%edx) = sp movl %edx,ready ready = current movl (%edx),%edx movl 4(%edx),%ecx sp = current->esp movl %ecx,%esp popal leave ret

  7. A kernel implementation IV pause: pushal movl ready,%eax movl (%eax),%edx current->esp movl %esp,4(%edx) = esp movl %edx,ready ready = current movl (%edx),%edx movl 4(%edx),%esp esp = current->esp popal ret

  8. Critical regions void enter_crit(Gate g) /* enter critical region */ {}; void leave_crit(Gate g) /* leave critical region */ {}; void init_crit(Gate g) {}; extern void await(Gate g, Boolean *b) /* wait in a critical region for a condition b to become true */ {while (!*b) { // leave_crit pause(); // enter crit } };

  9. Stop Process void stop(void) {/* called implicitly when a process exits its program Entry: esp -> | ... | dummy must not be used ebp -> | old ebp | <- stack before entry to stop */ Register dummy; Proc thisp; Register cursp; thisp = current; if (thisp == initproc) {/* set up for final exit from multiprogramming esp -> | saved registers | ... ebp = saved ebp saved ebp -> | final.oldebp ebp -> | final.eip | ... */ __asm__(" pushal movl %%esp,%0" : "=g" (cursp) ); ((SavedRegisters *)cursp)->ebp = (Register)ebp; initproc->esp = cursp; *(ebp+1) = final.eip; *ebp = final.oldebp; }; DISABLE /* remove current process */ #if TEST printf("Stop process %x\n",current); #endif current = thisp->next; if (head == thisp) {head = NULL; #if TEST printf("Stop kernel\n"); #endif /* exit for final program, prepared above */ cursp = initproc->esp;} else /* activate current */ cursp = current->esp; __asm__(" movl %0,%%esp popal" : : "g" (cursp) ); ENABLE return;};

  10. Stop Process II thisp = current; if (thisp == initproc) {/* set up for final exit from multiprogramming esp -> | saved registers | ... ebp = saved ebp saved ebp -> | final.oldebp ebp -> | final.eip | ... */ __asm__(" pushal movl %%esp,%0" : "=g" (cursp) ); ((SavedRegisters *)cursp)->ebp = (Register)ebp; initproc->esp = cursp; *(ebp+1) = final.eip; *ebp = final.oldebp; };

  11. Stop Process III DISABLE /* remove current process */ current = thisp->next; if (head == thisp) {head = NULL; /* exit for final program, prepared above */ cursp = initproc->esp;} else /* activate current */ cursp = current->esp; __asm__(" movl %0,%%esp popal" : : "g" (cursp) ); ENABLE return;};

  12. Create Process #define descriptor sizeof(Processdescriptor) #define overhead descriptor +sizeof(SavedRegisters) +2*sizeof(ReturnInfo) #define stopentry (Register) &stop Thread create(Program p,unsigned int stacksize) {Proc newp; Register *sp, bp; if ((head == NULL) && ((newp = (Proc)malloc(descriptor)) != NULL) ) { /* At this point, the process state is as follows: esp -> | ... ... ebp -> | old ebp old frame pointer | eip return from call of create ... old ebp -> | old2 ebp | eip return from call of initial process | ... stack of caller */

  13. Create Process II /* save call of initial process in "final" initialize return to call "stop" on final exit */ __asm__(" movl %%ebp,%0" : "=g" (ebp) ); (Register) ebp = *ebp; final.oldebp = *ebp; final.eip = *(ebp+1); *(ebp+1) = stopentry; /* save identity of initial process */ initproc = newp; DISABLE /* enter process descriptor in queue */ head = newp->next = newp; ENABLE };

  14. Create Process III if ( ( newp = (Proc)malloc(stacksize+overhead)) != NULL) { /* create new process The state when activated shall be: newp -> | next ProcessDescriptor | sp ... sp-> | saved registers fp -> | 0 sfp-> | p entry return address when activated | stopentry exit address | <- newp+stacksize+overhead immediately when p is entered, we have: ebp = 0 esp-> | stopentry exit address | <- newp+stacksize+overhead */ sp = (Register*)((unsigned int)newp+stacksize+overhead); *(--sp) = stopentry; *(--sp) = (Register)p; *(--sp) = 0; bp = (Register)sp; (Register)sp -= sizeof(SavedRegisters); ((SavedRegisters *)sp)->old_esp = ((SavedRegisters *)sp)->ebp = bp; newp->esp = (Register)sp; DISABLE newp->next = current; current = newp; head = newp; ENABLE #if TEST printf("Created new process\nhead %x %x %x %x esp %x ebp %x\n", head, head->next, (head->next)->next, ((head->next)->next)->next,sp,bp); #endif (Register)sp = bp; #if TEST printf("-> ... %x %x %x\n", *sp,*(sp+1),*(sp+2)); #endif }; return (Thread) newp; };

  15. Create Process IV sp = (Register*)((unsigned int)newp+stacksize+overhead); *(--sp) = stopentry; *(--sp) = (Register)p; *(--sp) = 0; bp = (Register)sp; (Register)sp -= sizeof(SavedRegisters); ((SavedRegisters *)sp)->old_esp = ((SavedRegisters *)sp)->ebp = bp; newp->esp = (Register)sp; DISABLE newp->next = current; current = newp; head = newp; ENABLE (Register)sp = bp; }; return (Thread) newp; };

  16. Create Process #define descriptor sizeof(Processdescriptor) #define overhead descriptor+sizeof(SavedRegisters)+2*sizeof(ReturnInfo) #define stopentry (Register) &stop Thread create(Program p,unsigned int stacksize) {Proc newp; Register *sp, bp; if ((head == NULL) && ((newp = (Proc)malloc(descriptor)) != NULL) ) { /* At this point, the process state is as follows: esp -> | ... ... ebp -> | old ebp old frame pointer | eip return from call of create ... old ebp -> | old2 ebp | eip return from call of initial process | ... stack of caller */ /* save call of initial process in "final" initialize return to call "stop" on final exit */ __asm__(" movl %%ebp,%0" : "=g" (ebp) ); (Register) ebp = *ebp; final.oldebp = *ebp; final.eip = *(ebp+1); *(ebp+1) = stopentry; /* save identity of initial process */ initproc = newp; DISABLE /* enter process descriptor in queue */ head = newp->next = newp; ENABLE #if TEST printf("Initial process created\nhead %x current %x ebp %x final %x %x\n", head,current, ebp, final.oldebp, final.eip); #endif }; if ( ( newp = (Proc)malloc(stacksize+overhead)) != NULL) { /* create new process The state when activated shall be: newp -> | next ProcessDescriptor | sp ... sp-> | saved registers fp -> | 0 sfp-> | p entry return address when activated | stopentry exit address | <- newp+stacksize+overhead immediately when p is entered, we have: ebp = 0 esp-> | stopentry exit address | <- newp+stacksize+overhead */ sp = (Register*)((unsigned int)newp +stacksize + overhead); *(--sp) = stopentry; *(--sp) = (Register)p; *(--sp) = 0; bp = (Register)sp; (Register)sp -= sizeof(SavedRegisters); ((SavedRegisters *)sp)->old_esp = ((SavedRegisters *)sp)->ebp = bp; newp->esp = (Register)sp; DISABLE newp->next = current; current = newp; head = newp; ENABLE #if TEST printf("Created new process\nhead %x %x %x %x esp %x ebp %x\n", head, head->next, (head->next)->next, ((head->next)->next)->next,sp,bp); #endif (Register)sp = bp; #if TEST printf("-> ... %x %x %x\n", *sp,*(sp+1),*(sp+2)); #endif }; return (Thread) newp; };

More Related