2010-04-09 20:04:25

by Frantisek Rysanek

[permalink] [raw]
Subject: setitimer vs. threads: SIGALRM returned to which thread? (process master or individual child)

Dear everyone,

I hope I'm not way too much off topic in this list... specifically, I
hope the issue takes place in the kernel, as opposed to the user-
space part of NPTL that ships with libc, distroes etc.
At the same time, I feel shame for asking this noob question in the
very LKML - except that there doesn't seem to be a better place to
ask... :->

Some years ago, I've written a couple programs that tend to use the
setitimer() syscall in a threaded environment, making use of its
special property at the time: setitimer() had per-thread granularity.
It used to deliver a SIGALRM from the timer to the particular thread
that called setitimer(). I believe that was around RH8 to Fedora 5.

Recently I've recompiled the programs on a newer distro (Fedora 10)
and voila: setitimer() now yields a SIGALRM to the program's master
thread, no matter what child thread called setitimer()...

Based on further reading, I assume this is related to making the NPTL
more POSIX-compliant. The latter is a correct POSIX behavior, the
former was not. See "man pthreads", and under the NPTL heading,
find a note saying
"Threads do not share interval timers (fixed in kernel 2.6.12)."

Yes, it used to be quite a relief to have Linux do the management of
timers for me. Now I have two options to choose from:
1) write my own "timer queueing" (timekeeping) code to order the
timers for me in the master thread
2) find another function, similar to setitimer(), that would function
the way setitimer() used to work in the old days...

Obviously option #2 is much easier for me to abuse :-)
Such as, does select() work in the desired per-thread way?
In the app that I'm trying to update right now, I have a serial
device open per thread, and I need to detect character timeouts
(frame breaks).
But I have other apps where I have a *myriad* of stand-alone timers,
not related to a "file descriptor like" device of any kind,
generating "spurious events" for me, used to propel a bunch of
threads doing some polling on various dumb "networked" devices
(external bus slaves)...

For a moment I was wondering how complex the relevant kernel patch
was, how difficult it would be to revert it - but then again such a
revert might disrupt various other pieces of user-space code in my
distro, so it's probably not such a good idea anyway :-) Also, if I
resort to patching my kernel, it makes my user-space code fairly non-
portable to other people's machines. Let alone the bulk of code
evolution in Linux kernel timekeeping and process management since
2.6.12, overlaying the original patch.
AIX appears to have ITMER_REAL_TH [sob]. Not that I'm going to try
AIX for this particular reason :-)

Wouldn't it be in fact more straightforward and "cheaper" (in terms
of processing overhead) to have the timers thread-aware? If I just
call a setitimer() in each thread, that requires some number of
ioctl() calls. Now if I need to do my own timekeeping (event
queueing) in user space, I'll probably need to call getitimer() or
gettimeofday() ahead of every setitimer(), every time a thread needs
to set a timer. Not sure about the required number of pointer
indirections in the kernel for either case :-)

I understand that POSIX compliance is a good thing, for portability
reasons. At the same time, resorting to per-process granularity of
timers somehow "feels backwards" - from thread awareness, back to the
old "no threads" UNIX world. It seems to remind me of the occasional
debate whether GCC extensions to standard C are a good thing to use,
or whether they should be avoided...

I haven't found much debate about this "timers vs. threads
granularity" point in mailinglist archives or on the web.
Any further hints/pointers/kicks in the right direction/recommended
reading are welcome :-)
If you've read this far, thanks for your time...

Frank Rysanek


2010-04-10 07:26:34

by Frantisek Rysanek

[permalink] [raw]
Subject: Re: setitimer vs. threads: SIGALRM returned to which thread? (process master or individual child)

On 9 Apr 2010 at 23:26, bill o gallmeister wrote:
>
> Check out timer_create() rather than setitimer().
>
Oh I *see* :-) There seems to be a way to deliver an event to a
specific thread. Just a quick guess, haven't validated this by a
compiler:

============ PSEUDOCODE SNIPPET ==========
struct my_thr_data
{
pthread_t ID; /* to be set upon pthread_create() */
/* ...further members... */
};

void* my_fn(void* my_user_data)
{
pthread_kill( ((my_thr_data*)my_user_data)->ID, SIGALRM);
}

