timer_create function returning EINVAL - c

I am writing a sample program where my main() will create a thread and then it will start a timer. When the timer expires, the thread should get the signal. This is on Ubuntu 18.04.4 LTS.
My problem is that timer_create() is failing and error number is set to EINVAL. My snippet of code for timer_create() is given below.
/* Create the timer */
sevp.sigev_notify = SIGEV_THREAD_ID;
sevp.sigev_signo = SIGALRM;
sevp.sigev_value.sival_int = somevalue;
sevp._sigev_un._tid = threadid;
retval = timer_create(CLOCK_MONOTONIC,&sevp,&timerid);
if ( 0 == retval )
{
printf("Success in creating timer [%p]",timerid);
}
else
{
printf("Error in creating timer [%s]\n",strerror(errno));
}
What am I doing wrong?

As per the linux man page entry for timer_create with SIGEV_THREAD_ID:
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.
The thread ID (threadid in the question code) needs to be a kernel thread ID. That ID can be obtained with gettid.

Related

How can I reuse a single thread for all timer_create callbacks when using SIGEV_THREAD?

I have a timer that runs at regular intervals. I create the timer using timer_create() using the SIGEV_THREAD option. This will fire a callback on a thread when the timer expires, rather than send a SIGALRM signal to the process. The problem is, every time my timer expires, a new thread is spawned. This means the program spawns potentially hundreds of threads, depending on the frequency of the timer.
What would be better is to have one thread that handles the callbacks. I can do this when using timer_create() with signals (by using sigaction), but not threads only.
Is there any way to not use signals, but still have the timer notify the process in a single existing thread?
Or should I even worry about this from a performance perspective (threads vs signals)?
EDIT:
My solution was to use SIGEV_SIGNAL and pthread_sigmask(). So, I continue to rely on signals to know when my timer expires, but I can be 100% sure only a single thread (created by me) is being used to capture the signals and execute the appropriate action.
tl;dr: The basic premise that SIGEV_THREAD doesn't work based on signals is false - signals are the underlying mechanism through which new threads are spawned. glibc has no support for reutilizing the same thread for multiple callbacks.
timer_create doesn't behave exactly the way you think - its second parameter, struct sigevent *restrict sevp contains the field sigevent_notify which has following documentation:
SIGEV_THREAD
Notify the process by invoking sigev_notify_function "as
if" it were the start function of a new thread. (Among the
implementation possibilities here are that each timer notification
could result in the creation of a new thread, or that a single thread
is created to receive all notifications.) The function is invoked
with sigev_value as its sole argument. If sigev_notify_attributes is
not NULL, it should point to a pthread_attr_t structure that defines
attributes for the new thread (see pthread_attr_init(3)).
And indeed, if we look at glibc's implementation:
else
{
/* Create the helper thread. */
pthread_once (&__helper_once, __start_helper_thread);
...
struct sigevent sev =
{ .sigev_value.sival_ptr = newp,
.sigev_signo = SIGTIMER,
.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID,
._sigev_un = { ._pad = { [0] = __helper_tid } } };
/* Create the timer. */
INTERNAL_SYSCALL_DECL (err);
int res;
res = INTERNAL_SYSCALL (timer_create, err, 3,
syscall_clockid, &sev, &newp->ktimerid);
And we can see __start_helper_thread's implementation:
void
attribute_hidden
__start_helper_thread (void)
{
...
int res = pthread_create (&th, &attr, timer_helper_thread, NULL);
And follow along to timer_helper_thread's implementation:
static void *
timer_helper_thread (void *arg)
{
...
/* Endless loop of waiting for signals. The loop is only ended when
the thread is canceled. */
while (1)
{
...
int result = SYSCALL_CANCEL (rt_sigtimedwait, &ss, &si, NULL, _NSIG / 8);
if (result > 0)
{
if (si.si_code == SI_TIMER)
{
struct timer *tk = (struct timer *) si.si_ptr;
...
(void) pthread_create (&th, &tk->attr,
timer_sigev_thread, td);
So - at least at the glibc level - when using SIGEV_THREAD you are necessarily using signals to signal a thread to create the function anyways - and it seems like your primary motivation to begin with was avoiding the use of alarm signals.
At the Linux source code level, timers seems to work on signals alone - the posix_timer_event in kernel/time/posix_timers.c function (called by alarm_handle_timer in kernel/time/alarmtimer.c) goes straight to code in signal.c that necessarily sends a signal. So it doesn't seem possible to avoid signals when working with timer_create, and this statement from your question - "This will fire a callback on a thread when the timer expires, rather than send a SIGALRM signal to the process." - is false (though it's true that the signal doesn't have to be SIGALRM).
In other words - there seem to be no performance benefits to be gained from SIGEV_THREAD as opposed to signals. Signals will still be used to trigger the creation of threads, and you're adding the additional overhead of creating new threads.

Right way to delete kthread waiting while semaphore will be upped

I write a kernel module that uses kernel threads and semaphores.
I call up(...) function for semaphore from interrupt handler and then my kthread starts to execute.
static int interrupt_handler_thread(void *data)
{
/* duty cycle */
while (!kthread_should_stop()) {
/*
* If semaphore has been uped in the interrupt, we will
* acquire it here, else thread will go to sleep.
*/
if (!down_interruptible(mysem)) {
/* proccess gpio interrupt */
dev_info(dev, "gpio interrupt detected\n");
}
}
do_exit(0);
return 0;
}
The semaphore and thread are initializated into module_init function. Error checking was omitted.
...
sema_init(mysem, 0);
thread = kthread_create(interrupt_handler_thread,client,"my_int_handler");
wake_up_process(thread);
...
And during unloading a module the semaphore and the thread are removed:
/*
* After this call kthread_should_stop() in the thread will return TRUE.
* See https://lwn.net/Articles/118935/
*/
kthread_stop(thread);
/*
* Release the semaphore to return
* from down_interruptible() function
*/
up(mysem);
When I try to unload my module the one frozes into thread in down_interruptible() function, because it waits while the semaphore ups in interrupt handler. And my code never returns from kthread_stop().
It seems, I need to disable the interrupt from my gpio, up the semaphore by hand and call kthread_stop() function. But it is a potential bug, because after the semaphore is uped by hand, the thread starts executing and the one can again down_interruptible() after its duty cycle.
Could anyone help me, please?
PS: I know about this question, but, it seems, this is not my case.
For correctly operate, your kthread should check "stop" status of the thread when waiting on semaphore. Unfortunately, there is no "stoppable" version of down function.
Instead of kthread use workqueue mechanism. Works already have all features you need:
You can add a work inside interrupt handler (queue_work),
Only a single work can be run at the same time,
Using destroy_workqueue you can safetly finalize all works.
Actually, workqueues are implemented using kthreads. See e.g. implementation of kthread_worker_fn function.

Causing a waiting thread to return to userspace

Would it be possible to wake up a thread that is waiting on a futex lock? I tried
using a signal mechanism but it does not seem to work. Are there any other approches
I could try out? Below, I've added in an example that might be similar to what I'm
trying to achieve.
I have a thread A that acquires a futex lock "lockA" as follows :-
ret = syscall(__NR_futex, &lockA, FUTEX_LOCK_PI, 1, 0, NULL, 0);
I have a thread B that tries to acquire the futex lock "lockA", and blocks in the kernel,
as thread A has acquired the lock.
ret = syscall(__NR_futex, &lockA, FUTEX_LOCK_PI, 1, 0, NULL, 0);
If thread B does acquire lockA, another thread, thread C will know about it. If thread B
does not acquire the lock, thread C would like thread B to stop waiting for the lock, and
do something else.
So basically, at this point I'm trying to figure out if I can make thread C "signal" thread B
so that it won't block in the kernel anymore. In order to do that, I set a signal handler in
thread B as follows :-
struct sigaction act;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_restorer = NULL;
sigaction(SIGSYS, &act, NULL);
...
...
void handler() {
fprintf(stderr, "Inside the handler, outta the kernel\n");
}
From thread C I try to send the signal as :-
pthread_kill(tid_of_B, SIGSYS);
What am I doing wrong? Can thread B be woken up at all? If so, should I use another approach?
[EDIT]
Based on a comment below, I tried checking the return value from pthread_kill and realised that the call was not returning.
A few things.
You're using FUTEX_LOCK_PI which is not in the man page. I've just looked at the kernel source and a document and it appears this version is only for use inside the kernel itself. It's used to implement a "PI mutex" as a replacement for a kernel spinlock.
If you use a futex, you must implement the semantics on data in the address it points to.
Here is a crude, pseudocode, and possibly/probably wrong example:
int mysem = 1;
void
lock(void)
{
// atomic_dec returns new value
while (1) {
if (atomic_dec(&mysem) == 0)
break;
futex(&mysem,FUTEX_WAIT,...)
}
}
void
unlock(void)
{
// non_atomic_swap returns old value
if (non_atomic_swap(&mysem,1) != 0)
futex(&mysem,FUTEX_WAKE,...)
}

Signal handler getting called in wrong thread

I want to know if its possible to interrupt main thread and ask it to execute some callback. The main thread should continue with what it was doing after completing the callback.
For instance, we have 2 threads t1 and m1 (main thread). t1 will interrupt m1 (main thread) and ask it to call a function with some parameters. The m1 (main thread) will stop doing what it was doing before and will start executing the function. The after finishing the function, it will get back to what it was doing earlier.
I want to replicate what hardware interrupt does. I have one thread that reads data from a file. Then it should ask main thread to call a function. Main thread will be doing something. It should stop doing it and start executing the function. After completing it, main thread should continue with what it was doing
I have written following code using signals
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
static void catch_function(int signo) {
int id = GetCurrentThreadId();
printf("\nThread ID is %d",id);
signal(SIGINT, catch_function);
}
DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
int id = GetCurrentThreadId();
printf("\nChild Thread ID is %d",id);
while(1)
{
Sleep(50);
if (raise(SIGINT) != 0) {
fputs("Error raising the signal.\n", stderr);
return EXIT_FAILURE;
}
}
return 0;
}
int main(void) {
int id = GetCurrentThreadId();
printf("\nMain Thread ID is %d",id);
if (signal(SIGINT, catch_function) == SIG_ERR) {
fputs("An error occurred while setting a signal handler.\n", stderr);
return EXIT_FAILURE;
}
HANDLE thread;
DWORD threadId;
thread = CreateThread(NULL, 0, &MyThreadFunction, NULL, 0, &threadId);
if(!thread)
{
printf("CreateThread() failed");
}
while(1)
{
Sleep(50);
}
return 0;
}
The output of code is
Main Thread ID is 6124
Child Thread ID is 7854
Thread ID is 7854
Thread ID is 7854
So my question is should not the signal handler be called in Main thread? I want main thread to call the handler function not the thread which raise the signal?
please let me know what is the correct way of achieving this.
PS. I have to do it for both windows and linux.
I can only offer advice from a Linux side, but as you said that was of interest too then...
... raise does the following (from the manual page):
The raise() function sends a signal to the calling process or thread.
So in a multi-threaded program it is the thread that calls raise that will get the signal.
On Linux, for threading, you'll probably be using pthreads, in which case you have pthread_kill, this sends a specific signal to a specific thread. You'd need to use pthread_self in the main thread to get the thread id, then pass this to the worker thread. The worker thread can then send signals directly to the main thread.
I suspect you need to find something similar for Windows, but that's not something I know about.
The only one that can interrupt a thread is itself or the Task Scheduler.
If you were to stop someone else you would need direct access to timer hardware.
You can do what Ed Heal said. Use conditional variables and semaphores. My advice is to build up a linked list or even just an array storing what to do and who is the one wich should do it.
See what Windows does to send messages to the program in "event-driven UI".
A MSG struct is given to the application with some integers, like message code, WPARAM and LPARAM.
Define a structure of your own and use it to send messages to each thread (some form of interprocess communication). And, that's important, set a timer to a callback function or keep with your Sleep(50) (or more) to not keep "bothering" your processor for nothing.
Hope this helps and sorry for bad english.

Interrupted system call

I have more then three timer running from main as given below, and I have defined one message queue in main section. My timer's expiration time in 10(max).
Why, when timer expires "msgrcv" gives error like "Interrupted system call"?
timer_t timer1 = create_timer(TT_SIGUSR1);
install_sighandler(TT_SIGUSR1, signal_handler);
set_timer(timer1, TIME_INTERVAL_1);
-
-
-
flag = IPC_CREAT | 0666;
key = 1234;
msgqid = msgget(key,flag);
printf("msgqid = %d\n",msgqid);
while (1)
{
msgsz = msgrcv(msgqid, &sendMsg, sizeof(sendMsg), 0,0);
perror("prashant");
sleep(1);
}
return 0;
Because you probably setup your timer to send you a signal when it expires. Receiving a signal while blocked on certain system calls will make said system calls fail with errno = EINTR.
The msgrcv() function shall fail if:
[EINTR]
The msgrcv() function was interrupted by a signal.

Resources