On 3/31/2023 8:56 AM, Gregory Nutt wrote:
Even more. In my previous example if semaphore is posted from the
interrupt
we do not know which of TaskA or TaskB is no longer a "holder l" of a
semaphore.
You are right. In this usage case, the counting semaphore is not
being used for locking; it is being used for signalling an event per
https://cwiki.apache.org/confluence/display/NUTTX/Signaling+Semaphores+and+Priority+Inheritance
In that case, priority inheritance must be turned off.
You example is really confusing because you are mixing two different
concepts, just subtly enough to be really confusing. If a counting
semaphore is used for locking a set of multiple resources, the posting
the semaphore does not release the resource. That is not the way that
it is done. Here is a more believable example of how this would work:
1. TaskA with priority 10 allocates DMA0 channel by calling a DMA
channel allocation function. If a DMA channel is available, it is
allocated and the allocation function takes the semaphore. TaskA
then starts DMA activity.
2. TaskA waits on another signaling semaphore for the DMA to complete.
3. TaskB with priority 20 does the same.
4. TaskC with priority 30 wants to allocate a DMA channel. It calls
the channel allocation function which waits on the sempahore for a
count to be available. This boost the priority of TaskA and TaskB
to 30.
5. When the DMA started by TaskA completes, it signals TaskA which
calls the resource deallocation function which increments the
counting semaphore, giving the count to TaskC and storing the base
priorities.
The confusion arises because you are mixing the signaling logic with the
resource deallocation logic.
The mm/iob logic works basically this way. The logic more complex then
you would think from above. IOBs is an example of a critical system
resource that has multiple copies and utilizes a counting semaphore with
priority inheritance to achieve good real time performance. IOB
handling is key logic for the correct real time operation of the overall
system. Nothing we do must risk this.
Other places where this logic is (probably) used:
arch/arm/src/rp2040/rp2040_i2s.c: nxsem_init(&priv->bufsem, 0,
CONFIG_RP2040_I2S_MAXINFLIGHT);
arch/arm/src/rtl8720c/amebaz_depend.c: if (sem_init(_sema, 0,
init_val))
arch/arm/src/sama5/sam_ssc.c: nxsem_init(&priv->bufsem, 0,
CONFIG_SAMA5_SSC_MAXINFLIGHT);
arch/arm/src/samv7/sam_ssc.c: nxsem_init(&priv->bufsem, 0,
CONFIG_SAMV7_SSC_MAXINFLIGHT);
arch/arm/src/stm32/stm32_i2s.c: nxsem_init(&priv->bufsem, 0,
CONFIG_STM32_I2S_MAXINFLIGHT);
drivers/can/mcp2515.c: nxsem_init(&priv->txfsem, 0,
MCP2515_NUM_TX_BUFFERS);
drivers/video/vnc/vnc_server.c: nxsem_init(&session->freesem, 0,
CONFIG_VNCSERVER_NUPDATES);
sched/pthread/pthread_completejoin.c: nxsem_init(&pjoin->data_sem,
0, (ntasks_waiting + 1));
wireless/bluetooth/bt_hcicore.c: nxsem_init(&g_btdev.le_pkts_sem, 0,
g_btdev.le_pkts);
wireless/bluetooth/bt_hcicore.c: nxsem_init(&g_btdev.ncmd_sem, 0, 1);
wireless/ieee802154/mac802154.c: nxsem_init(&priv->txdesc_sem, 0,
CONFIG_MAC802154_NTXDESC);
wireless/ieee802154/mac802154.c: nxsem_init(&mac->opsem, 0, 1);
Maybe:
arch/risc-v/src/bl602/bl602_os_hal.c: ret = nxsem_init(sem, 0, init);
arch/risc-v/src/esp32c3/esp32c3_ble_adapter.c: ret =
sem_init(&bt_sem->sem, 0, init);
arch/risc-v/src/esp32c3/esp32c3_wifi_adapter.c: ret =
nxsem_init(sem, 0, init);
arch/xtensa/src/esp32/esp32_ble_adapter.c: ret = sem_init(sem, 0, init);
arch/xtensa/src/esp32/esp32_wifi_adapter.c: ret = nxsem_init(sem, 0,
init);
arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c: ret =
nxsem_init(sem, 0, init);