Implementing Threads Operating Systems In Depth II 1 Copyright 2018 Thomas W Doeppner All rights reserved
The Unix Address Space stack dynamic bss data text Operating Systems In Depth II 2 Copyright 2018 Thomas W Doeppner All rights reserved
Adding More Stuff stack 1 stack 2 stack 3 mapped file 1 mapped file 2 mapped file 3 mapped file 117 bss & dynamic data text Operating Systems In Depth II 3 Copyright 2018 Thomas W Doeppner All rights reserved
Subroutines int main( ) { int i; int a; } i = sub(a, 1); return(0); int sub(int x, int y) { int i; int result = 1; for (i=0; i<y; i++) result *= x; return(result); } Operating Systems In Depth II 4 Copyright 2018 Thomas W Doeppner All rights reserved
Intel x86 (32-Bit): Subroutine Linkage args eip ebp saved registers local variables args eip ebp saved registers local variables stack frame ebp esp Operating Systems In Depth II 5 Copyright 2018 Thomas W Doeppner All rights reserved
Intel x86: Subroutine Code (1) main: pushl %ebp movl %esp, %ebp pushl %esi pushl %edi subl $8, %esp pushl $1 movl -12(%ebp), %eax pushl %eax call sub addl $8, %esp movl %eax, -16(%ebp) set up stack frame push args pop args; get result movl popl popl movl popl ret $0, %eax %edi %esi %ebp, %esp %ebp set return value and restore frame Operating Systems In Depth II 6 Copyright 2018 Thomas W Doeppner All rights reserved
Intel x86: Subroutine Code (2) sub: pushl %ebp movl %esp, %ebp subl $8, %esp movl $1, -4(%ebp) movl $0, -8(%ebp) movl -4(%ebp), %ecx movl -8(%ebp), %eax beginloop: cmpl 12(%ebp), %eax jge endloop imull 8(%ebp), %ecx addl $1, %eax jmp beginloop init locals get args endloop: movl %ecx, -4(%ebp) movl -4(%ebp), %eax movl %ebp, %esp popl %ebp ret Operating Systems In Depth II 7 Copyright 2018 Thomas W Doeppner All rights reserved
x86-64 Twice as many registers Arguments may be passed in registers, rather than on stack No special-purpose frame pointer use stack pointer instead Operating Systems In Depth II 8 Copyright 2018 Thomas W Doeppner All rights reserved
Intel x86-64: Subroutine Code (1) main: subq $24, %rsp movl 12(%rsp), %edi movl $1, %esi call sub addl $24, %rsp movl $0, %eax ret # reserve space on stack for locals # set first argument # set second argument # set return value Operating Systems In Depth II 9 Copyright 2018 Thomas W Doeppner All rights reserved
Intel x86-64: Subroutine Code (2) sub: testl %esi, %esi jle skiploop movl $1, %eax movl $0, %edx loop: imull %edi, %eax addl $1, %edx cmpl %esi, %edx jne loop ret skiploop: movl $1, %eax ret # leaf function: no stack setup Operating Systems In Depth II 10 Copyright 2018 Thomas W Doeppner All rights reserved
SPARC Architecture return address i7 r31 frame pointer i6 r30 i5 r29 i4 r28 i3 r27 i2 r26 i1 r25 i0 r24 Input Registers o7 r15 stack pointer o6 r14 o5 r13 o4 r12 o3 r11 o2 r10 o1 r9 o0 r8 Output Registers Local Registers l7 l6 l5 l4 l3 l2 l1 l0 r23 r22 r21 r20 r19 r18 r17 r16 g7 g6 g5 g4 g3 g2 g1 r7 r6 r5 r4 r3 r2 r1 0 g0 r0 Global Registers Operating Systems In Depth II 11 Copyright 2018 Thomas W Doeppner All rights reserved
SPARC Architecture: Register Windows input window 1 local output input local window 2 input output window 3 local output Operating Systems In Depth II 12 Copyright 2018 Thomas W Doeppner All rights reserved
SPARC Architecture: storage for local variables FP, old SP dynamically allocated stack space space for compiler temporaries and saved floating point registers outgoing parameters beyond 6th save area for callee to store register arguments one-word hidden parameter 16 words to save in and local regs SP Operating Systems In Depth II 13 Copyright 2018 Thomas W Doeppner All rights reserved
SPARC Architecture: Subroutine Code ld [%fp-8], %o0! put local var (a)! into out register mov 1, %o1! deal with 2nd! parameter call sub nop st %o0, [%fp-4]! store result into! local var (i) sub: save %sp, -64, %sp! push a new! stack frame add %i0, %i1, %i0! compute sum ret! return to caller restore! pop frame off! stack (in delay slot) Operating Systems In Depth II 14 Copyright 2018 Thomas W Doeppner All rights reserved
Representing Threads Thread A Control Block Thread B Control Block sp sp Operating Systems In Depth II 15 Copyright 2018 Thomas W Doeppner All rights reserved
Switching Between Threads thread_switch() thread_switch() Coroutine linkage thread_switch() thread_switch() thread_switch() Operating Systems In Depth II 16 Copyright 2018 Thomas W Doeppner All rights reserved
Switching Between Threads 1 void thread_switch(thread_t *next_thread) { 2 SaveContext(&CurrentThread->ctx); 3 CurrentThread = next_thread; 4 GetContext(&CurrentThread->ctx); 5 return; 6 } Operating Systems In Depth II 17 Copyright 2018 Thomas W Doeppner All rights reserved
Switching Between Threads, Take 2 1 void thread_switch(thread_t *next_thread) { 2 SwapContext(&CurrentThread->ctx, 3 &next_thread->ctx); 4 CurrentThread = next_thread; 5 return; 6 } Operating Systems In Depth II 18 Copyright 2018 Thomas W Doeppner All rights reserved
Quiz 1 Does this implementation of thread_switch work? a) yes: in all cases b) yes, except for a few edge cases c) no Operating Systems In Depth II 19 Copyright 2018 Thomas W Doeppner All rights reserved
Switching Between Threads, Take 3 1 void thread_switch(thread_t *next_thread) { 2 thread_t *oldcurrentthread = CurrentThread; 3 CurrentThread = next_thread; 4 SwapContext(&oldCurrentThread->ctx, 5 &CurrentThread->ctx); 6 return; 7 } Operating Systems In Depth II 20 Copyright 2018 Thomas W Doeppner All rights reserved
A Simple Threads Implementation Basis for user-level threads package Straight-threads implementation no interrupts everything in thread contexts one processor Operating Systems In Depth II 21 Copyright 2018 Thomas W Doeppner All rights reserved
Basic Representation Thread object Operating Systems In Depth II 22 Copyright 2018 Thomas W Doeppner All rights reserved
Current Thread A Collection of Threads Run Queue Mutex Queue Thread Object Thread Object Thread Object Thread Object Thread Object Thread Object Thread Object Operating Systems In Depth II 23 Copyright 2018 Thomas W Doeppner All rights reserved
Thread Switch (in C) void thread_switch( ) { thread_t *NextThread, *OldCurrent; NextThread = dequeue(runqueue); OldCurrent = CurrentThread; CurrentThread = NextThread; swapcontext(&oldcurrent->context, &NextThread->context); // We re now in the new thread s context } Operating Systems In Depth II 24 Copyright 2018 Thomas W Doeppner All rights reserved
Thread-Switch Exchange void thread_switch( ) { thread_t NextThread, OldCurrent; SP NextThread = dequeue(runqueue); OldCurrent = CurrentThread; CurrentThread = NextThread; swapcontext( &OldCurrent->context, thread_switch(); IP } &NextThread->context); Operating Systems In Depth II 25 Copyright 2018 Thomas W Doeppner All rights reserved
Thread-Switch Exchange void thread_switch( ) { thread_t NextThread, OldCurrent; NextThread = Return address NextThread OldCurrent SP dequeue(runqueue); OldCurrent = CurrentThread; CurrentThread = NextThread; swapcontext( &OldCurrent->context, thread_switch(); IP } &NextThread->context); Operating Systems In Depth II 26 Copyright 2018 Thomas W Doeppner All rights reserved
Thread-Switch Exchange void thread_switch( ) { thread_t NextThread, OldCurrent; Return address NextThread OldCurrent SP NextThread = dequeue(runqueue); OldCurrent = CurrentThread; CurrentThread = NextThread; swapcontext( &OldCurrent->context, IP Return address NextThread OldCurrent thread_switch(); } &NextThread->context); thread_switch(); Operating Systems In Depth II 27 Copyright 2018 Thomas W Doeppner All rights reserved
Thread-Switch Exchange void thread_switch( ) { thread_t NextThread, OldCurrent; NextThread = Return address NextThread OldCurrent SP dequeue(runqueue); OldCurrent = CurrentThread; CurrentThread = NextThread; swapcontext( &OldCurrent->context, IP Return address NextThread OldCurrent thread_switch(); } &NextThread->context); thread_switch(); Operating Systems In Depth II 28 Copyright 2018 Thomas W Doeppner All rights reserved
Thread-Switch Exchange void thread_switch( ) { thread_t NextThread, OldCurrent; NextThread = Return address NextThread OldCurrent dequeue(runqueue); OldCurrent = CurrentThread; CurrentThread = NextThread; swapcontext( SP Return address NextThread OldCurrent &OldCurrent->context, thread_switch(); } &NextThread->context); IP thread_switch(); Operating Systems In Depth II 29 Copyright 2018 Thomas W Doeppner All rights reserved
Thread-Switch Exchange void thread_switch( ) { thread_t NextThread, OldCurrent; NextThread = dequeue(runqueue); SP OldCurrent = CurrentThread; CurrentThread = NextThread; swapcontext( &OldCurrent->context, } &NextThread->context); IP thread_switch(); Operating Systems In Depth II 30 Copyright 2018 Thomas W Doeppner All rights reserved
Mutexes mutex_t mut; mutex_lock(&mut); x = x+1; mutex_unlock(&mut); Operating Systems In Depth II 31 Copyright 2018 Thomas W Doeppner All rights reserved
Implementing Mutexes void mutex_lock(mutex_t *m) { if (m->locked) { } } enqueue(m->wait_queue, CurrentThread); thread_switch(); m->locked = 1; void mutex_unlock(mutex_t *m) { m->locked = 0; } if (!queue_empty(m->wait_queue)) enqueue(runqueue, dequeue(m->wait_queue)); Operating Systems In Depth II 32 Copyright 2018 Thomas W Doeppner All rights reserved
Quiz 2 a) It works b) It works as long as there are just two threads c) It doesn t work Period Operating Systems In Depth II 33 Copyright 2018 Thomas W Doeppner All rights reserved
Implementing Mutexes, Take 2 void mutex_lock(mutex_t *m) { if (m->locked) { } enqueue(m->queue, CurrentThread); thread_switch(); } else m->locked = 1; void mutex_unlock(mutex_t *m) { if (queue_empty(m->queue)) } m->locked = 0; else enqueue(runqueue, dequeue(m->queue)); Operating Systems In Depth II 34 Copyright 2018 Thomas W Doeppner All rights reserved