KallistiOS git master
Independent SDK for the Sega Dreamcast
Loading...
Searching...
No Matches
mutex.h File Reference

Mutual exclusion locks. More...

#include <kos/cdefs.h>

Go to the source code of this file.

Data Structures

struct  mutex_t
 Mutual exclusion lock type. More...
 

Macros

#define MUTEX_INITIALIZER   { MUTEX_TYPE_NORMAL, NULL, 0 }
 Initializer for a transient mutex.
 
#define ERRORCHECK_MUTEX_INITIALIZER   { MUTEX_TYPE_ERRORCHECK, NULL, 0 }
 Initializer for a transient error-checking mutex.
 
#define RECURSIVE_MUTEX_INITIALIZER   { MUTEX_TYPE_RECURSIVE, NULL, 0 }
 Initializer for a transient recursive mutex.
 
#define mutex_lock_scoped(m)
 Lock a mutex with scope management.
 

Functions

int mutex_init (mutex_t *m, unsigned int mtype) __nonnull_all
 Initialize a new mutex.
 
int mutex_destroy (mutex_t *m) __nonnull_all
 Destroy a mutex.
 
int mutex_lock_irqsafe (mutex_t *m) __nonnull_all
 Lock a mutex.
 
int mutex_lock_timed (mutex_t *m, unsigned int timeout) __nonnull_all
 Lock a mutex (with a timeout).
 
static __nonnull_all int mutex_lock (mutex_t *m)
 Lock a mutex.
 
int __pure mutex_is_locked (const mutex_t *m) __nonnull_all
 Check if a mutex is locked.
 
int mutex_trylock (mutex_t *m) __nonnull_all
 Attempt to lock a mutex.
 
int mutex_unlock (mutex_t *m) __nonnull_all
 Unlock a mutex.
 

Mutex types

Types of Mutexes supported by KOS

The values defined in here are the various types of mutexes that KallistiOS supports.

#define MUTEX_TYPE_NORMAL   0
 Normal mutex type.
 
#define MUTEX_TYPE_OLDNORMAL   1
 Alias for MUTEX_TYPE_NORMAL.
 
#define MUTEX_TYPE_RECURSIVE   3
 Recursive mutex type.
 
#define MUTEX_TYPE_DESTROYED   4
 Mutex that has been destroyed.
 
#define MUTEX_TYPE_DEFAULT   MUTEX_TYPE_NORMAL
 Default mutex type.
 
static const unsigned int MUTEX_TYPE_ERRORCHECK = 2
 

Detailed Description

Mutual exclusion locks.

This file defines mutual exclusion locks (or mutexes for short). The concept of a mutex is one of the most common types of locks in a multi-threaded environment. Mutexes do exactly what they sound like, they keep two (or more) threads mutually exclusive from one another. A mutex is used around a block of code to prevent two threads from interfering with one another when only one would be appropriate to be in the block at a time.

KallistiOS implements 2 types of mutexes, normal mutexes and recursive mutexes. Internally the implementation is the same, the only difference lies in error-checking. When assert() calls are disabled (by setting the NDEBUG macro), they should have the exact same behaviour.

A normal mutex (MUTEX_TYPE_NORMAL) is roughly equivalent to a semaphore that has been initialized with a count of 1. If assert() is disabled, there is no protection against threads unlocking normal mutexes they didn't lock, nor is there any protection against a thread locking the same mutex twice.

A recursive mutex (MUTEX_TYPE_RECURSIVE) allows you to lock the mutex N times in the same thread; in which case, the mutex has to be unlocked N times for the mutex to be effectively released. Still only one thread can hold the lock, but it may hold it as many times as it needs to.

Author
Lawrence Sebald
See also
kos/sem.h

Macro Definition Documentation

◆ ERRORCHECK_MUTEX_INITIALIZER

#define ERRORCHECK_MUTEX_INITIALIZER   { MUTEX_TYPE_ERRORCHECK, NULL, 0 }

Initializer for a transient error-checking mutex.

Referenced by main().

◆ MUTEX_INITIALIZER

#define MUTEX_INITIALIZER   { MUTEX_TYPE_NORMAL, NULL, 0 }

Initializer for a transient mutex.

◆ mutex_lock_scoped

#define mutex_lock_scoped ( m)
Value:
__mutex_lock_scoped((m), __LINE__)

Lock a mutex with scope management.

This macro will lock a mutex, similarly to mutex_lock, with the difference that the mutex will automatically be unlocked once the execution exits the functional block in which the macro was called.

Parameters
mThe mutex to acquire

◆ MUTEX_TYPE_DEFAULT

#define MUTEX_TYPE_DEFAULT   MUTEX_TYPE_NORMAL

Default mutex type.

◆ MUTEX_TYPE_DESTROYED

#define MUTEX_TYPE_DESTROYED   4

Mutex that has been destroyed.

◆ MUTEX_TYPE_NORMAL

#define MUTEX_TYPE_NORMAL   0

Normal mutex type.

Referenced by reentrant_mutex_init().

◆ MUTEX_TYPE_OLDNORMAL

#define MUTEX_TYPE_OLDNORMAL   1

Alias for MUTEX_TYPE_NORMAL.

◆ MUTEX_TYPE_RECURSIVE

#define MUTEX_TYPE_RECURSIVE   3

Recursive mutex type.

◆ RECURSIVE_MUTEX_INITIALIZER

