I'm trying to port the real time Thread_Metric from ExpressLogic in POSIX, in order to benchmark PREEMPT_RT patches for Linux, Xenomai and RTAI for my thesis. They provide a C source file with the following functions, which you have to implement in order for the benchmark to work:
void tm_initialize(void (*test_initialization_function)(void));
int tm_thread_create(int thread_id, int priority, void (*entry_function)(void));
int tm_thread_resume(int thread_id);
int tm_thread_suspend(int thread_id);
void tm_thread_relinquish(void);
void tm_thread_sleep(int seconds);
int tm_queue_create(int queue_id);
int tm_queue_send(int queue_id, unsigned long *message_ptr);
int tm_queue_receive(int queue_id, unsigned long *message_ptr);
int tm_semaphore_create(int semaphore_id);
int tm_semaphore_get(int semaphore_id);
int tm_semaphore_put(int semaphore_id);
int tm_memory_pool_create(int pool_id);
int tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr);
int tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr);
Right now I'm trying to implement the tm_thread_suspend and tm_thread_resume functions, which take a pthread as input. I know that you can suspend a pthread with pthread_mutex_lock and pthread_cond_wait routines, but you have to call these from the thread start_function. I'm new at this kind of stuff and I'm way in over my head. Any help is appreciated.
The way you do this is to use sigwait() and pthread_kill.
// global variable
Before calling pthread_create we set a signal mask. Every thread will inherit the mask. You could set the mask in the thread function I suppose. Here is the code we use:
To SUSPEND:
To RESUME:
If you cant use SIGUSR1 for some reason be aware that not all signals work for us. We may be doing something wrong, but SIGCONT doesn't work.
We have benchmarked pausing threads this way and this method was 5x faster than using mutexes and condition variables.
Here is some code that uses this technique.
pthread_suspend
really seems the way to go if it's available. This solution might be more dirty than it's worth. For each thread keep asemaphore
. Make each thread listen for signals. In the signal handler simply do adown
on the associated semaphore.So when you want to
stop
a thread, simply send it a signal (perhaps using a real-time signal would be best) and it will stop in the handler. The handler masks itself by default (that is, it won't be called again if the same signal is received before it is done). When you want to restart the thread, simply do anup
on the semaphore.Caveat:
SA_RESTART
)sem_wait(3)
isn't async-signal safe, but it's safe as long as you don't useSA_NODEFER
(not that you'd have any reason)Unfortunately I can't find any really stellar free documentation about this. Still, stellar or not, there is a lot of free documentation.
Edit
As suggested by @R.. there are
async-signal-safe
functions that block that you could use (instead of the unsafesem_wait
). Here's a list of functions you may safely use.Some implementations of pthreads have these functions. http://www.unix.com/man-page/all/3t/pthread_suspend/ But your linux kernel may not support them.
You can do this completely portably (avoiding all issues with async-signal-unsafe functions) using two signals:
The "thread suspend" signal handler would use
pselect
to atomically unblock the second signal and sleep indefinitely. The second signal would terminate thepselect
and cause the signal handler to return.Also there are plenty of other solutions using async-signal-safe interfaces - basically anything that deals with file descriptors and blocking on them rather than on user-space synchronization primitives. For example, having the signal handler
read
from a pipe and writing a single byte to the pipe to resume the thread would work.