This is an automated email from the ASF dual-hosted git repository.

casaroli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 6fcad27d700 drivers/serial: scan tty control characters with memchr
6fcad27d700 is described below

commit 6fcad27d700da0abcf6494d551ad38db7bb3dca8
Author: yangsong8 <[email protected]>
AuthorDate: Mon Nov 2 18:10:08 2026 +0800

    drivers/serial: scan tty control characters with memchr
    
    uart_check_special() scanned the received buffer one byte at a time,
    comparing every byte against the configured tty control characters.
    Walk the buffer with memchr instead: locate the earliest control
    character (FORCE_PANIC/LAUNCH/SIGINT/SIGTSTP) in the remaining data,
    handle it, then continue past it, skipping the ordinary bytes in bulk.
    SIGINT/SIGTSTP return their signal; FORCE_PANIC (consecutive count,
    reset on any other byte) and LAUNCH are handled in passing so that a
    later signal in the same buffer is still delivered.
    
    Signed-off-by: yangsong8 <[email protected]>
---
 drivers/serial/serial.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 79 insertions(+), 5 deletions(-)

diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index 775c25938d5..1a6225dda6b 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -2600,18 +2600,94 @@ void uart_reset_sem(FAR uart_dev_t *dev)
 int uart_check_special(FAR uart_dev_t *dev, FAR char *buf,
                        FAR size_t *size)
 {
+  FAR char *src = buf;
+  FAR char *end = buf + *size;
   size_t kept = 0;
   int signo = 0;
-  size_t i;
 
   if ((dev->tc_lflag & ISIG) == 0)
     {
       return 0;
     }
 
-  for (i = 0; i < *size; i++)
+  /* Walk the buffer, jumping to the next special character with memchr
+   * instead of testing every byte.  The ordinary bytes before it are kept
+   * in one move, then the special character is acted on and dropped.
+   */
+
+  while (src < end)
     {
-      char ch = buf[i];
+      FAR char *special = NULL;
+      FAR char *tmp;
+      size_t n;
+      char ch;
+
+#ifdef CONFIG_TTY_FORCE_PANIC
+      tmp = memchr(src, CONFIG_TTY_FORCE_PANIC_CHAR, end - src);
+      if (tmp != NULL && (special == NULL || tmp < special))
+        {
+          special = tmp;
+        }
+#endif
+
+#ifdef CONFIG_TTY_LAUNCH
+      tmp = memchr(src, CONFIG_TTY_LAUNCH_CHAR, end - src);
+      if (tmp != NULL && (special == NULL || tmp < special))
+        {
+          special = tmp;
+        }
+#endif
+
+#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP)
+      if (dev->pid > 0)
+        {
+#ifdef CONFIG_TTY_SIGINT
+          if (dev->tc_vintr != _POSIX_VDISABLE)
+            {
+              tmp = memchr(src, dev->tc_vintr, end - src);
+              if (tmp != NULL && (special == NULL || tmp < special))
+                {
+                  special = tmp;
+                }
+            }
+#endif
+
+#ifdef CONFIG_TTY_SIGTSTP
+          if (dev->tc_vsusp != _POSIX_VDISABLE)
+            {
+              tmp = memchr(src, dev->tc_vsusp, end - src);
+              if (tmp != NULL && (special == NULL || tmp < special))
+                {
+                  special = tmp;
+                }
+            }
+#endif
+        }
+#endif
+
+      n = (special != NULL ? special : end) - src;
+      if (n > 0)
+        {
+          if (&buf[kept] != src)
+            {
+              memmove(&buf[kept], src, n);
+            }
+
+          kept += n;
+#ifdef CONFIG_TTY_FORCE_PANIC
+          dev->panic_count = 0;
+#endif
+        }
+
+      if (special == NULL)
+        {
+          break;
+        }
+
+      ch  = *special;
+      src = special + 1;
+
+      /* One action per special character, in this order, then drop it */
 
 #ifdef CONFIG_TTY_FORCE_PANIC
       if (ch == CONFIG_TTY_FORCE_PANIC_CHAR)
@@ -2660,8 +2736,6 @@ int uart_check_special(FAR uart_dev_t *dev, FAR char *buf,
           continue;
         }
 #endif
-
-      buf[kept++] = ch;
     }
 
   *size = kept;

Reply via email to