Skip to content

sched/pthread: Implement pthread_sigqueue - #20197

Merged
xiaoxiang781216 merged 2 commits into
apache:masterfrom
linguini1:pthread_sigqueue
Sep 21, 2026
Merged

xiaoxiang781216 merged 2 commits into
apache:masterfrom
linguini1:pthread_sigqueue

Conversation

@linguini1

@linguini1 linguini1 commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Implements the pthread_sigqueue function.

docs/pthread: Document pthread_sigqueue

Documents the new implementation of pthread_sigqueue.

sched/pthread: Implement pthread_sigqueue

Implements the pthread_sigqueue Linux extension to pthreads. Follows a similar implementation to sigqueue, except targeting a specific thread through nxsig_dispatch.

Impact

Closes #20163.

Users can now queue signals to pthreads using this Linux extension interface.

Testing

Tested using a custom application which uses a pthread to handle POSIX timer events. When it is time to clean up the thread, pthread_sigqueue is used to send SIGABRT which kills the thread.

Main program cancelling thread:

      cancelval.sival_ptr = NULL;
      err = pthread_sigqueue(g_thread, THREAD_CANCEL_SIG, cancelval);
      if (err)
        {
          syslog(LOG_ERR | LOG_USER,
                 "Couldn't send timer thread cancel signal: %d\n", err);

          /* No point joining if we couldn't cancel. */

          goto clean_topics;
        }

      err = pthread_join(g_thread, &threadret);
      if (err)
        {
          syslog(LOG_ERR | LOG_USER, "Couldn't join to timer thread: %d\n",
                 err);
          goto clean_topics;
        }

      syslog(LOG_INFO | LOG_USER, "Timer thread exited with status %d\n",
             (int)threadret);

Thread logic:

static void *timer_thread(void *arg)
{
  int err;
  int dep_fd = (int)arg;
  sigset_t set;
  siginfo_t info;
  struct pyrochan_s *chan;

  syslog(LOG_INFO | LOG_USER, "Timer thread started.\n");

  /* Configure the set of signals we're waiting for (just timer signals) */

  err = sigemptyset(&set);
  if (err < 0)
    {
      syslog(LOG_ERR | LOG_USER, "Couldn't configure signal set: %d\n",
             errno);
      return (void *)(uintptr_t)errno;
    }

  err = sigaddset(&set, TIMER_SIG); /* We wait for timer signal */
  if (err < 0)
    {
      syslog(LOG_ERR | LOG_USER, "Couldn't configure signal set: %d\n",
             errno);
      return (void *)(uintptr_t)errno;
    }

  /* We also allow a cancellation signal */

  err = sigaddset(&set, THREAD_CANCEL_SIG);
  if (err < 0)
    {
      syslog(LOG_ERR | LOG_USER, "Couldn't configure signal set: %d\n",
             errno);
      return (void *)(uintptr_t)errno;
    }

  /* We specifically unblock the timer signal from this thread's set of
   * blocked signals.
   */

  err = pthread_sigmask(SIG_UNBLOCK, &set, NULL);
  if (err)
    {
      syslog(LOG_ERR | LOG_USER, "Couldn't unblock timer signal: %d\n", err);
      return (void *)(uintptr_t)err;
    }

  /* We are waiting for the timer signal. */

  for (;;)
    {
      /* Block until we receive a signal, with continue to re-block on
       * spurious wake-ups.
       */

      err = sigwaitinfo(&set, &info);
      if (err < 0)
        {
          syslog(LOG_ERR | LOG_USER,
                 "Error while waiting for timer signal: %d", errno);
          continue;
        }

      /* If this was a cancellation signal, stop execution and return */

      if (info.si_signo == THREAD_CANCEL_SIG)
        {
          syslog(LOG_INFO | LOG_USER, "Timer thread cancelled.\n");
          return 0;
        }

      /* Handle the timer expiration by deploying the channel and indicating
       * the deployment event.
       */

      chan = (struct pyrochan_s *)info.si_value.sival_ptr;

      err = channel_fire(chan);
      if (err == 0)
        {
          err = publish_deployment(dep_fd, chan->id);

          /* Not really much to do if this fails; we continue so we can fire
           * any other timer-based channels.
           */
        }

      /* Clean up the expired timer */

      err = timer_delete(chan->timerid);
      if (err < 0)
        {
          syslog(LOG_ERR | LOG_USER, "Couldn't clean up expired timer: %d\n",
                 errno);
        }
    }

  return 0;
}

Log output:

