Mutual Exclusion lock

nxmutex

Use nxmutex prefixed api to protect resources. In fact, nxmutex is implemented based on nxsem. The difference between nxmutex and nxsem is that nxmutex supports priority inheritance by default, nxsem do not support priority inheritance by default.

Typical Usage

Call nxmutex_init() for driver, when two tasks will use driver, their timing will be:

taskA

taskB

nxmutex_lock()

nxmutex_lock()

get lock running

wait for lock

nxmutex_unlock()

wait for lock

get lock running

nxmutex_unlock()

Priority inheritance

If CONFIG_PRIORITY_INHERITANCE is chosen, the priority of the task holding the mutex may be changed. This is an example:

There are three tasks. Their priorities are high, medium, and low. We refer to them as Htask Mtask Ltask

Htask and Ltask will hold the same mutex. Mtask does not hold mutex

if CONFIG_PRIORITY_INHERITANCE is not chosen, task running order
  1. Ltask hold a mutex first

  2. Then Htask running, Htask can’t hold the mutex,so wait

  3. Then Mtask running, because Mtask priority higher than Ltask.

  4. When Mtask finish, Ltask will start running.

  5. When Ltask finish, Htask will start running.

From the above process, we can see that the medium-priority tasks run ahead of the high-priority tasks, which is unacceptable.

if CONFIG_PRIORITY_INHERITANCE is chosen, task running order
  1. Ltask hold a mutex first.

  2. Then Htask running, Htask can’t hold the mutex, then boost the priority of Ltask

to be the same as Htask.
  1. Because Ltask priority is higher than Mtask,so Mtask not running.

  2. When ‘Ltask’ finish, Htask will start running.

  3. When Htask finish, Mtask will start running.

Priority inheritance prevents medium-priority tasks from running ahead of high-priority tasks

Api description

void nxmutex_init(FAR mutex_t *mutex)

This function initialize the UNNAMED mutex :param mutex: mutex to be initialized.

Returns:

Zero(OK) is returned on success.A negated errno value is returned on failure.

void nxmutex_destroy(FAR mutex_t *mutex)

This function destroy the UNNAMED mutex :param mutex: mutex to be destroyed.

Returns:

Zero(OK) is returned on success.A negated errno value is returned on failure.

void nxmutex_lock(FAR mutex_t *mutex)

This function attempts to lock the mutex referenced by ‘mutex’. The mutex is implemented with a semaphore, so if the semaphore value is (<=) zero, then the calling task will not return until it successfully acquires the lock.

Parameters:
  • mutex – mutex descriptor.

Returns:

Zero(OK) is returned on success.A negated errno value is returned on failure.

void nxmutex_trylock(FAR mutex_t *mutex)

This function locks the mutex only if the mutex is currently not locked. If the mutex has been locked already, the call returns without blocking.

Parameters:
  • mutex – mutex descriptor.

Returns:

Zero(OK) is returned on success.A negated errno value is returned on failure. Possible returned errors:

EINVAL - Invalid attempt to lock the mutex EAGAIN - The mutex is not available.

void nxmutex_is_locked(FAR mutex_t *mutex)

This function get the lock state the mutex referenced by ‘mutex’.

Parameters:
  • mutex – mutex descriptor.

Returns:

if mutex is locked will return ture. if not will return false

void nxmutex_unlock(FAR mutex_t *mutex)

This function attempts to unlock the mutex referenced by ‘mutex’.

Parameters:
  • mutex – mutex descriptor.

Returns:

Zero(OK) is returned on success.A negated errno value is returned on failure.

void nxmutex_reset(FAR mutex_t *mutex)

This function resets mutex states by ‘mutex’.

Parameters:
  • mutex – mutex descriptor.

Returns:

Zero(OK) is returned on success.A negated errno value is returned on failure.