Why does not WiringPiISR block the main routine when it is fired? - c

I am developing a program in C to run on a raspberry board. In the program i want to use WiringPiISR to handle a pin triggered interrupt. However, I have found that instead of blocking the main routine, the wiringPiISR creates a concurrent thread. Am i missing something?
Minimal code example :
#include <WiringPi.h>
#include <unistd.h>
int Check=0;
void Isr()
{
while (1)
{
sleep(1);
Check++;
}
}
int main()
{
wiringPiSetup () ;
pinMode(7, INPUT) ;
wiringPiISR (7, INT_EDGE_BOTH ,&Isr);
while (1)
{
sleep(2);
printf("check : %d", Check );
}
return 0;
}
I would expect this minimal program to never resume after the interrupt is fired but in my case it kept on incrementing the variable check and printing it on the screen ( both threads working concurrently).

The documentation I've found is rather specific (emphasis mine):
int wiringPiISR (int pin, int edgeType, void (*function)(void)) ;
This function is run at a high priority (if the program is run using sudo, or as root) and executes concurrently with the main program. It has full access to all the global variables, open file handles and so on.
The sources don't leave anything to imagination. It just crates a new thread:
pthread_create (&threadId, NULL, interruptHandler, &pin) ;
that waits for interrupt and executes your handler:
static void *interruptHandler (void *arg)
{
int pin = *(int *)arg ;
(void)piHiPri (55) ;
for (;;)
{
if (waitForInterrupt (pin, -1) > 0)
isrFunctions [pin] () ;
}
return NULL ;
}
So your handler runs as a separate thread and your behavior is expected.

ISR stands for interrupt service routine aka interrupt handler.
Your code sets up an interrupt handler. If the interrupt is fired, the regular code (main() in your case) is interrupted and the interrupt handler is executed. It's not a second thread but the result is similar.
Interrupt handlers should only do minimal work and quickly return control to the interrupted program. The use of sleep() in an interrupt handler is not allowed and causes undefined behavior.

Assuming that you've made the infinite loop and the call of sleep() on purpose:
sleep() probably allows to switch between the threads.

Related

C Signal timer for task switching

