440 likes | 585 Views
The OS kernel: Implementing processes and Threads. Kernel Definitions and Objects Queue Structures Threads Implementing Processes and Threads Implementing Synchronization and Communication Mechanisms Interrupt Handling. Kernel Definitions and Objects.
E N D
The OS kernel: Implementing processes and Threads • Kernel Definitions and Objects • Queue Structures • Threads • Implementing Processes and Threads • Implementing Synchronization and Communication Mechanisms • Interrupt Handling
Kernel Definitions and Objects OS kernel: a basic set of objects, primitive operations, data structures, and processes from which the remainder of the system may be constructed • Process and thread management • Interrupt and trap handling • Resource management • Input and output
A Process Creation Hierarchy ps p1 pj q1 pn qm … … Kernel … Interactions with kernel objects
Queue structures • Queues in OSs --queue for PCB --queues for hardware managers --queues for synchronization --queues for shared software components • Implementations of Queues --single-level queues --priority queues
Implementations of queues Types of queues: --FIFO --priority based Elements of queues Operations related to queues --insert( queue Q, element x) --remove( queue Q, element x) --empty( queue Q) Header or descriptor of queues
Queue pointer front front rear rear . . . . . . . . . Occupied portion . . . header Queue pointer . . . null header Single-Level Queues • Circular array • Linked list
Priority queues Queue pointer • Fixed-number priorities . . . front 0 rear 1 . . . i . . . . . . N-1 . . .
25 125 73 800 650 100 2300 1392 700 • Binary heap 1125
Threads • The normal implementation of processes results in much runtime overhead. To alleviate this problem, multiple “lightweight” scheduling units is implemented within a process. These units share the same resources as there host process
Operations on threads: • Create a new thread; • Initiate or make a thread ready; • Destroy or terminate a thread; • Delay or terminate a thread • Delay or put a thread to sleep for a given amount of time; • Synchronize threads through semaphores, events or condition variables; • Perform lower-level operations, such as blocking, suspending, or scheduling a thread
Implementing processes and threads • Process and thread descriptors • Implementing operations on processes • Operations on threads
PCB • Identification • State vector • Processors • Status information • Creation tree • other information
PCB ID Cpu_state processors Processor_ID State vector memory Open_files resources Other_resources status type list Creation_tree parent child priority . . . Other information Structure of process descriptor
running Ready_a Ready_s Blocked_a Blocked_s Status information
Implementing operations on processes • Create Create(so,mo,pi,pid){ p=Get_New_PCB(); pid=Get_New_PID(); p->ID=pid; p->CPU_State=s0; p->Memory=m0; p->Priority=pi; p->State.Type=“ready_s”; p->Creation_tree.Parent=self; p->Creation_Tree.child=NULL; insert(self->Creation_tree.child,p); insert(RL,p); Scheduler(); }
Suspend suspend(pid){ p=Get_PCB(pid); s=p->Status.Type; if((s==“blocked_a”)||(s==“blocked_s”)) p->status.Type=“block_s”; else p->status.Type=“ready_s”; if(s==“running”){ cpu=p->Processor_ID; p->CPU_State=Interrupt(cpu); Scheduler(); } }
Activate Activate(pid){ p=Get_PCB(pid) if(p->Status.Type==“ready_s”){ p->Status.Type=“ready_a”; Scheduler(); } else p->status.Type=“blocked_a”; }
Destroy Destroy(pid){ p=Get_PCB(pid); Kill_Tree(p); Scheduler(); } Kill_Tree(p){ for(each q in p->Creation_Tree.Child) Kill_Tree(q); if(p->Status.Type==“running”){ cpu=p->Processor_ID Interrupt(cpu); } Remove(p->Status.List,p); Release_all(p->Memory); Release_all(p->Other_Resources); Close_all(p->Open_Files); Delete_PCB(p); }
Implementing synchronization and communication mechanisms • Semaphores and locks • Monitor primitives • Clock and time management • Communication
General version of the Request/Release Request(res){ if(Free(res)) Allocate(res,self); else{ Block(self,res); Scheduler(); } } Release(res){ Deallocate(res,self); if(Process_Blocked_on(res,pr){ Allocate(res,pr); Unblock(pr,res); Scheduler(); } }
Semaphores and locks Bit Test Instruction : • BT:carry appointed bit to CF; • BTC: carry appointed bit to CF, and reverse it; • BTR: carry appointed bit to CF, and change it to 0; • BTS: carry appointed bit to CF, and change it to 1;
Spin Locks on Binary Semaphores • Pb(sb): do TS(R,sb); while(!R);/*wait loop*/ • Vb(sb): sb=1;
General Semaphores with spin locks • P p(s){ s=s-1; if(s<0){ Pb(delay_s; } } • V v(s){ s=s+1; if(s<=0) Vb(delay_s); else } Pb(mutex_s); Vb(mutex_s); Vb(mutex_s); Pb(mutex_s); Vb(mutex_s);
Avoiding the Busy-Wait P(s){ Inhibit_Interrupts; Pb(mutex_s); s=s-1; if(s<0){ Block(self, Ls); Vb(mutex_s); Enable_Interrupts; Scheduler(); } else{ Vb(mutex_s); Enable_Interrupts; } } V(s){ Inhibit_Interrupts; Pb(mutex_s); s=s+1; if(s<=0){ Unblock(q, Ls); Vb(mutex_s); Enable_Interrupts; Scheduler(); } else{ Vb(mutex_s); Enable_Interrupts; } }
Primitive and atomic operation • Priority • Interrupt request • Switching tasks on single CPU • Switching tasks on multiple CPU
struct semaphore { atomic_t count; int sleepers; wait_queue_head_t wait; #if WAITQUEUE_DEBUG long __magic; #endif }; static inline void down(struct semaphore * sem) { #if WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif __asm__ __volatile__( "# atomic down operation\n\t" LOCK "decl %0\n\t" /* --sem->count */ "js 2f\n" "1:\n" LOCK_SECTION_START("") "2:\tcall __down_failed\n\t" "jmp 1b\n" LOCK_SECTION_END :"=m" (sem->count) :"c" (sem) :"memory"); }
asm( ".text\n" ".align 4\n" ".globl __down_failed\n" "__down_failed:\n\t" #if defined(CONFIG_FRAME_POINTER) "pushl %ebp\n\t" "movl %esp,%ebp\n\t" #endif "pushl %eax\n\t" "pushl %edx\n\t" "pushl %ecx\n\t" "call __down\n\t" "popl %ecx\n\t" "popl %edx\n\t" "popl %eax\n\t" #if defined(CONFIG_FRAME_POINTER) "movl %ebp,%esp\n\t" "popl %ebp\n\t" #endif "ret" );
void __down(struct semaphore * sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); tsk->state = TASK_UNINTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); spin_lock_irq(&semaphore_lock); sem->sleepers++; for (;;) { int sleepers = sem->sleepers; /* * Add "everybody else" into it. They aren't * playing, because we own the spinlock. */ if (!atomic_add_negative(sleepers - 1, &sem->count)) { sem->sleepers = 0; break; } sem->sleepers = 1; /* us - see -1 above */ spin_unlock_irq(&semaphore_lock); schedule(); tsk->state = TASK_UNINTERRUPTIBLE; spin_lock_irq(&semaphore_lock); } spin_unlock_irq(&semaphore_lock); remove_wait_queue(&sem->wait, &wait); tsk->state = TASK_RUNNING; wake_up(&sem->wait); }
static inline void spin_lock(spinlock_t *lock) { #if SPINLOCK_DEBUG __label__ here; here: if (lock->magic != SPINLOCK_MAGIC) { printk("eip: %p\n", &&here); BUG(); } #endif __asm__ __volatile__( spin_lock_string :"=m" (lock->lock) : : "memory"); } #define spin_lock_string \ "\n1:\t" \ "lock ; decb %0\n\t" \ "js 2f\n" \ LOCK_SECTION_START("") \ "2:\t" \ "cmpb $0,%0\n\t" \ "rep;nop\n\t" \ "jle 2b\n\t" \ "jmp 1b\n" \ LOCK_SECTION_END
#define spin_lock_irq(lock) do { local_irq_disable(); spin_lock(lock); } while (0)
Monitor primitives • Body of each procedure: p(mutex); procedure_body; if(urgentcnt) V(urgent); else V(mutex); • C.wait: condcnt_c=condcnt_c+1; if(urgentcnt) V(urgent); else V(mutex); P(condsem_c) condcnt_c=condcnt-1; • C.signal: if(condcnt_c){ urgentcnt=urgentcnt+1; V(condsem_c); P(urgent); urgentcnt=urgentcnt-1; }
Clock and Time Management • Countdown Timers -- Set_Timer(tdel) -- Delay(tdel) Delay(tdel){ Set_timer(tdel); P(delsem); } -- TimeOut() TimeOut( ){ V(delsem): } • Wall clock timer -- Update_clock -- Get_Time -- SetClock(tnew)
Implementing logical timers • Logical timer -- tn=Create_LTimer(); -- Destroy_LTimer(tn); -- SetLTimer(tn,tdel);
p4 p3 p2 p1 p1 p2 p4 p3 p5 135 115 150 115 150 138 140 140 135 • Using a Priority Queue with Absolute Wakeup Times Wall-clock countdown Hardware timers 103 12 Timer queue TQ a TQ b
p4 p4 p3 p2 p1 p2 p1 p3 p5 5 15 20 10 10 15 20 3 2 Using a Priority Queue with Time Differences countdown Hardware timers 12 Timer queue TQ a TQ b
Communication primitives • Generic form of message-passing primitives -- send(p,m) -- receive(q, m) • Two issues must be resolved -- how does the sender know that sbuf has been copied and may be reused? -- how does the system know that the contents of rbuf are no longer needed by the receiver and may be overwritten? • Solutions -- blocking -- nonblocking (system buffers)
Interrupt Handling • Interrupt concept -- an event occurring at an unpredictable time that forces a transfer of control out of the normal processing sequence of a computer -- the purpose of interrupt handling is to remove the notion of asynchronous events from higher levels of the kernel, the OS, and applications • Common operations on interrupts -- enable -- disable -- inhibit
monitor • More uniform abstract model of interrupt handling Fn() P call Hardware device . . . Init c.wait c Fn() . . . IH() call . . . OS c.signal interrupt