0% found this document useful (0 votes)
115 views

Chapter 4. Threads & Concurrency

This document provides an overview of threads and concurrency. It discusses multicore programming and challenges related to parallelism. It describes different multithreading models including many-to-one, one-to-one, and many-to-many mappings of user threads to kernel threads. Common thread libraries like Pthreads are also summarized, providing code examples for thread creation and synchronization functions. The document aims to introduce key concepts regarding threads, concurrency, and multithreading.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
115 views

Chapter 4. Threads & Concurrency

This document provides an overview of threads and concurrency. It discusses multicore programming and challenges related to parallelism. It describes different multithreading models including many-to-one, one-to-one, and many-to-many mappings of user threads to kernel threads. Common thread libraries like Pthreads are also summarized, providing code examples for thread creation and synchronization functions. The document aims to introduce key concepts regarding threads, concurrency, and multithreading.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 64

COMPUTER ORGANIZATION AND DESIGN

The Hardware/Software Interface

Chapter 4
Threads & Concurrency

Yunmin Go

School of CSEE
Agenda
◼ Overview
◼ Multicore Programming
◼ Multithreading Models
◼ Thread Libraries
◼ Implicit Threading
◼ Threading Issues
◼ Signal
◼ Operating System Examples

Threads & Concurrency - 2


Motivation
◼ Most modern applications are multithreaded
◼ Threads run within application
◼ Multiple tasks with the application can be implemented by separate
threads
◼ Update display
◼ Fetch data
◼ Spell checking
◼ Answer a network request
◼ Process creation is heavy-weight while thread creation is light-weight
◼ Can simplify code, increase efficiency
◼ Kernels are generally multithreaded
Threads & Concurrency - 3
Overview
◼ Process: program in execution
◼ Each process occupies resources required for execution

◼ Thread: a way for a program to split itself into two or more


simultaneously running tasks
◼ Basic unit of CPU utilization
◼ Smaller unit than process
◼ Threads in a process share resources

◼ A thread is comprised of
◼ Thread ID, program counter, register set, stack, etc.
Threads & Concurrency - 4
Single and Multithreaded Processes

Threads & Concurrency - 5


Thread Control Block (TCB)
◼ Thread Control Block (TCB) is a data structure in the operating
system kernel which contains thread-specific information needed to
manage it.

◼ Examples of information in TCB (thread_struct in Linux)


◼ Thread id
◼ State of the thread (running, ready, waiting, start, done)
◼ Stack pointer
◼ Program counter
◼ Thread's register values
◼ Pointer to the process control block (PCB)

Threads & Concurrency - 6


Why Thread?
◼ Process creation is expensive in time and resource
◼ ex) Web server accepting thousands of requests

Threads & Concurrency - 7


Benefits
◼ Responsiveness: may allow continued execution if part of process is
blocked, especially important for user interfaces
◼ Resource Sharing: threads share resources of process, easier than
shared memory or message passing
◼ Economy: cheaper than process creation, thread switching lower
overhead than context switching
◼ Scalability: process can take advantage of multiprocessor
architectures

Threads & Concurrency - 8


Agenda
◼ Overview
◼ Multicore Programming
◼ Multithreading Models
◼ Thread Libraries
◼ Implicit Threading
◼ Threading Issues
◼ Signal
◼ Operating System Examples

Threads & Concurrency - 9


Multicore Programming
◼ Multicore or multiprocessor systems putting pressure on
programmers, challenges include:
◼ Dividing activities
◼ Balance
◼ Data splitting
◼ Data dependency
◼ Testing and debugging
◼ Parallelism implies a system can perform more than one task
simultaneously
◼ Concurrency supports more than one task making progress
◼ Single processor / core, scheduler providing concurrency

Threads & Concurrency - 10


Multicore Programming
◼ Concurrency vs. Parallelism
◼ Concurrent execution on single-core system:

◼ Parallelism on a multi-core system:

Threads & Concurrency - 11


Types of Parallelism
◼ Data parallelism: distributes subsets of the same data across
multiple cores, same operation on each

◼ Task parallelism: distributing threads across cores, each thread


performing unique operation

