Author: Remi Meier <[email protected]>
Branch: 
Changeset: r1760:6f8794111ab4
Date: 2015-05-19 10:18 +0200
http://bitbucket.org/pypy/stmgc/changeset/6f8794111ab4/

Log:    re-add some missing comments in stmgc.h

diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -57,13 +57,16 @@
 typedef struct stm_thread_local_s {
     /* rewind_setjmp's interface */
     rewind_jmp_thread rjthread;
+    /* every thread should handle the shadow stack itself */
     struct stm_shadowentry_s *shadowstack, *shadowstack_base;
-
     /* a generic optional thread-local object */
     object_t *thread_local_obj;
-
+    /* in case this thread runs a transaction that aborts,
+       the following raw region of memory is cleared. */
     char *mem_clear_on_abort;
     size_t mem_bytes_to_clear_on_abort;
+    /* after an abort, some details about the abort are stored there.
+       (this field is not modified on a successful commit) */
     long last_abort__bytes_in_nursery;
     /* the next fields are handled internally by the library */
     int associated_segment_num;
@@ -73,22 +76,9 @@
     void *creating_pthread[2];
 } stm_thread_local_t;
 
-#ifndef _STM_NURSERY_ZEROED
-#define _STM_NURSERY_ZEROED               0
-#endif
 
-#define _STM_GCFLAG_WRITE_BARRIER      0x01
-#define _STM_FAST_ALLOC           (66*1024)
-#define _STM_NSE_SIGNAL_ABORT             1
-#define _STM_NSE_SIGNAL_MAX               2
-
-#define _STM_CARD_MARKED 1      /* should always be 1... */
-#define _STM_GCFLAG_CARDS_SET          0x8
-#define _STM_CARD_BITS                 5   /* must be 5/6/7 for the pypy jit */
-#define _STM_CARD_SIZE                 (1 << _STM_CARD_BITS)
-#define _STM_MIN_CARD_COUNT            17
-#define _STM_MIN_CARD_OBJ_SIZE         (_STM_CARD_SIZE * _STM_MIN_CARD_COUNT)
-
+/* this should use llvm's coldcc calling convention,
+   but it's not exposed to C code so far */
 void _stm_write_slowpath(object_t *);
 void _stm_write_slowpath_card(object_t *, uintptr_t);
 object_t *_stm_allocate_slowpath(ssize_t);
@@ -96,6 +86,7 @@
 void _stm_become_inevitable(const char*);
 void _stm_collectable_safe_point(void);
 
+/* for tests, but also used in duhton: */
 object_t *_stm_allocate_old(ssize_t size_rounded_up);
 char *_stm_real_address(object_t *o);
 #ifdef STM_TESTS
@@ -145,6 +136,24 @@
 uint64_t _stm_total_allocated(void);
 #endif
 
+
+#ifndef _STM_NURSERY_ZEROED
+#define _STM_NURSERY_ZEROED               0
+#endif
+
+#define _STM_GCFLAG_WRITE_BARRIER      0x01
+#define _STM_FAST_ALLOC           (66*1024)
+#define _STM_NSE_SIGNAL_ABORT             1
+#define _STM_NSE_SIGNAL_MAX               2
+
+#define _STM_CARD_MARKED 1      /* should always be 1... */
+#define _STM_GCFLAG_CARDS_SET          0x8
+#define _STM_CARD_BITS                 5   /* must be 5/6/7 for the pypy jit */
+#define _STM_CARD_SIZE                 (1 << _STM_CARD_BITS)
+#define _STM_MIN_CARD_COUNT            17
+#define _STM_MIN_CARD_OBJ_SIZE         (_STM_CARD_SIZE * _STM_MIN_CARD_COUNT)
+
+
 /* ==================== HELPERS ==================== */
 #ifdef NDEBUG
 #define OPT_ASSERT(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)
@@ -165,30 +174,32 @@
 */
 #define STM_NB_SEGMENTS    4
 
+/* Structure of objects
+   --------------------
 
+   Objects manipulated by the user program, and managed by this library,
+   must start with a "struct object_s" field.  Pointers to any user object
+   must use the "TLPREFIX struct foo *" type --- don't forget TLPREFIX.
+   The best is to use typedefs like above.
+
+   The object_s part contains some fields reserved for the STM library.
+   Right now this is only four bytes.
+*/
 struct object_s {
     uint32_t stm_flags;            /* reserved for the STM library */
 };
 
-extern ssize_t stmcb_size_rounded_up(struct object_s *);
-void stmcb_trace(struct object_s *obj, void visit(object_t **));
-/* a special trace-callback that is only called for the marked
-   ranges of indices (using stm_write_card(o, index)) */
-extern void stmcb_trace_cards(struct object_s *, void (object_t **),
-                              uintptr_t start, uintptr_t stop);
-/* this function will be called on objects that support cards.
-   It returns the base_offset (in bytes) inside the object from
-   where the indices start, and item_size (in bytes) for the size of
-   one item */
-extern void stmcb_get_card_base_itemsize(struct object_s *,
-                                         uintptr_t offset_itemsize[2]);
-/* returns whether this object supports cards. we will only call
-   stmcb_get_card_base_itemsize on objs that do so. */
-extern long stmcb_obj_supports_cards(struct object_s *);
 
-
-
-
+/* The read barrier must be called whenever the object 'obj' is read.
+   It is not required to call it before reading: it can be delayed for a
+   bit, but we must still be in the same "scope": no allocation, no
+   transaction commit, nothing that can potentially collect or do a safe
+   point (like stm_write() on a different object).  Also, if we might
+   have finished the transaction and started the next one, then
+   stm_read() needs to be called again.  It can be omitted if
+   stm_write() is called, or immediately after getting the object from
+   stm_allocate(), as long as the rules above are respected.
+*/
 __attribute__((always_inline))
 static inline void stm_read(object_t *obj)
 {
@@ -199,6 +210,11 @@
 #define _STM_WRITE_CHECK_SLOWPATH(obj)  \
     UNLIKELY(((obj)->stm_flags & _STM_GCFLAG_WRITE_BARRIER) != 0)
 
+/* The write barrier must be called *before* doing any change to the
+   object 'obj'.  If we might have finished the transaction and started
+   the next one, then stm_write() needs to be called again.  It is not
+   necessary to call it immediately after stm_allocate().
+*/
 __attribute__((always_inline))
 static inline void stm_write(object_t *obj)
 {
@@ -206,7 +222,14 @@
         _stm_write_slowpath(obj);
 }
 
-
+/* The following is a GC-optimized barrier that works on the granularity
+   of CARD_SIZE.  It can be used on any array object, but it is only
+   useful with those that were internally marked with GCFLAG_HAS_CARDS.
+   It has the same purpose as stm_write() for TM and allows write-access
+   to a part of an object/array.
+   'index' is the array-item-based position within the object, which
+   is measured in units returned by stmcb_get_card_base_itemsize().
+*/
 __attribute__((always_inline))
 static inline void stm_write_card(object_t *obj, uintptr_t index)
 {
@@ -245,7 +268,34 @@
     }
 }
 
+/* Must be provided by the user of this library.
+   The "size rounded up" must be a multiple of 8 and at least 16.
+   "Tracing" an object means enumerating all GC references in it,
+   by invoking the callback passed as argument.
+*/
+extern ssize_t stmcb_size_rounded_up(struct object_s *);
+void stmcb_trace(struct object_s *obj, void visit(object_t **));
+/* a special trace-callback that is only called for the marked
+   ranges of indices (using stm_write_card(o, index)) */
+extern void stmcb_trace_cards(struct object_s *, void (object_t **),
+                              uintptr_t start, uintptr_t stop);
+/* this function will be called on objects that support cards.
+   It returns the base_offset (in bytes) inside the object from
+   where the indices start, and item_size (in bytes) for the size of
+   one item */
+extern void stmcb_get_card_base_itemsize(struct object_s *,
+                                         uintptr_t offset_itemsize[2]);
+/* returns whether this object supports cards. we will only call
+   stmcb_get_card_base_itemsize on objs that do so. */
+extern long stmcb_obj_supports_cards(struct object_s *);
 
