Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libc/semaphore:sem_init change defult protocol #5070

Merged
merged 4 commits into from
Oct 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Documentation/reference/os/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ in other header files.
arch.rst
board.rst
time_clock.rst
mutex.rst
wqueue.rst
addrenv.rst
nuttx.rst
Expand Down
130 changes: 130 additions & 0 deletions Documentation/reference/os/mutex.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
=====================
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

usually 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
#. `Ltask` hold a mutex first
#. Then `Htask` running, `Htask` can't hold the mutex,so wait
#. Then `Mtask` running, because `Mtask` priority higher than `Ltask`.
#. When `Mtask` finish, `Ltask` will start running.
#. 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
#. `Ltask` hold a mutex first.
#. Then `Htask` running, `Htask` can't hold the mutex, then boost the priority of `Ltask`
to be the same as `Htask`.
#. Because `Ltask` priority is higher than `Mtask`,so `Mtask` not running.
#. When 'Ltask' finish, `Htask` will start running.
#. When `Htask` finish, `Mtask` will start running.

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

Api description
===============
.. c:function:: void nxmutex_init(FAR mutex_t *mutex)

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

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

.. c:function:: void nxmutex_destroy(FAR mutex_t *mutex)

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

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

.. c:function:: 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.

:param mutex: mutex descriptor.

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

.. c:function:: 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.

:param mutex: mutex descriptor.

:return:
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.

.. c:function:: void nxmutex_is_locked(FAR mutex_t *mutex)

This function get the lock state the mutex referenced by 'mutex'.

:param mutex: mutex descriptor.

:return:
if mutex is locked will return `ture`. if not will reutrn `false`

.. c:function:: void nxmutex_unlock(FAR mutex_t *mutex)

This function attempts to unlock the mutex referenced by 'mutex'.

:param mutex: mutex descriptor.

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

.. c:function:: void nxmutex_reset(FAR mutex_t *mutex)

This function resets mutex states by 'mutex'.

:param mutex: mutex descriptor.

:return:
Zero(OK) is returned on success.A negated errno value is returned on failure.
6 changes: 6 additions & 0 deletions Documentation/reference/user/05_counting_semaphore.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ different thread posts the semaphore. Priority inheritance should
*never* be used in this signaling case. Subtle, strange behaviors may
result.

Semaphore does not support priority inheritance by default. If you need to
use a semaphore as a mutex you need to change its default behavior.

In user space, it is recommended to use pthread_mutex instead of
semaphore for resource protection

When priority inheritance is enabled with
``CONFIG_PRIORITY_INHERITANCE``, the default *protocol* for the
semaphore will be to use priority inheritance. For signaling semaphores,
Expand Down
6 changes: 3 additions & 3 deletions arch/arm/src/am335x/am335x_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ static struct am335x_i2c_priv_s am335x_i2c0_priv =
.refs = 0,
.lock = NXMUTEX_INITIALIZER,
#ifndef CONFIG_I2C_POLLED
.sem_isr = NXSEM_INITIALIZER(0, PRIOINHERIT_FLAGS_DISABLE),
.sem_isr = SEM_INITIALIZER(0),
xiaoxiang781216 marked this conversation as resolved.
Show resolved Hide resolved
#endif
.intstate = INTSTATE_IDLE,
.msgc = 0,
Expand Down Expand Up @@ -351,7 +351,7 @@ static struct am335x_i2c_priv_s am335x_i2c1_priv =
.refs = 0,
.lock = NXMUTEX_INITIALIZER,
#ifndef CONFIG_I2C_POLLED
.sem_isr = NXSEM_INITIALIZER(0, PRIOINHERIT_FLAGS_DISABLE),
.sem_isr = SEM_INITIALIZER(0),
#endif
.intstate = INTSTATE_IDLE,
.msgc = 0,
Expand Down Expand Up @@ -386,7 +386,7 @@ static struct am335x_i2c_priv_s am335x_i2c2_priv =
.refs = 0,
.lock = NXMUTEX_INITIALIZER,
#ifndef CONFIG_I2C_POLLED
.sem_isr = NXSEM_INITIALIZER(0, PRIOINHERIT_FLAGS_DISABLE),
.sem_isr = SEM_INITIALIZER(0),
#endif
.intstate = INTSTATE_IDLE,
.msgc = 0,
Expand Down
1 change: 0 additions & 1 deletion arch/arm/src/cxd56xx/cxd56_emmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -942,7 +942,6 @@ int cxd56_emmcinitialize(void)
memset(priv, 0, sizeof(struct cxd56_emmc_state_s));
nxmutex_init(&priv->lock);
nxsem_init(&g_waitsem, 0, 0);
nxsem_set_protocol(&g_waitsem, SEM_PRIO_NONE);

