Are Processes Enough?
Possible scenarios
- A server with many clients (e.g. webserber)
- process: context switching -> overhead
- A powerful computer with many CPU cores
Problems with Processes
Process creation is heavyweight (i.e. slow)
- Space must be allocated for the new process
- fork() copies all state of the parnet to the child
- memory access -> long time
IPC(Inter Process Communication) mechanisms are cumbersome
- Difficult to use fine-grained synchronization
- Message passing is slow
- Each message may have to go through the kernel
- process는 세밀한 동기화가 어렵기 때문에 Message passing을 이용해야 하는데, 이는 매우 느림
Threads : a flow of contorl
Light-weight processes that share the same memory and state space
Every process has at least one thread
Benefits
- Resoures sharing, no need for IPC
- Economy: faster to create, faster to context switch
- address space change X -> change EIP, stack, Register
- Scalability: simple to take advantage of multi-core CPUs

Thread Implementations
Threads can be implemented in two ways
-
User threads
- User-level library manages threads within a single process
-
Kernel threads
- kernel manages threads for all processes
User Threads and Kernel Threads
User threads - management done by user-level threads library
- Three primary thread libraries
- POSIX Pthreads (Linux, Unix)
- in Linux, Pthread 생성하면 kernel level이 자동 생성되도록 구현됨
- Windows threads
- Java threads
Kernel threads - Supported by the Kernel
- Examples - virtually all general purpose operating systems, including
- Windows
- Solaris
- Linux
- Mac OS X
Multithreading Models
- Many-to-One
- One-to-One
- Many-to-Many
Many-to-One
- Many user-level threads mappend to single kernel thread
- one thread blocking causes all to block
User thread request I/O
- OS 입장에서는 kernel thread가 I/O인 줄 알고 waiting state 처리
-> user threads 전부 wait queue에 들어가게 됨
=> CPU wait, scheduling 대상에서 제외되는 문제 발생
- kernel thread를 지원하지 않는 OS는 process만 보이고, user-level을 여러개 생성하여 처리 -> 문제점이 많아서 현재는 native (kernel thread) 지원
- Multiple thread may not run in parallel on multi-core system because only one may be in kernel an a time
- Example
- Solaris Green Threaads
- GNU Portable Threads

One-to-One
- Each user-level threads 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 restriced due to overhead
- Example
- Windows
- Linux
- Pthread 하나 만들면 대응되는 kernel thread 생성
- Solaris 9 and later

묶을 수 있으면 multi-core이지만 완전한 light model은 아님
address space를 공유하는 thread 생성 가능
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
- Solaris prior to version 9
- Windows with ThreadFiber package
- Fiber(섬유)끼리 context switching
- kernel thread안에 Fiber(user-level)
- blocking X -> CPU끼리, I/O끼리 사용

Two-level Model
- Similar to M:M, except that it allows a user thread to be bound to kernel thread
- Exmaples
- IRIX
- HP-UX
- Solaris 8 and eariler

POSIX Pthreads
POSIX standart API for thread creation
- IEEE 1003.1c
- Specification, not implemention
- Defines the API and the expected behavior
Implementation is system dependent
- On some platforms, user-level threads
- On others, maps to kernel-level threads
Pthread API
- pthread_attr_init()
- initialize the threading library
- pthread_create()
- create a new thread
- similar fork(), exec() 존재 x
- address copy가 일어나지 않기 때문에 create()에서 code 채움
- pthread_exit()
- pthread_join()
- wait for another thread to exit : 동기화
- Pthreads also contains a full range of synchronization primitives
Pthread Example
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid, &attr, runner, 0);
pthread_join(tid, 0);
void * runner(void * params) {
…
pthread_exit(0);
}
- create()
- process's address space share
- runner: 새로 생성된 스레드가 시작될 때 실행될 함수의 포인터를 넘김
- 0: runner 함수에 넘길 parameter -> NULL
Linux Threads
In Linux, process와 thread의 명확한 구분이 없음
In the kernel, threads are just task
- Remember the task_struct from eariler?
New threads created using form clone() API
- Sort of like fork()
- Creates a new child task(not process) that copies the address space of the parent
- Same code, same environment, etc => share space
- New stack is allocated
- No memory needs to be dcopied (unlike fork())
Thread Oddities
What happens if you fork() a process that has multiple threads?
- You get a child process with exactly one thread
- Whichever thread called fork() survives
What happens if you run exec() in a multi-threaded process ?
- All but one threads are killed
- exec() gets run normally
- 새로운 거로 치환하여 원래 있던 거 전부 날아감, exec()를 부른 애는 남아서 새로운 코드 적재
Advanced Threading
Thread pools
- Create many thread in advance
- Dynamically give work to threads form the pool as it becomes available
Advantages
- Cost of creating threads in handled up-front
- Bounds the maximum number of threads in the process
많이 만들면 overhead -> embeded, real-time처럼 overhead 발생 시 급격한 성능 저하가 발생하는 경우 사용
Thread Local Storage
Sometimes, you want each thread to have its own "global" data
- Not global to all threads
- Not local storage on the stack
Thread local storage(TLS) allows each thread to have its own space for "global" variables
- Similar to staic variables
- in gcc compiler, thread_local()

OpenMP
#include <omp.h>
int main() {
int i, N = 20;
#pragma omp parallel
{
printf(“I am a parallel region\n”);
}
# pragma omp parallel for
for (i = 0; i < N; i++)
printf(“This is a parallel for loop\n”);
return 0;
}
Compiler extensions for C, C++ that adds native support for parallel programming
Controlled with parallel resions
- Automatically creates as many thread as there
Processes vs Threads
Threads are better if
- You need to create new ones quickly, on-the-fly
- You need to share lots of state
- multi-core 활용 가능
- multi-core하고 싶으면 multi-thread-> but protection problem...
- 한 thread가 잘못되면 process 전체 crash
- overhead down ∵ address space share -> faster context switching
Processes are better if
- You want protection
- One process that crashes or freezes doesn't impact the others
- You need high security
- Only way to move state is through weel-defined, sanitized message passing interface
- e.g. Java VM: 하나의 process가 잘못되어도 VM만 crash, OS에는 영향 x