C Signal timer for task switching - c

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?

Related

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

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.

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.

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

How do I measure how long a (linux C) function takes to execute?

I have a particular function (well, set of functions) that I want to start every 400ms. I'm not much of a C programmer, and so anything outside of the standard libraries is a mystery to me, as well as quite a bit within them.
My first thought is to use nanosleep to pause execution for 400ms in some sort of loop, but this of course doesn't take into account the execution time of the code I will be running. If I could measure it, and if it seemed fairly certain that it ran for the same approximate duration after 10 or 20 tests, I could then nanosleep() for the difference. This wouldn't be perfect, of course... but it might be close enough for a first try.
How do I measure the execution time of a C function? Or is there a better way to do this altogether, and what keywords do I need to be googling for?
You should be able to use settimer
int setitimer(int which, const struct itimerval *value,
struct itimerval *ovalue);
Just put the code that you want to execute every 400ms inside the SIGALRM handler. This way you don't need to account for the time that your code takes to run, which could potentially vary. I'm not sure what happens if the signal handler doesn't return before the next signal is generated.
An outline of what some of the code might look like is shown below.
void periodic_fuc(int signal_num)
{
...
signam(SIGALRM, periodic_func);
}
int main(...)
{
struct itimerval timerval = {0};
signal(SIGALRM, periodic_func);
...
timerval.it_interval.tv_usec = 400000;
timerval.it_value.tv_usec = 400000; // Wait 400ms for first trigger
settimer(ITIMER_REAL, &timerval, NULL);
while (!exit)
sleep(1);
return 0;
}
Take a look at gprof. It allows you to quickly recompile your code and generate information on which functions are being called and what is taking up the most time in your program.
I concur with torak about using setitimer(). However, since it's not clear if the interval is restarted when the SIGALRM handler exits, and you're really not supposed to do much work in a signal handler anyway, it's better to just have it set a flag, and do the work in the main routine:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
volatile sig_atomic_t wakeup = 0;
void alarm_handler(int signal_num)
{
wakeup = 1;
}
int main()
{
struct itimerval timerval = { 0 };
struct sigaction sigact = { 0 };
int finished = 0;
timerval.it_interval.tv_usec = 400000;
timerval.it_value.tv_usec = 400000;
sigact.sa_handler = alarm_handler;
sigaction(SIGALRM, &sigact, NULL);
setitimer(ITIMER_REAL, &timerval, NULL);
while (!finished)
{
/* Wait for alarm wakeup */
while (!wakeup)
pause();
wakeup = 0;
/* Code here... */
printf("(Wakeup)\n");
}
return 0;
}
You could use gettimeofday() or clock_gettime() before and after the functions to time, and then calculate the delta between the two times.
For Linux, you can use gettimeofday. Call gettimeofday at the start of the function. Run whatever you have to run. Then get the end time and figure out how much longer you have to sleep. Then call usleep for the appropriate number of microseconds.
Look at POSIX timers. Here is some documentation at HP.
You can do the same functions as with setitimer, but you also have timer_getoverrun() to let you know if you missed any timer events during your function.

Signal handler for SIGALRM does not work even if resetting in the handler

The example code of section 10.6, the expected result is:
after several iterations, the static structure used by getpwnam will be corrupted, and the program will terminate with SIGSEGV signal.
But on my platform, Fedora 11, gcc (GCC) 4.4.0, the result is
[Langzi#Freedom apue]$ ./corrupt
in sig_alarm
I can see the output from sig_alarm only once, and the program seems hung up for some reason, but it does exist, and still running.
But when I try to use gdb to run the program, it seems OK, I will see the output from sig_alarm at regular intervals.
And from my manual, it said the signal handler will be set to SIG_DEF after the signal is handled, and system will not block the signal. So at the beginning of my signal handler I reset the signal handler.
Maybe I should use sigaction instead, but I only want to know the reason about the difference between normal running and gdb running.
Any advice and help will be appreciated.
following is my code:
#include "apue.h"
#include <pwd.h>
void sig_alarm(int signo);
int main()
{
struct passwd *pwdptr;
signal(SIGALRM, sig_alarm);
alarm(1);
for(;;) {
if ((pwdptr = getpwnam("Zhijin")) == NULL)
err_sys("getpwnam error");
if (strcmp("Zhijin", pwdptr->pw_name) != 0) {
printf("data corrupted, pw_name: %s\n", pwdptr->pw_name);
}
}
}
void sig_alarm(int signo)
{
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
err_sys("getpwnam error");
alarm(1);
}
According to the standard, you're really not allowed to do much in a signal handler. All you are guaranteed to be able to do in the signal-handling function, without causing undefined behavior, is to call signal, and to assign a value to a volatile static object of the type sig_atomic_t.
The first few times I ran this program, on Ubuntu Linux, it looked like your call to alarm in the signal handler didn't work, so the loop in main just kept running after the first alarm. When I tried it later, the program ran the signal handler a few times, and then hung. All this is consistent with undefined behavior: the program fails, sometimes, and in various more or less interesting ways.
It is not uncommon for programs that have undefined behavior to work differently in the debugger. The debugger is a different environment, and your program and data could for example be laid out in memory in a different way, so errors can manifest themselves in a different way, or not at all.
I got the program to work by adding a variable:
volatile sig_atomic_t got_interrupt = 0;
And then I changed your signal handler to this very simple one:
void sig_alarm(int signo) {
got_interrupt = 1;
}
And then I inserted the actual work into the infinite loop in main:
if (got_interrupt) {
got_interrupt = 0;
signal(SIGALRM, sig_alarm);
struct passwd *rootptr;
printf("in sig_alarm\n");
if ((rootptr = getpwnam("root")) == NULL)
perror("getpwnam error");
alarm(1);
}
I think the "apue" you mention is the book "Advanced Programming in the UNIX Environment", which I don't have here, so I don't know if the purpose of this example is to show that you shouldn't mess around with things inside of a signal handler, or just that signals can cause problems by interrupting the normal work of the program.
According to the spec, the function getpwnam is not reentrant and is not guaranteed to be thread safe. Since you are accessing the structure in two different threads of control (signal handlers are effectively running in a different thread context), you are running into this issue. Whenever you have concurrent or parallel execution (as when using pthreads or when using a signal handler), you must be sure not to modify shared state (e.g. the structure owned by 'getpwnam'), and if you do, then appropriate locking/synchronization must be used.
Additionally, the signal function has been deprecated in favor of the sigaction function. In order to ensure portable behavior when registering signal handlers, you should always use the sigaction invocation.
Using the sigaction function, you can use the SA_RESETHAND flag to reset the default handler. You can also use the sigprocmask function to enable/disable the delivery of signals without modifying their handlers.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void sigalrm_handler(int);
int main()
{
signal(SIGALRM, sigalrm_handler);
alarm(3);
while(1)
{
}
return 0;
}
void sigalrm_handler(int sign)
{
printf("I am alive. Catch the sigalrm %d!\n",sign);
alarm(3);
}
For example, my code is runing in main doing nothing and every 3 seconds my program says im alive x)
I think that if you do as i done calling in the handler function alarm with value 3, the problem is resolved :)

Resources