1

I have the following:

f1()
{
    while(1)
    {
        call f(2) if hardware interrupt pin goes high
    }
}

f2()
{
    if( th() not started )
    {
        start thread th()
    }
    else
    {
        return thread th() status
    }
}

th()
{
    time-consuming operation
}

At the moment, I use the following to initiate a struct in f2():

static struct SharedData shared;
if( shared == NULL)
{
    initialize shared
}

Then I pass a pointer to shared to the thread. The thread then updates shared periodically. f2() will then know if th() has been started based on elements of shared and it will check the status of th() by reading from shared.

Let's assume one of the elements of shared is a mutex to provide thread safety. Is this a good solution? Is there a more elegant way of doing this? I have tested the code and it works. I just need some expert advice here.

Thanks,

Arash Fotouhi
  • 1,933
  • 2
  • 22
  • 43
  • 1
    ?? 'I have tested the code and it works'. In every OS I've ever used, it is not possible to create threads from interrupt-handlers. Usually, the only thing you can do in there is signal a semaphore and then exit the handler via the OS interrupt entry point to ensure that a scheduler run is made so that any thread waiting on the semaphore is made ready/running. – Martin James Jun 27 '13 at 19:22
  • Oh - hang on - are you using a thread to poll some boolean that is set by the interrupt-handler? If so, that is not remotely an efficient way of communicating between interrupt-handlers and a multithreading OS. It defeats the major advantage of a preemptive, multitasking OS - good I/O performance. – Martin James Jun 27 '13 at 19:30
  • @MartinJames Yes, I'm polling a boolean set by the interrupt-handler because I couldn't start a thread inside the handler as you mentioned in your first comment. What is the best way to do this? You've explained a solution in your first comment, is this the best way? Thanks. – Arash Fotouhi Jun 27 '13 at 19:47
  • 1
    It's the way it's usually done. The handler thread waits on a semaphore at the top of a loop that processes the interrupt, maybe by calling your 'time-consuming operation'. The interrupt-handler signals the semaphore and then calls/jumps/whatever to some 'ExitInterrupt(bool schedRequired)' OS entry. That makes the handler thread ready/running 'immediately', (and possibly preempting another thread that was running before the interrupt). There is no polling and no continual thread creation/termination. Summary - it's a pile faster and much more efficient. – Martin James Jun 27 '13 at 20:16

1 Answers1

2

Assuming that f2() uses the same mutex in the shared structure to lock before reading the data that the thread th uses to modify the data, I don't see any issues.

If you have more than one thread calling f2(), you may want to use a read-write lock for reading and writing of the thread status of th. The mutex could still be used to serialize the thread creation check. You could also use a pthread_rwlock_wrlock() to serialize th creation, but the code is arguably less clear.

Using a mutex to serialize th creation in f2():

pthread_rwlock_rdlock(&shared.rwlock);
result = shared.th_status;
if (! shared.th_created) {
    pthread_mutex_lock(&shared.mutex);
    if (! shared.th_created) {
        pthread_create(...);
        shrared.th_created = 1;
    }
    pthread_mutex_unlock(&shared_mutex);
}
pthread_rwlock_unlock(&shared.rwlock);
return result;

Using the read-write lock to serialize th creation in f2():

pthread_rwlock_rdlock(&shared.rwlock);
result = shared.th_status;
if (! shared.th_created) {
    pthread_rwlock_unlock(&shared.rwlock);
    pthread_rwlock_wrlock(&shared.rwlock);
    if (! shared.th_created) {
        pthread_create(...);
        shrared.th_created = 1;
    }
}
pthread_rwlock_unlock(&shared.rwlock);
return result;
jxh
  • 69,070
  • 8
  • 110
  • 193