Author: Remi Meier <[email protected]>
Branch: 
Changeset: r1664:e32b94df8ecb
Date: 2015-02-25 13:15 +0100
http://bitbucket.org/pypy/stmgc/changeset/e32b94df8ecb/

Log:    c8: add some marker macros and stop/resume_all_other_threads

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -1089,6 +1089,27 @@
 }
 
 
+void stm_stop_all_other_threads(void)
+{
+    if (!stm_is_inevitable())         /* may still abort */
+        _stm_become_inevitable("stop_all_other_threads");
+
+    s_mutex_lock();
+    synchronize_all_threads(STOP_OTHERS_AND_BECOME_GLOBALLY_UNIQUE);
+    s_mutex_unlock();
+}
+
+void stm_resume_all_other_threads(void)
+{
+    /* this calls 'committed_globally_unique_transaction()' even though
+       we're not committing now.  It's a way to piggyback on the existing
+       implementation for stm_become_globally_unique_transaction(). */
+    s_mutex_lock();
+    committed_globally_unique_transaction();
+    s_mutex_unlock();
+}
+
+
 
 static inline void _synchronize_fragment(stm_char *frag, ssize_t frag_size)
 {
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -269,6 +269,37 @@
 void stm_become_globally_unique_transaction(stm_thread_local_t *tl, const char 
*msg);
 void stm_validate(void);
 
+/* Temporarily stop all the other threads, by waiting until they
+   reach a safe-point.  Don't nest the calls to stop/resume and make sure
+   that resume is called.  The current transaction is turned inevitable. */
+void stm_stop_all_other_threads(void);
+void stm_resume_all_other_threads(void);
+
+
+/* Convenience macros to push the markers into the shadowstack */
+#define STM_PUSH_MARKER(tl, odd_num, p)   do {  \
+    uintptr_t _odd_num = (odd_num);             \
+    assert(_odd_num & 1);                       \
+    STM_PUSH_ROOT(tl, _odd_num);                \
+    STM_PUSH_ROOT(tl, p);                       \
+} while (0)
+
+#define STM_POP_MARKER(tl)   ({                 \
+    object_t *_popped = STM_POP_ROOT_RET(tl);   \
+    STM_POP_ROOT_RET(tl);                       \
+    _popped;                                    \
+})
+
+#define STM_UPDATE_MARKER_NUM(tl, odd_num)  do {                \
+    uintptr_t _odd_num = (odd_num);                             \
+    assert(_odd_num & 1);                                       \
+    struct stm_shadowentry_s *_ss = (tl).shadowstack - 2;       \
+    while (!(((uintptr_t)(_ss->ss)) & 1)) {                     \
+        _ss--;                                                  \
+        assert(_ss >= (tl).shadowstack_base);                   \
+    }                                                           \
+    _ss->ss = (object_t *)_odd_num;                             \
+} while (0)
 
 
 /* Support for light finalizers.  This is a simple version of
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -78,6 +78,8 @@
 bool _check_abort_transaction(void);
 bool _check_become_inevitable(stm_thread_local_t *tl);
 bool _check_become_globally_unique_transaction(stm_thread_local_t *tl);
+bool _check_stop_all_other_threads(void);
+void stm_resume_all_other_threads(void);
 int stm_is_inevitable(void);
 long current_segment_num(void);
 
@@ -225,6 +227,10 @@
     CHECKED(stm_become_globally_unique_transaction(tl, "TESTGUT"));
 }
 
+bool _check_stop_all_other_threads(void) {
+    CHECKED(stm_stop_all_other_threads());
+}
+
 bool _check_stm_validate(void) {
     CHECKED(stm_validate());
 }
@@ -668,3 +674,11 @@
         tl = self.tls[self.current_thread]
         if lib._check_become_globally_unique_transaction(tl):
             raise Conflict()
+
+    def stop_all_other_threads(self):
+        if lib._check_stop_all_other_threads():
+            raise Conflict()
+
+    def resume_all_other_threads(self):
+        if lib.stm_resume_all_other_threads():
+            raise Conflict()
diff --git a/c8/test/test_extra.py b/c8/test/test_extra.py
--- a/c8/test/test_extra.py
+++ b/c8/test/test_extra.py
@@ -192,3 +192,24 @@
         assert lib.stm_is_inevitable()
         #
         py.test.raises(Conflict, self.switch, 0)
+
+    def test_stm_stop_all_other_threads_1(self):
+        self.start_transaction()
+        #
+        self.switch(1)
+        self.start_transaction()
+        self.stop_all_other_threads()
+        assert lib.stm_is_inevitable()
+        #
+        py.test.raises(Conflict, self.switch, 0)
+
+    def test_stm_stop_all_other_threads_2(self):
+        self.start_transaction()
+        #
+        self.switch(1)
+        self.start_transaction()
+        self.stop_all_other_threads()
+        self.resume_all_other_threads()
+        assert lib.stm_is_inevitable()
+        #
+        self.switch(0)   # no conflict
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to