Threads & Concurrency - 12


Amdahl’s Law
◼ Identifies performance gains from adding additional cores to an
application that has both serial and parallel components
◼ S is serial portion, N processing cores
1
𝑠𝑝𝑒𝑒𝑑𝑢𝑝 ≤
1−𝑆
𝑆+
𝑁

◼ ex) Application is 75% parallel (25% serial), moving from


1 to 2 cores results in speedup of 1.6 times
◼ As N approaches infinity, speedup approaches 1 / S
◼ Serial portion of an application has disproportionate effect on performance
gained by adding additional cores.
But does the law take into account contemporary multicore systems?
Threads & Concurrency - 13
Agenda
◼ Overview
◼ Multicore Programming
◼ Multithreading Models
◼ Thread Libraries
◼ Implicit Threading
◼ Threading Issues
◼ Signal
◼ Operating System Examples

Threads & Concurrency - 14


User Threads and Kernel Threads
◼ User thread: thread supported ◼ Kernel thread: thread
by thread library in user level supported by kernel
◼ Created by library function call (not ◼ Created and managed by kernel
system call) ◼ Scheduled by kernel
◼ Kernel is not concerned in user ◼ Cheaper than process
thread ◼ More expensive than user thread
◼ Switching of user thread is faster
than kernel thread.

Threads & Concurrency - 15


Kernel Thread
◼ Most operating system kernels are also typically multithreaded
◼ Each thread performs a specific task, such as managing devices, memory
management, or interrupt handling

Threads & Concurrency - 16


Multithreading Models
◼ Major issue: correspondence between user treads and kernel threads

◼ Multithreading Models
◼ Many-to-One
◼ One-to-One
◼ Many-to-Many

Threads & Concurrency - 17


Many-to-One
◼ Many user-level threads mapped to single kernel thread
◼ One thread blocking causes all to block
◼ Multiple threads may not run in parallel on muticore system because
only one may be in kernel at a time
◼ Few systems currently use this model
◼ Examples:
◼ Solaris Green Threads
◼ Early version of Java

Threads & Concurrency - 18


One-to-One
◼ Each user-level thread maps to kernel thread
◼ Creating a user-level thread creates a kernel thread
◼ More concurrency than many-to-one
◼ Number of threads per process sometimes restricted due to overhead
◼ Examples
◼ Windows
◼ Linux

Threads & Concurrency - 19


Many-to-Many Model
◼ Allows many user level threads to be mapped to many kernel threads
◼ Allows the operating system to create a sufficient number of kernel
threads
◼ Windows with the ThreadFiber package
◼ Otherwise not very common

Threads & Concurrency - 20


Two-level Model
◼ Similar to Many-to-Many, except that it allows a user thread to be
bound to kernel thread

Threads & Concurrency - 21


Agenda
◼ Overview
◼ Multicore Programming
◼ Multithreading Models
◼ Thread Libraries
◼ Implicit Threading
◼ Threading Issues
◼ Signal
◼ Operating System Examples

Threads & Concurrency - 22


Thread Libraries
◼ Thread library provides programmer with API for creating and
managing threads
◼ Two primary ways of implementing
◼ User level library (entirely in user space with no kernel support)
◼ Kernel-level library supported by the OS

Threads & Concurrency - 23


Pthreads
◼ May be provided either as user-level or kernel-level
◼ A POSIX standard (IEEE 1003.1c) API for thread creation and
synchronization
◼ Specification, not implementation
◼ API specifies behavior of the thread library, implementation is up to
development of the library
◼ Common in UNIX operating systems (Solaris, Linux, Mac OS X)

Threads & Concurrency - 24


Pthreads
◼ pthread_create()
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Create a new thread
◼ Starts a new thread in the calling ◼ arg: argument to be passed to
process ◼ Return value
◼ thread: new thread ID on success ◼ Success: 0
◼ attr: to set thread attribute. NULL ◼ Error: error number
for default value.
◼ start_routine: the routine that the
thread will execute when it is
created
https://man7.org/linux/man-pages/man3/pthread_create.3.html Threads & Concurrency - 25
Pthreads
◼ pthread_join()
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);

