1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
Some old globals (e.g. stack_sp, op) and some old per-interpreter
variables (e.g. tmps_stack, cxstack) move into struct thread.
All fields of struct thread (apart from a few only applicable to
FAKE_THREADS) are of the form Tfoo. For example, stack_sp becomes
the field Tstack_sp of struct thread. For those fields which moved
from original perl, thread.h does
#define foo (thr->Tfoo)
This means that all functions in perl which need to use one of these
fields need an (automatic) variable thr which points at the current
thread's struct thread. For pp_foo functions, it is passed around as
an argument, for other functions they do
dTHR;
which declares and initialises thr from thread-specific data
via pthread_getspecific. If a function fails to compile with an
error about "no such variable thr", it probably just needs a dTHR
at the top.
For FAKE_THREADS, thr is a global variable and perl schedules threads
by altering thr in between appropriate ops. The next and prev fields
of struct thread keep all fake threads on a doubly linked list and
the next_run and prev_run fields keep all runnable threads on a
doubly linked list. Mutexes are stubs for FAKE_THREADS. Condition
variables are implemented as a list of waiting threads.
Mutexes and condition variables
The API is via macros MUTEX_{INIT,LOCK,UNLOCK,DESTROY} and
COND_{INIT,WAIT,SIGNAL,BROADCAST,DESTROY}. For POSIX threads,
perl mutexes and condition variables correspond to POSIX ones.
For FAKE_THREADS, mutexes are stubs and condition variables are
implmented as lists of waiting threads. For FAKE_THREADS, a thread
waits on a condition variable by removing itself from the runnable
list, calling SCHEDULE to change thr to the next appropriate
runnable thread and returning op (i.e. the new threads next op).
This means that fake threads can only block while in PP code.
A PP function which contains a COND_WAIT must be prepared to
handle such restarts and can use the field "private" of struct
thread to record its state. For fake threads, COND_SIGNAL and
COND_BROADCAST work by putting back all the threads on the
condition variables list into the run queue. Note that a mutex
must *not* be held while returning from a PP function.
Perl locks are a condpair_t structure (a triple of a mutex, a
condtion variable and an owner thread field) attached by 'm'
magic to any SV. pp_lock locks such an object by waiting on the
condition variable until the owner field is zero and then setting
the owner field to its own thread pointer. The lock is recursive
so if the owner field already matches the current thread then
pp_lock returns straight away. If the owner field has to be filled
in then unlock_condpair is queued as an end-of-block destructor and
that function zeroes out the owner field, releasing the lock.
|