#define RECURSIVE_MUTEX_INITIALIZER   { MUTEX_TYPE_RECURSIVE, NULL, 0 }

Initializer for a transient recursive mutex.

Function Documentation

◆ mutex_destroy()

int mutex_destroy ( mutex_t * m)

Destroy a mutex.

This function destroys a mutex, releasing any memory that may have been allocated internally for it. It is your responsibility to make sure that all threads waiting on the mutex are taken care of before destroying the mutex.

This function can be called on statically initialized as well as dynamically initialized mutexes.

Parameters
mThe mutex to destroy
Return values
0On success
-1On error, errno will be set as appropriate
Error Conditions:
EBUSY - the mutex is currently locked

Referenced by main(), and reentrant_mutex_uninit().

◆ mutex_init()

int mutex_init ( mutex_t * m,
unsigned int mtype )

Initialize a new mutex.

This function initializes a new mutex for use.

Parameters
mThe mutex to initialize
mtypeThe type of the mutex to initialize it to
Return values
0On success
-1On error, errno will be set as appropriate
Error Conditions:
EINVAL - an invalid type of mutex was specified
See also
mutex_types

Referenced by reentrant_mutex_init().

◆ mutex_is_locked()

int __pure mutex_is_locked ( const mutex_t * m)

Check if a mutex is locked.

This function will check whether or not a mutex is currently locked. This is not a thread-safe way to determine if the mutex will be locked by the time you get around to doing it. If you wish to attempt to lock a mutex without blocking, look at mutex_trylock(), not this.

Parameters
mThe mutex to check
Return values
0If the mutex is not currently locked
1If the mutex is currently locked

Referenced by main(), main(), and reentrant_mutex_lock().

◆ mutex_lock()

static __nonnull_all int mutex_lock ( mutex_t * m)
inlinestatic

Lock a mutex.

This function will lock a mutex, if it is not already locked by another thread. If it is locked by another thread already, this function will block until the mutex has been acquired for the calling thread.

The semantics of this function depend on the type of mutex that is used.

This function cannot be used in an interrupt context.

Parameters
mThe mutex to acquire
Return values
0On success
-1On error, sets errno as appropriate
Error Conditions:
EPERM - called inside an interrupt
EAGAIN - lock has been acquired too many times (recursive)

References mutex_lock_timed().

Referenced by check_controller(), draw_wave(), inner_once_func(), kb_test(), load_song_list(), main(), reentrant_mutex_lock(), snd_hook(), song_menu_render(), st_add_fds(), st_create(), st_destroy(), thd0(), thd1(), thd2(), and thd_3().

◆ mutex_lock_irqsafe()

int mutex_lock_irqsafe ( mutex_t * m)

Lock a mutex.

This function will lock a mutex, if it is not already locked by another thread. If it is locked by another thread already, this function will block until the mutex has been acquired for the calling thread. This function can be called from within an interrupt context. In that case, if the mutex is already locked, an error will be returned.

The semantics of this function depend on the type of mutex that is used.

Parameters
mThe mutex to acquire
Return values
0On success
-1On error, sets errno as appropriate
Error Conditions:
EAGAIN - lock has been acquired too many times (recursive), or the function was called inside an interrupt and the mutex was already locked

◆ mutex_lock_timed()

int mutex_lock_timed ( mutex_t * m,
unsigned int timeout )

Lock a mutex (with a timeout).

This function will attempt to lock a mutex. If the lock can be acquired immediately, the function will return immediately. If not, the function will block for up to the specified number of milliseconds to wait for the lock. If the lock cannot be acquired in this timeframe, this function will return an error.

This function cannot be used in an interrupt context.

Parameters
mThe mutex to acquire
timeoutThe number of milliseconds to wait for the lock
Return values
0On success
-1On error, errno will be set as appropriate
Error Conditions:
ETIMEDOUT - the timeout expired
EAGAIN - lock has been acquired too many times (recursive)

Referenced by mutex_lock().

◆ mutex_trylock()

int mutex_trylock ( mutex_t * m)

Attempt to lock a mutex.

This function will attempt to acquire the mutex for the calling thread, returning immediately whether or not it could be acquired. If the mutex cannot be acquired, an error will be returned.

This function is safe to call inside an interrupt.

Parameters
mThe mutex to attempt to acquire
Return values
0On successfully acquiring the mutex
-1If the mutex cannot be acquired without blocking
Error Conditions:
EBUSY - the mutex is already locked (mutex_lock() would block)
EAGAIN - lock has been acquired too many times (recursive)
EDEADLK - would deadlock (error-checking)

Referenced by on_key_event().

◆ mutex_unlock()

int mutex_unlock ( mutex_t * m)

Unlock a mutex.

This function will unlock a mutex, allowing other threads to acquire it. The semantics of this operation depend on the mutex type in use.

Parameters
mThe mutex to unlock
Return values
0On success
-1On error, errno will be set as appropriate.
Error Conditions: None defined

References mutex_unlock().

Referenced by check_controller(), draw_wave(), inner_once_func(), kb_test(), load_song_list(), main(), mutex_unlock(), on_key_event(), reentrant_mutex_unlock(), snd_hook(), song_menu_render(), st_add_fds(), st_create(), st_destroy(), thd0(), thd1(), thd2(), and thd_3().

Variable Documentation

◆ MUTEX_TYPE_ERRORCHECK

const unsigned int MUTEX_TYPE_ERRORCHECK = 2
static