Author: Armin Rigo <[email protected]>
Branch: nogil-unsafe
Changeset: r89671:8ecb513bacb4
Date: 2017-01-19 14:38 +0100
http://bitbucket.org/pypy/pypy/changeset/8ecb513bacb4/
Log: in-progress
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -72,6 +72,7 @@
from rpython.rlib.rarithmetic import LONG_BIT_SHIFT
from rpython.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
from rpython.rlib.objectmodel import specialize
+from rpython.rlib import rthread
from rpython.memory.gc.minimarkpage import out_of_memory
#
@@ -190,10 +191,9 @@
FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB)
NURSARRAY = lltype.Array(llmemory.Address)
-GCTL = lltype.Struct('GCThreadLocal',
- ('nursery_free', llmemory.Address),
- ('nursery_top', llmemory.Address),
- hints={'thread_local': True})
+NURSERY_FREE = rthread.ThreadLocalField(llmemory.Address, 'nursery_free')
+NURSERY_TOP = rthread.ThreadLocalField(llmemory.Address, 'nursery_top')
+NEXT_NUBLOCK = rthread.ThreadLocalField(llmemory.Address, 'next_nublock')
# ____________________________________________________________
@@ -275,7 +275,7 @@
# Objects whose total size is at least 'large_object' bytes are
# allocated out of the nursery immediately, as old objects.
- "large_object": 13000,
+ "large_object": 26000,
# Thread-local Block size: the nursery is divided into blocks of
# at most this size each, and allocations go on in a
@@ -285,12 +285,10 @@
# allocated nursery size is 2 times "tl_block_size".
# "cache_line_min" is used to round the actual thread-local
# blocks to a cache line, to avoid pointless cache conflicts.
- "tl_block_size": 32768,
+ "tl_block_size": 65536,
"cache_line_min": 256,
}
- tl = lltype.malloc(GCTL, flavor='raw', immortal=True)
-
def __init__(self, config,
read_from_env=False,
nursery_size=32*WORD,
@@ -335,8 +333,8 @@
self.cache_line_min = cache_line_min
#
self.nursery = llmemory.NULL
- self.tl.nursery_free = llmemory.NULL
- self.tl.nursery_top = llmemory.NULL
+ self.nublocks = llmemory.NULL # <= linked list of threadlocal_base
+ # for all active nursery consumers
self.debug_tiny_nursery = -1
self.debug_rotating_nurseries = lltype.nullptr(NURSARRAY)
self.extra_threshold = 0
@@ -539,6 +537,7 @@
"cache_line_min is not a power a two")
self.tl_block_size = ((self.tl_block_size + self.cache_line_min - 1)
& ~(self.cache_line_min - 1))
+ self.gil_gc_color = llop.new_gil_color(lltype.Signed)
def _nursery_memory_size(self):
@@ -636,6 +635,15 @@
"size", self.nursery_size)
debug_stop("gc-debug")
+ get_nursery_free = NURSERY_FREE.getraw
+ set_nursery_free = NURSERY_FREE.setraw
+
+ get_nursery_top = NURSERY_TOP.getraw
+ set_nursery_top = NURSERY_TOP.setraw
+
+ get_next_nublock = NEXT_NUBLOCK.getraw
+ set_next_nublock = NEXT_NUBLOCK.setraw
+
def malloc_fixedsize(self, typeid, size,
needs_finalizer=False,
@@ -673,10 +681,11 @@
#
# Get the memory from the nursery. If there is not enough space
# there, do a collect first.
- result = self.tl.nursery_free
- ll_assert(result != llmemory.NULL, "uninitialized nursery")
- self.tl.nursery_free = new_free = result + totalsize
- if new_free > self.tl.nursery_top:
+ result = self.get_nursery_free()
+ #ll_assert(result != llmemory.NULL, "uninitialized nursery")
+ new_free = result + totalsize
+ self.set_nursery_free(new_free)
+ if new_free > self.get_nursery_top():
result = self.collect_and_reserve(totalsize)
#
# Build the object.
@@ -733,10 +742,11 @@
#
# Get the memory from the nursery. If there is not enough space
# there, do a collect first.
- result = self.tl.nursery_free
- ll_assert(result != llmemory.NULL, "uninitialized nursery")
- self.tl.nursery_free = new_free = result + totalsize
- if new_free > self.tl.nursery_top:
+ result = self.get_nursery_free()
+ #ll_assert(result != llmemory.NULL, "uninitialized nursery")
+ new_free = result + totalsize
+ self.set_nursery_free(new_free)
+ if new_free > self.get_nursery_top():
result = self.collect_and_reserve(totalsize)
#
# Build the object.
@@ -825,13 +835,14 @@
major collection, and finally reserve totalsize bytes.
"""
minor_collection_count = 0
- must_downgrade_gil = False
+ old_color = 0
+ self._gc_lock()
+
while True:
- self.tl.nursery_free = llmemory.NULL # debug: don't use me
+ self.set_nursery_free(llmemory.NULL) # debug: don't use me
# note: no "raise MemoryError" between here and the next time
# we initialize nursery_free!
- self._gc_lock()
if self.nursery_barriers.non_empty():
# Pinned object in front of nursery_top. Try reserving
totalsize
# by jumping into the next, yet unused, area inside the
@@ -860,16 +871,17 @@
# four addresses which match the four "B".
#
# update used nursery space to allocate objects
- self.tl.nursery_free = self.nursery_barriers.popleft()
- self.tl.nursery_top = self.nursery_barriers.popleft()
- self._gc_unlock()
- prev_gil = False
+ self.set_nursery_free(self.nursery_barriers.popleft())
+ self.set_nursery_top(self.nursery_barriers.popleft())
+ if self.get_nursery_top() == llmemory.NULL:
+ # needs to add this threadlocal to the nublocks list
+ self.set_next_nublock(self.nublocks)
+ self.nublocks = rthread.get_threadlocal_base()
else:
- self._gc_unlock()
- if not llop.gil_is_exclusive(lltype.Bool):
- ll_assert(not must_downgrade_gil,
- "collect_and_reverse: bad gil state")
- must_downgrade_gil = llop.gil_wait(lltype.Bool)
+ if llop.get_gil_share_count(lltype.Signed) > 1:
+ assert old_color == 0
+ old_color = llop.get_gil_color(lltype.Signed)
+ llop.set_gil_color(lltype.Void, self.gil_gc_color)
continue # waited, maybe the situation changed
minor_collection_count += 1
if minor_collection_count == 1:
@@ -897,14 +909,14 @@
# Tried to do something about nursery_free overflowing
# nursery_top before this point. Try to reserve totalsize now.
# If this succeeds break out of loop.
- result = self.tl.nursery_free
- if self.tl.nursery_free + totalsize <= self.tl.nursery_top:
- self.tl.nursery_free = result + totalsize
- ll_assert(self.tl.nursery_free <= self.tl.nursery_top,
"nursery overflow")
+ result = self.get_nursery_free()
+ if result + totalsize <= self.get_nursery_top():
+ self.set_nursery_free(result + totalsize)
break
#
- if must_downgrade_gil:
- llop.gil_downgrade(lltype.Void)
+ self._gc_unlock()
+ if old_color != 0:
+ llop.set_gil_color(lltype.Void, old_color)
#
if self.debug_tiny_nursery >= 0: # for debugging
if self.tl.nursery_top - self.tl.nursery_free >
self.debug_tiny_nursery:
diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py
--- a/rpython/rlib/rthread.py
+++ b/rpython/rlib/rthread.py
@@ -373,6 +373,10 @@
def _freeze_(self):
return True
[email protected]_invariant
+def get_threadlocal_base():
+ return llop.threadlocalref_addr(llmemory.Address)
+
class ThreadLocalReference(ThreadLocalField):
# A thread-local that points to an object. The object stored in such
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit