tags:

views:

203

answers:

4

Looks like linux doesnt implement pthread_suspend and continue, but I really need em.

I have tried cond_wait, but it is too slow. The work being threaded mostly executes in 50us but occasionally executes upwards of 500ms. The problem with cond_wait is two-fold. The mutex locking is taking comparable times to the micro second executions and I don't need locking. Second, I have many worker threads and I don't really want to make N condition variables when they need to be woken up.

I know exactly which thread is waiting for which work and could just pthread_continue that thread. A thread knows when there is no more work and can easily pthread_suspend itself. This would use no locking, avoid the stampede, and be faster. Problem is....no pthread_suspend or _continue.

Any ideas?

+3  A: 

Make the thread wait for a specific signal.

Use pthread_sigmask and sigwait.

jweyrich
+1 for a promising answer. I will test this out tonight and give you the answer if it works. Thanks!
johnnycrash
Forgot to mention you MUST use `pthread_kill` to signal a specific thread, otherwise you can't predict which thread is going to resume.
jweyrich
A: 

It seems to me that such a solution (that is, using "pthread_suspend" and "pthread_continue") is inevitably racy.

An arbitrary amount of time can elapse between the worker thread finishing work and deciding to suspend itself, and the suspend actually happening. If the main thread decides during that time that that worker thread should be working again, the "continue" will have no effect and the worker thread will suspend itself regardless.

(Note that this doesn't apply to methods of suspending that allow the "continue" to be queued, like the sigwait() and read() methods mentioned in other answers).

caf
Note that signals are queued (at least on NPTL).
jweyrich
@jweyrich: Aye, you can do it with signals, since `sigwait()` effectively does an atomic unblock-wait-block.
caf
When the dispatcher adds work to the circular work queue, it will check the corresponding circular suspended queue. A suspended thread at the same index as the work will be woken up. The waking thread clears its suspended flag. The dispatcher will from time to time scan the suspended queue looking for threads that didnt wake up (the race) and signal them again. At the end of processing that suspended scan needs to be repeated (perhaps with a 1ms sleep) until all threads wake and complete. Since the race condition is rare I estimate 1/100 transactions will need the extra scan at the end.
johnnycrash
@caf: What do you mean by atomic unblock-wait-block?
johnnycrash
@johnnycrash: `sigwait()` requires that you have the signal you are going to wait on blocked in the thread's signal mask. It then waits for that signal to occur (effectively unblocking it), and when it returns the signal is blocked again.
caf
+1  A: 

Have the threads block on a pipe read. Then dispatch the data through the pipe. The threads will awaken as a result of the arrival of the data they need to process. If the data is very large, just send a pointer through the pipe.

If specific data needs to go to specific threads you need one pipe per thread. If any thread can process any data, then all threads can block on the same pipe and they will awaken round robin.

Amardeep
A: 

May be try an option of pthread_cancel but be careful if any locks to be released,Read the man page to identify cancel state

Yusuf