tagged release 0.7.1
[parrot.git] / docs / stm / internals.pod
blob02fee24ffe4acb1d4633277fd9386a6a7406de59
1 # Copyright (C) 2006-2007, The Perl Foundation.
2 # $Id$
4 =head1 NAME
6 Software Transactional Memory internals
8 =head1 VERSION
10 $Revision$
12 =head1 DESCRIPTION
14 The STM implementation is based on Robert Ennals' paper called "Software
15 Transactional Memory Should Not Be Obstruction-Free", originally at
16 L<http://www.cambridge.intel-research.net/~rennals/052_Rob_Ennals.pdf>, now
17 apparently available from
18 L<http://www.cs.wisc.edu/trans-memory/misc-papers/052_Rob_Ennals.pdf>.
20 Most of the internals of the STM implementation are contained in
21 C<src/stm/backend.c> and C<src/stm/stm_internals.h>
23 =head2 Shared PMCs
25 Before any transaction is committed, the STM system calls the
26 VTABLE method C<share_ro()> on the PMC to make it safe to share.
27 This VTABLE method should make the PMC read-only and mark it as
28 sharable. Doing this typically requires substantailly less effort
29 (and less synchoronization) than making it safe to share a writable
30 PMC. Implementations of this VTABLE method currently exist in the
31 scalar, array, ParrotObject, STMVar, and STMRef PMC types. 
32 C<share_ro()> returns a potentially different PMC that is the shared
33 and read-only version.
34 (The PMC is allowed to be relocated for a potentially different future 
35 implementation, but the current implementation actually always returns
36 the pmc it is called on.)
38 Note that C<share_ro()> needs to share everything to which the PMC refers.
39 PMCs not marked as shared may not be garbage collected correctly (i.e.
40 freed when references to them still exist) if they are not always referenced
41 through their 'owning' interpreter.
43 To support this feature, pmc2c generates a second vtable for most types
44 with the writing methods removed. (Generation of this second vtable
45 can be disabled with the C<no_ro> PMC flag.) A pointer to this vtable
46 is stored in the C<ro_variant_vtable> entry of the VTABLE structure.
47 One can switch to this vtable by calling C<setprop()> to set the 
48 "_ro" property to a true value. The implementation of C<setprop()>
49 in C<default.pmc> performs the switch.
51 Methods which are considered read-only point to automatically generated
52 versions that call C<exit_fatal()> in the read-only vtable.
53 The notion of read-onlyness is obtained first from C<src/vtable.tbl>'s
54 marking of methods with C<:write>. For MMD methods, it is guessed when
55 a method will write a value based on the signature of the method,
56 and if it would, then the check 
57 C<<(pmc->vtable->flags & VTABLE_IS_READONLY_FLAG)>> is performed to see
58 if the object is unsafe to write. (This is implemented by calls to
59 C<mmd_ensure_writable> in C<mmd.c>.) For other methods, C<find_method>
60 is overriden in the read-only variant to check the "write" property
61 on the method that would be returned. (See also C<Parrot_mark_method_writes>
62 in C<inter_misc.c>.) If it is set, then C<PMCNULL> is returned, 
63 making the method lookup fail. 
65 C<.pmc> files may mark vtable and NCI methods with the annotations
66 C<:read> and C<:write> to override the default notion of whether or
67 not they read and write. These values should be inherited properly.
68 See C<src/dynpmc/rotest.pmc> for an example.
70 C<share_ro()> implementations should also call C<pt_shared_fixup()>.
71 Currently, C<pt_shared_fixup()> changes the vtable pointer to the equivalent
72 one in the first interpreter, hopefully ensuring the vtable pointer will
73 remain valid if the current interpreter exits. It also marks the PMC
74 as shared so garbage collection will work properly on it. The PMC
75 C<pt_shared_fixup()> returns is the one implementations of C<share_ro()>
76 returns. Currently, this is the same PMC that is passed in.
78 When a user of STM requests a writable copy of a PMC stored in an PMC handle
79 a clone is made. C<local_pmc_copy> in C<src/stm/backend.c> performs
80 the cloning using C<VTABLE_clone()> on some types where it is safe
81 and C<Parrot_clone()> otherwise. (C<Parrot_clone()> is much slower
82 than C<VTABLE_clone()> in most cases, but it not always a deep clone,
83 or in the special case of Strings, safe to do from an interpreter other
84 than the one in which the object was created.)
86 Note that the PMC referred to by a PMC handle may still contain C<STMVar>s
87 and C<STMRef>s, which should be preserved by C<local_pmc_copy()>; that is
88 they will still refer to the same PMC handle. This allows
89 structures like linked lists (where each node contains the value, and
90 STMVars acting as next and previous pointers) and is safe because
91 C<STMVar>s and C<STMRef>s are immutable in the sense that they cannot be
92 made to point to a different PMC handle.
94 =head2 PMC Handles
96 STM wraps each PMC it manages with a 'PMC handle', which is a garbage-
97 collectable structure. C<STMVar> and C<STMRef> PMCs contain a pointer
98 to the PMC handle in their C<struct_val> field. A PMC handle's fields
99 are as follows:
101      Parrot_atomic_pointer owner_or_version;
103 If this pointer contains an odd memory address, it is a version number.
104 If it contains an even memory address, it points to the transaction
105 log of the current owner. Ownership of a PMC handle is only obtained
106 when a write is planned and block other reads and writes so long as the
107 owner is not aborted.
109 (Note that, as this implies, the STM implementation assumes its
110 subtransaction logs are aligned on a 2-byte boundary, at least.)
112      void * volatile last_version;
114 This contains the last version number that was committed to this
115 handle. It is always updated before C<owner_or_version> is.
117      PMC *value;
119 This contains the current value of the wrapped PMC. This value
120 should only be used after reading a version number (not owner
121 address from C<owner_or_version>). This value may only be changed
122 after setting C<owner_or_version> to point to a transaction log
123 and marking the transaction as committed.
124   
125      STM_waitlist change_waitlist;
127 This waitlist is signalled after writes are made and threads will
128 add themselves to it after C<Parrot_STM_wait()> is called.
130 =head2 Transaction Logs
132 Transaction logs contain a list of values read and written by a thread.
133 Currently, these lists are kept in (dynamically allocated) arrays.
134 To support nested transactions, each level of nesting has its own small
135 structure:
137  struct STM_tx_log sub {
138      Parrot_atomic_integer status;
140 One of STM_STATUS_ACTIVE, STM_STATUS_ABORTED, or STM_STATUS_COMMITTED.
141 An active transaction is one that may potentially commit. An aborted
142 transaction is one that may never commit. A committed transaction has
143 committed or is in the process of committing and can no longer be aborted.
145      Parrot_atomic_integer wait_length;
147 Used for simple deadlock detection.
149      int first_write;
150      int first_read;
152 The first read and first write record of this transaction. Note that these
153 will be set even if the transaction has no reads or writes. The innermost
154 transaction owns the write records between first_write and last_write
155 (in C<struct STM_tx_log>) inclusive.
157  };
159 The threads' entire transaction log is represented by a 
160 C<struct STM_tx_log> structure:
162  struct STM_tx_log {
163      int depth;
165 How many transactions are active in this thread. C<0> when no transaction
166 is opened.
168      STM_tx_log_sub inner[STM_MAX_TX_DEPTH];
170 Logs for individual nested transactions. 0 is the first used. 
171 C<STM_MAX_TX_DEPTH> is the maximum transaction nesting depth, which is 
172 currently 32.
174      int last_write;
175      int last_read;
177 The last read and write record in use. (-1 when no read or write records
178 are in use.)
180      STM_write_record *writes;
181      int writes_alloced;
182      STM_read_record *reads;
183      int reads_alloced;
185 Point to the actual read and write records. There should only be one
186 read record active for any PMC handle. There may be multiple write
187 records for a PMC handle because an inner transaction must create a new
188 write record even if the outer transaction has one to support aborts.
189 If there are multiple write records for a single PMC handle, only the
190 last should be used. If there is both a write and read record,
191 the value derived from the write record should be used.
193 Note that a lot of linear searching through these record lists needs 
194 to be done, so it would probably better if some other data structure
195 were used, though there is likely to be little performance difference
196 (or worse performance) when transactions are small.
198      struct waitlist_thread_data *waitlist_data;
200 Used internally by the waitlist implementation in C<src/stm/waitlist.[ch]>
202   };
204 To support saving and replaying logs through the STMLog PMC, a structure
205 that merely holds read and write records and no status information exists.
206 Note that because version numbers in this saved log are out-of-date, a
207 replayed transaction is unlikely to commit.
209  struct STM_saved_tx_log {
210      int num_reads;
211      int num_writes;
212      STM_read_record *reads;
213      STM_write_record *writes;
214  };
216 =head3 Read and write records
218 Read and write record structures are currently identical and
219 have the following fields:
221  Parrot_STM_PMC_handle handle;
223 The handle to which this record refers.
225  void *saw_version;
227 If we got the C<value> from an outer transaction's write record,
228 then this may be the address of the the outer transaction's log.
229 Otherwise: in read records, it is the value of C<owner_or_version> 
230 just before we read C<value> from the PMC handle, and, in write records, 
231 it is the value of C<owner_or_version> before we used
232 C<PARROT_ATOMIC_PTR_CAS> to change it to point to our transaction log.
234  PMC *value;
236 The value seen by the user of the transaction. For read records,
237 this is taken directly from the PMC handle; for write records, it
238 is whatever value we intend to write (but before we called
239 C<VTABLE_share_ro()> on it).
241 =head2 wait_for_version
243 One of the most hackish routines in C<src/stm/backend.c> is 
244 C<wait_for_version> which waits for a PMC handle's C<owner_or_version>
245 field to become a version number. When C<owner_or_version> does not have
246 a version number, that essentially means that the transaction it points to
247 has an exclusive lock on the value. It does this with a busy wait, under
248 the assumption that the thread it is waiting on will complete soon. For the
249 sake of systems with few processors, it also calls C<YIELD> each
250 iteration after 10 loops to give other programs a change to run.
251 While waiting it does a number of other things:
253 =over 4
255 =item *
257 Deadlock detection. Deadlocks are detected by having each thread
258 keep a counter that is initially 0. Each time a thread waits, it reads
259 this number from the transaction on which it is waiting, and if that
260 number is less than or equal to its number, it changes its number to
261 be one larger than the other. When a deadlock exists, these numbers
262 will increase without bound. When C<wait_for_version> sees its number
263 increase beyond the number of active threads, it aborts the competing
264 transaction (using C<PARROT_ATOMIC_INT_CAS> to ensure the transaction 
265 was previously active because it is not safe to aborted a 'committed' 
266 transaction.)
268 =item *
270 Lock revokation. If a competing transaction marked as aborted but hasn't 
271 set C<owner_for_version> to the old version number, C<wait_for_version>
272 can do it for them using the C<last_version> field of the PMC handle.
274 =item *
276 Interrupts for garbage collection. C<wait_for_version> checks a flag that
277 indicates the current thread has an event queued to stop it for garbage
278 collection. If so, it runs C<pt_suspend_self_for_gc()> to assure that
279 the garbage collection run occurs in a timely manner.
281 =item *
283 Detects if the current transaction is aborted. If the current
284 transaction or any of its outer transactions are marked as aborted,
285 C<wait_for_version> returns a bogus version number.
287 =item *
289 Aborts the current transaction if it waits an exceptionally long time.
291 =back
293 =head2 Creating read records
295 Values are read from PMC handles as follows:
297 First, the current transaction log is searched for an existing
298 write or read record for the PMC handle in question. If one exists,
299 the value stored in the record is returned.
301 Otherwise a new read record is created, then the version number is read,
302 then the value is read, then the version number is read again. This
303 is retried until the version number read in both cases is the same.
305 =head2 Creating write records
307 The function C<find_write_record()> performs all the work involved in
308 creating new write records. It first searches for an old write record
309 in the innermost transaction. If there is one, it returns it. Otherwise,
310 it searches for an outer write record or read record that refers
311 to the value. If one is found, then the version number from 
312 that record is used. For write records this 'version number' is actually
313 the address of the C<STM_tx_log_sub> structure for the outer transaction.
314 If no version number can be derived from the transaction log,
315 C<wait_for_version()> is called to get
316 and potentially wait for the version number of the PMC handle. 
317 After finding the version number C<PARROT_ATOMIC_PTR_CAS> is used to
318 set the C<owner_or_version> field of the PMC handle to the current
319 transaction. A new write record is then populated with the
320 seen version and possibly a copy of the previously seen value.
321 If the C<PARROT_ATOMIC_PTR_CAS> fails and the version number
322 came from C<wait_for_version()>, 
323 C<find_write_record()> retries the C<wait_for_version()> and C<CAS> 
324 until it suceeds or the transaction (or its outer transactions)
325 are aborted.
326 If the C<CAS> fails using a version number from the transaction log,
327 the current transaction is marked as aborted.
329 When C<find_write_record()> aborts the transaction or detects that it
330 (or its outer transactions) are aborted, it will still create a write
331 record if an appropriate one did not already exist.
332 To prevent code from failing too spectacularly,
333 if a copy of the old value is desired C<find_write_record()> uses
334 the value pointed to by the PMC handle. Note that in these cases
335 C<find_write_record()> may create a write record with a bogus
336 C<saw_version> field, which should be fine since the transaction will never
337 commit anyways.
339 =head2 Aborting transactions
341 To abort a transaction, first C<PARROT_ATOMIC_INT_SET> is used to change
342 the transaction's status field to C<STM_STATUS_ABORTED>. Then,
343 C<PARROT_ATOMIC_PTR_CAS> is used to change the 
344 C<owner_or_version> field of all PMC handles listed in the write records
345 to the old version if the current transaction still owned them.
346 (This work is done in the function C<do_partial_abort>.)
348 Then (except on 'partial aborts' as occurs to outer transactions
349 before C<STM_wait>) the current transaction depth is changed and the old
350 read and write records silently discarded.
352 =head2 Committing transactions
354 To commit the outermost transaction, first C<PARROT_ATOMIC_INT_CAS>
355 is used to change the status of the transaction from ACTIVE to
356 COMMITTED. (If this fails, the commit fails and the only explanation is
357 that the transaction was aborted by some other thread.) A transaction
358 logically occurs at the point when its status changes to COMMITTED
359 if it commits at all. (The
360 values may actually be written later, but any reads of them from
361 this point on will see the new values.) 
362 First, the transactions
363 read records are checked against the PMC handles. If the version numbers
364 do not match, the commit fails and the transaction is marked as aborted.
365 (Since the version number was the same when the value was read initially
366 and now, they must have been that when the transaction logically occured.)
367 Otherwise, for each write record a new version number is created from the
368 previous one. The PMC handle's C<last_version> is set to this. The
369 C<value> field is set to the result of C<VTABLE_share_ro()> for the PMC
370 in the write record. Then the C<owner_or_version> field is changed from
371 a pointer to our transaction log to the new version number.
372 (These tasks are done in the function C<do_real_commit>.)
374 =head2 Merging transactions
376 To 'commit' inner transactions, they are merged with their outer transaction.
377 (This is done in the function C<merge_transactions>.) Currently,
378 merges always succeed -- even if the inner transaction is aborted.
379 It is necessary to either have the merges always succeed or support
380 immediatelly retrying the outer transaction instead of retrying the
381 inner transaction which may be unable to ever merge in the presence
382 of an invalid outer transaction.
383 If the inner transaction is aborted, then after a successful merge, the outer
384 transaction will also be aborted. Merging is done by iterating through
385 write records and updating the C<owner_or_version> field of the corresponding
386 PMC handles (if the inner transaction still owns them) to point to
387 the outer transaction. If this fails, the outer transaction will be aborted.
388 If the inner transaction writes a value that the
389 outer transaction also has a write record for, then the outer transaction's
390 old write record is invalidated and the new write record inherits
391 its C<saw_version> field. Then the depth of the log is changed, making
392 the inner transaction's read and write records logically be owned
393 by the outer transaction.
395 =head2 Implementing STM_wait()
397 STM_wait() aborts the current (potentially inner) transaction and waits until
398 some value the transaction depends on has been changed. To do so,
399 it first adds the current thread to the change waitlists for every 
400 value it has a read or write record for (including values in outer
401 transactions).  Then it aborts the innermost
402 transaction and 'partially' aborts the outer transactions (merely
403 removing itself as the owner of any write records). After being taken off
404 one of the waitlists, it tries to recover ownership of its outer transaction's
405 write records (using C<replay_writes()>) and verifies its read records are
406 correct (since it is fairly likely that they will have become invalid).
407 Outer transactions where this recovery and verification is not successful 
408 are left as aborted.
410 Immediately after adding itself to the waitlists and before actually waiting
411 on them, the STM implementation verifies that the version number has changed
412 from what is listed in C<saw_version>. For PMC handles whose 
413 C<owner_or_version> field does not contain a verison number, it checks this
414 against the C<last_version> field, which will contain the newer version if
415 another transaction committed before the current one got ownership of the PMC
416 handle. If the check shows the value already changed, then the waiting is
417 skipped. Otherwise, the thread is signalled right after a new value is
418 committed by the committing thread.
420 The waitlist implementation (in C<src/stm/waitlist.c>) sets a flag
421 in the per-thread data structure indicating that a thread has been signalled,
422 so that if it is signalled anytime between calling the function to add itself
423 to a wailist and calling the wait function, this will be detected.
425 =head1 SEE ALSO
427 C<docs/stm/thread-issues.pod>, C<docs/stm/stm-frontend.pod>
429 =cut