CV-Bowen opened a new pull request, #21547:
URL: https://github.com/apache/nuttx/pull/21547
## Summary
Make libmetal's `metal_mutex` a recursive spinlock on NuttX, so
`rdev->lock` can be taken from interrupt context. This is what
apache/nuttx#21381 review asked for before the rpmsg_virtio rx path can
be dispatched in the interrupt (follow-up PR).
- `drivers/rpmsg`: `rpmsg_device_destroy()` no longer holds
`rdev->lock` around the endpoint release loop. `rpmsg_destroy_ept()`
sends NS_DESTROY there, which may sleep waiting for a tx buffer.
- `drivers/rptun`: `g_rptun_lock` becomes a plain `rmutex_t`; it is held
across ioctls that may block.
- `openamp/libmetal`: replace patch 0003 (rmutex) with a recursive
spinlock (irqsave + nopreempt) by default and an `is_mutex` flag to
switch one instance to an rmutex. `rptun_init()` sets it on
`rproc->lock`, which is held across the remoteproc ops. The nesting
depth is kept in `metal_mutex` because `rspinlock_t` does not count
without `CONFIG_SPINLOCK`. `metal_mutex_try_acquire()` now returns
non-zero on success as libmetal documents; the old patch passed
`nxrmutex_trylock()`'s 0 through.
- `drivers/rpmsg`: rpmsg_port/rpmsg_virtio `dump()` always take
`rdev->lock` now, also from interrupt and idle context.
## Impact
- `rdev->lock` (every rpmsg transport) now disables interrupts and
preemption while held. All regions under it on master are short list
and refcount updates; callbacks and sends already run outside it.
- `rproc->lock` stays a sleeping rmutex.
- Out-of-tree code that sleeps while holding a `metal_mutex` must set
`is_mutex` before first use.
- No Kconfig change.
## Testing
Host: Ubuntu 22.04.5 LTS x86_64, QEMU version 10.2.1, sim: cc (Ubuntu
13.1.0-8ubuntu1~22.04) 13.1.0, qemu-armv8a: aarch64-none-elf-gcc (Arm GNU
Toolchain 12.2.Rel1 (Build arm-12.24)) 12.2.1 20221205
**metal_mutex semantics** (`sim:rpserver` with a test-only replacement
of `examples/hello`, not part of this PR): nested acquire/release,
`try_acquire` return value, irq state after the inner and outermost
release, `is_mutex` (rmutex) mode, and two threads doing 200000 nested
lock/inc/unlock each.
| build | extra Kconfig | result |
| --- | --- | --- |
| sim:rpserver | `CONFIG_EXAMPLES_HELLO=y` | `count=400000 fail=0 PASSED` |
| sim:rpserver | + `CONFIG_SMP=y CONFIG_SMP_NCPUS=4 CONFIG_SPINLOCK=y` |
`count=400000 fail=0 PASSED` |
The first row is the case the depth counter is for: without
`CONFIG_SPINLOCK`, `rspin_lock_irqsave()` is plain `up_irq_save()`,
so a count-based check would treat every release as the outermost one
and turn interrupts back on inside the outer critical section.
**rpmsg/rptun over the new lock** (baseline, `rdev->lock` is now a
spinlock on both cores):
<details><summary>results.md</summary>
Baseline (`test.sh`, cases: baseline.yaml):
- host: Ubuntu 22.04.5 LTS x86_64, QEMU version 10.2.1, sim: cc (Ubuntu
13.1.0-8ubuntu1~22.04) 13.1.0, qemu-armv8a: aarch64-none-elf-gcc (Arm GNU
Toolchain 12.2.Rel1 (Build arm-12.24)) 12.2.1 20221205
- tested: nuttx 8558e9be001 apps f8bd442c2
- qemu-armv8a:rpserver qemu-armv8a:rpproxy built with test-only overlay:
disabled LIBC_ENVPATH BINFMT_CHECKEXEC
- sim:rpserver + sim:rpproxy: PASS
- [x] `uname -a` (server)
- [x] `rpmsg dump all` (server)
- [x] `rpmsg ping all 10 1024 3 0` (server)
- [x] `uname -a` (proxy)
- [x] `rpmsg ping all 10 1024 3 0` (proxy)
- [x] `mount -t rpmsgfs -o cpu=server,fs=/proc /sp` (proxy)
- [x] `cat /sp/version` (proxy)
- [x] `rpmsg dump all` (proxy)
- qemu-armv8a:rpserver + qemu-armv8a:rpproxy: PASS
- [x] `uname -a` (server)
- [x] `uname -a` (proxy)
- [x] `rpmsg dump all` (server)
- [x] `rpmsg ping all 10 1024 3 0` (server)
- [x] `rpmsg ping all 10 1024 3 0` (proxy)
- [x] `mount -t rpmsgfs -o cpu=server,fs=/proc /sp` (proxy)
- [x] `cat /sp/version` (proxy)
</details>
qemu-armv8a:rpserver/rpproxy also enable `CONFIG_RPMSG_PORT_UART`, so
the rpmsg_port rx/ns paths run under the new lock there as well.
Not run: rpmsg_port_spi (no QEMU environment), SMP rptun.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]