3

I'm trying to start a thread as soon as an interrupt occurs. However, I have realized that I can't start a thread from within an interrupt handler (or any function that is directly or indirectly being called by the interrupt handler). So, what I have decided to do is have the handler assert a flag. Then, a separate thread continously monitors that flag and if it's asserted it will in turn create (and start) a thread. Here's a pseudocode:

int interrupt_flag = 0;

interrupt_handler(void)
{
  interrupt_flag = 1
}

monitoring_thread(void) //this thread is started at the start of the program
{
  while(1)
  {
    if(interrupt_flag)
    {
      interrupt_flag = 0;
      //start the thread here
      sleep(/*some amount of time*/);
    }
  }
}

I'm not really happy with having a dedicated while loop constantly monitoring a flag. The problem with this is that it significantly reduces the speed of the other threads in my program. For this reason, I'm calling the sleep function to increase the speed of the other threads in my program.

Question: Is there a way I can truly start a thread upon interrupt, without having a dedicated while loop? Is there a workaround for starting a thread from within an interrupt handler?

If it makes any difference, I'm using the POSIX library.

Thanks,

PS. This question is somewhat related to an earlier question posted here:

Sharing data between master thread and slave thread in interrupt driven environment in C

Community
  • 1
  • 1
Arash Fotouhi
  • 1,933
  • 2
  • 22
  • 43
  • If the interrupt handler is pre-empting the current task, I would expect that it would have some API to call that would schedule some other task (or callback) to run to do the real work. Is there nothing like this you can do in your system? That task could then spawn the thread. – jxh Jul 11 '13 at 01:00
  • Yes, if this is an operating system (what else would be handling an interrupt?) then it should have a way to wake a waiting task. – Zan Lynx Jul 11 '13 at 01:15
  • The traditional method is to use a semaphore. Calling any methods that could potentially block, (eg. mutex), in an interrupt-handler will result in eventual disaster. – Martin James Jul 11 '13 at 06:07

2 Answers2

4

Instead of having your monitoring thread spin on a flag, it could wait until the interrupt handler provides notification that a thread should be spawned. One way to do this is with a semaphore:

sem_t interrupt_sem;

void interrupt_handler(void)
{
  sem_post(&interrupt_sem);
}

void monitoring_thread(void)
{
  while(1)
  {
    sem_wait(&interrupt_sem);
    //start the thread here
  }
}

Previously, I had a solution based on a condition variable, but it is unlikely your system would operate correctly if the interrupt handler makes blocking calls. It could cause a deadlock or other undefined behaviors, as the variables in the system may not have consistent values at the time the interrupt takes place.

As pointed out in comments by myself and others, your operating system should provide some kind of interface to explicitly wake up a waiting task. In the code above, we are assuming the monitoring thread is always active in the background.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • It is very unlikely that calling `pthread_mutex_lock()` in the interrupt handler is safe. If the interrupt fires in the monitoring thread at a point where it holds the lock, a deadlock will result. – caf Jul 11 '13 at 05:20
  • @caf: You are right if the interrupt handler is running at an elevated priority. I am assuming the monitoring thread is in a different context from the interrupt handler. – jxh Jul 11 '13 at 05:36
  • In every OS I have worked on, it is not permitted to issue potentially blocking calls from an interupt handler. Like @caf says, an interrupt-handler has no thread context and must not block. The classic solution is as posted by user2569075. – Martin James Jul 11 '13 at 06:04
  • @MartinJames: I thought a multithreaded kernel would have a dedicated context for interrupt handlers. I have updated the answer to note the limitations of the mutex and condition variable solution, and provided the simpler semaphore based solution. – jxh Jul 11 '13 at 08:00
  • `pthread_mutex_lock()` is not async-signal safe, i.e. it can not be called from a signal handler. Even more convenient portable solution is a self-pipe trick: the signal handler writes a byte into a pipe. The other thread waits of the read end of the pipe. – Maxim Egorushkin Jul 11 '13 at 09:19
  • @jxh well, it may have a separate interrupt stack that it gets switched to, but it cannot easily have any thread context - it can, and probably will, interrupt any thread in any process belonging to any user, probably during OS kernel calls that are already in the process of changing thread state. This is why the number of OS calls available to the lowest-level of hardware interrupt-handlers are usually restricted to setting flags, posting semaphore units. An interrupt-handler cannot block. Calling anything that could possibly block will result in a UB disaster, maybe kernel panic, BSOD. – Martin James Jul 11 '13 at 10:00
  • @MartinJames: Answer adjusted accordingly. Thanks. – jxh Jul 11 '13 at 17:49
1

you can use POSIX semaphore too

you can wait a semaphore that initial value is 0 by a thread that will be blocked by wait

and post this semaphore in your signal handle function

then , thread above will be waked up and do things you want(create thread)

  • This is the traditional method of handling comms between a interrupt handler/driver and a thread. – Martin James Jul 11 '13 at 06:05
  • Note that, if the interrupt-handler posts to the semaphore, it must then take some special action to be effective, instead of just interrupt-returning. Sometimes there is an OS 'flag' that needs to be set, or maybe a 'ExitInterruptSchedule' function call or an actual jump to an OS entry point. This allows an interrupt handler to make a thread ready/running 'immediately' after the interrupt-return, possibly preempting some other thread that happened to be running before the interrupt. – Martin James Jul 11 '13 at 06:26