This is the mail archive of the mailing list for the glibc project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: POSIX timers and threads in a realtime context


looking at the glibc timer API, there is a Linux-specific interface to send timer events to a dedicated thread belonging to the current process:

$ man timer_create
SIGEV_THREAD_ID (Linux-specific)
As  for  SIGEV_SIGNAL,  but the signal is targeted at the thread
whose ID is given in sigev_notify_thread_id, which must be a
thread in the same process as the caller.  The sigev_notify_thread_id
field specifies a kernel thread ID, that is, the value returned by
clone(2) or gettid(2).  This flag is intended only for use by threading

But as this interface requires a Linux kernel thread id, it allows to only set up timer events being sent to the _current_ thread using the gettid() system call, because gettid() only returns the tid of the current thread. To facilitate the discussion, the example below shows some working code. You may just copy and paste it to a terminal to compile and run:

$ cat << EOF | gcc -xc - -pthread -lrt && ./a.out
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/syscall.h>

int main(void) {
        struct timespec period = {1, 0};
        struct itimerspec itime = {period, period};
        timer_t timer;
        siginfo_t info;
        sigset_t set;
        struct sigevent event;
        pid_t tid = syscall(SYS_gettid);

        memset(&event, 0, sizeof(event));
        event.sigev_notify = SIGEV_THREAD_ID;
        event.sigev_signo = SIGRTMIN;
        event._sigev_un._tid = tid;
        event.sigev_value.sival_ptr = (void *) 0xdeadbeef;
        assert(timer_create(CLOCK_MONOTONIC, &event, &timer) == 0);
        assert(timer_settime(timer, 0, &itime, 0) == 0);

        sigaddset(&set, SIGRTMIN);
        assert(!pthread_sigmask(SIG_BLOCK, &set, NULL));
        while(1) {
                assert(sigwaitinfo(&set, &info) == SIGRTMIN);
                printf("Got signal %d with value %p\n",  info.si_signo, info.si_ptr);
        return 0;

Unfortunately, there is no interface to send timer events to _another_ dedicated POSIX thread of the current process, because there is no interface that calculates the kernel thread id for another than the current POSIX thread id.

To get around this restriction, I'd like to suggest extending the GLIBC API to support sending timer events to arbitrary POSIX threads belonging to the current process by either:

introducing a new Linux specific function that calculates the kernel thread id from a POSIX thread id along the lines
        pid_t pthread_to_tid_np (pthread_t id) {
                return ((struct pthread *) id)->tid;


introducing a new Linux-specific sigev_notify value named e.g. SIGEV_PTHREAD_ID and a new member in struct sigevent, e.g. _sigev_un._pthread, allowing to directly pass a POSIX thread id to struct sigevent.  Furthermore, adding something like #define sigev_notify_pthread   _sigev_un._sigev_thread._pthread to siginfo.h  would then be appropriate to make access to the newly defined interface look nicer.

The main reason for my suggestion is better realtime support: The suggested solution provides a rather low-latency path to send timer events to threads.

I would be more than happy to provide a GLIBC patch that implements either of the two suggested solutions, or any other solution allowing to send timer events to dedicated threads, as long as chances are that it may be acceptable for the GLIBC maintainers. Personally, I'd be in favor for the second of the presented solutions, as it would not expose kernel thread ids to application code and would more smoothly fit into the currently available  interface.

Please comment.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]