struct my_thr_data this_thread;
timer_t my_timer;
struct sigevent my_event =
{
sigev_notify: SIGEV_THREAD,
sigev_notify_function: my_fn,
sigev_value.sival_ptr: &this_thread,
sigev_notify_attributes: NULL
}

timer_create(CLOCK_REALTIME, &my_event, &my_timer);

/* by now we're set up, but the timer doesn't tick yet. */

/* someplace later in the code: */
timer_settime(my_timer, ... );


=========== /PSEUDOCODE SNIPPET ==============
thank you :-)

Frank Rysanek

2010-04-11 20:56:43

by Andi Kleen

[permalink] [raw]
Subject: Re: setitimer vs. threads: SIGALRM returned to which thread? (process master or individual child)

"Frantisek Rysanek" <[email protected]> writes:

> Yes, it used to be quite a relief to have Linux do the management of
> timers for me. Now I have two options to choose from:
> 1) write my own "timer queueing" (timekeeping) code to order the
> timers for me in the master thread
> 2) find another function, similar to setitimer(), that would function
> the way setitimer() used to work in the old days...

POSIX timers (timer_create et.al.) allow specifying the signal.

So if you use custom RT signals for each threads and block them in the
threads you don't want them it should work. This would limit the
maximum number of threads though because there's only a limited
range of RT signals.

There are probably other ways to do this too, e.g. with some clever
use of timerfd_create in recent kernels.

Or you could overwrite the clone in the thread library to not
set signal sharing semantics. This might have other bad side effects
though.

-Andi

--
[email protected] -- Speaking for myself only.

2010-04-11 22:00:31

by Davide Libenzi

[permalink] [raw]
Subject: Re: setitimer vs. threads: SIGALRM returned to which thread? (process master or individual child)

On Sun, 11 Apr 2010, Andi Kleen wrote:

> "Frantisek Rysanek" <[email protected]> writes:
>
> > Yes, it used to be quite a relief to have Linux do the management of
> > timers for me. Now I have two options to choose from:
> > 1) write my own "timer queueing" (timekeeping) code to order the
> > timers for me in the master thread
> > 2) find another function, similar to setitimer(), that would function
> > the way setitimer() used to work in the old days...
>
> POSIX timers (timer_create et.al.) allow specifying the signal.
>
> So if you use custom RT signals for each threads and block them in the
> threads you don't want them it should work. This would limit the
> maximum number of threads though because there's only a limited
> range of RT signals.
>
> There are probably other ways to do this too, e.g. with some clever
> use of timerfd_create in recent kernels.

Definitely timerfd allows you to handle the timer event wherever you
like, independently from signals. Much much simpler routing.
But if you need to be compatible with multiple unixes, of even older linux
kernel, you are out of luck with timerfd.


- Davide

2010-04-11 22:10:21

by Thomas Gleixner

[permalink] [raw]
Subject: Re: setitimer vs. threads: SIGALRM returned to which thread? (process master or individual child)



On Sun, 11 Apr 2010, Andi Kleen wrote:

> "Frantisek Rysanek" <[email protected]> writes:
>
> > Yes, it used to be quite a relief to have Linux do the management of
> > timers for me. Now I have two options to choose from:
> > 1) write my own "timer queueing" (timekeeping) code to order the
> > timers for me in the master thread
> > 2) find another function, similar to setitimer(), that would function
> > the way setitimer() used to work in the old days...
>
> POSIX timers (timer_create et.al.) allow specifying the signal.
>
> So if you use custom RT signals for each threads and block them in the
> threads you don't want them it should work. This would limit the
> maximum number of threads though because there's only a limited
> range of RT signals.
>
> There are probably other ways to do this too, e.g. with some clever
> use of timerfd_create in recent kernels.
>
> Or you could overwrite the clone in the thread library to not
> set signal sharing semantics. This might have other bad side effects
> though.

Nonsense. Just use the right flags when creating the posix
timer. posix timers support per thread delivery of a signal, i.e. you
can use the same signal for all threads.

sigev.sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL;
sigev.sigev_signo = YOUR_SIGNAL;
sigev.sigev_notify_thread_id = gettid();
timer_create(CLOCK_MONOTONIC, &sigev, &timer);

That signal for that timer will not be delivered to any other thread
than the one specified in sigev.sigev_notify_thread_id as long as that
thread has not exited w/o canceling the timer.

Thanks,

tglx