pthread_sigqueue: tid=19 sig=10 value=0                     
nxsig_tcbdispatch: TCB=0x3fcb1cf8 pid=19 signo=10 code=1 value=0
Timer thread cancelled.
nx_pthread_exit: exit_value=0
pthread_completejoin: pid=19 exit_value=0
nxtask_exit: deployment pid=19,TCB=0x3fcb1cf8
pthread_join: Returning 0, exit_value 0
Timer thread exited with status 0
nxsig_tcbdispatch: TCB=0x3fca79b0 pid=7 signo=17 code=5 value=0 masked=NO
nxsig_tcbdispatch: Group 0x3fca7a90
nxtask_exit: deployment pid=16,TCB=0x3fcad620
Service 'deployment' pid 16 exited status 1
Removing service 'deployment' ...

@github-actions github-actions Bot added Area: Documentation Improvements or additions to documentation Arch: simulator Issues related to the SIMulator Size: M The size of the change in this PR is medium labels Sep 19, 2026
@github-actions

github-actions Bot commented Sep 19, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report

arduino-mega2560

  • flash: .text +182 B (+0.3%, 65,308 B / 262,144 B, total: 25% used)

esp32-devkitc

  • ROM: .flash.text -72 B (-0.1%, 124,968 B / 4,194,272 B, total: 3% used)
  • irom0_0_seg: .flash.text -72 B (-0.1%, 89,172 B / 3,342,304 B, total: 3% used)

hifive1-revb

  • flash: .text +112 B (+0.1%, 83,832 B / 4,194,304 B, total: 2% used)

mirtoo

  • kseg0_progmem: .text +132 B (+0.2%, 67,896 B / 131,072 B, total: 52% used)

qemu-armv8a

  • Code: .text.file_mq_unlink -4 B, .text.file_mq_vopen -12 B, .text.file_vopen -4 B, .text.find_blockdriver -4 B, .text.inode_find +20 B, .text.inode_reserve +8 B, .text.inode_search -496 B, .text.mkdir -4 B, .text.nx_mount -8 B, .text.nx_stat -4 B, .text.nx_umount2 +16 B, .text.nx_unlink -20 B, .text.rename -80 B, .text.rmdir -20 B (+0.0%, 344,572 B)

qemu-intel64

  • Code: .text -421 B (-0.0%, 8,659,582 B)
  • Data: .rodata +32 B (+0.0%, 120,177 B)

rx65n-rsk2mb

  • ROM: .text -96 B (-0.1%, 86,912 B / 2,097,152 B, total: 4% used)

s698pm-dkit

  • Code: .text +304 B (+0.1%, 368,592 B)

stm32-nucleo-f103rb

  • flash: .text +76 B (+0.2%, 34,636 B / 131,072 B, total: 26% used)

@acassis

acassis commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

@linguini1 yes, you need to add it to syscall.csv, this file works like a database that is used to create the syscall when compiling NuttX to protected mode and kernel mode.
https://nuttx.apache.org/docs/latest/components/syscall.html

@linguini1

Copy link
Copy Markdown
Contributor Author

@acassis should pthread_sigqueue really be a syscall? It's a Linux extension.

Also, I see that the function signature is causing problems. All the other syscall definitions have arguments which are pointers or ints, but pthread_sigqueue takes a const union sigval as the last argument which is causing this "aggregate value" error in the build CI when it's trying to cast the sigval to a uintptr_t.

@acassis

acassis commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

pthread_

Good point, there are only some pthread_* at syscall but all pthread functions are listed at libs/libc/libc.csv:

alan@dev:~/nuttxspace/nuttx$ find . -name *.csv | xargs grep pthread_

I think it is a good idea to add it there

Implements the pthread_sigqueue Linux extension to pthreads. Follows a
similar implementation to sigqueue, except targeting a specific thread
through nxsig_dispatch.

Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
Documents the new implementation of pthread_sigqueue.

Signed-off-by: Matteo Golin <matteo.golin@gmail.com>

@cederom cederom left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @linguini1 :-)

We may want to add test app in pair to nuttx-apps? :-)

@linguini1

Copy link
Copy Markdown
Contributor Author

We may want to add test app in pair to nuttx-apps? :-)

Might be a little while until I get to that, but I'd be happy to add one to OSTest or whatever we use for testing pthreads at some point in the near future.

@xiaoxiang781216
xiaoxiang781216 merged commit 3305366 into apache:master Sep 21, 2026
33 of 46 checks passed
@linguini1
linguini1 deleted the pthread_sigqueue branch September 21, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: simulator Issues related to the SIMulator Area: Documentation Improvements or additions to documentation Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Implementation for pthread_sigqueue

4 participants