KallistiOS  ##version##
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
Data Structures | Macros | Typedefs | Functions
mutex.h File Reference

Mutual exclusion locks. More...

#include <sys/cdefs.h>
#include <kos/thread.h>

Go to the source code of this file.

Data Structures

struct  kos_mutex
 Mutual exclusion lock type. More...
 

Macros

#define MUTEX_TYPE_NORMAL   1
 Normal mutex type. More...
 
#define MUTEX_TYPE_ERRORCHECK   2
 Error-checking mutex type. More...
 
#define MUTEX_TYPE_RECURSIVE   3
 Recursive mutex type. More...
 
#define MUTEX_TYPE_DEFAULT   MUTEX_TYPE_NORMAL
 Default mutex type. More...
 
#define MUTEX_INITIALIZER   { MUTEX_TYPE_NORMAL, 0, NULL, 0 }
 Initializer for a transient mutex. More...
 
#define ERRORCHECK_MUTEX_INITIALIZER   { MUTEX_TYPE_ERRORCHECK, 0, NULL, 0 }
 Initializer for a transient error-checking mutex. More...
 
#define RECURSIVE_MUTEX_INITIALIZER   { MUTEX_TYPE_RECURSIVE, 0, NULL, 0 }
 Initializer for a transient recursive mutex. More...
 

Typedefs

typedef struct kos_mutex mutex_t
 Mutual exclusion lock type. More...
 

Functions

mutex_tmutex_create () __attribute__((deprecated))
 Allocate a new mutex. More...
 
int mutex_init (mutex_t *m, int mtype)
 Initialize a new mutex. More...
 
int mutex_destroy (mutex_t *m)
 Destroy a mutex. More...
 
int mutex_lock (mutex_t *m)
 Lock a mutex. More...
 
int mutex_lock_timed (mutex_t *m, int timeout)
 Lock a mutex (with a timeout). More...
 
int mutex_is_locked (mutex_t *m)
 Check if a mutex is locked. More...
 
int mutex_trylock (mutex_t *m)
 Attempt to lock a mutex. More...
 
int mutex_unlock (mutex_t *m)
 Unlock a mutex. More...
 

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 interfereing with one another when only one would be appropriate to be in the block at a time.

KallistiOS implments 3 types of mutexes, to bring it roughly in-line with POSIX. The types of mutexes that can be made are normal, error-checking, and recursive. Each has its own strengths and weaknesses, which are briefly discussed below.

A normal mutex (MUTEX_TYPE_NORMAL) is the fastest and simplest mutex of the bunch. This is roughly equivalent to a semaphore that has been initialized with a count of 1. There is no protection against threads unlocking normal mutexes they didn't lock, nor is there any protection against deadlocks that would arise from locking the mutex twice.

An error-checking mutex (MUTEX_TYPE_ERRORCHECK) adds a small amount of error checking on top of a normal mutex. This type will not allow you to lock the mutex twice (it will return an error if the same thread tries to lock it two times so it will not deadlock), and it will not allow a different thread to unlock the mutex if it isn't the one holding the lock.

A recursive mutex (MUTEX_TYPE_RECURSIVE) extends the error checking mutex by allowing you to lock the mutex twice in the same thread, but you must also unlock it twice (this works for any number of locks – lock it n times, you must unlock it n times). Still only one thread can hold the lock, but it may hold it as many times as it needs to. This is equivalent to the recursive_lock_t type that was available in KallistiOS for a while (before it was basically merged back into a normal mutex).

There is a fourth type of mutex defined (MUTEX_TYPE_DEFAULT), which maps to the MUTEX_TYPE_NORMAL type. This is simply for alignment with POSIX.

Author
Lawrence Sebald
See also
kos/sem.h

Macro Definition Documentation

#define ERRORCHECK_MUTEX_INITIALIZER   { MUTEX_TYPE_ERRORCHECK, 0, NULL, 0 }

Initializer for a transient error-checking mutex.

#define MUTEX_INITIALIZER   { MUTEX_TYPE_NORMAL, 0, NULL, 0 }

Initializer for a transient mutex.

#define RECURSIVE_MUTEX_INITIALIZER   { MUTEX_TYPE_RECURSIVE, 0, NULL, 0 }

Initializer for a transient recursive mutex.

Typedef Documentation

typedef struct kos_mutex mutex_t

Mutual exclusion lock type.

All members of this structure should be considered to be private. It is unsafe to change anything in here yourself.

Function Documentation

mutex_t* mutex_create ( )

Allocate a new mutex.

This function allocates and initializes a new mutex for use. This function will always create mutexes of the type MUTEX_TYPE_NORMAL.

Returns
The newly created mutex on success, or NULL on failure (errno will be set as appropriate).
Note
This function is formally deprecated. It should not be used in any future code, and may be removed in the future. You should instead use mutex_init().
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 ones.

Return values
0On success
-1On error, errno will be set as appropriate
Error Conditions:
EBUSY - the mutex is currently locked
int mutex_init ( mutex_t m,
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
int mutex_is_locked ( 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
int mutex_lock ( 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.

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:
EPERM - called inside an interrupt
EINVAL - the mutex has not been initialized properly
EAGAIN - lock has been acquired too many times (recursive)
EDEADLK - would deadlock (error-checking)
int mutex_lock_timed ( mutex_t m,
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.

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:
EPERM - called inside an interrupt
EINVAL - the mutex has not been initialized properly
EINVAL - the timeout value was invalid (less than 0)
ETIMEDOUT - the timeout expired
EAGAIN - lock has been acquired too many times (recursive)
EDEADLK - would deadlock (error-checking)
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:
EAGAIN - the mutex is already locked (mutex_lock() would block)
EINVAL - the mutex has not been initialized properly
EAGAIN - lock has been acquired too many times (recursive)
EDEADLK - would deadlock (error-checking)
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:
EPERM - the current thread does not own the mutex (error-checking or recursive)