Im building a simple task switcher that runs two functions in a loop. The idea is that it runs a f1 for an amount of time and then gives control to f2 for the same amout, then f1, f2, in an endless loop.
The problem is that whenever i run the program, the first switch goes well but the following switches never happen. Getting stuck in f2.
Ive tried other implementations archieving 3 switches at most (with the program getting frozen after that).
This is my current implementation:
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>
int count = 0;
int flag = 0;
void f1() {
for (;;) printf("A");
}
void f2() {
for (;;) printf("B");
}
void sched() {
flag = !flag;
if (flag)
f1();
else
f2();
}
void sighandler(int signo)
{
printf("signal %d occurred %d times\n",signo, ++count);
sched();
}
int main(void)
{
struct itimerval it;
struct sigaction act, oact;
act.sa_handler = sighandler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGPROF, &act, &oact);
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 10000;
it.it_value.tv_sec = 0;
it.it_value.tv_usec = 10000;
setitimer(ITIMER_PROF, &it, NULL);
sched();
}
Any suggestion would be greatly appreciated.
Your signal handler calls sched(), which never returns (but ends up in either of the for (;;) loops). So after the first switch, you are always inside the signal handler, and further signals are masked.
Despite the fact that you have already been answered with the good answer
Your signal handler calls sched(), which never returns (but ends up in either of the for (;;)...
the problem with your multitask implementation is that for a task switcher to work you need to do a context switch. A context switcher is a routine that doesn't return until it has done all context switches to other processes and the next task to be scheduled is the one to return. It's some king of call to
yield();
but the actual context switch ocurrs inside of yield. A context switch is something that cannot be implemented as a simple routine (some piece of code that you call and returns) because it mus return in another context. For this, you need to call yield() and the code of yield must change all the cpu registers to the values they had in the other context (including the stack pointer, so this makes the appointment that you'll need two stacks) and then continue executing that code (that will make the program to return in the other context)
So you need to have some place to store the contexts of all the tasks you are going to allow to run in parallel. This includes the cpu state and the stack of the task. Then you need a routine (this is what does the actual context switch) that stores the old context (the one the cpu is using) in the save storage and recalls (and installs) the contexts of the new task to be scheduled. Something like:
void task_switch(struct context *old_ctx, struct context *new_ctx);
and this routine must be written in assembler.... as it must do a context switch which includes switching the stacks of each task.
How do you see it now?

setjmp/longjmp between threads to handle timeout

I'm porting a software from an embedded computer to a Linux machine. (Ubuntu 14.04 or Raspbian (raspberry pi))
The original program was using setjmp/longjmp to handle timeout and CTRL+C event. It was running on a Microcontroller with a single main (one thread).
I'm trying to have a similar behaviour while using threads (pthreads).
The idea is that I want either a timeout or a CTRL+C to restart an infinite loop.
The original code was doing something like the code below. I don't mind to drop the setjmp/longjmp by something else. (ex: try/catch or signal or pthread_kill, conditional variable, etc..)
Any idea how to implement similar behavior with C/C++ ?
Here is the code which seems to partially work and is probably not recommended/broken:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <setjmp.h>
// Define
#define TICK_NS_TIME (10000000) // 0.01 sec = 10 ms (100 times per second)
#define NS_PER_SEC (1000000000) // Nano sec per second.
#define TICK_PER_SEC (NS_PER_SEC/TICK_NS_TIME) // Number of tick per second (Ex:100)
#define TIMEOUT_COUNT (30*TICK_PER_SEC) // 30 seconds timeout (with 100 tick per second)
// Env set/long jmp
#define ENV_SZ (2)
#define ENV_TIMEOUT (0)
#define ENV_CTRLC (1)
static jmp_buf env[ENV_SZ];
// Variables
int timeout_val;
// sig handler.
void signal_handler(int signo)
{
pthread_t self = pthread_self();
printf("Thread %lu in signal handler\n", (long)self);
if (signo == SIGINT) {
longjmp(env[ENV_CTRLC], 1); // Q?: Is it in the same thread ? (Never, Always, Sometimes?)
}
else
{
printf("Other signal received..quitting."); // Ex: kill -9 pid
exit(0);
}
}
// thread timer function
void* timer_function(void* in_param)
{
// Loop approx 100x per second.
for (;;) {
nanosleep((const struct timespec[]){{0, TICK_NS_TIME }}, NULL); // Sleep 10 ms seconds.
if (timeout_val) {
if (!--timeout_val) {
longjmp(env[ENV_TIMEOUT], 1); // longjmp when timer reaches 0. (Q?: Is this valid with multithread?)
}
}
}
}
// main
int main(int argc, char **argv)
{
int i;
int val;
struct sigaction actions;
pthread_t thread;
setvbuf (stdout, NULL, _IONBF, 0); // Make sure stdout is not buffered (ex:printf, etc.)
printf("[Program started]\r\n");
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = signal_handler;
val = sigaction(SIGINT, &actions, NULL);
pthread_create(&thread, NULL, timer_function, NULL); // timer thread for example
printf("[Timer thread started]\r\n");
// setting env.
val = setjmp(env[ENV_TIMEOUT]);
if (val!=0){ printf("[JMP TIMEOUT]\r\n"); }
val = setjmp(env[ENV_CTRLC]);
if (val!=0){ printf("[JMP CTRLC]\r\n"); }
// main loop
timeout_val = TIMEOUT_COUNT;
i = 0;
for (;;)
{
i++;
if (i > 10){ i = 0; printf("[%d]", timeout_val/TICK_PER_SEC); } // Number of seconds before time out.
sleep(1);
printf(".");
}
printf("Main completed\n");
return 0;
}
//Compile: g++ -pthread main.cpp -o main
Suggestion for alternative implementation would be great since I'm new to programming with threads !
setjmp() saves the information required to restore the calling environment. longjmp() can then restore this environment, but only within the same thread.
The C11 standard is explicit about the constraint of having the same thread:
7.13.2.1/2 If there has been no such invocation (i.e: of a previous setjmp), or if the invocation was from another thread of
execution, or if the function containing the invocation of the
setjmp macro has terminated execution in the interim, or if the
invocation of the setjmp macro was within the scope of an identifier
with variably modified type and execution has left that scope in the
interim, the behavior is undefined.
In fact, setjmp/longjmp are generally implemented by saving the stack pointer so that restoring it makes sense only int the same execution context.
Alternative
Unless I've missed something, you use the second thread only to act as a timer. You could instead get rid of your POSIX pthread, and use a timer signal activated with POSIX timer_create().
But be aware that using setjmp/longjmp from a signal handler (so already in your original code for CTRL+C) is tricky, as explained in this SO answer. So you'd consider sigsetjmp/siglongjmp.
For the records: C or C++ ?
Your question is tagged C. But you mention c++ try and catch. So for the sake of completeness:
in C++ setjmp should be replaced by a try/catch and the longjmp by throwing an exception. setjmp/longjmp are supported in C++ only if unwinding the stack wouldn't require invocation of any non-trivial destructor (see C++ standard, 18.10/4).
the exceptions are not propagated across the threads, unless catched and explicitely rethrown using std::rethrow_exception(). It's delicate, so refer to this SO question for for additional details. But it's possible and could solve your issue.

C: SIGALRM - alarm to display message every second

So I'm trying to call an alarm to display a message "still working.." every second.
I included signal.h.
Outside of my main I have my function: (I never declare/define s for int s)
void display_message(int s); //Function for alarm set up
void display_message(int s) {
printf("copyit: Still working...\n" );
alarm(1); //for every second
signal(SIGALRM, display_message);
}
Then, in my main
while(1)
{
signal(SIGALRM, display_message);
alarm(1); //Alarm signal every second.
That's in there as soon as the loop begins. But the program never outputs the 'still working...' message. What am I doing incorrectly? Thank you, ver much appreciated.
Signal handlers are not supposed to contain "business logic" or make library calls such as printf. See C11 ยง7.1.4/4 and its footnote:
Thus, a signal handler cannot, in general, call standard library functions.
All the signal handler should do is set a flag to be acted upon by non-interrupt code, and unblock a waiting system call. This program runs correctly and does not risk crashing, even if some I/O or other functionality were added:
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
volatile sig_atomic_t print_flag = false;
void handle_alarm( int sig ) {
print_flag = true;
}
int main() {
signal( SIGALRM, handle_alarm ); // Install handler first,
alarm( 1 ); // before scheduling it to be called.
for (;;) {
sleep( 5 ); // Pretend to do something. Could also be read() or select().
if ( print_flag ) {
printf( "Hello\n" );
print_flag = false;
alarm( 1 ); // Reschedule.
}
}
}
Move the calls to signal and alarm to just before your loop. Calling alarm over and over at high speed keeps resetting the alarm to be in one second from that point, so you never reach the end of that second!
For example:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void display_message(int s) {
printf("copyit: Still working...\n" );
alarm(1); //for every second
signal(SIGALRM, display_message);
}
int main(void) {
signal(SIGALRM, display_message);
alarm(1);
int n = 0;
while (1) {
++n;
}
return 0;
}
Do not call alarm() twice, just call it once in main() to initiate the callback, then once in display_message().
Try this code on Linux (Debian 7.8) :
#include <stdio.h>
#include <signal.h>
void display_message(int s); //Function for alarm set up
void display_message(int s)
{
printf("copyit: Still working...\n" );
alarm(1); //for every second
signal(SIGALRM, display_message);
}
int main()
{
signal(SIGALRM, display_message);
alarm(1); // Initial timeout setting
while (1)
{
pause();
}
}
The result will be the following one :
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
copyit: Still working...
The alarm() call is for a one off signal.
To repeat an alarm, you have to call alarm() again each time the signal occurs.
Another issue, also, is that you're likely to get EINTR errors. Many system functions get interrupted when you receive a signal. This makes for much more complicated programming since many of the OS functions are affected.
In any event, the correct way to wait for the next SIGALRM is to use the pause() function. Something the others have not mentioned (instead they have tight loops, ugly!)
That being said, what you are trying to do would be much easier with a simple sleep() call as in:
// print a message every second (simplified version)
for(;;)
{
printf("My Message\n");
sleep(1);
}
and such a loop could appear in a separate thread. Then you don't need a Unix signal to implement the feat.
Note: The sleep() function is actually implemented using the same timer as the alarm() and it is clearly mentioned that you should not mix both functions in the same code.
sleep(3) may be implemented using SIGALRM; mixing calls to alarm() and sleep(3) is a bad idea.
(From Linux man alarm)
void alarm_handler(int)
{
alarm(1); // recurring alarm
}
int main(int argc, char *argv[])
{
signal(SIGALRM, alarm_handler);
alarm(1);
for(;;)
{
printf("My Message\n");
// ...do other work here if needed...
pause();
}
// not reached (use Ctrl-C to exit)
return 0;
}
You can create variations. For example, if you want the first message to happen after 1 second instead of immediately, move the pause() before the printf().
The "other work" comment supposes that your other work does not take more than 1 second.
It is possible to get the alarm signal on a specific thread if work is required in parallel, however, this can be complicated if any other timers are required (i.e. you can't easily share the alarm() timer with other functions.)
P.S. as mentioned by others, doing your printf() inside the signal handler is not a good idea at all.
There is another version where the alarm() is reset inside main() and the first message appears after one second and the loop runs for 60 seconds (1 minute):
void alarm_handler(int)
{
}
int main(int argc, char *argv[])
{
signal(SIGALRM, alarm_handler);
for(int seconds(0); seconds < 60; ++seconds)
{
alarm(1);
// ...do other work here if needed...
pause();
printf("My Message\n");
}
// reached after 1 minute
return 0;
}
Note that with this method, the time when the message will be printed is going to be skewed. The time to print your message is added to the clock before you restart the alarm... so it is always going to be a little over 1 second between each call. The other loop is better in that respect but it still is skewed. For a perfect (much better) timer, the poll() function is much better as you can specify when to wake up next. poll() can be used just and only with a timer. My Snap library uses that capability (look for the run() function, near the bottom of the file). In 2019. I moved that one .cpp file to the eventdispatcher library. The run() function is in the communicator.cpp file.
POSIX permits certain of its functions to be called from signal handling context, the async-signal safe functions, search for "async-sgnal safe" here. (These may be understood as "system calls" rather than library calls). Notably, this includes write(2).
So you could do
void
display_message (int s) {
static char const working_message [] = "copyit: Still working...\n";
write (1, working_message, sizeof working_message - sizeof "");
alarm(1); /* for every second */
}
By the way, precise periodic alarms are better implemented using setitimer(2),
since these will not be subject to drift. Retriggering the alarm via software, as done here, will unavoidably accumulate error over time because of the time spent executing the software as well as scheduling latencies.
In POSIX sigaction(2) superceedes signal(2) for good reason:
the original Unix signal handling model was simple. In particular,
a signal handler was reset to its original "deposition" (e.g., terminate
the process) once it was fired. You would have to re-associate
SIGALRM with display_message() by calling signal() just before
calling alarm() in display_message().
An even more important reason for using sigaction(2) is the
SA_RESTART flag. Normally, system calls are interrupted when
a signal handler is invoked. I.e., when then signal handler returns,
the system call returns an error indication (often -1) and errno is
set to EINTR, interrupted system call. (One reason for this
is to be able to use SIGALRM to effect time outs, another is
to have a higher instance, such as a user, to "unblock" the
current process by sending it a signal, e.g.,
SIGINT by pressing control-C at the terminal).
In your case, you want signal handling to be transparent
to the rest of the code, so you would set the SA_RESTART flag
when invoking sigaction(2). This means the kernel should
restart the interrupted system call automatically.
ooga is correct that you keep reloading the alarm so that it will never go off. This works. I just put a sleep in here so you don't keep stepping on yourself in the loop but you might want to substitute something more useful depending on where you are headed with this.
void display_message(int s)
{
printf("copyit: Still working...\n" );
// alarm(1); //for every second
// signal(SIGALRM, display_message);
}
int main(int argc, char *argv[])
{
int ret;
while(1)
{
signal(SIGALRM, display_message);
alarm(1);
if ((ret = sleep(3)) != 0)
{
printf("sleep was interrupted by SIGALRM\n");
}
}
return (0);
}

Calling infinite loop code multiple times on alarm

I'm currently using an alarm signal SIGALRM to exit from an infinite loop.
My code is structured as follows
main_loop() {
set_alarm();
while(1)
counter++;
}
The logic is
- Set an alarm
- Enter while loop
- Read counter when we get SIGALRM
The code that runs upon SIGALRM is given below:
VERBOSE("Cycles :%u\n", counter);
iteration_index++;
if(iteration_index == iterations)
exit(0);
counter = 0;
main_loop();
I would now like to now give the user an option to specify the number of times (iterations) the alarm should go off. In short, modify the above logic into:
- Set an alarm
- Enter while loop
- Read counter when we get SIGALRM
- Increment iteration_index
-If iteration_index < iterations: call main_loop
- Else exit
I implemented the above logic and found that it segfaults after a few thousand iterations. I believe that the reason for this is that:
When the alarm triggers and it makes a new call to main_loop, the original main_loop frame still exists. This keeps repeatedly happening until it runs out of space and throws a segfault.
I've tried coming up with some design that does what I want, but I'm unable to visualize code-flow after the signal is triggered.
What is the right way to implement what I've described?
Regrading the modifications you listed:
- Set an alarm
- Enter while loop
- Read counter when we get SIGALRM
- Increment iteration_index
- If iteration_index < iterations: call main_loop
- Else exit
You could provide a series of keystrokes (say <ctrl> - 1 to allow the user to specify a number of times (just once). This example runs (with delays to allow some time for GetAsyncKeys(). Until the user presses <ctrl> 1, the loop will run forever. When <ctrl> 1 is pressed, program prompts them with how many time to let the alarm sound, then programs runs that many iterations, then quits..
#include <stdio.h>
#include <windows.h>
void set_alarm(void);
int main(void) {
int iterations=-1, counter=0;
while (iterations != counter)
{
if(iterations == -1)//code will run forever if iteration is not set by user
{
set_alarm();
counter++;
if (GetAsyncKeyState(VK_CONTROL)<0)
{
if (GetAsyncKeyState('1')<0)
{
printf("Enter how many time alarm should activate:\n");
scanf("%d", &iterations);
counter = 0;
Sleep(10);
}
}
}
else//this block will monitor alarm count, program quits when limit reached.
{
if(counter < iterations)
{
set_alarm();
counter++;
}
}
Sleep(10);//changed here for my test, you might need to change again
}
return 0;
}
void set_alarm(void)
{
//do something;
}
Yes, you are right. When the handler for SIGALRM runs, the main_loop() function is still running. Both functions will in fact be running on the same thread. If you never exit from the SIGALRM handler, then the next handler will go on top, and this will keep happening until you run out of stack and crash.
To fix this, simply return from the signal handler.
// Make sure that both of these are volatile
volatile int iteration_index;
volatile int counter;
void catch_sigalrm(int signo)
{
// Note: this is not safe, so I commented it out
// VERBOSE("Cycles :%u\n", counter);
iteration_index++;
if(iteration_index == iterations)
exit(0);
counter = 0;
set_alarm();
}
void main_loop(void)
{
set_alarm();
while (1)
__sync_fetch_and_add(&counter, 1);
}
I think this will work. It should use ldrex and strex for incrementing counter.
The problem with using counter++ is that it can be interrupted: counter++ is actually something like this:
int old_value = counter; // memory access
int new_value = old_value + 1;
counter = new_value; // memory access
As you can see, if the alarm goes off in the middle of counter++ the results will get wiped out. That is why you need to use __sync_fetch_and_add() instead.
The volatile specifier is MANDATORY
Here's the main loop with a normal counter variable. I've removed the call to set_alarm() because we're not concerned about it right now.
// This is wrong
int counter;
void main_loop()
{
while (1)
counter++;
}
Here's the assembly:
_main_loop:
b _main_loop
.comm _counter, 4, 2
Wait a second! It doesn't increment anything, it's just an infinite loop!
That's right. The compiler detected that counter can not possibly be read anywhere, and so optimized the increment right out of existence. You MUST use volatile. The volatile keyword instructs the compiler that counter may be read or written by something else that is not a thread (actually, it instructs the compiler to be strict about loads and stores, but that's the technical version). (For working with threads, volatile is almost never useful, you have to use atomics which are different.)
Here's the version with volatile:
// This is ALSO wrong
volatile int counter;
void main_loop(void)
{
while (1) counter++;
}
And the assembly:
_main_loop:
; load address of counter into r0
...
loop:
; increment counter
ldr r1, [r0]
adds r1, #1
str r1, [r0]
b loop
As you can see, this can be interrupted in the middle. This is why you have to use __sync_fetch_and_add(): it detects when counter++ was interrupted and it restarts the operation from the beginning.
Here is the correct version:
// MUST be volatile
volatile int counter;
void main_loop(void)
{
while (1)
__sync_fetch_and_add(&counter, 1);
}
More notes
You can't call printf() in a signal handler.
In fact, try to avoid doing anything in a signal handler.
At most, set a flag, write a byte to a pipe, or something like that.

How to call function with infinite-loop?

I need help to clear my concepts.
I have a function which toggle the Led status on/off after every second. Now the code for the on/off runs inside infite loop.
Example:
void ToggleLed( int pin_number)
{
// some code
while(1)
{
// code to execute the Led status
}
}
Now when I integrate this code with base line and called that function inside other function it just doesnt work no other functionality of software works.
Question: Function has infinite-loop and that it doesn't come out of control and other functions called after that function doesn't work.
If that is the case do I need to provide separate thread to it?
Any suggestion will be helpful.
Yes you will need a separate thread, or some other form of asynchronous execution. Once you enter that while loop, no other code runs in that thread. Ever.
If I understand correcctly nothing works in your integrated version. In that case, yes you probably need to run the infinite loop on a separate thread, because your function with the infinit loop will never exit, so no other code will ever run on that thread.
You don't say what OS, but yes, set it as a low-priority thread, minimal stack size. I flash a LED in my projects, just so I can easily see if the code has reached the abort-handler yet :)
void LEDflash_task_code(void *p)
{
while (1)
{
FIO1CLR=STATUS_LED;
OSsleep(750);
FIO1SET=STATUS_LED;
OSsleep(250);
};
};
If you have access to hardware peripheral timers (any micrcontroller/microprocessor application), you should use those hardware timers, not threads nor software sleep().
void init_toggle_led (uint32_t interval)
{
setup_hardware_timer(interval);
}
void toggle_led (void)
{
if( (hardware_timer_register & flag) > 0 )
{
port = port ^ pin_mask;
}
}
main()
{
init_toggle_led(1000);
for(;;)
{
do_stuff();
toggle_led();
}
}
This was an example with polling. Alternatively, you can use hardware interrupts from the timers and toggle the port from there.
As David mentioned, you should run your LED code in a separate thread. http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html#BASICS
Once you have threads, if you want your code to be able to stop your LED from blinking, then add a flag that's checked inside the while loop at each iteration, and if it's set then break out.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void * toggle_led(void *ptr);
int stop=0;
int main (int argc, const char * argv[])
{
printf("Hello, World!\n");
// set up thread
pthread_t LED_thread;
char * message = "blink!";
pthread_create( &LED_thread, NULL, toggle_led, (void*) message);
// do some other work
sleep(5);
// ok you want to quit now
stop=1;
pthread_join(LED_thread, NULL);
printf("Goodbye!\n");
return 0;
}
void *toggle_led(void *ptr)
{
while (!stop)
{
printf("%s \n", (char *)ptr);
sleep(1);
}
}
I think you need to implement as a watchdog functionality. Because if you use threads then even if other threads has some issues(like deadlock), your LEDs will toggle as long as toggle_led thread works. You need to implement an toggle_led() function and call from each of other threads /functions before returning to make sure all other threads/functions are getting executed successfully without waiting continuously for some resources

Resources