480 likes | 580 Views
Explore the concepts of process management, including allocation of resources, and the significance of clock interrupts. Learn about key data structures, assembly procedures, and code flow. Get an in-depth understanding of how processes are managed efficiently.
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?