480 likes | 572 Views
Introduction. Chapter 8: Process Management What and Why swtch() Overview Data Structures Assembly Procedures Code Flow Chart Calling Functions sleep() expand(). Introduction (cont.). Chapter 11: Clock Interrupts clock() Overview Data Structures & Variables Related Functions
E N D
Introduction • Chapter 8: Process Management • What and Why • swtch() • Overview • Data Structures • Assembly Procedures • Code • Flow Chart • Calling Functions • sleep() • expand()
Introduction (cont.) • Chapter 11: Clock Interrupts • clock() • Overview • Data Structures & Variables • Related Functions • Code • Example • Flow Chart
Ch 8: Process Management • What is it? • Allocation of processor and memory to the various processes • Why do we need it? • Monopolization of resources • Optimization of processes
swtch() • Only means of switching processes • When is “swtch” called? • By a process • By “sleep” • Called by a process when it can no longer proceed • By a Kernel process • When returning from interrupts Ch 8: Process Management
Structures & Procedures • Data Structures utilized • proc • user • Assembly Procedures utilized • savu • sureg • retu • aretu Ch 8: Process Management
Data Structure (proc) struct proc { char p_pri; /* priority, negative is high */ int p_addr; /* address of swappableimage */ int p_wchan; /* event process is awaiting */ char p_stat; char p_flag; int p_size; /* size of swappableimage */ char p_cpu; /* cpu usage for scheduling */ char p_nice; /* nice for scheduling */ ⋮ } proc[NPROC]; Ch 8: Process Management
Data Structure (user) struct user { int u_rsav[2]; /* save r5,r6 when exchanging stacks */ int u_procp; /* pointer to proc structure */ int u_qsav[2]; /* label variable for quits & interrupts */ int u_ssav[2]; /* label variable for swapping */ ⋮ } u ; Ch 8: Process Management
Assembly Procedures • savu(u.u_rsav) • Stores the values of r5 and r6 to u.u_rsav • sureg( ) • Loads physical segmentation registers with values in user data structure • retu(p->p_addr) • Loads values of r5 and r6 from p->addr • Resets 7th kernel segmentation address register(pc) • aretu(p->p_addr) • Loads values of r5 and r6 from p->addr Ch 8: Process Management
savu() sureg() retu() aretu() Begin Flow Chart swtch() Ch 8: Process Management
swtch() 1 of 3 swtch() { static struct proc *p; register i, n; register struct proc *rp; if(p == NULL) p = &proc[0]; savu(u.u_rsav); retu(proc[0].p_addr); loop: runrun = 0; rp = p; p = NULL; n = 128; ⋮ Remember the stack of the caller. Switch to scheduler’s stack Ch 8: Process Management
swtch() 2 of 3 Search for the highest priority runnable process. i = NPROC; do { rp++; if(rp >= &proc[NPROC]) rp = &proc[0]; if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) { if(rp->p_pri < n) { p = rp; n = rp->p_pri; } } } while(--i); if(p == NULL) { p = rp; idle(); goto loop; } ⋮ If no process is runnable then idle. Ch 8: Process Management
swtch() 3 of 3 ⋮ rp = p; curpri = n; retu(rp->p_addr); sureg(); if(rp->p_flag&SSWAP) { rp->p_flag =& ~SSWAP; aretu(u.u_ssav); } return(1); } Switch to the stack of the new process and set up its segmentation registers. Ch 8: Process Management
Besides using traps, how else is swtch() called? traps Current Flow Chart swtch() savu() sureg() retu() aretu() Ch 8: Process Management
sleep() Channel to sleep on Priority to run with when awoken Finally, switch to the next process and end. If the process cannot be awoken by signals: Sleep Load next process End ⋮ swtch(); if(issig()) goto psig; } else { spl6(); rp->p_wchan = chan; rp->p_stat = SSLEEP; rp->p_pri = pri; spl0(); swtch(); } PS->integ = s; return; psig: aretu(u.u_qsav); } sleep(chan, pri) { register *rp, s; s = PS->integ; rp = u.u_procp; if(pri >= 0) { if(issig()) goto psig; spl6(); rp->p_wchan = chan; rp->p_stat = SWAIT; rp->p_pri = pri; spl0(); if(runin != 0) { runin = 0; wakeup(&runin); } ⋮ Processes with positive priorities can be awoken by signals. Return immediately if a signal exists. If the scheduler is waiting, wake it up. Ch 8: Process Management
sleep() Current Flow Chart traps swtch() savu() sureg() retu() aretu() Ch 8: Process Management
expand() Changes the size of the data and stack regions of the process expand(newsize) { int i, n; register *p, a1, a2; p = u.u_procp; n = p->p_size; p->p_size = newsize; a1 = p->p_addr; if(n >= newsize) { mfree(coremap, n-newsize, a1+newsize); return; } savu(u.u_rsav); a2 = malloc(coremap, newsize); if(a2 == NULL) { savu(u.u_ssav); xswap(p, 1, n); p->p_flag =| SSWAP; swtch(); /* no return */ } p->p_addr = a2; for(i=0; i<n; i++) copyseg(a1+i, a2++); 2292 mfree(coremap, n, a1); retu(p->p_addr); sureg(); } If shrinking, just release the extra space If there isn’t enough space, swap out the process Otherwise, copy the data into the new, larger area. Ch 8: Process Management
expand() Completed Flow Chart traps sleep() swtch() savu() sureg() retu() aretu() Ch 8: Process Management
Ch. 11: Clock Interrupts • clock() • Overview • Data Structures & Variables • Related Functions • Code • Example • Flow Chart
Overview • Handle and display system time • Manage timed events and processes • Execute clock() with every “tick” of system clock, approximately every 20 milliseconds in real-time. • Monitor “sleep” duration Ch 11: Clock Interrupts
Data Structures & Variables • Data Structures • callo • callout array • Variables • lbolt • time • tout Ch 11: Clock Interrupts
Data Structure (callo) struct callo { int c_time; /* ticks between events */ int c_arg; /* function argument */ int (*c_func)(); /* function pointer */ } callout[NCALL]; The “callout” array maintains a list of functions to be executed after “c_time” passes. Ch 11: Clock Interrupts
Variables int lbolt; • Milliseconds int time[2]; • time in sec from 1970 • That’s about 14,295,592,800 seconds int tout[2]; • time of next sleep Ch 11: Clock Interrupts
Related Functions • issig( ) • Checks if a signal has been sent to the user program and has not been attended to yet • Software interrupts • psig( ) • Performs the appropriate actions for the signals Ch 11: Clock Interrupts
issig() psig() Begin Flow Chart clock() Ch 11: Clock Interrupts
Related Functions • incupc( ) • Increment user program counter • Signals Recording of usage statistics • timeout( ) • Makes new entries in the callout[ ] array Ch 11: Clock Interrupts
incupc() ttrstrt() timeout() ttstart() Current Flow Chart clock() issig() psig() Ch 11: Clock Interrupts
setpri() setpri(up) { register *pp, p; pp = up; p = (pp->p_cpu & 0377)/16; p =+ PUSER + pp->p_nice; if(p > 127) p = 127; if(p > curpri) runrun++; pp->p_pri = p; } Calculate the new priority using: (cpu time + 100 + p_nice) And verify it doesn’t exceed 127. Ch 11: Clock Interrupts
setpri() Current Flow Chart clock() issig() psig() incupc() ttrstrt() timeout() ttstart() Ch 11: Clock Interrupts
Additional Functions • setrun(p) • Set p_stat to SRUN • Set ‘runrun’ flag if current process has lower priority • Wake up scheduler • wakeup(chan) • Wake up processes on channel ‘chan’ • By calling setrun(p) Ch 11: Clock Interrupts
setrun() wakeup() Current Flow Chart clock() issig() setpri() psig() incupc() ttrstrt() timeout() ttstart() Ch 11: Clock Interrupts
clock() 1 of 6 clock(dev, sp, r1, nps, r0, pc, ps) { register struct callo *p1, *p2; register struct proc *pp; *lks = 0115; display(); if(callout[0].c_func == 0) goto out; p2 = &callout[0]; while(p2->c_time<=0 && p2->c_func!=0) p2++; p2->c_time--; ⋮ If there are no callouts, just return Find the first non-zero time in the list. Ch 11: Clock Interrupts
clock() 2 of 6 Set Priority Level to 5, to allow for interrupts spl5(); if(callout[0].c_time <= 0) { p1 = &callout[0]; while(p1->c_func != 0 && p1->c_time <= 0) { (*p1->c_func)(p1->c_arg); p1++; } p2 = &callout[0]; while(p2->c_func = p1->c_func) { p2->c_time = p1->c_time; p2->c_arg = p1->c_arg; p1++; p2++; } } ⋮ Execute the functions with time <= 0 Update the array by removing the executed functions Ch 11: Clock Interrupts
Example Callout Array: p2 = &callout[0]; while(p2->c_time<=0 && p2->c_func!=0) p2++; = p1 C50 C90 C31 C45 C120 C61 C72 C80 … = p2 Ch 11: Clock Interrupts
Example Callout Array: p2->c_time--; ⋮ if(callout[0].c_time <= 0) { p1 = &callout[0]; = p1 C50 C90 C31 C30 C45 C120 C61 C72 C80 … = p2 Ch 11: Clock Interrupts
Example Callout Array: while(p1->c_func != 0 && p1->c_time <= 0) { (*p1->c_func)(p1->c_arg); p1++; } = p1 C50 C90 C30 C45 C120 C61 C72 C80 … = p2 Ch 11: Clock Interrupts
Example Callout Array: p2 = &callout[0]; while(p2->c_func = p1->c_func) { p2->c_time = p1->c_time; p2->c_arg = p1->c_arg; p1++; p2++; } = p1 C45 C120 C61 C72 C45 C120 C61 C72 … … =p2 Ch 11: Clock Interrupts
clock() 3 of 6 If the previous mode was user mode, increment the user time. out: if((ps&UMODE) == UMODE) { u.u_utime++; if(u.u_prof[3]) incupc(ps, u.u_prof); } else u.u_stime++; ⋮ if(++lbolt >= HZ) { if((ps&0340) != 0) return; Otherwise, increment the system time. Continue if lbolt has reached 60. Ch 11: Clock Interrupts
clock() 4 of 6 Another second has passed, increment time accordingly. lbolt =- HZ; if(++time[1] == 0) ++time[0]; spl1(); if(time[1]==tout[1] && time[0]==tout[0]) wakeup(tout); if((time[1]&03) == 0) { runrun++; wakeup(&lbolt); } Allow for all interrupts except another clock interrupt. If we have reached time ‘tout’, wake up sleeping processes. Every 4 seconds, send lightning bolt to initiate miscellaneous housekeeping. (pcopen) Ch 11: Clock Interrupts
clock() 5 of 6 for(pp = &proc[0]; pp < &proc[NPROC]; pp++) if (pp->p_stat) { if(pp->p_time != 127) pp->p_time++; if((pp->p_cpu & 0377) > SCHMAG) pp->p_cpu =- SCHMAG; else pp->p_cpu = 0; if(pp->p_pri > PUSER) setpri(pp); } Increment “p_time” for all processes. And decrement the cpu usage. Re-calculate the priorities of processes with “p_pri” greater than 100 Ch 11: Clock Interrupts
clock() 6 of 6 If the scheduler is waiting, wake it up. if(runin!=0) { runin = 0; wakeup(&runin); } if((ps&UMODE) == UMODE) { u.u_ar0 = &r0; if(issig()) psig(); setpri(u.u_procp); } } } If the previous mode was user mode, save the contents of register 0, and give priority to that process. Ch 11: Clock Interrupts
Completed Flow Chart clock() issig() setpri() psig() incupc() setrun() ttrstrt() wakeup() timeout() ttstart() Ch 11: Clock Interrupts
Ch. 8 Review • Process Management • swtch() • Data Structures • proc • user • Assembly Procedures • savu() • sureg() • retu() • aretu() • Calling Functions • sleep() • expand()
Final Flow Chart traps sleep() expand() swtch() savu() sureg() retu() aretu() Ch 8: Review
Ch. 11 Review • Clock Interrupts • clock() • Data Structures • callo & callout Array • Variables • lbolt • time • tout • Related Functions • issig() & psig() • incupc() • timeout() • setpri() • setrun() & wakeup() • Code
Current Flow Chart clock() issig() setpri() psig() incupc() setrun() ttrstrt() wakeup() timeout() ttstart() Ch 11: Review
References • Lions’ Commentary on UNIX, 6th Edition with Source Code • PDP 11/40 Processor Handbook • www.pdos.lcs.mit.edu/6.828/
Questions Do you have any?