yangsong8-a1 opened a new pull request, #21746:
URL: https://github.com/apache/nuttx/pull/21746

   ## Summary
   - Add a per-device recursive spinlock (`rspinlock_t lock`) to
     `struct uart_dev_s`, plus `uart_spinlock()` / `uart_spinunlock()`.
     The `nopreempt` argument also locks the scheduler while the lock is held.
   - Use it instead of `enter_critical_section()` in the serial upper half,
      the 16550 and CMSDK lower halves. The lock is released around 
`nxsem_wait()`.
   - 16550 `txint` holds the lock with the scheduler locked, so a wakeup inside
     `uart_xmitchars()` cannot switch tasks while the lock is held.
   - With `CONFIG_SERIAL_TXDMA`, take the lock around the `uart_dmatxavail()`
     calls in `uart_readv()` and `uart_writev()`, which touch `dev->xmit`.
   - pl011 `txint` uses the uart lock instead of the critical section, to keep
     one lock order with `uart_xmitchars()`.
   - A style-only commit fixes the existing nxstyle errors in serial_cmsdk.c.
   
   ## Impact
   Serial drivers using `drivers/serial/serial.c`. One UART no longer takes the
   global critical section, so it does not block other CPUs or drivers on SMP.
   `struct uart_dev_s` grows by one `rspinlock_t`.
   
   ## Testing
   Ubuntu 22.04, gcc 13.1, arm-none-eabi-gcc 10.3, aarch64-none-elf-gcc.
   
   Builds (each commit on its own, no new warnings):
   - Built and booted: sim:nsh, sim:smp, qemu-armv8a:nsh, qemu-armv8a:nsh_smp
     (-smp 4, pl011), qemu-intel64:nsh (16550) with and without CONFIG_SMP
     (-smp 4, KVM), mps2-an500:nsh (CMSDK).
   - Built with `CONFIG_SERIAL_TXDMA=y`: sim:nsh, imxrt1180-evk:nsh,
     nucleo-f446re:ihm08m1_f32.
   
   Concurrent read/write stress test. A test app runs three threads on the
   console at the same time:
   - Writers A and B each write 1500 numbered lines (`WA 00000` ...
     `WA 01499`, `WB ...`) to stdout. They sleep 10 ms every 5 lines so the two
     interleave, call `FIONWRITE`/`FIONSPACE` every 100 lines and `tcdrain()`
     every 500 lines. This exercises `uart_writev()`, `uart_putxmitbuf()`
     (including the buffer-full wait), `uart_xmitchars()` from the TX
     interrupt and `uart_tcdrain()`.
   - A reader opens `/dev/console` with `O_NONBLOCK` and loops on
     `poll(POLLIN, 10 ms)`, `read()` and `FIONREAD`. This exercises
     `uart_poll()`, `uart_readv()` and `uart_recvchars()` from the RX
     interrupt.
   - While the test runs, the host types characters on the console (a line
     every 200 ms), so RX interrupts, echo (and the `uart_dmatxavail()` echo
     paths on sim, which uses TX DMA) run at the same time as the TX traffic.
   - After the test, the host types another command to check that nsh still
     responds.
   
   Pass criteria: the console log contains exactly 1500 lines from each writer,
   numbered 0..1499 in order with none lost or repeated, the app prints
   `STRESS DONE`, and nsh responds afterwards (no deadlock or lost TX
   wakeup).
   
   ```
   sim:nsh               A: 1500 lines, in order  B: 1500 lines, in order  PASS
   qemu-armv8a:nsh_smp   A: 1500 lines, in order  B: 1500 lines, in order  PASS
   qemu-intel64 SMP x4   A: 1500 lines, in order  B: 1500 lines, in order  PASS
   STRESS DONE rx=64 polls=16
   ```
   


-- 
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]

Reply via email to