thread synchronization with semaphores

26
Lab 8 CIS 370 UMass Dartmouth

Upload: jerzy

Post on 20-Jan-2016

95 views

Category:

Documents


0 download

DESCRIPTION

Thread Synchronization with Semaphores. Lab 8 CIS 370 UMass Dartmouth. Threads. Threads allow parallel execution of processes or distinct parts of a single process. All threads within a process share: The same address space Process instructions Most data Open files (descriptors) - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Thread Synchronization with Semaphores

Lab 8CIS 370

UMass Dartmouth

Page 2: Thread Synchronization with Semaphores

Threads allow parallel execution of processes or distinct parts of a single process.

All threads within a process share:⋄ The same address space⋄ Process instructions ⋄ Most data ⋄ Open files (descriptors) ⋄ Signals and signal handlers ⋄ Current working directory ⋄ User and group id

Page 3: Thread Synchronization with Semaphores

Each thread has a unique: ⋄ Thread ID (tid)⋄ Set of registers, stack pointer ⋄ Stack for local variables, return addresses ⋄ Signal mask ⋄ Priority ⋄ Return value: errno

Basic thread operations:⋄ Creation⋄ Termination⋄ Joining⋄ Synchronization

Page 4: Thread Synchronization with Semaphores
Page 5: Thread Synchronization with Semaphores

In Linux, threads are handled with the Pthreads API.

#include <pthread.h>

pthread_t tid; //Thread Identifierpthread_attr_t attr; //Set of attributes for a thread

A thread can get its own thread identifier using:pthread_t pthread_self();

Attributes can be initialized using:int pthread_attr_init(&attr);

Page 6: Thread Synchronization with Semaphores

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*thread_func)(void*), void *arg);

⋄Returns 0 on success, or error on failure.

⋄ thread is a pointer to the created thread.⋄ attr is a pointer to a set of thread

attributes. - If attr is NULL, default attributes are used.⋄ thread_func is the first function a newly

created thread will execute. ⋄ arg is the only parameter to thread_func.

Page 7: Thread Synchronization with Semaphores

int pthread_join(pthread_t thread, void **value_ptr);

⋄Returns 0 on success, or error on failure.

⋄ thread is an executing thread.⋄ value_ptr contains the value of the

target thread’s exit parameter.

A call to join() will suspend the calling thread until the target thread terminates.

Page 8: Thread Synchronization with Semaphores

void pthread_exit(void *value_ptr);

⋄Never returns.

⋄ value_ptr is the thread’s exit parameter.

A call to pthread_exit() will terminate the calling process and send a reference to value_ptr to any joining thread.

Page 9: Thread Synchronization with Semaphores

Output:Child Thread: Value = 5Parent Thread: Value = 15

Page 10: Thread Synchronization with Semaphores
Page 11: Thread Synchronization with Semaphores
Page 12: Thread Synchronization with Semaphores

Expected Output:Value = 2,000,000

Actual Output:Run1: Value = 1,090,299

Run2: Value = 1,002,569

Run3: Value = 1,003,650

Run4: Value = 1,806,077

Run5: Value = 1,010,439

Run6: Value = 1,243,521

Run7: Value = 1,455,218

Page 13: Thread Synchronization with Semaphores

If this code is executed serially (Thread 1, followed by Thread 2) there are no problems. However threads execute in an arbitrary order.

Consider the following execution scenario:Thread 1 Thread 2 Value

tmp = value --- 0

tmp = tmp + 1 --- 0

--- tmp = value 0

--- tmp = tmp + 1 0

value = tmp --- 1

value = tmp 1

Page 14: Thread Synchronization with Semaphores

The problem is caused by allowing multiple threads to operate on the same data simultaneously.

Solution: provide functions that will block one thread if another thread is trying to access data that it is currently using.

Pthreads may use semaphores to achieve this.

Page 15: Thread Synchronization with Semaphores

Concept introduced by E.W. Dijkstra as a solution to process synchronization.

A Semaphore can be viewed as an integer variable on which the following operations are allowed:⋄ Wait()⋄ Signal()

In order to provide mutual exclusion:wait(semaphore) // Critical section

signal(semaphore)

Page 16: Thread Synchronization with Semaphores

Given a Semaphore sem, we’ll define the wait() and signal() operations as follows.

wait(sem)if(sem != 0)

decrement sem by oneelse

wait until sem becomes non-zero, then decrement

signal(sem)increment sem by one