Join with a terminated thread


◼ It blocks the calling thread until the ◼ retval: return value from the
specified thread returns terminated thread (a pointer returned
◼ When a parent thread returns, all by reference)
the child thread are terminated ◼ Return value
◼ thread: specified thread to ◼ Success: 0
terminate ◼ Error: error number

https://man7.org/linux/man-pages/man3/pthread_join.3.html Threads & Concurrency - 26


Example: Pthreads
#include <pthread.h>
#include <stdio.h> // thread will execute in this function
#include <stdlib.h> void *runner(void *param)
{
int sum; // this data is shared by the thread(s) int i, upper = atoi(param);
void *runner(void *param); // thread call this function sum = 0;

int main(int argc, char *argv[]) for (i = 1; i <= upper; i++)


{ sum += i;
pthread_t tid; // thread ID
pthread_attr_t attr; // set of attributes for the thread pthread_exit(0); // or return NULL
}
// get the default attributes
pthread_attr_init(&attr);

// create the thread


pthread_create(&tid, &attr, runner, argv[1]);

// now wait for the thread to exit


pthread_join(tid, NULL); Results
printf("sum = %d\n",sum);
}

https://man7.org/linux/man-pages/man3/pthread_attr_init.3.html
https://man7.org/linux/man-pages/man3/pthread_exit.3.html Threads & Concurrency - 27
Example: Pthreads
#include <stdio.h> // thread will execute in this function
#include <pthread.h> void *thread_summation(void * arg)
{
void *thread_summation(void * arg); int start = ((int*)arg)[0];
int sum = 0; int end = ((int*)arg)[1];

int main(int argc, char *argv[]) while (start <= end)


{ {
pthread_t id_t1, id_t2; // thread id sum+=start;
int range1[] = {1, 5}; start++;
int range2[] = {6, 10}; }
return NULL; // or pthread_exit(0);
// create thread }
pthread_create(&id_t1, NULL, thread_summation, (void *)range1);
pthread_create(&id_t2, NULL, thread_summation, (void *)range2);

// wait for the thread to exit


pthread_join(id_t1, NULL);
pthread_join(id_t2, NULL);
printf("result: %d \n", sum); Results
return 0;
}

Threads & Concurrency - 28


Pthreads
◼ Pthreads code for joining 10 threads
#define NUM_THREADS 10

// an array of threads to be joined upon


pthread_t workers[NUM_THREADS];

for (int i = 0; i < NUM_THREADS; i++)


pthread_join(workers[i], NULL);

Threads & Concurrency - 29


Pthreads
◼ pthread_cancel()
#include <pthread.h>
int pthread_cancel(pthread_t thread);

Send a cancellation request to a thread


◼ This function sends a cancellation ◼ Cancelability state is determined by
request to the thread pthread_setcancelstate()
◼ Whether and when the target thread ◼ Cancellation type is determined by
reacts to the cancellation request pthread_setcanceltype()
depends on two attributes that are ◼ thread: thread ID to cancel
under the control of that thread: its ◼ Return value
cancelability state and type. ◼ Success: 0
◼ Error: nonzero erro number
https://man7.org/linux/man-pages/man3/pthread_join.3.html Threads & Concurrency - 30
Example: Pthreads
#include <stdio.h> int main()
#include <unistd.h> {
#include <sys/types.h> pthread_t thread_one, thread_two;
#include <pthread.h>
// create thread_one and thread_two
int counter = 0; // Counter pthread_create(&thread_one, NULL, func1, NULL);
pthread_t tmp_thread; // Thread ID fo func2 pthread_create(&thread_two, NULL, func2, NULL);

void* func1(void* arg) // waiting for when threads are completed


{ pthread_join(thread_one, NULL);
while (1) { pthread_join(thread_two, NULL);
printf("Thread #1 (counter=%d)\n", counter);
if (counter == 5) { return 0;
// for cancel thread_two }
pthread_cancel(tmp_thread);
// for exit from thread_one
pthread_exit(NULL);
}
sleep(1); // sleep 1 second
}
}

void* func2(void* arg)


{
// get thread ID
tmp_thread = pthread_self();
while (1) {
printf("Thread #2 (counter=%d)\n", counter);
counter++;
sleep(1); // sleep 1 second
}
} https://man7.org/linux/man-pages/man3/pthread_self.3.html Threads & Concurrency - 31
Java Threads
◼ Java threads are managed by the JVM
◼ Typically implemented using the threads model provided by
underlying OS
◼ Java threads may be created by
◼ Extending Thread class
◼ Implementing the Runnable interface
public interface Runnable
{
public abstract void run();
}

Threads & Concurrency - 32


Java Threads
◼ Implementing the Runnable interface
class Task implements Runnable
{
public void run() {
System.out.println("I am a thread.");
}
}

◼ Creating a thread
Thread worker = new Thread(new Task());
worker.start(); 1. It allocates memory and initializes a new
thread in JVM.
2. It calls the run() method, making the thread
◼ Waiting on a thread eligible to be run by the JVM.
try {
worker.join();
} catch (InterruptedException e) {
}

Threads & Concurrency - 33


Java Threads
◼ Thread cancellation
◼ Deferred cancellation uses the interrupt() method, which sets the
interrupted status of a thread.
Thread worker;

// Set the interruption status of the thread
worker.interrupt()

◼ A thread can then check to see if it has been interrupted:


while (!Thread.currentThread().isInterrupted()) {
...
}

Threads & Concurrency - 34


Java Executor Framework
◼ Rather than explicitly creating threads, Java also allows thread
creation around the Executor interface:
// In java.util.concurrent;

public interface Executor


{
void execute(Runnable command);
}

◼ The Executor is used as follows:


Executor service = new Executor;
service.execute(new Task());

Threads & Concurrency - 35


Example: Java Executor Framework
import java.util.concurrent.*;
public class Driver
class Summation implements Callable<Integer>
{
{
public static void main(String[] args) {
private int upper;
if (args.length == 1) {
int upper = Integer.parseInt(args[0]);
public Summation(int upper) {
this.upper = upper;
ExecutorService pool = Executors.newSingleThreadExecutor();
}
Future<Integer> result = pool.submit(new Summation(upper));
public Integer call() {
try {
int sum = 0;
System.out.println("sum = " + result.get());
for (int i = 1; i <= upper; i++)
}
sum += i;
catch (InterruptedException | ExecutionException ie) { }
return Integer.valueOf(sum);
pool.shutdown();
}
}
}
}
}
Results

Threads & Concurrency - 36


Agenda
◼ Overview
◼ Multicore Programming
◼ Multithreading Models
◼ Thread Libraries
◼ Implicit Threading
◼ Threading Issues
◼ Signal
◼ Operating System Examples

Threads & Concurrency - 37


Implicit Threading
◼ Implicit Threading: Creation and management of threads done by
compilers and run-time libraries rather than programmers
◼ Three methods explored
◼ Thread pools
◼ Fork Join model
◼ OpenMP
◼ Other methods include Grand Central Dispatch and Microsoft
Threading Building Blocks (TBB), etc

Threads & Concurrency - 38


Thread Pools
◼ Create a number of threads in a pool where they await work
◼ Advantages
◼ Usually slightly faster to service a request with an existing thread than create a
new thread
◼ Allows the number of threads in the application(s) to be bound to the size of
the pool
◼ Separating task to be performed from mechanics of creating task allows
different strategies for running task
◼ i.e. tasks could be scheduled to execute after a time delay or to execute periodically

Thread Pool
Thread Thread
Thread Thread
Thread Thread
Threads & Concurrency - 39
Java Thread Pools
◼ Supported by Java executor framework in java.util.concurrent
package
◼ Three factory methods for creating thread pools in Executors class:
◼ static ExecutorService newSingleThreadExecutor()
◼ Creates a pool of size 1
◼ static ExecutorService newFixedThreadPool(int size)
◼ Creates a thread pool with a specified number of threads
◼ static ExecutorService newCachedThreadPool()
◼ Creates an unbounded thread pool, reusing in many instances

Threads & Concurrency - 40


Example: Java Thread Pools
import java.util.concurrent.*;

class Task implements Runnable


{
public void run() {
System.out.println(Thread.currentThread().getName());
}
}

public class ThreadPoolExample


{
public static void main(String[] args) {
int numTasks = Integer.parseInt(args[0].trim());

// Create the thread pool


ExecutorService pool = Executors.newCachedThreadPool();
Results
// Run each task using a thread in the pool
for (int i = 0; i < numTasks; i++)
pool.execute(new Task());

// Shut down the pool once all threads have completed


pool.shutdown();
}
}
Threads & Concurrency - 41
Fork Join Parallelism
◼ Multiple threads (tasks) are forked, and then joined

Threads & Concurrency - 42


Fork Join Parallelism
◼ The ForkJoinTask is an abstract base class
◼ RecursiveTask and RecursiveAction classes extend
ForkJoinTask
◼ RecursiveTask returns a result (via the return value from the compute()
method)
◼ RecursiveAction does not return a result

Threads & Concurrency - 43


Example: Fork Join Parallelism else {
// divide stage
import java.util.concurrent.*;
int mid = begin + (end - begin) / 2;
import java.util.Arrays;
SumTask leftTask = new SumTask(begin, mid, array);
public class SumTask extends RecursiveTask<Integer>
SumTask rightTask = new SumTask(mid + 1, end, array);
{
static final int SIZE = 10000;
leftTask.fork();
static final int THRESHOLD = 1000;
rightTask.fork();
private int begin;
return rightTask.join() + leftTask.join();
private int end;
}
private int[] array;
}
public SumTask(int begin, int end, int[] array) {
public static void main(String[] args) {
this.begin = begin;
ForkJoinPool pool = new ForkJoinPool();
this.end = end;
int[] array = new int[SIZE];
this.array = array;
}
// create SIZE random integers between 0 and 9
java.util.Random rand = new java.util.Random();
protected Integer compute() {
if (end - begin < THRESHOLD) {
for (int i = 0; i < SIZE; i++) {
// conquer stage
array[i] = rand.nextInt(10);
int sum = 0;
}
for (int i = begin; i <= end; i++)
sum += array[i];
// use fork-join parallelism to sum the array
SumTask task = new SumTask(0, SIZE-1, array);
return sum;
int sum = pool.invoke(task);
}
Results (with SIZE=10)
System.out.println(Arrays.toString(array));
System.out.println("The sum is " + sum);
} Threads & Concurrency - 44
}
OpenMP
◼ Provides support for parallel programming in shared-memory
environments
◼ Set of compiler directives and an API for C, C++, FORTRAN
◼ Identifies parallel regions: blocks of code that can run in parallel
◼ Create as many threads as there are cores
#pragma omp parallel // each runs the statement
printf("Hello, World!\n");

◼ Run for loop in parallel


#pragma omp parallel for // unroll loop over cores
for(i=0; i<N; i++) {
c[i] = a[i] + b[i];
}

Threads & Concurrency - 45


Example: OpenMP
#include <omp.h>
#include <stdio.h>

int main(int argc, char *argv[]) Results (depends on your machine)


{
/* sequential code */
#pragma omp parallel
{
printf("I am a parallel region\n");
}

/* sequential code */
return 0;
}

Threads & Concurrency - 46


Agenda
◼ Overview
◼ Multicore Programming
◼ Multithreading Models
◼ Thread Libraries
◼ Implicit Threading
◼ Threading Issues
◼ Signal
◼ Operating System Examples

Threads & Concurrency - 47


fork() and exec()
◼ fork() on multithreaded process
◼ Duplicates all threads in the process?
◼ Duplicates only corresponding thread?

→ UNIX supports two versions of fork


◼ fork(), fork1()

◼ exec() on multithreaded process


◼ Replace entire process including all threads

Threads & Concurrency - 48


Thread Cancellation
◼ Problem with thread cancellation
◼ A thread share the resource with other threads
cf. A process has its own resource.
→ A thread can be cancelled while it updates data shared with other threads

◼ Two general approaches:


◼ Asynchronous cancellation terminates the target thread immediately
◼ Deferred cancellation allows the target thread to periodically check if it
should be cancelled

Threads & Concurrency - 49


Thread Cancellation
◼ Invoking thread cancellation requests cancellation, but actual
cancellation depends on thread state
pthread_t pthread_setcanceltype(int type, int *oldtype);
type:
- PTHREAD_CANCEL_ASYNCHRONOUS (Asynchronous cancellation)
- PTHREAD_CANCEL_DEFERRED (Deferred cancellation)

◼ If thread has cancellation disabled, pthread_t pthread_setcancelstate(int state, int *oldstate);


state:
cancellation remains pending - PTHREAD_CANCEL_DISABLE
- PTHREAD_CANCEL_ENABLE
until thread enables it
◼ Default type is deferred
◼ Cancellation only occurs when thread reaches cancellation point i.e.
pthread_testcancel(), then cleanup handler is invoked
◼ On Linux systems, thread cancellation is handled through signals

https://man7.org/linux/man-pages/man3/pthread_setcancelstate.3.html Threads & Concurrency - 50


Thread-Local Storage
◼ In a process, all threads share global variables
◼ Thread-local storage (TLS) allows each thread to have its own copy
of data
__thread int tls; // on pthread
◼ Each thread has its own ‘int tls’ variable

◼ Different from local variables

◼ Local variables visible only during single function invocation


◼ TLS visible across function invocations
◼ Similar to static data
◼ TLS is unique to each thread
◼ Useful when you do not have control over the thread creation process
(i.e., when using a thread pool)
Threads & Concurrency - 51
Thread-Local Storage in pthread
#include <stdio.h> int main() {
#include <stdlib.h> int ret;
#include <unistd.h> pthread_t thread[THREADS];
#include <pthread.h> int num;

#define THREADS 3 for (num = 0; num < THREADS; num++) {


ret = pthread_create(&thread[num], NULL, &func, (void*)&num);
__thread int tls; if (ret) {
int global; printf("error pthread_create\n");
exit(1);
void *func(void *arg) }
{ }
int num = *((int*)arg);
tls = num; for (num = 0; num < THREADS; num++) {
global = num; ret = pthread_join(thread[num], NULL);
sleep(1); if (ret) {
printf("Thread = %d tls = %d global = %d\n", printf("error pthread_join\n");
num, tls, global); exit(1);
} }
}
return 0;
} Threads & Concurrency - 52
Scheduler Activations
◼ Both M:M and Two-level models require communication to
maintain the appropriate number of kernel threads allocated
to the application
◼ Typically use an intermediate data structure between user
and kernel threads – lightweight process (LWP)
◼ Appears to be a virtual processor on which process can schedule
user thread to run
◼ Each LWP attached to kernel thread
◼ How many LWPs to create?
◼ Scheduler activations provide upcalls - a communication
mechanism from the kernel to the upcall handler in the
thread library
◼ This communication allows an application to maintain the
correct number kernel threads
Threads & Concurrency - 53
Agenda
◼ Overview
◼ Multicore Programming
◼ Multithreading Models
◼ Thread Libraries
◼ Implicit Threading
◼ Threading Issues
◼ Signal
◼ Operating System Examples