ret = emmc_hwinitialize();
if (ret != OK)
Expand Down
1 change: 0 additions & 1 deletion arch/arm/src/cxd56xx/cxd56_farapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,6 @@ void cxd56_farapiinitialize(void)
#endif
nxmutex_init(&g_farlock);
nxsem_init(&g_farwait, 0, 0);
nxsem_set_protocol(&g_farwait, SEM_PRIO_NONE);

cxd56_iccinit(CXD56_PROTO_MBX);
cxd56_iccinit(CXD56_PROTO_FLG);
Expand Down
1 change: 0 additions & 1 deletion arch/arm/src/cxd56xx/cxd56_ge2d.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ int cxd56_ge2dinitialize(const char *devname)

nxmutex_init(&g_lock);
nxsem_init(&g_wait, 0, 0);
nxsem_set_protocol(&g_wait, SEM_PRIO_NONE);

ret = register_driver(devname, &g_ge2dfops, 0666, NULL);
if (ret != 0)
Expand Down
4 changes: 0 additions & 4 deletions arch/arm/src/cxd56xx/cxd56_gnss.c
Original file line number Diff line number Diff line change
Expand Up @@ -2609,8 +2609,6 @@ static int cxd56_gnss_open(struct file *filep)
goto err0;
}

nxsem_set_protocol(&priv->syncsem, SEM_PRIO_NONE);

/* Prohibit the clock change during loading image */

up_pm_acquire_freqlock(&g_hold_lock);
Expand Down Expand Up @@ -3029,8 +3027,6 @@ static int cxd56_gnss_register(const char *devpath)
goto err0;
}

nxsem_set_protocol(&priv->apiwait, SEM_PRIO_NONE);

ret = nxmutex_init(&priv->ioctllock);
if (ret < 0)
{
Expand Down
1 change: 0 additions & 1 deletion arch/arm/src/cxd56xx/cxd56_hostif.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,6 @@ static int hif_initialize(struct hostif_buff_s *buffer)
cxd56_iccinit(CXD56_PROTO_HOSTIF);

nxsem_init(&drv->sync, 0, 0);
nxsem_set_protocol(&drv->sync, SEM_PRIO_NONE);

ret = cxd56_iccregisterhandler(CXD56_PROTO_HOSTIF, hif_rxhandler, NULL);

Expand Down
6 changes: 3 additions & 3 deletions arch/arm/src/cxd56xx/cxd56_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static struct cxd56_i2cdev_s g_i2c0dev =
.base = CXD56_SCU_I2C0_BASE,
.irqid = CXD56_IRQ_SCU_I2C0,
.lock = NXMUTEX_INITIALIZER,
.wait = NXSEM_INITIALIZER(0, PRIOINHERIT_FLAGS_DISABLE),
.wait = SEM_INITIALIZER(0),
.refs = 0,
};
#endif
Expand All @@ -116,7 +116,7 @@ static struct cxd56_i2cdev_s g_i2c1dev =
.base = CXD56_SCU_I2C1_BASE,
.irqid = CXD56_IRQ_SCU_I2C1,
.lock = NXMUTEX_INITIALIZER,
.wait = NXSEM_INITIALIZER(0, PRIOINHERIT_FLAGS_DISABLE),
.wait = SEM_INITIALIZER(0),
.refs = 0,
};
#endif
Expand All @@ -127,7 +127,7 @@ static struct cxd56_i2cdev_s g_i2c2dev =
.base = CXD56_I2CM_BASE,
.irqid = CXD56_IRQ_I2CM,
.lock = NXMUTEX_INITIALIZER,
.wait = NXSEM_INITIALIZER(0, PRIOINHERIT_FLAGS_DISABLE),
.wait = SEM_INITIALIZER(0),
.refs = 0,
};
#endif
Expand Down
1 change: 0 additions & 1 deletion arch/arm/src/cxd56xx/cxd56_icc.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ static struct iccdev_s *icc_devnew(void)
memset(priv, 0, sizeof(struct iccdev_s));

nxsem_init(&priv->rxwait, 0, 0);
nxsem_set_protocol(&priv->rxwait, SEM_PRIO_NONE);

/* Initialize receive queue and free list */

Expand Down
2 changes: 0 additions & 2 deletions arch/arm/src/cxd56xx/cxd56_powermgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -837,14 +837,12 @@ int cxd56_pm_initialize(void)
}

ret = nxsem_init(&g_freqlockwait, 0, 0);
nxsem_set_protocol(&g_freqlockwait, SEM_PRIO_NONE);
if (ret < 0)
{
return ret;
}

