This is the mail archive of the libc-alpha@sourceware.org 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]

Re: RFC: POSIX timers and threads in a realtime context


On Mon, Oct 05, 2015 at 03:04:31PM +0000, Warlich, Christof wrote:
> Hi,
> 
> 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
> libraries.
> ....
> 
> 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);
> 
>         sigemptyset(&set);
>         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;
> }
> EOF
> 
> 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.

There is if the target thread gets and reports its own kernel tid,
which seems practical to do since you would presumably only want to
send such timer event signals to a thread which is already prepared to
handle them... Or are you intending to use this for some sort of
instrumentation/profiling purpose where you would be targeting threads
that don't expect a signal?

> 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;
>         }
> 
> or:
> 
> 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.

AFAIK there is still an unresolved question as to whether glibc wants
to expose kernel tids as an API. This is the reason there is no
gettid() function and you have to use syscall(). Other interfaces are
affected too.

Note that even if glibc does want to support your proposed usage,
there are two possible approaches. One is exposing the kernel tid. The
other is having timer_create accept userspace pthread_t identifiers
and translating them internally. These are incompatible approaches so
some consideration of their pros and cons is needed before adopting
one or the other.

Rich


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