Threads & Concurrency - 54


Signal
◼ Signal: mechanism provided by UNIX to notify a process that a
particular event has occurred
◼ A signal can be generated by various sources
◼ The signal is delivered to a process
◼ The process handles it
◼ Default signal handler (kernel)
◼ User-defined signal handler
◼ Types of signal
◼ Synchronous: signal from same process
◼ Ex) illegal memory access, division by 0
◼ Asynchronous: signal from external sources
◼ Ex) <Ctrl>-C

Threads & Concurrency - 55


Signal
◼ Signal disposition (action associated with a signal)
◼ Each signal has a current disposition, which determines how the process
behaves when it is delivered the signal.
◼ We can provide a function that is called whenever a specific signal occurs.
This function is called a signal handler
◼ We can ignore a signal by setting its disposition to SIG_IGN.
◼ We can set default disposition for a signal by setting its disposition to
SIG_DFL.

Threads & Concurrency - 56


Signal
◼ Signal types
Signal name Description Default action

SIGALRM Time-out occurs (alarm) Terminate

SIGCHLD Change in status of a child Ignore

SIGINT Terminal interrupt character (ctrl+C) Terminate

SIGKILL Termination Terminate

SIGPIPE Write to pipe with no readers Terminate

SIGSTOP Stop (ctrl+S) Stop process

