Download as pdf or txt
Download as pdf or txt
You are on page 1of 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