Management of locks in multithreaded applications
A thread-safe function protects shared resources from concurrent
access using locks. There are functions in the C library that you
can re-implement, that enable you to manage the locking mechanisms
and so prevent the corruption of shared data such as the heap. These
functions are mutex functions, where the lifecycle of a mutex is
one of initialization, iterative acquisition and releasing of the
mutex as required, and then optionally freeing the mutex when it
is never going to be required again. The mutex functions wrap onto
your own Real-Time Operating System (RTOS)
calls, and their function prototypes are:
_mutex_initialize()
int _mutex_initialize(mutex *m);
This function accepts a pointer to a 32-bit word and initializes
it as a valid mutex.
By default, _mutex_initialize() returns
zero for a nonthreaded application. Therefore, in a multithreaded
application, _mutex_initialize() must return
a nonzero value on success so that at runtime, the library knows
that it is being used in a multithreaded environment.
Ensure that _mutex_initialize() initializes
the mutex to an unlocked state.
This function must be supplied if you are using mutexes.
_mutex_acquire()
void _mutex_acquire(mutex *m);
This function causes the calling thread to obtain a lock on
the supplied mutex.
_mutex_acquire() returns immediately
if the mutex has no owner. If the mutex is owned by another thread, _mutex_acquire() must
block it until it becomes available.
_mutex_acquire() is not called by the
thread that already owns the mutex.
This function must be supplied if you are using mutexes.
_mutex_release()
void _mutex_release(mutex *m);
This function causes the calling thread to release the lock
on a mutex acquired by _mutex_acquire().
The mutex remains in existence, and can be re-locked by a
subsequent call to mutex_acquire().
_mutex_release() assumes that the mutex
is owned by the calling thread.
This function must be supplied if you are using mutexes.
_mutex_free()
void _mutex_free(mutex *m);
This function causes the calling thread to free the supplied
mutex. Any operating system resources associated with the mutex
are freed. The mutex is destroyed and cannot be reused.
_mutex_free() assumes that the mutex
is owned by the calling thread.
This function is optional. If you do not supply this function,
the C library does not attempt to call it.
The mutex data structure type that is used
as the parameter to the _mutex_*() functions
is not defined in any of the ARM compiler toolchain header files,
but must be defined elsewhere. Typically, it is defined as part
of RTOS code.
Functions that call _mutex_*() functions
create 4 bytes of memory for holding the mutex data structure. __Heap_Initialize() is
one such function.
For the C library, a mutex is specified as a single 32-bit
word of memory that can be placed anywhere. However, if your mutex
implementation requires more space than this, or demands that the
mutex be in a special memory area, then you must treat the default
mutex as a pointer to a real mutex.
A typical example of a re-implementation framework for _mutex_initialize(), _mutex_acquire(),
and _mutex_release() is as follows, where SEMAPHORE_ID, CreateLock(), AcquireLock(),
and ReleaseLock() are defined in the RTOS,
and (...) implies additional parameters:
int _mutex_initialize(SEMAPHORE_ID sid)
{
/* Create a mutex semaphore */
sid = CreateLock(...);
return 1;
}
void _mutex_acquire(SEMAPHORE_ID sid)
{
/* Task sleep until get semaphore */
AcquireLock(sid, ...);
}
void _mutex_release(SEMAPHORE_ID sid)
{
/* Release the semaphore. */
ReleaseLock(sid);
}
void _mutex_free(SEMAPHORE_ID sid)
{
/* Free the semaphore. */
FreeLock(sid, ...);
}
Note
_mutex_release() releases
the lock on the mutex that was acquired by _mutex_acquire(), but
the mutex still exists, and can be re-locked by a subsequent call
to _mutex_acquire().
It is only when the optional wrapper function _mutex_free() is
called that the mutex is destroyed. After the mutex is destroyed,
it cannot be used without first calling _mutex_initialize() to
set it up again.
See also