https://man7.org/linux/man-pages/man7/signal.7.html Threads & Concurrency - 57


Signal
◼ signal()
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
Define the action associated with a signal
◼ Sets the disposition of the signal ◼ func: the address of a function to be
signum to handler, which is either called when the signal occurs,
SIG_IGN, SIG_DFL, or the address SIG_IGN or SIG_DFL
of a programmer-defined function ◼ Return value
(a "signal handler") ◼ Success: the previous value of the signal
◼ signum: the name of signal handler
◼ Error: SIG_ERR

https://man7.org/linux/man-pages/man2/signal.2.html Threads & Concurrency - 58


Example: signal()
#include <stdio.h> int main(int argc, char *argv[])
#include <unistd.h> {
#include <signal.h> int i;
signal(SIGALRM, timeout); // for timeout
// Signal handler for timeout signal(SIGINT, keycontrol); // for key control
void timeout(int sig) alarm(2); // generate SIGALRM after 2 seconds
{
if (sig == SIGALRM) for (i = 0; i < 3; i++)
puts("Time out!"); {
puts("wait...");
// generate SIGALRM after 2 seconds sleep(10); // sleep for 10 seconds
alarm(2); }
} return 0;
}
// Signal handler for key control
void keycontrol(int sig)
{ Results
if (sig == SIGINT)
puts("CTRL+C pressed");
}

