Chapter 4

Thread Synchronization

The AVR Threads Library provides two basic ways to synchronize threads: mutual exclusion semaphores(mutexes) and events.

4.1  Mutexes

Mutual exclusion semaphores, or mutexes, provide a way to ensure that only one thread is executing a particular piece of code at a time.

The mutexes described here keep track of ownership and lock counts. This allows a thread to lock a mutex a number of times in the code path without having to worry about the thread blocking. Also, threads that are blocked on these mutexes are awakened in the order that they blocked so that the thread that has been waiting the longest will be awakened when the mutex become available.

4.1.1  Functions

uint8_t avr_thread_mutex_gain(volatile avr_thread_mutex* mutex, uint16_t ticks)   function

This function tries to gain ownership of the given mutex, mutex.

If the mutex is unlocked, the current thread locks the mutex and thereby gains ownership of the mutex, and this function returns 1 immediately.

If the mutex is already locked and owned by the current thread, the lock-count is incremented and the function returns 1 immediately.

If the mutex is already locked and owned by another thread, this thread blocks until the mutex becomes available or until the given number of ticks, ticks, have elapsed. If the thread successfully locks the mutex before the number of ticks have elapsed, the function return 1. Otherwise, the function times-out and returns 0. If the thread blocks and you have passed ticks as zero, the function will wait indefinitely until the mutex becomes available.

void avr_thread_mutex_release(volatile avr_thread_mutex* mutex)   function

This function releases the given mutex. The mutex is not really released until this function is called the same number of times as the avr_thread_mutex_gain() function was called in locking the mutex.

If multiple threads are waiting on this mutex, the thread that has been waiting the longest is released.

struct avr_thread_mutex   structure

This structure is used by the AVR Threads Library to hold mutex data. It should be treated as an opaque object.

4.2  Basic Mutexes

Basic mutexes are very simple and lack some important features of the regular mutexes (see 4.1). While the advantage of basic mutexes is their execution-speed and a smaller code and memory foot-print, you should exercise care in using them since they do not keep track of ownership or lock counts. For example, if a thread locks a basic mutex and tries to lock it again, the thread will block.

4.2.1  Functions

void avr_thread_mutex_basic_gain(volatile avr_thread_mutex_basic* mutex)   function

This function tries to lock the given basic mutex, mutex. If the mutex is already locked, the thread blocks on the basic-mutex waiting for another thread to release the lock on the thread.

A thread that has called avr_thread_mutex_basic_gain() should not call it again without first releasing the lock with avr_thread_mutex_basic_release().

uint8_t avr_thread_mutex_basic_test_and_gain(volatile avr_thread_mutex_basic* mutex)   function

This function tries to lock the given basic mutex, mutex. If it is not already locked by another thread, the mutex is locked and the function returns 1. If it is already locked by another thread, the function does not block but instead returns 0 immediately.

void avr_thread_mutex_basic_release(volatile avr_thread_mutex_basic* mutex)   function

This function releases the lock on the given basic mutex, mutex.

struct avr_thread_mutex_basic   structure

This structure is used by the AVR Threads Library to hold basic mutex data. It should be treated as an opaque object.