ret = nxsem_init(&g_bootsync, 0, 0);
nxsem_set_protocol(&g_bootsync, SEM_PRIO_NONE);
if (ret < 0)
{
return ret;
Expand Down
3 changes: 0 additions & 3 deletions arch/arm/src/cxd56xx/cxd56_scu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1990,7 +1990,6 @@ static int seq_fifoinit(struct seq_s *seq, int fifoid, uint16_t fsize)
/* Initialize DMA done wait semaphore */

nxsem_init(&fifo->dmawait, 0, 0);
nxsem_set_protocol(&fifo->dmawait, SEM_PRIO_NONE);

fifo->dmaresult = -1;
#endif
Expand Down Expand Up @@ -3429,12 +3428,10 @@ void scu_initialize(void)

nxmutex_init(&priv->synclock);
nxsem_init(&priv->syncwait, 0, 0);
nxsem_set_protocol(&priv->syncwait, SEM_PRIO_NONE);

for (i = 0; i < 3; i++)
{
nxsem_init(&priv->oneshotwait[i], 0, 0);
nxsem_set_protocol(&priv->oneshotwait[i], SEM_PRIO_NONE);
}

scufifo_initialize();
Expand Down
6 changes: 0 additions & 6 deletions arch/arm/src/cxd56xx/cxd56_sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1319,12 +1319,6 @@ static void cxd56_sdio_sdhci_reset(struct sdio_dev_s *dev)

nxsem_init(&priv->waitsem, 0, 0);

/* The waitsem semaphore is used for signaling and, hence, should not have
* priority inheritance enabled.
*/

nxsem_set_protocol(&priv->waitsem, SEM_PRIO_NONE);

/* The next phase of the hardware reset would be to set the SYSCTRL INITA
* bit to send 80 clock ticks for card to power up and then reset the card
* with CMD0. This is done elsewhere.
Expand Down
1 change: 0 additions & 1 deletion arch/arm/src/cxd56xx/cxd56_sph.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ static inline int cxd56_sphdevinit(const char *devname, int num)
}

nxsem_init(&priv->wait, 0, 0);
nxsem_set_protocol(&priv->wait, SEM_PRIO_NONE);
priv->id = num;

irq_attach(CXD56_IRQ_SPH0 + num, cxd56_sphirqhandler, NULL);
Expand Down
2 changes: 0 additions & 2 deletions arch/arm/src/cxd56xx/cxd56_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,6 @@ void cxd56_spi_dmaconfig(int port, int chtype, DMA_HANDLE handle,
if (!priv->dmaenable)
{
nxsem_init(&priv->dmasem, 0, 0);
nxsem_set_protocol(&priv->dmasem, SEM_PRIO_NONE);
priv->dmaenable = true;
}
}
Expand All @@ -1346,7 +1345,6 @@ void cxd56_spi_dmaconfig(int port, int chtype, DMA_HANDLE handle,
if (!priv->dmaenable)
{
nxsem_init(&priv->dmasem, 0, 0);
nxsem_set_protocol(&priv->dmasem, SEM_PRIO_NONE);
priv->dmaenable = true;
}
}
Expand Down
1 change: 0 additions & 1 deletion arch/arm/src/cxd56xx/cxd56_sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ void cxd56_sysctlinitialize(void)

nxmutex_init(&g_lock);
nxsem_init(&g_sync, 0, 0);
nxsem_set_protocol(&g_sync, SEM_PRIO_NONE);

cxd56_iccregisterhandler(CXD56_PROTO_SYSCTL, sysctl_rxhandler, NULL);

Expand Down
4 changes: 2 additions & 2 deletions arch/arm/src/efm32/efm32_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ static struct efm32_i2c_priv_s efm32_i2c0_priv =
.refs = 0,
.lock = NXMUTEX_INITIALIZER,
#ifndef CONFIG_I2C_POLLED
.sem_isr = NXSEM_INITIALIZER(0, PRIOINHERIT_FLAGS_DISABLE),
.sem_isr = SEM_INITIALIZER(0),
#endif
.result = I2CRESULT_NONE,
.msgc = 0,
Expand Down Expand Up @@ -363,7 +363,7 @@ static struct efm32_i2c_priv_s efm32_i2c1_priv =
.refs = 0,
.lock = NXMUTEX_INITIALIZER,
#ifndef CONFIG_I2C_POLLED
.sem_isr = NXSEM_INITIALIZER(0, PRIOINHERIT_FLAGS_DISABLE),
.sem_isr = SEM_INITIALIZER(0),
#endif
.result = I2CRESULT_NONE,
.msgc = 0,
Expand Down
6 changes: 0 additions & 6 deletions arch/arm/src/efm32/efm32_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1607,12 +1607,6 @@ static int spi_portinitialize(struct efm32_spidev_s *priv)
nxsem_init(&priv->rxdmasem, 0, 0);
nxsem_init(&priv->txdmasem, 0, 0);

/* These semaphores are used for signaling and, hence, should not have
* priority inheritance enabled.
*/

nxsem_set_protocol(&priv->rxdmasem, SEM_PRIO_NONE);
nxsem_set_protocol(&priv->txdmasem, SEM_PRIO_NONE);
#endif

/* Enable SPI */
Expand Down
Loading