https://man7.org/linux/man-pages/man2/alarm.2.html Threads & Concurrency - 59


Signal
◼ sigaction ()
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

Examine and change a signal action ◼ struct sigaction


◼ Used to change the action taken by a struct sigaction {
void (*sa_handler)(int);
process on receipt of a specific signal. void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
◼ signum: the name of signal int sa_flags;
◼ act: the new action void (*sa_restorer)(void);
};
◼ oldact: the previous actions • sa_handler: the address of a function to be called when
◼ Return value the signal occurs
• sa_mask: specifies a set of signals that will be blocked
◼ Success: 0 when the signal handler is called
◼ Error: -1 • sa_flags: options. Basically 0
https://man7.org/linux/man-pages/man2/sigaction.2.html Threads & Concurrency - 60
Example: sigaction()
#include <stdio.h> int main(int argc, char *argv[])
#include <unistd.h> {
#include <signal.h> int i;
struct sigaction act;
// Signal handler for timeout act.sa_handler = timeout;
void timeout(int sig) sigemptyset(&act.sa_mask);
{ act.sa_flags = 0;
if (sig == SIGALRM)
puts("Time out!"); // specify signal type and signal handler
sigaction(SIGALRM, &act, 0);
// generate SIGALRM after 2 seconds
alarm(2); alarm(2);
}
for (i = 0; i < 3; i++)
{
puts("wait...");
sleep(10); Results
}
return 0;
}

https://man7.org/linux/man-pages/man3/sigemptyset.3p.html Threads & Concurrency - 61


Signal Handling
◼ Question: To what thread the signal should be delivered?
◼ Possible options
◼ To the thread to which the signal applies
◼ To every thread in the process

◼ To certain threads in the process

◼ Assign a specific thread to receive all signals

→ depend on type of signal

◼ Another scheme: specify a thread to deliver the signal


◼ Ex) pthread_kill(tid, signal) in POSIX

Threads & Concurrency - 62


Agenda
◼ Overview
◼ Multicore Programming
◼ Multithreading Models
◼ Thread Libraries
◼ Implicit Threading
◼ Threading Issues
◼ Signal
◼ Operating System Examples

Threads & Concurrency - 63


Linux Threads
◼ Linux refers to them as tasks rather than threads
◼ Thread creation is done through clone() system call
◼ clone() allows a child task to share the address space of the parent
task (process)
◼ Flags control behavior

◼ struct task_struct points to process data structures (shared or


unique)
Threads & Concurrency - 64

You might also like