if (queue of waiting processes/threads is not empty)restart the first process/thread in wait queue

Page 17: Thread Synchronization with Semaphores

To use Semaphores in UNIX:#include <sys/sem.h>

UNIX semaphore operations are geared to work on sets of semaphores, rather than single objects.

⋄ As a result, most semaphore routines are fairly complicated

Page 18: Thread Synchronization with Semaphores

Associated with each semaphore in the set:⋄ semval – The semaphore value 0 or a positive integer

⋄ sempid – The pid of the process that last acted on the semaphore

⋄ semcnt – Number of processes waiting for the semaphore to reach a value greater than its current value

⋄ semzcnt – Number of processes waiting for the semaphore to reach the value zero.

Page 19: Thread Synchronization with Semaphores

int semget(key_t key, int nsems, int permflags);

◊returns the semaphore set ID on success, or -1 on failure.

◊key is a system-wide unique identifier describing the semaphore you want to connect to (or create).

◊nsems gives the number of semaphores required in the semaphore set.

◊permflags tells semget() what to do with the semaphore in question.

-IPC_CREAT: Create the semaphore if it doesn't already exist in the kernel. 

-IPC_EXCL: When used with IPC_CREAT, fail if semaphore already exists.

Page 20: Thread Synchronization with Semaphores

int semctl(int semid, int sem_num, int command, union semun ctl_arg);

◊semid is a valid semaphore identifier, returned by a previous call to semget().

◊sem_num identifies a particular semaphore from the set. The first semaphore in a set is numbered 0.

◊command controls the behavior of semctl().

◊ctl_arg is a union defined as:

union semun{ int val; struct semid_ds *buf; unsigned short *array;

};

Page 21: Thread Synchronization with Semaphores

More about the command parameter:

IPC_STATIPC_SETIPC_RMID

Place status info into ctl_arg.bufSet ownerships/permissions from ctl_arg.buf Remove semaphore set from system

Standard IPC functions

GETVALSETVALGETPIDGETNCNTGETZCNT

Return value of semaphore (semval)Set value of semaphore to ctl_arg.valReturn value of sempidReturn semcntReturn semzcnt

Single semaphore operations

GETALLSETALL

Place all semvals into ctl_arg.arraySet all semvals according to ctl_arg.array

All semaphore (set) operations

Page 22: Thread Synchronization with Semaphores

‣One important use of semctl() is to set the initial values of semaphores, since semget() does not allow a process to do this.

Page 23: Thread Synchronization with Semaphores
Page 24: Thread Synchronization with Semaphores

int semop(int semid, struct sembuf *op_array, size_t num_ops);

‣This call actually performs fundamental semaphore operations. If unsuccessful, -1 is returned.

◊semid is a valid semaphore identifier, returned by a previous call to semget().

◊op_array is an array of sembuf structures, defined in <sys/sem.h>.

◊num_ops is the number of sembuf structures in the array.

struct sembuf{ unsigned short sem_num; //index in semaphore set short sem_op; //tells semop() what to do short sem_flg; //options

};

Page 25: Thread Synchronization with Semaphores

More about the sem_op parameter:

This is basically the semaphore wait() operation. If the semaphore’s semval is ≥ |sem_op|, decrement semval by |sem_op|, otherwise wait until semval ≥ |sem_op|.*If sem_flg is set to IPC_NOWAIT, semop() will return an error.

Case 1: sem_op value negative

This is basically the semaphore signal() operation. The value of sem_op is simply added to the corresponding semval. Processes waiting on the new value of the semaphore will be woken up.

Case 2: sem_op value positive

In this case semop() will wait until the semaphore value is zero, but doesn’t alter semval.*If sem_flg is set to IPC_NOWAIT, and semval is not already zero, semop() will return an error immediately.

Case 3: sem_op value zero

Page 26: Thread Synchronization with Semaphores

In this lab, you will experiment with Linux Semaphores to provide mutual exclusion between threads trying to access a critical section of code.

You will first have to implement the Semaphore wait() and signal() functions using the UNIX Semaphore procedures described in these slides.

Download the template code and modify it to include various Semaphore operations which will ensure that the threads will always increment the critical_value variable to 2,000,000.

www.cis.umassd.edu/~jplante/cis370/lab08/lab8_template.c

To compile C code implementing Threads, you will need to append “-lpthread” in the terminal.

Ex: gcc –o lab8 lab8_template.c -lpthread