Linux Device Drivers

Linux Device Drivers


Linux
Modules
Character drivers
IO & Memory
Linux Kernel
Process Management
Process Address space

Linux Scheduler
Memory Management
Interrupts
Signals
System Calls
Kernel Synchronization
Linux Inter Process Communications




Serial Ports
Parallel Ports
Introduction to Hardware
Linux Timers
DMA in Linux
Linux Threads
Linux Thread Synchronization

Linux Multi Threading
Debugging in Linux
GDB GNU Debugger
KDB Kernel Debugger
KGDB Kernel GNU Debugger
Example Ethernet Driver




Synchronization and Critical-sections

Synchronization and Critical-sections

 

Multi-threaded programs are concurrent and share the same process space and can access the same data structures. Threads are scheduled by OS and are executed at random. When

threads are executing (racing to complete) they may give unexpected results (race condition).

 

Race Condition is a situation in which an unfortunate order of execution causes undesirable behavior.

 

Thread Synchronization

 

The threads library provides three synchronization mechanisms:

 

mutexes:                     Mutual exclusion lock: Block access to variables by other threads. This enforces exclusive access by a thread to a variable or set of variables.

joins:                           Make a thread wait till others are complete (terminated).

condition variables:    data type pthread_cond_t

 

 

Joins:

 

A join is performed when one wants to wait for a thread to finish.

A thread calling routine may launch multiple threads then wait for them to finish to get the results. One wait for the completion of the threads with a join.

 

int pthread_join( pthreadth, void **thread_return) ;

 

 

POSIX Mutexes

 

A mutex is a MUTual EXclusion device, and is useful for protecting shared data structures from concurrent modifications, and implementing critical sections and monitors.

A mutex has two possible states: unlocked (not owned by any thread), and locked (owned by one thread).

 

#include < pthread .h >

int pthread_mutex_init ( pthread_mutex_t *mutex,

const pthread_mutex attr_t *mutexattr ) ;

int pthread_mutex_lock ( pthread_mutex_t *mutex );

int pthread_mutex_unlock (pthread_mutex_t *mutex);

int pthread_mutex_destroy (pthread_mutex_t *mutex);

int pthread_trylock ( pthread_mutex_t *mutex ) ;

 

MutexAttributes :

 

int pthread_mutexattr_init ( pthread_mutexattr_t *attr ) ;

int pthread_mutexattr_destroy( pthread_mutex_t *attr ) ;

int pthread_mutexattr_setkind_np (pthread_mutexattr_t *attr,

int kind ) ;

int pthread_mutexattr_getkind_np ( pthread_mutexattr_t *attr ,

int *kind ) ;

 

Kind can be either PTHREAD_MUTEX_FAST_NP or

PTHREAD_MUTEX_RECURSIVE_NP

 

POSIX SEMAPHORES

 

A semaphore is a counter that can be used to synchronize multiple threads. Linux guarantees that checking or modifying the value of a semaphore can be done safely, without creating a race condition. Each semaphore has a counter value, which is a non-negative integer.

 

A semaphore supports two basic operations:

A wait operation decrements the value of the semaphore by 1. If the value is already zero, the operation blocks until the value of the semaphore becomes positive. When the semaphore’s value becomes positive, it is decremented by 1 and the wait operation returns.

 

A post operation increments the value of the semaphore by 1. If the semaphore was previously zero and other threads are blocked in await operation on that semaphore, one of those threads is unblocked and its wait operation completes.

 

POSIX SEMAPHORES

 

#include <semaphore .h>

int sem_init( sem_t*sem, intpshared, unsigned intval) ;

int sem_wait( sem_t*sem) ;

int sem_trywait( sem_t*sem) ;

int sem_post( sem_t*sem) ;

int sem_getvalue( sem_t*sem, int*sval) ;

int sem_destroy( sem_t*sem) ;

 

 

Condition Variables

 

A condition variable is a variable of type pthread_cond_t and is used with the appropriate functions for waiting and later, process continuation.

 

The condition variable mechanism allows threads to suspend execution and relinquish the processor until some condition is true

 

A condition variable must always be associated with a mutex to avoid a race condition created by one thread preparing to wait and another thread which may signal the condition before the first thread actually waits on it resulting in a deadlock.

 

Functions used in conjunction with the condition variable:

ü     Creating/Destroying:

o       pthread_cond_init

o       pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

o      pthread_cond_destroy

 

ü     Waiting on condition:

o      pthread_cond_wait

o      pthread_cond_timedwait              -place limit on how long it will block.

 

ü     Waking thread based on condition:

o      pthread_cond_signal

o      pthread_cond_broadcast              -wake up all threads blocked by the

specified condition variable.

 

 

Deadlocks with Two or More Threads

 

Deadlocks can occur when two (or more) threads are each blocked, waiting for a condition to occur that only the other one can cause.

 

For instance, if thread A is blocked on a condition variable waiting for thread B to signal it, and thread B is blocked on a condition variable waiting for thread A to signal it, a deadlock has occurred Because neither thread will ever signal the other.

 

You should take care to avoid the possibility of such situations because they are quite difficult to detect.