+
+
+
+/* Allocate an object of the given size, which must be a multiple
+   of 8 and at least 16.  In the fast-path, this is inlined to just
+   a few assembler instructions.
+*/
 __attribute__((always_inline))
 static inline object_t *stm_allocate(ssize_t size_rounded_up)
 {
@@ -267,21 +317,48 @@
     return (object_t *)p;
 }
 
-
+/* Allocate a weakref object. Weakref objects have a
+   reference to an object at the byte-offset
+       stmcb_size_rounded_up(obj) - sizeof(void*)
+   You must assign the reference before the next collection may happen.
+   After that, you must not mutate the reference anymore. However,
+   it can become NULL after any GC if the reference dies during that
+   collection.
+   NOTE: For performance, we assume stmcb_size_rounded_up(weakref)==16
+*/
 object_t *stm_allocate_weakref(ssize_t size_rounded_up);
 
 
+/* stm_setup() needs to be called once at the beginning of the program.
+   stm_teardown() can be called at the end, but that's not necessary
+   and rather meant for tests.
+ */
 void stm_setup(void);
 void stm_teardown(void);
 
+/* The size of each shadow stack, in number of entries.
+   Must be big enough to accomodate all STM_PUSH_ROOTs! */
 #define STM_SHADOW_STACK_DEPTH   163840
+
+/* Push and pop roots from/to the shadow stack. Only allowed inside
+   transaction. */
 #define STM_PUSH_ROOT(tl, p)   ((tl).shadowstack++->ss = (object_t *)(p))
 #define STM_POP_ROOT(tl, p)    ((p) = (typeof(p))((--(tl).shadowstack)->ss))
 #define STM_POP_ROOT_RET(tl)   ((--(tl).shadowstack)->ss)
 
+/* Every thread needs to have a corresponding stm_thread_local_t
+   structure.  It may be a "__thread" global variable or something else.
+   Use the following functions at the start and at the end of a thread.
+   The user of this library needs to maintain the two shadowstack fields;
+   at any call to stm_allocate(), these fields should point to a range
+   of memory that can be walked in order to find the stack roots.
+*/
 void stm_register_thread_local(stm_thread_local_t *tl);
 void stm_unregister_thread_local(stm_thread_local_t *tl);
 
+/* At some key places, like the entry point of the thread and in the
+   function with the interpreter's dispatch loop, you need to declare
+   a local variable of type 'rewind_jmp_buf' and call these macros. */
 #define stm_rewind_jmp_enterprepframe(tl, rjbuf)                        \
     rewind_jmp_enterprepframe(&(tl)->rjthread, rjbuf, (tl)->shadowstack)
 #define stm_rewind_jmp_enterframe(tl, rjbuf)       \
@@ -303,37 +380,23 @@
     rewind_jmp_enum_shadowstack(&(tl)->rjthread, callback)
 
 
+/* Starting and ending transactions.  stm_read(), stm_write() and
+   stm_allocate() should only be called from within a transaction.
+   The stm_start_transaction() call returns the number of times it
+   returned, starting at 0.  If it is > 0, then the transaction was
+   aborted and restarted this number of times. */
 long stm_start_transaction(stm_thread_local_t *tl);
 void stm_start_inevitable_transaction(stm_thread_local_t *tl);
-
 void stm_commit_transaction(void);
 
 /* Temporary fix?  Call this outside a transaction.  If there is an
    inevitable transaction running somewhere else, wait until it finishes. */
 void stm_wait_for_current_inevitable_transaction(void);
 
+/* Abort the currently running transaction.  This function never
+   returns: it jumps back to the stm_start_transaction(). */
 void stm_abort_transaction(void) __attribute__((noreturn));
 
-void stm_collect(long level);
-
-long stm_identityhash(object_t *obj);
-long stm_id(object_t *obj);
-void stm_set_prebuilt_identityhash(object_t *obj, long hash);
-
-long stm_can_move(object_t *obj);
-
-object_t *stm_setup_prebuilt(object_t *);
-object_t *stm_setup_prebuilt_weakref(object_t *);
-
-long stm_call_on_abort(stm_thread_local_t *, void *key, void callback(void *));
-long stm_call_on_commit(stm_thread_local_t *, void *key, void callback(void 
*));
-
-static inline void stm_safe_point(void) {
-    if (STM_SEGMENT->nursery_end <= _STM_NSE_SIGNAL_MAX)
-        _stm_collectable_safe_point();
-}
-
-
 #ifdef STM_NO_AUTOMATIC_SETJMP
 int stm_is_inevitable(void);
 #else
