s10: threads required: lab 10a - threads recommended: multithreaded programming (posix pthreads...

20
S10: Threads Required : Lab 10a - Threads Recommended : Multithreaded Programming (POSIX pthreads Tutorial)

Upload: mae-hall

Post on 30-Dec-2015

255 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

S10: Threads

Required: Lab 10a - Threads

Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Page 2: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

BYU CS 224 Threads 2

CS 224Chapter Lab Homework S00: Introduction

Unit 1: Digital Logic

S01: Data Types S02: Digital Logic

L01: Data TypesL02: FSM

HW01HW02

Unit 2: ISA

S03: ISA S04: Microarchitecture S05: Stacks / Interrupts S06: Assembly

L03: BlinkyL04: MicroarchL05b: Traffic LightL06a: Morse Code

HW03HW04HW05HW06

Unit 3: C

S07: C Language S08: Pointers S09: Structs S10: Threads S11: I/O

L07b: Morse IIL08a: LifeL09b: SnakeL10a: Threads

HW07HW08HW09HW10

Page 3: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Learning Objectives…

Learning Outcomes

After completing this section, you should be able to Explain the concept of a thread – a

fundamental unit of CPU utilization. Use POSIX Pthread APIs to

multithread a process. Use POSIX Pthread mutexes to

protect critical code. Use POSIX Pthread semaphores to

synchronize program events. Demonstrate the differences between

event driven models and multithreading programming solutions.

BYU CS 224 Threads 3

Topics Processes vs Threads CPU Context Thread Control Block Thread Management

Initialization Creation Termination Join

Scheduling Mutexes Thread-safe Semaphores

Page 4: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 4BYU CS 224

Processes vs Threads

Traditionally, a process is considered an instance of a computer program that is being executed.

A process contains System resources: program code, user data, buffers, devices, I/O

channels, files. Current activity: CPU, registers, state, execution path, “On the

clock”, interleaved with other processes. Resources and CPU activity can be treated

independently: Unit of resource ownership process or task Unit of execution thread or lightweight process

A Thread is an independent program counter operating within a process.

Smallest unit of processing (context) that can be scheduled by an operating system.

Page 5: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 5

Multi-threaded Process

BYU CS 224

Single threaded Process

code(.text)

dataglobal (.bss)

heap

systemfiles

MMU

contextPC, SR

registersstack

dataglobal (.bss)

heap

systemfiles

MMU

pthread 1PC, SR

registersstack

Multi-threaded Process

pthread 2PC, SR

registersstack

pthread 3PC, SR

registersstack

code(.text)

Page 6: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 6

Concurrent Threads

BYU CS 224

pthread 1pthread 2pthread 3

Time

pthread 3

pthread 2

pthread 1

Threads only "appear" to be executing at the same time (unless running on multi-core hardware).

Unnecessary context switching between threads is pure wasted CPU usage (overhead).

In addition, resource sharing introduces concurrency problems of mutual exclusion, deadlock, and synchronization.

Because there are an infinite number of ways a multithreaded program can execute, often testing and debugging multithreaded programs are inherently more difficult than single-threaded applications.

Page 7: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 7BYU CS 224

CPU Context

Processor state data are those pieces of information that define the status of a process when it's suspended, allowing the OS to restart it later and still execute correctly.

This always includes the content of the CPU program counter, general-purpose registers, the CPU process status word, stack and frame pointers etc.

During context switch, the running thread is stopped and another thread is given a chance to run.

The scheduler must stop the execution of the running thread, copy out the values in hardware registers to its Thread Control Block (TCB), and update the hardware registers with the values from the TCB of the new thread.

Page 8: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 8BYU CS 224

Thread Control Block

A Thread Control Block (TCB) is a data structure that holds:

Thread identification data – unique identifier of thread (ctid). Thread state data - information that define the status of a thread

when it is not running. Thread program counter CPU general-purpose registers CPU process status register Thread stack pointer

Thread control data - information used to mange the thread. Thread scheduling state (“Running”, “Ready“, or “Blocked“) Scheduling information such as ID of event blocking the thread.

Other information such as priority, elapsed time, children id's, signals, usage, privileges,…

Page 9: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 9

TCB States

BYU CS 224

R4R5R6R7R8R9

R10R11R12R13R14R15

R2 (SR)R0 (PC)&exit

tcbs[0].thread 0x0572.stack 0x05d4.block 0x0000.retval 0x0000

tcbs[1].thread 0x0202.stack 0x0254.block 0x0000.retval 0x0000

tcbs[2].thread 0x0282.stack 0x02d4.block 0x0422.retval 0x0000

tcbs[3].thread 0x0000.stack 0x0000.block 0x0000.retval 0x0000

Th

read

#2 S

tack

&exit

Th

read

#0 S

tack

Running

R4R5R6R7R8R9

R10R11R12R13R14R15

R2 (SR)R0 (PC)&exit

Th

read

#1 S

tack

Ready

Blocked

Thread #2 blockedon mutex/semaphore

0x0422

(Available)

Non-assignedThread

0x0000

ctid = 0(Available)

Thread #1Context

R4R5R6R7R8R9

R10R11R12R13R14R15

R2 (SR)R0 (PC)

Tcb tcbs[MAX_THREADS]; // thread control blocksvolatile pthread_t ctid; // current task id

Page 10: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 10BYU CS 224

Thread Management

int pthread_init(pthread_attr_t*); Init TCB’s Start TimerA.

int pthread_create(pthread_t*, pthread_attr_t*, void* (*func)(void*), void*);

Malloc a new stack Add thread to ready queue (tcbs).

int pthread_join(pthread_t tid, void** return_value); Waits for thread to terminate.

void pthread_exit(void* return_value); Free thread stack Delete thread from ready queue (tcbs).

int pthread_yield(void); Forces rescheduling of threads.

Page 11: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 11

Blockedse

m_w

ait

pth

read_m

ute

x_lo

ck

sem_sig

nal

pth

read_m

utex_u

nlo

ck

Scheduling

BYU CS 224

pthread_createNew Ready

pthread_exitExit

TA ISR

Time-outpthread_yiel

d

Running

The CPU scheduler (TA_ISR) decides which of the ready, in-memory threads is to be executed after a thread’s time quantum (time slice) is consumed or another form of signal from a thread or interrupt occurs.

Page 12: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 12

pthreadsISR.asm

BYU CS 224

.cdecls C,"msp430.h" ; MSP430 .cdecls C,"pthreads.h" ; threads header

.def TA_isr .ref ctid,tcbs

tcb_thread .equ (tcbs + 0) ; beginning of thread stacktcb_stack .equ (tcbs + 2) ; ready/blocked stack pointertcb_block .equ (tcbs + 4) ; blocking event

; Timer A ISR ----------------------------------------------------------- .text ; beginning of executable codeTA_isr: bic.w #TAIFG|TAIE,&TACTL ; acknowledge & disable TA interrupt;; >>>>>> 1. Save current context on stack; >>>>>> 2. Save SP in task control block; >>>>>> 3. Find next non-blocked thread tcb; >>>>>> 4. If all threads blocked, set LPM0+GIE in SR and repeat step 3; >>>>>> 5. Set new SP; >>>>>> 6. Load context from stack; bis.w #TAIE,&TACTL ; enable TA interrupts reti

; Interrupt Vector ------------------------------------------------------ .sect ".int08" ; timer A section .word TA_isr ; timer A isr .end

Page 13: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 13

pthreadsISR.c

BYU CS 224

#pragma vector = TIMERA1_VECTOR__interrupt void TIMERA1_ISR(void){ TACTL &= ~(TAIFG | TAIE); // acknowledge & disable TA interrupt saveCurrentState(); // save current thread state on stack tcbs[ctid].stack = (void*)__get_SP_register();

// find next non-blocked task in tcbs array register int count = 0; while (!tcbs[ctid = ++ctid & 0x0003].thread || tcbs[ctid].block) { if (!(count = ++count & 0x0003)) __bis_SR_register(LPM0 | GIE); }

__set_SP_register((unsigned short)tcbs[ctid].stack); restoreState(); // restore new thread state TACTL |= TAIE; // enable TA interrupts return;} // end TIMERA1_ISR

C Example of TimerA Scheduler:

Page 14: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 14BYU CS 224

Reentrant vs Thread-safe

A reentrant function can be safely called from any thread at any time without crashing your program.

A thread-safe function guarantees the function is atomic and can complete without fear of corrupted results.

While POSIX stdio.h operations are generally thread-safe, our lcd functions are not.

The printf function is reentrant, but not thread-safe. You can not guarantee that during a lcd function (such as printf)

the output from one thread won't start half way through the output from another thread also using a lcd function.

Without some application-level locking, whatever is written by multiple threads could be interleaved.

Use a pthread mutex (lock, unlock) functions to achieve larger-than-single-function-call atomic segments of code.

Page 15: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 15BYU CS 224

Mutexes

A mutex is locking mechanism used to synchronize access to a resource (such as code).

Only one task can acquire the mutex. It means there is ownership associated with mutex, and only the

owner can release the lock (mutex). A mutex is designed to protect critical data so that only

one thread can access it at the same time, such as a section of code or access to a variable.

Page 16: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 16BYU CS 224

Mutex Example

void* thread1(void* arg){ int count = 0; while (1) { pthread_mutex_lock(lcd_mutex); lcd_cursor(20, 20); lcd_printf(“Thread1 %d", ++count); pthread_mutex_unlock(lcd_mutex); } return (void*)0;} // end thread1

pthread_mutex_t lcd_mutex;int main(){ pthread_init_mutex(lcd_mutex); pthread_create(NULL, NULL, thread1, NULL); pthread_create(NULL, NULL, thread2, NULL);}

void* thread2(void* arg){ int count = 0; while (1) { pthread_mutex_lock(lcd_mutex); lcd_cursor(20, 40); lcd_printf(“Thread2 %d", ++count); pthread_mutex_unlock(lcd_mutex); } return (void*)0;} // end thread2

Page 17: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 17

Thread-safe Code

BYU CS 224

pthread_lock(m)

pthread_lock(m)pthread_lock(m)

pthread_unlock(m)

pthread_unlock(m)

pthread_unlock()

pthread 1pthread 2pthread 3

Critical Code

Exec

utio

n

TimeSlice

Context Switch

Critical Code

Thread 2 BlockedThread 3 Blocked

pthread_lock(m)

pthread_lock(m)pthread_lock(m)

Critical Code

Thread 1 Thread 2 Thread 3

Thread 2 BlockedThread 3 Blocked

Critical Code

Critical Code

pthread_unlock(m)

pthread_unlock(m)

pthread_unlock(m)

Page 18: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 18BYU CS 224

Semaphores

A semaphore is a protected variable whose value is accessed and altered by the operations signal (produce) and wait (consume).

A semaphore is used for controlling access to a common resource in a concurrent system, such as multi-threading.

The value of a semaphore is the number of available resources and may be used to synchronize various task activities.

A useful way to think of a semaphore is as a record of how many units of a particular resource are available, coupled with operations to safely consume those units, and, if necessary, wait until a unit of the resource becomes available.

Page 19: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 19BYU CS 224

Semaphore Example

//-- Watchdog Timer ISR#pragma vector = WDT_VECTOR__interrupt void WDT_ISR(void){ // 1 second counter if (--WDT_cps_cnt == 0) { LED_GREEN_TOGGLE; WDT_cps_cnt = WDT_CPS; seconds++; sem_signal(&sem_1sec); __ bic_SR_register_on_exit(LPM0_bits); } return;} // end WDT_ISR

//-- Timer Threadvoid* myThread(void* arg){ while (1) { sem_wait(&sem_1sec); pthread_mutex_lock(lcd_mutex); lcd_cursor(20, 40); lcd_printf(“Seconds = %d", seconds); pthread_mutex_unlock(lcd_mutex); } return (void*)0;} // end myThread

Producer Consumer

Page 20: S10: Threads Required: Lab 10a - Threads Recommended: Multithreaded Programming (POSIX pthreads Tutorial)

Threads 20BYU CS 224