[pypy-commit] stmgc bag: in-progress: add locks
arigo
noreply at buildbot.pypy.org
Sun Jan 25 09:34:39 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: bag
Changeset: r1590:d0a565d0fc07
Date: 2015-01-25 09:35 +0100
http://bitbucket.org/pypy/stmgc/changeset/d0a565d0fc07/
Log: in-progress: add locks
diff --git a/c7/stm/bag.c b/c7/stm/bag.c
--- a/c7/stm/bag.c
+++ b/c7/stm/bag.c
@@ -23,6 +23,8 @@
| already | | next items | added in this |
| popped items | | to pop | transaction |
+--------------+ +-----------------------+---------------+
+ ^ ^ ^
+ left middle right
Adding objects puts them at the right end of the deque. Popping them
takes them off the left end and stores a copy of the pointer into a
@@ -42,11 +44,39 @@
typedef union {
+ /* Data describing the deque and abort_list belonging to the segment i. */
struct {
- uintptr_t *deque_left, *deque_middle, *deque_right;
+ /* Left deque position: read/write by whoever has got the 'lock'.
+ Don't access at all without holding the lock. */
+ uintptr_t *deque_left;
+
+ /* Middle deque position: written only by segment i when it holds
+ the 'lock'. Can be read freely by segment i. Can be
+ read by the other segments when they hold the 'lock'. */
+ uintptr_t *deque_middle;
+
+ /* Right deque position: only accessed by the segment i. No
+ locking needed. */
+ uintptr_t *deque_right;
+
+ /* Abort list. Only accessed by the segment i. */
struct list_s *abort_list;
- uint64_t start_time; /* the transaction's unique_start_time */
+
+ /* The segment i's transaction's unique_start_time, as it was
+ the last time we did a change to this stm_bag_seg_t. Used
+ to detect lazily when a commit occurred in-between. */
+ uint64_t start_time;
+
+ /* This flag is set to arm the bag-specific "write barrier".
+ When adding new items to the bag, when this flag is set we
+ must record the bag into the 'modified_bags' list, used for
+ minor collections, so that we can trace the newly added
+ items. */
bool must_add_to_modified_bags;
+
+ /* The lock, to access deque_left and deque_middle as
+ explained above. */
+ uint8_t lock;
};
char alignment[64]; /* 64-bytes alignment, to prevent false sharing */
} stm_bag_seg_t;
@@ -75,6 +105,7 @@
LIST_CREATE(bs->abort_list);
bs->start_time = 0;
bs->must_add_to_modified_bags = false; /* currently young */
+ bs->lock = 0;
}
return bag;
}
@@ -128,11 +159,15 @@
bs->deque_right = bs->deque_middle;
/* reinstall the items from the "abort_list" */
- LIST_FOREACH_F(bs->abort_list, object_t *, bag_add(bs, item));
- list_clear(bs->abort_list);
+ if (!list_is_empty(bs->abort_list)) {
+ LIST_FOREACH_F(bs->abort_list, object_t *, bag_add(bs, item));
+ list_clear(bs->abort_list);
- /* these items are not "added in this transaction" */
- bs->deque_middle = bs->deque_right;
+ /* these items are not "added in this transaction" */
+ spinlock_acquire(bs->lock);
+ bs->deque_middle = bs->deque_right;
+ spinlock_release(bs->lock);
+ }
}
static stm_bag_seg_t *bag_check_start_time(stm_bag_t *bag)
@@ -151,7 +186,11 @@
more "added in this transaction" entries. And the
"already popped items" list is forgotten.
*/
- bs->deque_middle = bs->deque_right;
+ if (bs->deque_middle != bs->deque_right) {
+ spinlock_acquire(bs->lock);
+ bs->deque_middle = bs->deque_right;
+ spinlock_release(bs->lock);
+ }
list_clear(bs->abort_list);
bs->start_time = STM_PSEGMENT->unique_start_time;
bs->must_add_to_modified_bags = true;
@@ -182,7 +221,11 @@
object_t *stm_bag_try_pop(stm_bag_t *bag)
{
stm_bag_seg_t *bs = bag_check_start_time(bag);
+
+ spinlock_acquire(bs->lock);
+
if (bs->deque_left == bs->deque_right) {
+ spinlock_release(bs->lock);
return NULL;
}
@@ -196,8 +239,10 @@
}
if (from_same_transaction) {
bs->deque_middle = bs->deque_left;
+ spinlock_release(bs->lock);
}
else {
+ spinlock_release(bs->lock);
LIST_APPEND(bs->abort_list, result);
}
return (object_t *)result;
More information about the pypy-commit
mailing list