@@ -352,7 +415,64 @@
         _stm_become_inevitable(msg);
 }
 
+/* Forces a safe-point if needed.  Normally not needed: this is
+   automatic if you call stm_allocate(). */
+static inline void stm_safe_point(void) {
+    if (STM_SEGMENT->nursery_end <= _STM_NSE_SIGNAL_MAX)
+        _stm_collectable_safe_point();
+}
+
+/* Forces a collection. */
+void stm_collect(long level);
+
+
+/* Prepare an immortal "prebuilt" object managed by the GC.  Takes a
+   pointer to an 'object_t', which should not actually be a GC-managed
+   structure but a real static structure.  Returns the equivalent
+   GC-managed pointer.  Works by copying it into the GC pages, following
+   and fixing all pointers it contains, by doing stm_setup_prebuilt() on
+   each of them recursively.  (Note that this will leave garbage in the
+   static structure, but it should never be used anyway.) */
+object_t *stm_setup_prebuilt(object_t *);
+/* The same, if the prebuilt object is actually a weakref. */
+object_t *stm_setup_prebuilt_weakref(object_t *);
+
+/* Hash, id.  The id is just the address of the object (of the address
+   where it *will* be after the next minor collection).  The hash is the
+   same, mangled -- except on prebuilt objects, where it can be
+   controlled for each prebuilt object individually.  (Useful uor PyPy) */
+long stm_identityhash(object_t *obj);
+long stm_id(object_t *obj);
+void stm_set_prebuilt_identityhash(object_t *obj, long hash);
+
+/* Returns 1 if the object can still move (it's in the nursery), or 0
+   otherwise.  After a minor collection no object can move any more. */
+long stm_can_move(object_t *obj);
+
+/* If the current transaction aborts later, invoke 'callback(key)'.  If
+   the current transaction commits, then the callback is forgotten.  You
+   can only register one callback per key.  You can call
+   'stm_call_on_abort(key, NULL)' to cancel an existing callback
+   (returns 0 if there was no existing callback to cancel).
+   Note: 'key' must be aligned to a multiple of 8 bytes. */
+long stm_call_on_abort(stm_thread_local_t *, void *key, void callback(void *));
+/* If the current transaction commits later, invoke 'callback(key)'.  If
+   the current transaction aborts, then the callback is forgotten.  Same
+   restrictions as stm_call_on_abort().  If the transaction is or becomes
+   inevitable, 'callback(key)' is called immediately. */
+long stm_call_on_commit(stm_thread_local_t *, void *key, void callback(void 
*));
+
+
+/* Similar to stm_become_inevitable(), but additionally suspend all
+   other threads.  A very heavy-handed way to make sure that no other
+   transaction is running concurrently.  Avoid as much as possible.
+   Other transactions will continue running only after this transaction
+   commits.  (xxx deprecated and may be removed) */
 void stm_become_globally_unique_transaction(stm_thread_local_t *tl, const char 
*msg);
+
+/* Moves the transaction forward in time by validating the read and
+   write set with all commits that happened since the last validation
+   (explicit or implicit). */
 void stm_validate(void);
 
 /* Temporarily stop all the other threads, by waiting until they
@@ -411,8 +531,8 @@
 /* The markers pushed in the shadowstack are an odd number followed by a
    regular object pointer. */
 typedef struct {
-    uintptr_t odd_number;
-    object_t *object;
+    uintptr_t odd_number;  /* marker odd number, or 0 if marker is missing */
+    object_t *object;      /* marker object, or NULL if marker is missing */
 } stm_loc_marker_t;
 extern void (*stmcb_timing_event)(stm_thread_local_t *tl, /* the local thread 
*/
                                   enum stm_event_e event,
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to