A Win32 Perspective:
- Kernel.
- Preemptive.
- (On win32) yield() translates to sleep 0; which is the standard way for a thread (or process) to give up the rest of its current timeslice.
However, if there are no other threads eligable to run, it can lead to the same thread being immediately given another timeslice, which if it has nothing to do, it will again immediately yield. And if there are still no other threads eligable to run, it is again immediately given another timeslice... As you can see, this can lead to intense context swapping, maxed out cpu, energy usage etc.
For most cases, it is better to use a sleep (or Win32::Sleep) with a short duration, as this can reduce cpu usage and context thrashing to almost 0 with little or no affect upon the responsiveness or throughput of the application.
What are the 'break points' or commands that may be preempted?
That is a really vague question to ask on a perl forum. As we are talking kernel threads, the scheduler can interupt between any two machine level instructions unless the programmer takes steps to prevent it by using some serialisation mechanism like Critical Sections (not available from Perl).
At the Perl-level, it is really hard to discuss as Perl itself does some serialisation for its own internal integrity. And the C-runtime libraries do some serialisation for their own internal integrity.
For user-level Perl code, you theortically only need concern yourself with controlling access to variables explicitly marked as shared. However, the user does have to concern themselves with access to process-global entities like files, directories, sockets etc.
what functions or operators are atomic?
As above, are you talking Perl-level functions and operators; C-level functions and operators; machine-level?
how are signals handled? I have found differing write ups that don't versions.
Very platform specific. Whilst Perl attempts to emulate a very limited set of signal-type behaviours on Win32, and later versions of threads have attempted to extend that emulation to inter-threading, neither is very satisfactory.
(ITMO) attempting to use signals for inter-thread communications is a bastardisation of a primitive mechanism that doesn't work anywhere well.
This should be simple if I can find the correct "FM" to "RT"; or a link to such.
If you find one, please come back and post a link. I'd like to read it also.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
These are good answers, thank you...
On the subjects of signals, my intent is to be able to use signals to 'signal' my daemon app to do a clean shutdown; or for logrotate to notify that the logfile I am watching has been rotated.
My testing has shown that once my main thread drops into a 'join', signals are no longer processed. That would make 'join()' non-interruptable. In place of that I am trying:
#done starting all threads
while (!$cleanShutDown) { # set in SIGHUP handler
sleep 30; # which is interupted by a signal
}
$logmon -> join();
... #more joins
exit 0;
| [reply] [d/l] |
That would make 'join()' non-interruptable.
Actually, there are many things that are not interuptable by signals, and most of them are unrelated to threading.For example, most IO (read, print, sys* accept etc.), sort, the regex engine etc.
This is especially true since the advent of "Safe signals" in 5.8.1. See the discussion under the description of the environment variable PERL_SIGNALS at the bottom of perlrun and the section "Deferred signals" in perlipc.
In place of that I am trying
Well, you could always move the joins into a thread:
my $done :shared = 0;
async{
$_->join for @threads;
$done = 1;
}->detach;
sleep 1 until $done;
exit 0;
This will ensure that your main thread remains responsive to signals whilst the joins take place, and by detaching the join thread, it will clean up after itself without further intervention.
Of course, you could also use the cond_* calls in threads::shared instead of $done, but you still need a shared var for the signalling; the cond_* calls are the least well documented (and tested) part of threading; and the hardest to grasp, test and debug.
Besides which , cond_wait() is itself non-interuptable so that wouldn't help much.
Indeed, I only really mention cond_* for completeness. And because there are certain parties that frown upon my use of this "crude" (their word, I prefer "simple") signalling mechanism. In my experience, this simple signalling construct is far more reliable and far easier to debug than condition variables.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |