summaryrefslogtreecommitdiff
path: root/libphobos/libdruntime
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2025-01-09 23:56:49 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2025-01-12 23:18:25 +0100
commita2e540bf0150b1a2f05924ce6d5210dc0048471d (patch)
treeb46d2d634704cfea7200180a0d03ddc5303aab0b /libphobos/libdruntime
parentf4fa0b7d493a4ba217d989d3df75bbe3730874fc (diff)
d: Merge dmd, druntime c7902293d7, phobos 03aeafd20
D front-end changes: - Import dmd v2.110.0-rc.1. - An error is now given for subtracting pointers of different types. D runtime changes: - Import druntime v2.110.0-rc.1. Phobos changes: - Import phobos v2.110.0-rc.1. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd c7902293d7. * dmd/VERSION: Bump version to v2.110.0-rc.1. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime c7902293d7. * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Rename core/thread/fiber.d to core/thread/fiber/package.d. Add core/thread/fiber/base.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 63fdb282f. gcc/testsuite/ChangeLog: * gdc.dg/asm3.d: Adjust test. * gdc.dg/torture/pr96435.d: Adjust test.
Diffstat (limited to 'libphobos/libdruntime')
-rw-r--r--libphobos/libdruntime/MERGE2
-rw-r--r--libphobos/libdruntime/Makefile.am3
-rw-r--r--libphobos/libdruntime/Makefile.in34
-rw-r--r--libphobos/libdruntime/core/demangle.d10
-rw-r--r--libphobos/libdruntime/core/gc/gcinterface.d65
-rw-r--r--libphobos/libdruntime/core/internal/array/construction.d6
-rw-r--r--libphobos/libdruntime/core/internal/atomic.d6
-rw-r--r--libphobos/libdruntime/core/internal/dassert.d2
-rw-r--r--libphobos/libdruntime/core/internal/gc/blkcache.d10
-rw-r--r--libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d38
-rw-r--r--libphobos/libdruntime/core/internal/gc/os.d18
-rw-r--r--libphobos/libdruntime/core/internal/postblit.d2
-rw-r--r--libphobos/libdruntime/core/internal/qsort.d2
-rw-r--r--libphobos/libdruntime/core/internal/string.d2
-rw-r--r--libphobos/libdruntime/core/internal/utf.d2
-rw-r--r--libphobos/libdruntime/core/runtime.d6
-rw-r--r--libphobos/libdruntime/core/stdc/errno.d2
-rw-r--r--libphobos/libdruntime/core/stdc/stdio.d2
-rw-r--r--libphobos/libdruntime/core/sync/condition.d17
-rw-r--r--libphobos/libdruntime/core/sync/config.d8
-rw-r--r--libphobos/libdruntime/core/sync/event.d20
-rw-r--r--libphobos/libdruntime/core/sync/mutex.d7
-rw-r--r--libphobos/libdruntime/core/sync/rwmutex.d5
-rw-r--r--libphobos/libdruntime/core/sync/semaphore.d18
-rw-r--r--libphobos/libdruntime/core/sys/darwin/mach/stab.d2
-rw-r--r--libphobos/libdruntime/core/sys/linux/sys/procfs.d7
-rw-r--r--libphobos/libdruntime/core/sys/posix/spawn.d2
-rw-r--r--libphobos/libdruntime/core/sys/posix/stdc/time.d2
-rw-r--r--libphobos/libdruntime/core/sys/windows/dbghelp.d2
-rw-r--r--libphobos/libdruntime/core/sys/windows/stdc/time.d2
-rw-r--r--libphobos/libdruntime/core/thread/fiber/base.d1091
-rw-r--r--libphobos/libdruntime/core/thread/fiber/package.d (renamed from libphobos/libdruntime/core/thread/fiber.d)869
-rw-r--r--libphobos/libdruntime/core/thread/osthread.d94
-rw-r--r--libphobos/libdruntime/core/thread/threadbase.d2
-rw-r--r--libphobos/libdruntime/core/thread/threadgroup.d2
-rw-r--r--libphobos/libdruntime/core/thread/types.d6
-rw-r--r--libphobos/libdruntime/core/time.d41
-rw-r--r--libphobos/libdruntime/rt/aApply.d26
-rw-r--r--libphobos/libdruntime/rt/aApplyR.d26
-rw-r--r--libphobos/libdruntime/rt/adi.d2
-rw-r--r--libphobos/libdruntime/rt/arraycat.d2
-rw-r--r--libphobos/libdruntime/rt/cast_.d16
-rw-r--r--libphobos/libdruntime/rt/lifetime.d16
-rw-r--r--libphobos/libdruntime/rt/monitor_.d5
44 files changed, 1433 insertions, 1069 deletions
diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE
index e5884c6a798..b145d1bd659 100644
--- a/libphobos/libdruntime/MERGE
+++ b/libphobos/libdruntime/MERGE
@@ -1,4 +1,4 @@
-c57da0cf5945cfb45eed06f1fd820435cda3ee3a
+c7902293d7df9d02546562cb09fc8439004a70d1
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 7713c8cf5a8..fd117eca202 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -210,7 +210,8 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/sync/barrier.d core/sync/condition.d core/sync/config.d \
core/sync/event.d core/sync/exception.d core/sync/mutex.d \
core/sync/package.d core/sync/rwmutex.d core/sync/semaphore.d \
- core/thread/context.d core/thread/fiber.d core/thread/osthread.d \
+ core/thread/context.d core/thread/fiber/base.d \
+ core/thread/fiber/package.d core/thread/osthread.d \
core/thread/package.d core/thread/threadbase.d \
core/thread/threadgroup.d core/thread/types.d core/time.d \
core/vararg.d core/volatile.d etc/valgrind/valgrind.d gcc/attribute.d \
diff --git a/libphobos/libdruntime/Makefile.in b/libphobos/libdruntime/Makefile.in
index f4d55523bfa..2d87c8162af 100644
--- a/libphobos/libdruntime/Makefile.in
+++ b/libphobos/libdruntime/Makefile.in
@@ -234,16 +234,17 @@ am__objects_1 = core/atomic.lo core/attribute.lo core/bitop.lo \
core/sync/condition.lo core/sync/config.lo core/sync/event.lo \
core/sync/exception.lo core/sync/mutex.lo core/sync/package.lo \
core/sync/rwmutex.lo core/sync/semaphore.lo \
- core/thread/context.lo core/thread/fiber.lo \
- core/thread/osthread.lo core/thread/package.lo \
- core/thread/threadbase.lo core/thread/threadgroup.lo \
- core/thread/types.lo core/time.lo core/vararg.lo \
- core/volatile.lo etc/valgrind/valgrind.lo gcc/attribute.lo \
- gcc/attributes.lo gcc/backtrace.lo gcc/builtins.lo gcc/deh.lo \
- gcc/emutls.lo gcc/gthread.lo gcc/sections/common.lo \
- gcc/sections/elf.lo gcc/sections/macho.lo \
- gcc/sections/package.lo gcc/sections/pecoff.lo gcc/simd.lo \
- gcc/unwind/arm.lo gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
+ core/thread/context.lo core/thread/fiber/base.lo \
+ core/thread/fiber/package.lo core/thread/osthread.lo \
+ core/thread/package.lo core/thread/threadbase.lo \
+ core/thread/threadgroup.lo core/thread/types.lo core/time.lo \
+ core/vararg.lo core/volatile.lo etc/valgrind/valgrind.lo \
+ gcc/attribute.lo gcc/attributes.lo gcc/backtrace.lo \
+ gcc/builtins.lo gcc/deh.lo gcc/emutls.lo gcc/gthread.lo \
+ gcc/sections/common.lo gcc/sections/elf.lo \
+ gcc/sections/macho.lo gcc/sections/package.lo \
+ gcc/sections/pecoff.lo gcc/simd.lo gcc/unwind/arm.lo \
+ gcc/unwind/arm_common.lo gcc/unwind/c6x.lo \
gcc/unwind/generic.lo gcc/unwind/package.lo gcc/unwind/pe.lo \
object.lo rt/aApply.lo rt/aApplyR.lo rt/aaA.lo rt/adi.lo \
rt/arraycat.lo rt/cast_.lo rt/config.lo rt/critical_.lo \
@@ -891,7 +892,8 @@ DRUNTIME_DSOURCES = core/atomic.d core/attribute.d core/bitop.d \
core/sync/barrier.d core/sync/condition.d core/sync/config.d \
core/sync/event.d core/sync/exception.d core/sync/mutex.d \
core/sync/package.d core/sync/rwmutex.d core/sync/semaphore.d \
- core/thread/context.d core/thread/fiber.d core/thread/osthread.d \
+ core/thread/context.d core/thread/fiber/base.d \
+ core/thread/fiber/package.d core/thread/osthread.d \
core/thread/package.d core/thread/threadbase.d \
core/thread/threadgroup.d core/thread/types.d core/time.d \
core/vararg.d core/volatile.d etc/valgrind/valgrind.d gcc/attribute.d \
@@ -1352,7 +1354,11 @@ core/thread/$(am__dirstamp):
@$(MKDIR_P) core/thread
@: > core/thread/$(am__dirstamp)
core/thread/context.lo: core/thread/$(am__dirstamp)
-core/thread/fiber.lo: core/thread/$(am__dirstamp)
+core/thread/fiber/$(am__dirstamp):
+ @$(MKDIR_P) core/thread/fiber
+ @: > core/thread/fiber/$(am__dirstamp)
+core/thread/fiber/base.lo: core/thread/fiber/$(am__dirstamp)
+core/thread/fiber/package.lo: core/thread/fiber/$(am__dirstamp)
core/thread/osthread.lo: core/thread/$(am__dirstamp)
core/thread/package.lo: core/thread/$(am__dirstamp)
core/thread/threadbase.lo: core/thread/$(am__dirstamp)
@@ -2147,6 +2153,8 @@ mostlyclean-compile:
-rm -f core/sys/windows/stdc/*.lo
-rm -f core/thread/*.$(OBJEXT)
-rm -f core/thread/*.lo
+ -rm -f core/thread/fiber/*.$(OBJEXT)
+ -rm -f core/thread/fiber/*.lo
-rm -f etc/valgrind/*.$(OBJEXT)
-rm -f etc/valgrind/*.lo
-rm -f gcc/*.$(OBJEXT)
@@ -2312,6 +2320,7 @@ clean-libtool:
-rm -rf core/sys/windows/.libs core/sys/windows/_libs
-rm -rf core/sys/windows/stdc/.libs core/sys/windows/stdc/_libs
-rm -rf core/thread/.libs core/thread/_libs
+ -rm -rf core/thread/fiber/.libs core/thread/fiber/_libs
-rm -rf etc/valgrind/.libs etc/valgrind/_libs
-rm -rf gcc/.libs gcc/_libs
-rm -rf gcc/sections/.libs gcc/sections/_libs
@@ -2478,6 +2487,7 @@ distclean-generic:
-rm -f core/sys/windows/$(am__dirstamp)
-rm -f core/sys/windows/stdc/$(am__dirstamp)
-rm -f core/thread/$(am__dirstamp)
+ -rm -f core/thread/fiber/$(am__dirstamp)
-rm -f etc/valgrind/$(am__dirstamp)
-rm -f gcc/$(am__dirstamp)
-rm -f gcc/sections/$(am__dirstamp)
diff --git a/libphobos/libdruntime/core/demangle.d b/libphobos/libdruntime/core/demangle.d
index c197262384f..c9bde27da69 100644
--- a/libphobos/libdruntime/core/demangle.d
+++ b/libphobos/libdruntime/core/demangle.d
@@ -21,8 +21,12 @@ else version (TVOS)
else version (WatchOS)
version = Darwin;
-debug(trace) import core.stdc.stdio : printf;
-debug(info) import core.stdc.stdio : printf;
+debug (trace) debug = needPrintf;
+debug (info) debug = needPrintf;
+
+debug (needPrintf)
+private int printf(Args...)(scope const char* fmt, scope const Args args)
+ => __ctfe ? 0 : imported!"core.stdc.stdio".printf(fmt, args);
extern (C) alias CXX_DEMANGLER = char* function (const char* mangled_name,
char* output_buffer,
@@ -2128,7 +2132,7 @@ pure @safe:
}
name = dst[beg .. nameEnd];
- debug(info) printf( "name (%.*s)\n", cast(int) name.length, name.ptr );
+ debug(info) printf( "name (%.*s)\n", cast(int) name.length, name.getSlice.ptr );
if ( 'M' == front )
popFront(); // has 'this' pointer
diff --git a/libphobos/libdruntime/core/gc/gcinterface.d b/libphobos/libdruntime/core/gc/gcinterface.d
index 173e6abecff..c4e78bae782 100644
--- a/libphobos/libdruntime/core/gc/gcinterface.d
+++ b/libphobos/libdruntime/core/gc/gcinterface.d
@@ -193,28 +193,33 @@ interface GC
// ARRAY FUNCTIONS
/**
- * Get the current used capacity of an array block. Note that this is only
- * needed if you are about to change the array used size and need to deal
- * with the memory that is about to go away. For appending or shrinking
- * arrays that have no destructors, you probably don't need this function.
+ * Get the current used capacity of an array block.
+ *
+ * Note that this is only needed if you are about to change the array used
+ * size and need to deal with the memory that is about to go away. For
+ * appending or shrinking arrays that have no destructors, you probably
+ * don't need this function.
+ *
* Params:
* ptr = The pointer to check. This can be an interior pointer, but if it
* is beyond the end of the used space, the return value may not be
* valid.
- * atomic = If true, the value is fetched atomically (for shared arrays)
- * Returns: Current array slice, or null if the pointer does not point to a
- * valid appendable GC block.
+ * atomic = The value is fetched atomically (for shared arrays)
+ * Returns:
+ * Current array slice, or null if the pointer does not point to a valid
+ * appendable GC block.
*/
void[] getArrayUsed(void *ptr, bool atomic = false) nothrow;
/**
- * Expand the array used size. Used for appending and expanding the length
- * of the array slice. If the operation can be performed without
- * reallocating, the function succeeds. Newly expanded data is not
- * initialized.
+ * Expand the array used size in place.
+ *
+ * Used for appending and expanding the length of the array slice. If the
+ * operation can be performed without reallocating, the function succeeds.
+ * Newly expanded data is not initialized. Slices that do not point at
+ * expandable GC blocks cannot be affected, and this function will always
+ * return false.
*
- * slices that do not point at expandable GC blocks cannot be affected, and
- * this function will always return false.
* Params:
* slice = the slice to attempt expanding in place.
* newUsed = the size that should be stored as used.
@@ -225,37 +230,43 @@ interface GC
bool expandArrayUsed(void[] slice, size_t newUsed, bool atomic = false) nothrow @safe;
/**
- * Expand the array capacity. Used for reserving space that can be used for
- * appending. If the operation can be performed without reallocating, the
- * function succeeds. The used size is not changed.
+ * Expand the array capacity in place.
+ *
+ * Used for reserving space that can be used for appending. If the
+ * operation can be performed without reallocating, the function succeeds.
+ * The used size is not changed. Slices that do not point at expandable GC
+ * blocks cannot be affected, and this function will always return zero.
*
- * slices that do not point at expandable GC blocks cannot be affected, and
- * this function will always return zero.
* Params:
* slice = the slice to attempt reserving capacity for.
* request = the requested size to expand to. Includes the existing data.
* Passing a value less than the current array size will result in no
* changes, but will return the current capacity.
- * atomic = if true, the array may be shared between threads, and this
- * operation should be done atomically.
- * Returns: resulting capacity size, 0 if the operation could not be performed.
+ * atomic = The array may be shared between threads, and this operation
+ * should be done atomically.
+ *
+ * Returns:
+ * Resulting capacity size or 0 if the operation could not be performed.
*/
size_t reserveArrayCapacity(void[] slice, size_t request, bool atomic = false) nothrow @safe;
/**
- * Shrink used space of a slice. Unlike the other array functions, the
- * array slice passed in is the target slice, and the existing used space
- * is passed separately. This is to discourage code that ends up with a
- * slice to dangling valid data.
+ * Shrink used space of a slice in place.
+ *
+ * Unlike the other array functions, the array slice passed in is the
+ * target slice, and the existing used space is passed separately. This is
+ * to discourage code that ends up with a slice to dangling valid data.
+ *
* If slice.ptr[0 .. existingUsed] does not point to the end of a valid GC
* appendable slice, then the operation fails.
+ *
* Params:
* slice = The proposed valid slice data.
* existingUsed = The amount of data in the block (starting at slice.ptr)
* that is currently valid in the array. If this amount does not match
* the current used size, the operation fails.
- * atomic = If true, the slice may be shared between threads, and the
- * operation should be atomic.
+ * atomic = The slice may be shared between threads, and the operation
+ * should be atomic.
* Returns: true if successful.
*/
bool shrinkArrayUsed(void[] slice, size_t existingUsed, bool atomic = false) nothrow;
diff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d
index 8098597a72a..c9761ece24b 100644
--- a/libphobos/libdruntime/core/internal/array/construction.d
+++ b/libphobos/libdruntime/core/internal/array/construction.d
@@ -48,7 +48,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma
import core.stdc.stdint : uintptr_t;
debug(PRINTF) import core.stdc.stdio : printf;
- debug(PRINTF) printf("_d_arrayctor(from = %p,%d) size = %d\n", from.ptr, from.length, T.sizeof);
+ debug(PRINTF) printf("_d_arrayctor(from = %p,%zd) size = %zd\n", from.ptr, from.length, T.sizeof);
void[] vFrom = (cast(void*) from.ptr)[0..from.length];
void[] vTo = (cast(void*) to.ptr)[0..to.length];
@@ -513,7 +513,7 @@ version (D_ProfileGC)
*/
Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trusted
{
- debug(PRINTF) printf("_d_newarraymTX(dims.length = %d)\n", dims.length);
+ debug(PRINTF) printf("_d_newarraymTX(dims.length = %zd)\n", dims.length);
if (dims.length == 0)
return null;
@@ -547,7 +547,7 @@ Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trust
}
auto result = __allocateInnerArray(dims);
- debug(PRINTF) printf("result = %llx\n", result.ptr);
+ debug(PRINTF) printf("result = %p\n", result.ptr);
return (cast(U*) result.ptr)[0 .. dims[0]];
}
diff --git a/libphobos/libdruntime/core/internal/atomic.d b/libphobos/libdruntime/core/internal/atomic.d
index 36cf6891feb..43e50acacb7 100644
--- a/libphobos/libdruntime/core/internal/atomic.d
+++ b/libphobos/libdruntime/core/internal/atomic.d
@@ -10,7 +10,7 @@
module core.internal.atomic;
-import core.atomic : MemoryOrder, has128BitCAS;
+import core.atomic : has128BitCAS, MemoryOrder;
version (DigitalMars)
{
@@ -912,7 +912,7 @@ else version (GNU)
{
static if (GNU_Thread_Model == ThreadModel.Posix)
{
- import core.sys.posix.pthread;
+ import core.sys.posix.sys.types : pthread_mutex_t, pthread_mutexattr_t;
alias atomicMutexHandle = pthread_mutex_t;
pragma(mangle, "pthread_mutex_init") int fakePureMutexInit(pthread_mutex_t*, pthread_mutexattr_t*);
@@ -921,7 +921,7 @@ else version (GNU)
}
else static if (GNU_Thread_Model == ThreadModel.Win32)
{
- import core.sys.windows.winbase;
+ import core.sys.windows.winbase : CRITICAL_SECTION;
alias atomicMutexHandle = CRITICAL_SECTION;
pragma(mangle, "InitializeCriticalSection") int fakePureMutexInit(CRITICAL_SECTION*);
diff --git a/libphobos/libdruntime/core/internal/dassert.d b/libphobos/libdruntime/core/internal/dassert.d
index 76948c8bde8..9d120e576c9 100644
--- a/libphobos/libdruntime/core/internal/dassert.d
+++ b/libphobos/libdruntime/core/internal/dassert.d
@@ -14,7 +14,7 @@
*
* Copyright: D Language Foundation 2018 - 2020
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/internal/dassert.d, _dassert.d)
+ * Source: $(DRUNTIMESRC core/internal/_dassert.d)
* Documentation: https://dlang.org/phobos/core_internal_dassert.html
*/
module core.internal.dassert;
diff --git a/libphobos/libdruntime/core/internal/gc/blkcache.d b/libphobos/libdruntime/core/internal/gc/blkcache.d
index 908f66656e1..b141a6959f7 100644
--- a/libphobos/libdruntime/core/internal/gc/blkcache.d
+++ b/libphobos/libdruntime/core/internal/gc/blkcache.d
@@ -8,6 +8,8 @@ module core.internal.gc.blkcache;
import core.memory;
import core.attribute;
+debug (PRINTF) import core.stdc.stdio : printf;
+
alias BlkInfo = GC.BlkInfo;
alias BlkAttr = GC.BlkAttr;
@@ -98,17 +100,17 @@ void processGCMarks(void* data, scope IsMarkedDg isMarked) nothrow
// called after the mark routine to eliminate block cache data when it
// might be ready to sweep
- debug(PRINTF) printf("processing GC Marks, %x\n", cache);
+ debug(PRINTF) printf("processing GC Marks, %p\n", cache);
debug(PRINTF) foreach (i; 0 .. N_CACHE_BLOCKS)
{
- printf("cache entry %d has base ptr %x\tsize %d\tflags %x\n", i, cache[i].base, cache[i].size, cache[i].attr);
+ printf("cache entry %d has base ptr %p\tsize %zd\tflags %x\n", i, cache[i].base, cache[i].size, cache[i].attr);
}
auto cache_end = cache + N_CACHE_BLOCKS;
for (;cache < cache_end; ++cache)
{
if (cache.base != null && isMarked(cache.base) == IsMarked.no)
{
- debug(PRINTF) printf("clearing cache entry at %x\n", cache.base);
+ debug(PRINTF) printf("clearing cache entry at %p\n", cache.base);
cache.base = null; // clear that data.
}
}
@@ -250,7 +252,7 @@ debug(PRINTF)
printf("CACHE: \n");
foreach (i; 0 .. N_CACHE_BLOCKS)
{
- printf(" %d\taddr:% .8x\tsize:% .10d\tflags:% .8x\n", i, ptr[i].base, ptr[i].size, ptr[i].attr);
+ printf(" %d\taddr:% .8p\tsize:% .10zd\tflags:% .8x\n", i, ptr[i].base, ptr[i].size, ptr[i].attr);
}
}
}
diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
index 6ddd4c1fb60..40e361c50f1 100644
--- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
+++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
@@ -503,7 +503,7 @@ class ConservativeGC : GC
assert(size != 0);
debug(PRINTF)
- printf("GC::malloc(gcx = %p, size = %d bits = %x, ti = %s)\n", gcx, size, bits, debugTypeName(ti).ptr);
+ printf("GC::malloc(gcx = %p, size = %zd bits = %x, ti = %s)\n", gcx, size, bits, debugTypeName(ti).ptr);
assert(gcx);
//debug(PRINTF) printf("gcx.self = %x, pthread_self() = %x\n", gcx.self, pthread_self());
@@ -876,7 +876,7 @@ class ConservativeGC : GC
//
private void freeNoSync(void *p) nothrow @nogc
{
- debug(PRINTF) printf("Freeing %p\n", cast(size_t) p);
+ debug(PRINTF) printf("Freeing %#zx\n", cast(size_t) p);
assert (p);
Pool* pool;
@@ -891,7 +891,7 @@ class ConservativeGC : GC
pagenum = pool.pagenumOf(p);
- debug(PRINTF) printf("pool base = %p, PAGENUM = %d of %d, bin = %d\n", pool.baseAddr, pagenum, pool.npages, pool.pagetable[pagenum]);
+ debug(PRINTF) printf("pool base = %p, PAGENUM = %zd of %zd, bin = %d\n", pool.baseAddr, pagenum, pool.npages, pool.pagetable[pagenum]);
debug(PRINTF) if (pool.isLargeObject) printf("Block size = %d\n", pool.bPageOffsets[pagenum]);
bin = pool.pagetable[pagenum];
@@ -1763,7 +1763,7 @@ struct Gcx
long apiTime = mallocTime + reallocTime + freeTime + extendTime + otherTime + lockTime;
printf("\tGC API: %lld ms\n", toDuration(apiTime).total!"msecs");
- sprintf(apitxt.ptr, " API%5ld ms", toDuration(apiTime).total!"msecs");
+ sprintf(apitxt.ptr, " API%5lld ms", toDuration(apiTime).total!"msecs");
}
printf("GC summary:%5lld MB,%5lld GC%5lld ms, Pauses%5lld ms <%5lld ms%s\n",
@@ -2169,7 +2169,7 @@ struct Gcx
*/
void* bigAlloc(size_t size, ref size_t alloc_size, uint bits, const TypeInfo ti = null) nothrow
{
- debug(PRINTF) printf("In bigAlloc. Size: %d\n", size);
+ debug(PRINTF) printf("In bigAlloc. Size: %zd\n", size);
LargeObjectPool* pool;
size_t pn;
@@ -2233,7 +2233,7 @@ struct Gcx
debug(PRINTF) printFreeInfo(&pool.base);
auto p = pool.baseAddr + pn * PAGESIZE;
- debug(PRINTF) printf("Got large alloc: %p, pt = %d, np = %d\n", p, pool.pagetable[pn], npages);
+ debug(PRINTF) printf("Got large alloc: %p, pt = %d, np = %zd\n", p, pool.pagetable[pn], npages);
invalidate(p[0 .. size], 0xF1, true);
alloc_size = npages * PAGESIZE;
//debug(PRINTF) printf("\tp = %p\n", p);
@@ -3575,7 +3575,7 @@ Lmark:
version (Posix)
{
- import core.sys.posix.signal;
+ import core.sys.posix.signal : pthread_sigmask, SIG_BLOCK, SIG_SETMASK, sigfillset, sigset_t;
// block all signals, scanBackground inherits this mask.
// see https://issues.dlang.org/show_bug.cgi?id=20256
sigset_t new_mask, old_mask;
@@ -3659,9 +3659,12 @@ Lmark:
if (atomicLoad(busyThreads) == 0)
return;
- debug(PARALLEL_PRINTF)
+ version (Posix) debug (PARALLEL_PRINTF)
+ {
+ import core.sys.posix.pthread : pthread_self, pthread_t;
pthread_t threadId = pthread_self();
- debug(PARALLEL_PRINTF) printf("scanBackground thread %d start\n", threadId);
+ printf("scanBackground thread %d start\n", threadId);
+ }
ScanRange!precise rng;
alias toscan = scanStack!precise;
@@ -3677,13 +3680,16 @@ Lmark:
busyThreads.atomicOp!"+="(1);
if (toscan.popLocked(rng))
{
- debug(PARALLEL_PRINTF) printf("scanBackground thread %d scanning range [%p,%lld] from stack\n", threadId,
- rng.pbot, cast(long) (rng.ptop - rng.pbot));
+ version (Posix) debug (PARALLEL_PRINTF)
+ {
+ printf("scanBackground thread %d scanning range [%p,%lld] from stack\n",
+ threadId, rng.pbot, cast(long) (rng.ptop - rng.pbot));
+ }
mark!(precise, true, true)(rng);
}
busyThreads.atomicOp!"-="(1);
}
- debug(PARALLEL_PRINTF) printf("scanBackground thread %d done\n", threadId);
+ version (Posix) debug (PARALLEL_PRINTF) printf("scanBackground thread %d done\n", threadId);
}
}
@@ -4203,12 +4209,12 @@ struct Pool
debugTypeName(ti).ptr, p, bitmap, cast(ulong)element_size);
debug(PRINTF)
for (size_t i = 0; i < element_size/((void*).sizeof); i++)
- printf("%d", (bitmap[i/(8*size_t.sizeof)] >> (i%(8*size_t.sizeof))) & 1);
+ printf("%zd", (bitmap[i/(8*size_t.sizeof)] >> (i%(8*size_t.sizeof))) & 1);
debug(PRINTF) printf("\n");
if (tocopy * (void*).sizeof < s) // better safe than sorry: if allocated more, assume pointers inside
{
- debug(PRINTF) printf(" Appending %d pointer bits\n", s/(void*).sizeof - tocopy);
+ debug(PRINTF) printf(" Appending %zd pointer bits\n", s/(void*).sizeof - tocopy);
is_pointer.setRange(offset/(void*).sizeof + tocopy, s/(void*).sizeof - tocopy);
}
}
@@ -4734,7 +4740,7 @@ debug(PRINTF) void printFreeInfo(Pool* pool) nothrow
if (pool.pagetable[i] >= Bins.B_FREE) nReallyFree++;
}
- printf("Pool %p: %d really free, %d supposedly free\n", pool, nReallyFree, pool.freepages);
+ printf("Pool %p: %d really free, %zd supposedly free\n", pool, nReallyFree, pool.freepages);
}
debug(PRINTF)
@@ -4743,7 +4749,7 @@ void printGCBits(GCBits* bits)
for (size_t i = 0; i < bits.nwords; i++)
{
if (i % 32 == 0) printf("\n\t");
- printf("%x ", bits.data[i]);
+ printf("%zx ", bits.data[i]);
}
printf("\n");
}
diff --git a/libphobos/libdruntime/core/internal/gc/os.d b/libphobos/libdruntime/core/internal/gc/os.d
index 0db1753575b..bde90e95228 100644
--- a/libphobos/libdruntime/core/internal/gc/os.d
+++ b/libphobos/libdruntime/core/internal/gc/os.d
@@ -33,8 +33,8 @@ else version (Posix)
else version (WatchOS)
version = Darwin;
- import core.sys.posix.sys.mman;
import core.stdc.stdlib;
+ import core.sys.posix.sys.mman : MAP_ANON, MAP_FAILED, MAP_PRIVATE, MAP_SHARED, mmap, munmap, PROT_READ, PROT_WRITE;
/// Possible results for the wait_pid() function.
@@ -74,9 +74,9 @@ else version (Posix)
return ChildStatus.done;
}
- public import core.sys.posix.unistd: pid_t, fork;
- import core.sys.posix.sys.wait: waitpid, WNOHANG;
- import core.stdc.errno: errno, EINTR, ECHILD;
+ public import core.sys.posix.unistd : fork, pid_t;
+ import core.stdc.errno : ECHILD, EINTR, errno;
+ import core.sys.posix.sys.wait : waitpid, WNOHANG;
//version = GC_Use_Alloc_MMap;
}
@@ -292,12 +292,18 @@ else version (Posix)
{
ulong os_physical_mem(bool avail) nothrow @nogc
{
- import core.sys.posix.unistd;
+ static import core.sys.posix.unistd;
+ import core.sys.posix.unistd : _SC_PAGESIZE, _SC_PHYS_PAGES, sysconf;
const pageSize = sysconf(_SC_PAGESIZE);
- static if (__traits(compiles, _SC_AVPHYS_PAGES)) // not available on all platforms
+ static if (__traits(compiles, core.sys.posix.unistd._SC_AVPHYS_PAGES)) // not available on all platforms
+ {
+ import core.sys.posix.unistd : _SC_AVPHYS_PAGES;
const sc = avail ? _SC_AVPHYS_PAGES : _SC_PHYS_PAGES;
+ }
else
+ {
const sc = _SC_PHYS_PAGES;
+ }
const pages = sysconf(sc);
return pageSize * pages;
}
diff --git a/libphobos/libdruntime/core/internal/postblit.d b/libphobos/libdruntime/core/internal/postblit.d
index ed4ec1b7ff4..3377ba5c3d9 100644
--- a/libphobos/libdruntime/core/internal/postblit.d
+++ b/libphobos/libdruntime/core/internal/postblit.d
@@ -5,7 +5,7 @@
License: Distributed under the
$(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
(See accompanying file LICENSE)
- Source: $(DRUNTIMESRC core/_internal/_destruction.d)
+ Source: $(DRUNTIMESRC core/_internal/_postblit.d)
*/
module core.internal.postblit;
diff --git a/libphobos/libdruntime/core/internal/qsort.d b/libphobos/libdruntime/core/internal/qsort.d
index 0040f6b4609..fce1067812c 100644
--- a/libphobos/libdruntime/core/internal/qsort.d
+++ b/libphobos/libdruntime/core/internal/qsort.d
@@ -12,6 +12,8 @@ module core.internal.qsort;
import core.stdc.stdlib;
+debug (qsort) import core.stdc.stdio : printf;
+
version (OSX)
version = Darwin;
else version (iOS)
diff --git a/libphobos/libdruntime/core/internal/string.d b/libphobos/libdruntime/core/internal/string.d
index 7bb319ecfa5..e5abce47db8 100644
--- a/libphobos/libdruntime/core/internal/string.d
+++ b/libphobos/libdruntime/core/internal/string.d
@@ -4,7 +4,7 @@
* Copyright: Copyright Sean Kelly 2005 - 2009.
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
* Authors: Sean Kelly, Walter Bright
- * Source: $(DRUNTIMESRC rt/util/_string.d)
+ * Source: $(DRUNTIMESRC core/internal/_string.d)
*/
module core.internal.string;
diff --git a/libphobos/libdruntime/core/internal/utf.d b/libphobos/libdruntime/core/internal/utf.d
index 9808b9947f5..71c32119473 100644
--- a/libphobos/libdruntime/core/internal/utf.d
+++ b/libphobos/libdruntime/core/internal/utf.d
@@ -21,6 +21,8 @@
module core.internal.utf;
+debug (utf) import core.stdc.stdio : printf;
+
extern (C) void onUnicodeError( string msg, size_t idx, string file = __FILE__, size_t line = __LINE__ ) @safe pure;
/*******************************
diff --git a/libphobos/libdruntime/core/runtime.d b/libphobos/libdruntime/core/runtime.d
index 182886175a6..dc765e7ecad 100644
--- a/libphobos/libdruntime/core/runtime.d
+++ b/libphobos/libdruntime/core/runtime.d
@@ -4,7 +4,7 @@
* Copyright: Copyright Sean Kelly 2005 - 2009.
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: Sean Kelly
- * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/runtime.d, _runtime.d)
+ * Source: $(DRUNTIMESRC core/_runtime.d)
* Documentation: https://dlang.org/phobos/core_runtime.html
*/
@@ -575,7 +575,9 @@ extern (C) UnitTestResult runModuleUnitTests()
static if (__traits(compiles, new LibBacktrace(0)))
{
- import core.sys.posix.signal; // segv handler
+ // segv handler
+ import core.sys.posix.signal : SA_RESETHAND, SA_SIGINFO, sigaction, sigaction_t, SIGBUS, sigfillset, siginfo_t,
+ SIGSEGV;
static extern (C) void unittestSegvHandler(int signum, siginfo_t* info, void* ptr)
{
diff --git a/libphobos/libdruntime/core/stdc/errno.d b/libphobos/libdruntime/core/stdc/errno.d
index 0430e6b33e9..db347e404b4 100644
--- a/libphobos/libdruntime/core/stdc/errno.d
+++ b/libphobos/libdruntime/core/stdc/errno.d
@@ -8,7 +8,7 @@
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Sean Kelly, Alex Rønne Petersen
- * Source: https://github.com/dlang/dmd/blob/master/druntime/src/core/stdc/errno.d
+ * Source: $(DRUNTIMESRC core/stdc/_errno.d)
* Standards: ISO/IEC 9899:1999 (E)
*/
diff --git a/libphobos/libdruntime/core/stdc/stdio.d b/libphobos/libdruntime/core/stdc/stdio.d
index 8afb68f8585..d3ee2cae8e5 100644
--- a/libphobos/libdruntime/core/stdc/stdio.d
+++ b/libphobos/libdruntime/core/stdc/stdio.d
@@ -9,7 +9,7 @@
* (See accompanying file LICENSE)
* Authors: Sean Kelly,
* Alex Rønne Petersen
- * Source: https://github.com/dlang/dmd/blob/master/druntime/src/core/stdc/stdio.d
+ * Source: $(DRUNTIMESRC core/stdc/_stdio.d)
* Standards: ISO/IEC 9899:1999 (E)
*/
diff --git a/libphobos/libdruntime/core/sync/condition.d b/libphobos/libdruntime/core/sync/condition.d
index afcfd744f0a..51ab7b5aa31 100644
--- a/libphobos/libdruntime/core/sync/condition.d
+++ b/libphobos/libdruntime/core/sync/condition.d
@@ -35,10 +35,11 @@ version (Windows)
}
else version (Posix)
{
- import core.sync.config;
import core.stdc.errno;
- import core.sys.posix.pthread;
- import core.sys.posix.time;
+ import core.sync.config;
+ import core.sys.posix.pthread : pthread_cond_broadcast, pthread_cond_destroy, pthread_cond_init,
+ pthread_cond_signal, pthread_cond_t, pthread_cond_timedwait, pthread_cond_wait;
+ import core.sys.posix.time : timespec;
}
else
{
@@ -127,8 +128,12 @@ class Condition
{
m_assocMutex = m;
}
- static if ( is( typeof( pthread_condattr_setclock ) ) )
+ static if ( is( typeof( imported!"core.sys.posix.pthread".pthread_condattr_setclock ) ) )
{
+ import core.sys.posix.pthread : pthread_condattr_destroy, pthread_condattr_init,
+ pthread_condattr_setclock;
+ import core.sys.posix.sys.types : pthread_condattr_t;
+ import core.sys.posix.time : CLOCK_MONOTONIC;
() @trusted
{
pthread_condattr_t attr = void;
@@ -620,9 +625,9 @@ private:
unittest
{
- import core.thread;
import core.sync.mutex;
import core.sync.semaphore;
+ import core.thread;
void testNotify()
@@ -786,9 +791,9 @@ unittest
unittest
{
- import core.thread;
import core.sync.mutex;
import core.sync.semaphore;
+ import core.thread;
void testNotify()
diff --git a/libphobos/libdruntime/core/sync/config.d b/libphobos/libdruntime/core/sync/config.d
index 39f7a8cd769..f68502464e0 100644
--- a/libphobos/libdruntime/core/sync/config.d
+++ b/libphobos/libdruntime/core/sync/config.d
@@ -18,16 +18,16 @@ module core.sync.config;
version (Posix)
{
- import core.sys.posix.pthread;
- import core.sys.posix.time;
- import core.sys.posix.sys.time;
+ import core.sys.posix.sys.time : gettimeofday, timeval;
+ import core.sys.posix.time : timespec;
import core.time;
void mktspec( ref timespec t ) nothrow @nogc
{
- static if ( is (typeof ( pthread_condattr_setclock ) ) )
+ static if ( is (typeof ( imported!"core.sys.posix.pthread".pthread_condattr_setclock ) ) )
{
+ import core.sys.posix.time : clock_gettime, CLOCK_MONOTONIC;
clock_gettime( CLOCK_MONOTONIC, &t );
}
else
diff --git a/libphobos/libdruntime/core/sync/event.d b/libphobos/libdruntime/core/sync/event.d
index 048607f6ed2..6278218f673 100644
--- a/libphobos/libdruntime/core/sync/event.d
+++ b/libphobos/libdruntime/core/sync/event.d
@@ -20,17 +20,19 @@ version (Windows)
}
else version (Posix)
{
- import core.sys.posix.pthread;
- import core.sys.posix.sys.types;
- import core.sys.posix.time;
+ import core.sys.posix.pthread : pthread_cond_broadcast, pthread_cond_destroy, pthread_cond_init,
+ pthread_cond_timedwait, pthread_cond_wait, pthread_mutex_destroy, pthread_mutex_init, pthread_mutex_lock,
+ pthread_mutex_unlock;
+ import core.sys.posix.sys.types : pthread_cond_t, pthread_mutex_t;
+ import core.sys.posix.time : timespec;
}
else
{
static assert(false, "Platform not supported");
}
-import core.time;
import core.internal.abort : abort;
+import core.time;
/**
* represents an event. Clients of an event are suspended while waiting
@@ -105,8 +107,13 @@ nothrow @nogc:
return;
pthread_mutex_init(cast(pthread_mutex_t*) &m_mutex, null) == 0 ||
abort("Error: pthread_mutex_init failed.");
- static if ( is( typeof( pthread_condattr_setclock ) ) )
+
+ static if ( is( typeof( imported!"core.sys.posix.pthread".pthread_condattr_setclock ) ) )
{
+ import core.sys.posix.pthread : CLOCK_MONOTONIC, pthread_condattr_destroy, pthread_condattr_init,
+ pthread_condattr_setclock;
+ import core.sys.posix.sys.types : pthread_condattr_t;
+
pthread_condattr_t attr = void;
pthread_condattr_init(&attr) == 0 ||
abort("Error: pthread_condattr_init failed.");
@@ -320,7 +327,8 @@ private:
unittest
{
- import core.thread, core.atomic;
+ import core.atomic;
+ import core.thread;
scope event = new Event(true, false);
int numThreads = 10;
diff --git a/libphobos/libdruntime/core/sync/mutex.d b/libphobos/libdruntime/core/sync/mutex.d
index 5f547cd04ef..8993f85071b 100644
--- a/libphobos/libdruntime/core/sync/mutex.d
+++ b/libphobos/libdruntime/core/sync/mutex.d
@@ -26,7 +26,10 @@ version (Windows)
}
else version (Posix)
{
- import core.sys.posix.pthread;
+ import core.sys.posix.pthread : pthread_mutex_destroy, pthread_mutex_init, pthread_mutex_lock,
+ PTHREAD_MUTEX_RECURSIVE, pthread_mutex_trylock, pthread_mutex_unlock, pthread_mutexattr_destroy,
+ pthread_mutexattr_init, pthread_mutexattr_settype;
+ import core.sys.posix.sys.types : pthread_mutex_t, pthread_mutexattr_t;
}
else
{
@@ -344,8 +347,8 @@ unittest
// Test @nogc usage.
@system @nogc nothrow unittest
{
- import core.stdc.stdlib : malloc, free;
import core.lifetime : emplace;
+ import core.stdc.stdlib : free, malloc;
auto mtx = cast(shared Mutex) malloc(__traits(classInstanceSize, Mutex));
emplace(mtx);
diff --git a/libphobos/libdruntime/core/sync/rwmutex.d b/libphobos/libdruntime/core/sync/rwmutex.d
index 07c5bdbe360..cb581621ec5 100644
--- a/libphobos/libdruntime/core/sync/rwmutex.d
+++ b/libphobos/libdruntime/core/sync/rwmutex.d
@@ -21,11 +21,6 @@ import core.sync.condition;
import core.sync.mutex;
import core.memory;
-version (Posix)
-{
- import core.sys.posix.pthread;
-}
-
////////////////////////////////////////////////////////////////////////////////
// ReadWriteMutex
diff --git a/libphobos/libdruntime/core/sync/semaphore.d b/libphobos/libdruntime/core/sync/semaphore.d
index cf2bddbf106..a4dae042ee3 100644
--- a/libphobos/libdruntime/core/sync/semaphore.d
+++ b/libphobos/libdruntime/core/sync/semaphore.d
@@ -37,17 +37,18 @@ version (Windows)
}
else version (Darwin)
{
- import core.sync.config;
import core.stdc.errno;
- import core.sys.posix.time;
- import core.sys.darwin.mach.semaphore;
+ import core.sync.config;
+ import core.sys.darwin.mach.kern_return : KERN_ABORTED, KERN_OPERATION_TIMED_OUT;
+ import core.sys.darwin.mach.semaphore : mach_task_self, mach_timespec_t, semaphore_create, semaphore_destroy,
+ semaphore_signal, semaphore_t, semaphore_timedwait, semaphore_wait, SYNC_POLICY_FIFO;
}
else version (Posix)
{
- import core.sync.config;
import core.stdc.errno;
- import core.sys.posix.pthread;
- import core.sys.posix.semaphore;
+ import core.sync.config;
+ import core.sys.posix.semaphore : sem_destroy, sem_init, sem_post, sem_t, sem_timedwait, sem_trywait, sem_wait;
+ import core.sys.posix.time : clock_gettime, CLOCK_REALTIME, timespec;
}
else
{
@@ -253,8 +254,6 @@ class Semaphore
}
else version (Posix)
{
- import core.sys.posix.time : clock_gettime, CLOCK_REALTIME;
-
timespec t = void;
clock_gettime( CLOCK_REALTIME, &t );
mvtspec( t, period );
@@ -364,7 +363,8 @@ protected:
unittest
{
- import core.thread, core.atomic;
+ import core.atomic;
+ import core.thread;
void testWait()
{
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/stab.d b/libphobos/libdruntime/core/sys/darwin/mach/stab.d
index ecdb4560a68..7125cf28143 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/stab.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/stab.d
@@ -24,7 +24,7 @@
*
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
* Authors: Mathias 'Geod24' Lang
- * Source: $(DRUNTIMESRC core/sys/darwin/mach/_nlist.d)
+ * Source: $(DRUNTIMESRC core/sys/darwin/mach/_stab.d)
*/
module core.sys.darwin.mach.stab;
diff --git a/libphobos/libdruntime/core/sys/linux/sys/procfs.d b/libphobos/libdruntime/core/sys/linux/sys/procfs.d
index 6a113e172dc..ceea5223ed3 100644
--- a/libphobos/libdruntime/core/sys/linux/sys/procfs.d
+++ b/libphobos/libdruntime/core/sys/linux/sys/procfs.d
@@ -7,9 +7,8 @@
module core.sys.linux.sys.procfs;
+version (linux):
+
import core.sys.posix.sys.types : pid_t;
-version (linux)
-{
- alias lwpid_t = pid_t;
-}
+alias lwpid_t = pid_t;
diff --git a/libphobos/libdruntime/core/sys/posix/spawn.d b/libphobos/libdruntime/core/sys/posix/spawn.d
index 789053396f0..081270b42c5 100644
--- a/libphobos/libdruntime/core/sys/posix/spawn.d
+++ b/libphobos/libdruntime/core/sys/posix/spawn.d
@@ -4,7 +4,7 @@
* Copyright: Copyright (C) 2018 by The D Language Foundation, All Rights Reserved
* Authors: Petar Kirov
* License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
- * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/druntime/src/core/sys/posix/spawn.d, _spawn.d)
+ * Source: $(DRUNTIMESRC core/sys/posix/_spawn.d)
* Standards: The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
*/
module core.sys.posix.spawn;
diff --git a/libphobos/libdruntime/core/sys/posix/stdc/time.d b/libphobos/libdruntime/core/sys/posix/stdc/time.d
index d48a0ea3eda..c5a2e1b7182 100644
--- a/libphobos/libdruntime/core/sys/posix/stdc/time.d
+++ b/libphobos/libdruntime/core/sys/posix/stdc/time.d
@@ -9,7 +9,7 @@
* (See accompanying file LICENSE)
* Authors: Sean Kelly,
* Alex Rønne Petersen
- * Source: $(DRUNTIMESRC core/stdc/_time.d)
+ * Source: $(DRUNTIMESRC core/sys/posix/stdc/_time.d)
* Standards: ISO/IEC 9899:1999 (E)
*/
diff --git a/libphobos/libdruntime/core/sys/windows/dbghelp.d b/libphobos/libdruntime/core/sys/windows/dbghelp.d
index 55fbc56a754..fb6fb668672 100644
--- a/libphobos/libdruntime/core/sys/windows/dbghelp.d
+++ b/libphobos/libdruntime/core/sys/windows/dbghelp.d
@@ -6,7 +6,7 @@
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Benjamin Thaut, Sean Kelly
- * Source: $(DRUNTIMESRC core/sys/windows/_stacktrace.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/_dbghelp.d)
*/
module core.sys.windows.dbghelp;
diff --git a/libphobos/libdruntime/core/sys/windows/stdc/time.d b/libphobos/libdruntime/core/sys/windows/stdc/time.d
index 97eb4bf1e11..407b92c20a6 100644
--- a/libphobos/libdruntime/core/sys/windows/stdc/time.d
+++ b/libphobos/libdruntime/core/sys/windows/stdc/time.d
@@ -9,7 +9,7 @@
* (See accompanying file LICENSE)
* Authors: Sean Kelly,
* Alex Rønne Petersen
- * Source: $(DRUNTIMESRC core/stdc/_time.d)
+ * Source: $(DRUNTIMESRC core/sys/windows/stdc/_time.d)
* Standards: ISO/IEC 9899:1999 (E)
*/
diff --git a/libphobos/libdruntime/core/thread/fiber/base.d b/libphobos/libdruntime/core/thread/fiber/base.d
new file mode 100644
index 00000000000..2afc2690261
--- /dev/null
+++ b/libphobos/libdruntime/core/thread/fiber/base.d
@@ -0,0 +1,1091 @@
+/**
+ * Base fiber module provides OS-indepedent part of lightweight threads aka fibers.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2012.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
+ * Source: $(DRUNTIMESRC core/thread/fiber/base.d)
+ */
+
+/* NOTE: This file has been patched from the original DMD distribution to
+ * work with the GDC compiler.
+ */
+module core.thread.fiber.base;
+
+package:
+version (GNU)
+ import gcc.config;
+
+import core.thread.fiber;
+import core.thread.threadbase;
+import core.thread.threadgroup;
+import core.thread.types;
+import core.thread.context;
+
+import core.memory : pageSize;
+
+package
+{
+ import core.atomic : atomicStore, cas, MemoryOrder;
+ import core.exception : onOutOfMemoryError;
+ import core.stdc.stdlib : abort;
+
+ extern (C) void fiber_entryPoint() nothrow
+ {
+ FiberBase obj = FiberBase.getThis();
+ assert( obj );
+
+ assert( ThreadBase.getThis().m_curr is obj.m_ctxt );
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&ThreadBase.getThis().m_lock, false);
+ obj.m_ctxt.tstack = obj.m_ctxt.bstack;
+ obj.m_state = FiberBase.State.EXEC;
+
+ try
+ {
+ obj.run();
+ }
+ catch ( Throwable t )
+ {
+ obj.m_unhandled = t;
+ }
+
+ static if ( __traits( compiles, ucontext_t ) )
+ obj.m_ucur = &obj.m_utxt;
+
+ obj.m_state = Fiber.State.TERM;
+ obj.switchOut();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Fiber
+///////////////////////////////////////////////////////////////////////////////
+/*
+ * Documentation of Fiber internals:
+ *
+ * The main routines to implement when porting Fibers to new architectures are
+ * fiber_switchContext and initStack. Some version constants have to be defined
+ * for the new platform as well, search for "Fiber Platform Detection and Memory Allocation".
+ *
+ * Fibers are based on a concept called 'Context'. A Context describes the execution
+ * state of a Fiber or main thread which is fully described by the stack, some
+ * registers and a return address at which the Fiber/Thread should continue executing.
+ * Please note that not only each Fiber has a Context, but each thread also has got a
+ * Context which describes the threads stack and state. If you call Fiber fib; fib.call
+ * the first time in a thread you switch from Threads Context into the Fibers Context.
+ * If you call fib.yield in that Fiber you switch out of the Fibers context and back
+ * into the Thread Context. (However, this is not always the case. You can call a Fiber
+ * from within another Fiber, then you switch Contexts between the Fibers and the Thread
+ * Context is not involved)
+ *
+ * In all current implementations the registers and the return address are actually
+ * saved on a Contexts stack.
+ *
+ * The fiber_switchContext routine has got two parameters:
+ * void** a: This is the _location_ where we have to store the current stack pointer,
+ * the stack pointer of the currently executing Context (Fiber or Thread).
+ * void* b: This is the pointer to the stack of the Context which we want to switch into.
+ * Note that we get the same pointer here as the one we stored into the void** a
+ * in a previous call to fiber_switchContext.
+ *
+ * In the simplest case, a fiber_switchContext rountine looks like this:
+ * fiber_switchContext:
+ * push {return Address}
+ * push {registers}
+ * copy {stack pointer} into {location pointed to by a}
+ * //We have now switch to the stack of a different Context!
+ * copy {b} into {stack pointer}
+ * pop {registers}
+ * pop {return Address}
+ * jump to {return Address}
+ *
+ * The GC uses the value returned in parameter a to scan the Fibers stack. It scans from
+ * the stack base to that value. As the GC dislikes false pointers we can actually optimize
+ * this a little: By storing registers which can not contain references to memory managed
+ * by the GC outside of the region marked by the stack base pointer and the stack pointer
+ * saved in fiber_switchContext we can prevent the GC from scanning them.
+ * Such registers are usually floating point registers and the return address. In order to
+ * implement this, we return a modified stack pointer from fiber_switchContext. However,
+ * we have to remember that when we restore the registers from the stack!
+ *
+ * --------------------------- <= Stack Base
+ * | Frame | <= Many other stack frames
+ * | Frame |
+ * |-------------------------| <= The last stack frame. This one is created by fiber_switchContext
+ * | registers with pointers |
+ * | | <= Stack pointer. GC stops scanning here
+ * | return address |
+ * |floating point registers |
+ * --------------------------- <= Real Stack End
+ *
+ * fiber_switchContext:
+ * push {registers with pointers}
+ * copy {stack pointer} into {location pointed to by a}
+ * push {return Address}
+ * push {Floating point registers}
+ * //We have now switch to the stack of a different Context!
+ * copy {b} into {stack pointer}
+ * //We now have to adjust the stack pointer to point to 'Real Stack End' so we can pop
+ * //the FP registers
+ * //+ or - depends on if your stack grows downwards or upwards
+ * {stack pointer} = {stack pointer} +- ({FPRegisters}.sizeof + {return address}.sizeof}
+ * pop {Floating point registers}
+ * pop {return Address}
+ * pop {registers with pointers}
+ * jump to {return Address}
+ *
+ * So the question now is which registers need to be saved? This depends on the specific
+ * architecture ABI of course, but here are some general guidelines:
+ * - If a register is callee-save (if the callee modifies the register it must saved and
+ * restored by the callee) it needs to be saved/restored in switchContext
+ * - If a register is caller-save it needn't be saved/restored. (Calling fiber_switchContext
+ * is a function call and the compiler therefore already must save these registers before
+ * calling fiber_switchContext)
+ * - Argument registers used for passing parameters to functions needn't be saved/restored
+ * - The return register needn't be saved/restored (fiber_switchContext hasn't got a return type)
+ * - All scratch registers needn't be saved/restored
+ * - The link register usually needn't be saved/restored (but sometimes it must be cleared -
+ * see below for details)
+ * - The frame pointer register - if it exists - is usually callee-save
+ * - All current implementations do not save control registers
+ *
+ * What happens on the first switch into a Fiber? We never saved a state for this fiber before,
+ * but the initial state is prepared in the initStack routine. (This routine will also be called
+ * when a Fiber is being resetted). initStack must produce exactly the same stack layout as the
+ * part of fiber_switchContext which saves the registers. Pay special attention to set the stack
+ * pointer correctly if you use the GC optimization mentioned before. the return Address saved in
+ * initStack must be the address of fiber_entrypoint.
+ *
+ * There's now a small but important difference between the first context switch into a fiber and
+ * further context switches. On the first switch, Fiber.call is used and the returnAddress in
+ * fiber_switchContext will point to fiber_entrypoint. The important thing here is that this jump
+ * is a _function call_, we call fiber_entrypoint by jumping before it's function prologue. On later
+ * calls, the user used yield() in a function, and therefore the return address points into a user
+ * function, after the yield call. So here the jump in fiber_switchContext is a _function return_,
+ * not a function call!
+ *
+ * The most important result of this is that on entering a function, i.e. fiber_entrypoint, we
+ * would have to provide a return address / set the link register once fiber_entrypoint
+ * returns. Now fiber_entrypoint does never return and therefore the actual value of the return
+ * address / link register is never read/used and therefore doesn't matter. When fiber_switchContext
+ * performs a _function return_ the value in the link register doesn't matter either.
+ * However, the link register will still be saved to the stack in fiber_entrypoint and some
+ * exception handling / stack unwinding code might read it from this stack location and crash.
+ * The exact solution depends on your architecture, but see the ARM implementation for a way
+ * to deal with this issue.
+ *
+ * The ARM implementation is meant to be used as a kind of documented example implementation.
+ * Look there for a concrete example.
+ *
+ * FIXME: fiber_entrypoint might benefit from a @noreturn attribute, but D doesn't have one.
+ */
+
+/**
+ * This class provides a cooperative concurrency mechanism integrated with the
+ * threading and garbage collection functionality. Calling a fiber may be
+ * considered a blocking operation that returns when the fiber yields (via
+ * Fiber.yield()). Execution occurs within the context of the calling thread
+ * so synchronization is not necessary to guarantee memory visibility so long
+ * as the same thread calls the fiber each time. Please note that there is no
+ * requirement that a fiber be bound to one specific thread. Rather, fibers
+ * may be freely passed between threads so long as they are not currently
+ * executing. Like threads, a new fiber thread may be created using either
+ * derivation or composition, as in the following example.
+ *
+ * Warning:
+ * Status registers are not saved by the current implementations. This means
+ * floating point exception status bits (overflow, divide by 0), rounding mode
+ * and similar stuff is set per-thread, not per Fiber!
+ *
+ * Warning:
+ * On ARM FPU registers are not saved if druntime was compiled as ARM_SoftFloat.
+ * If such a build is used on a ARM_SoftFP system which actually has got a FPU
+ * and other libraries are using the FPU registers (other code is compiled
+ * as ARM_SoftFP) this can cause problems. Druntime must be compiled as
+ * ARM_SoftFP in this case.
+ *
+ * Authors: Based on a design by Mikola Lysenko.
+ */
+class FiberBase
+{
+ /**
+ * Initializes a fiber object which is associated with a static
+ * D function.
+ *
+ * Params:
+ * fn = The fiber function.
+ * sz = The stack size for this fiber.
+ * guardPageSize = size of the guard page to trap fiber's stack
+ * overflows. Beware that using this will increase
+ * the number of mmaped regions on platforms using mmap
+ * so an OS-imposed limit may be hit.
+ *
+ * In:
+ * fn must not be null.
+ */
+ this( void function() fn, size_t sz, size_t guardPageSize ) nothrow
+ in
+ {
+ assert( fn );
+ }
+ do
+ {
+ allocStack( sz, guardPageSize );
+ reset( fn );
+ }
+
+
+ /**
+ * Initializes a fiber object which is associated with a dynamic
+ * D function.
+ *
+ * Params:
+ * dg = The fiber function.
+ * sz = The stack size for this fiber.
+ * guardPageSize = size of the guard page to trap fiber's stack
+ * overflows. Beware that using this will increase
+ * the number of mmaped regions on platforms using mmap
+ * so an OS-imposed limit may be hit.
+ *
+ * In:
+ * dg must not be null.
+ */
+ this( void delegate() dg, size_t sz, size_t guardPageSize ) nothrow
+ {
+ allocStack( sz, guardPageSize );
+ reset( cast(void delegate() const) dg );
+ }
+
+
+ /**
+ * Cleans up any remaining resources used by this object.
+ */
+ ~this() nothrow @nogc
+ {
+ // NOTE: A live reference to this object will exist on its associated
+ // stack from the first time its call() method has been called
+ // until its execution completes with State.TERM. Thus, the only
+ // times this dtor should be called are either if the fiber has
+ // terminated (and therefore has no active stack) or if the user
+ // explicitly deletes this object. The latter case is an error
+ // but is not easily tested for, since State.HOLD may imply that
+ // the fiber was just created but has never been run. There is
+ // not a compelling case to create a State.INIT just to offer a
+ // means of ensuring the user isn't violating this object's
+ // contract, so for now this requirement will be enforced by
+ // documentation only.
+ freeStack();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // General Actions
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Transfers execution to this fiber object. The calling context will be
+ * suspended until the fiber calls Fiber.yield() or until it terminates
+ * via an unhandled exception.
+ *
+ * Params:
+ * rethrow = Rethrow any unhandled exception which may have caused this
+ * fiber to terminate.
+ *
+ * In:
+ * This fiber must be in state HOLD.
+ *
+ * Throws:
+ * Any exception not handled by the joined thread.
+ *
+ * Returns:
+ * Any exception not handled by this fiber if rethrow = false, null
+ * otherwise.
+ */
+ // Not marked with any attributes, even though `nothrow @nogc` works
+ // because it calls arbitrary user code. Most of the implementation
+ // is already `@nogc nothrow`, but in order for `Fiber.call` to
+ // propagate the attributes of the user's function, the Fiber
+ // class needs to be templated.
+ final Throwable call( Rethrow rethrow = Rethrow.yes )
+ {
+ return rethrow ? call!(Rethrow.yes)() : call!(Rethrow.no);
+ }
+
+ /// ditto
+ final Throwable call( Rethrow rethrow )()
+ {
+ callImpl();
+ if ( m_unhandled )
+ {
+ Throwable t = m_unhandled;
+ m_unhandled = null;
+ static if ( rethrow )
+ throw t;
+ else
+ return t;
+ }
+ return null;
+ }
+
+ private void callImpl() nothrow @nogc
+ in
+ {
+ assert( m_state == State.HOLD );
+ }
+ do
+ {
+ FiberBase cur = getThis();
+
+ static if ( __traits( compiles, ucontext_t ) )
+ m_ucur = cur ? &cur.m_utxt : &Fiber.sm_utxt;
+
+ setThis( this );
+ this.switchIn();
+ setThis( cur );
+
+ static if ( __traits( compiles, ucontext_t ) )
+ m_ucur = null;
+
+ // NOTE: If the fiber has terminated then the stack pointers must be
+ // reset. This ensures that the stack for this fiber is not
+ // scanned if the fiber has terminated. This is necessary to
+ // prevent any references lingering on the stack from delaying
+ // the collection of otherwise dead objects. The most notable
+ // being the current object, which is referenced at the top of
+ // fiber_entryPoint.
+ if ( m_state == State.TERM )
+ {
+ m_ctxt.tstack = m_ctxt.bstack;
+ }
+ }
+
+ /// Flag to control rethrow behavior of $(D $(LREF call))
+ enum Rethrow : bool { no, yes }
+
+ /**
+ * Resets this fiber so that it may be re-used, optionally with a
+ * new function/delegate. This routine should only be called for
+ * fibers that have terminated, as doing otherwise could result in
+ * scope-dependent functionality that is not executed.
+ * Stack-based classes, for example, may not be cleaned up
+ * properly if a fiber is reset before it has terminated.
+ *
+ * In:
+ * This fiber must be in state TERM or HOLD.
+ */
+ final void reset() nothrow @nogc
+ in
+ {
+ assert( m_state == State.TERM || m_state == State.HOLD );
+ }
+ do
+ {
+ m_ctxt.tstack = m_ctxt.bstack;
+ m_state = State.HOLD;
+ initStack();
+ m_unhandled = null;
+ }
+
+ /// ditto
+ final void reset( void function() fn ) nothrow @nogc
+ {
+ reset();
+ m_call = fn;
+ }
+
+ /// ditto
+ final void reset( void delegate() dg ) nothrow @nogc
+ {
+ reset();
+ m_call = dg;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // General Properties
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /// A fiber may occupy one of three states: HOLD, EXEC, and TERM.
+ enum State
+ {
+ /** The HOLD state applies to any fiber that is suspended and ready to
+ be called. */
+ HOLD,
+ /** The EXEC state will be set for any fiber that is currently
+ executing. */
+ EXEC,
+ /** The TERM state is set when a fiber terminates. Once a fiber
+ terminates, it must be reset before it may be called again. */
+ TERM
+ }
+
+
+ /**
+ * Gets the current state of this fiber.
+ *
+ * Returns:
+ * The state of this fiber as an enumerated value.
+ */
+ final @property State state() const @safe pure nothrow @nogc
+ {
+ return m_state;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Actions on Calling Fiber
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Forces a context switch to occur away from the calling fiber.
+ */
+ static void yield() nothrow @nogc
+ {
+ FiberBase cur = getThis();
+ assert( cur, "Fiber.yield() called with no active fiber" );
+ assert( cur.m_state == State.EXEC );
+
+ static if ( __traits( compiles, ucontext_t ) )
+ cur.m_ucur = &cur.m_utxt;
+
+ cur.m_state = State.HOLD;
+ cur.switchOut();
+ cur.m_state = State.EXEC;
+ }
+
+
+ /**
+ * Forces a context switch to occur away from the calling fiber and then
+ * throws obj in the calling fiber.
+ *
+ * Params:
+ * t = The object to throw.
+ *
+ * In:
+ * t must not be null.
+ */
+ static void yieldAndThrow( Throwable t ) nothrow @nogc
+ in
+ {
+ assert( t );
+ }
+ do
+ {
+ FiberBase cur = getThis();
+ assert( cur, "Fiber.yield() called with no active fiber" );
+ assert( cur.m_state == State.EXEC );
+
+ static if ( __traits( compiles, ucontext_t ) )
+ cur.m_ucur = &cur.m_utxt;
+
+ cur.m_unhandled = t;
+ cur.m_state = State.HOLD;
+ cur.switchOut();
+ cur.m_state = State.EXEC;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Fiber Accessors
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Provides a reference to the calling fiber or null if no fiber is
+ * currently active.
+ *
+ * Returns:
+ * The fiber object representing the calling fiber or null if no fiber
+ * is currently active within this thread. The result of deleting this object is undefined.
+ */
+ static FiberBase getThis() @safe nothrow @nogc
+ {
+ version (GNU) pragma(inline, false);
+ return sm_this;
+ }
+
+
+private:
+
+ //
+ // Fiber entry point. Invokes the function or delegate passed on
+ // construction (if any).
+ //
+ final void run()
+ {
+ m_call();
+ }
+
+ //
+ // Standard fiber data
+ //
+ Callable m_call;
+ bool m_isRunning;
+ Throwable m_unhandled;
+ State m_state;
+
+
+protected:
+ ///////////////////////////////////////////////////////////////////////////
+ // Stack Management
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Allocate a new stack for this fiber.
+ //
+ abstract void allocStack( size_t sz, size_t guardPageSize ) nothrow;
+
+
+ //
+ // Free this fiber's stack.
+ //
+ abstract void freeStack() nothrow @nogc;
+
+
+ //
+ // Initialize the allocated stack.
+ // Look above the definition of 'class Fiber' for some information about the implementation of this routine
+ //
+ abstract void initStack() nothrow @nogc;
+
+
+ StackContext* m_ctxt;
+ size_t m_size;
+ void* m_pmem;
+
+ static if ( __traits( compiles, ucontext_t ) )
+ {
+ // NOTE: The static ucontext instance is used to represent the context
+ // of the executing thread.
+ static ucontext_t sm_utxt = void;
+ ucontext_t m_utxt = void;
+ package ucontext_t* m_ucur = null;
+ }
+ else static if (GNU_Enable_CET)
+ {
+ // When libphobos was built with --enable-cet, these fields need to
+ // always be present in the Fiber class layout.
+ import core.sys.posix.ucontext;
+ static ucontext_t sm_utxt = void;
+ ucontext_t m_utxt = void;
+ package ucontext_t* m_ucur = null;
+ }
+
+
+private:
+ ///////////////////////////////////////////////////////////////////////////
+ // Storage of Active Fiber
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Sets a thread-local reference to the current fiber object.
+ //
+ static void setThis( FiberBase f ) nothrow @nogc
+ {
+ sm_this = f;
+ }
+
+ static FiberBase sm_this;
+
+
+private:
+ ///////////////////////////////////////////////////////////////////////////
+ // Context Switching
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Switches into the stack held by this fiber.
+ //
+ final void switchIn() nothrow @nogc
+ {
+ ThreadBase tobj = ThreadBase.getThis();
+ void** oldp = &tobj.m_curr.tstack;
+ void* newp = m_ctxt.tstack;
+
+ // NOTE: The order of operations here is very important. The current
+ // stack top must be stored before m_lock is set, and pushContext
+ // must not be called until after m_lock is set. This process
+ // is intended to prevent a race condition with the suspend
+ // mechanism used for garbage collection. If it is not followed,
+ // a badly timed collection could cause the GC to scan from the
+ // bottom of one stack to the top of another, or to miss scanning
+ // a stack that still contains valid data. The old stack pointer
+ // oldp will be set again before the context switch to guarantee
+ // that it points to exactly the correct stack location so the
+ // successive pop operations will succeed.
+ *oldp = getStackTop();
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, true);
+ tobj.pushContext( m_ctxt );
+
+ fiber_switchContext( oldp, newp );
+
+ // NOTE: As above, these operations must be performed in a strict order
+ // to prevent Bad Things from happening.
+ tobj.popContext();
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
+ tobj.m_curr.tstack = tobj.m_curr.bstack;
+ }
+
+
+ //
+ // Switches out of the current stack and into the enclosing stack.
+ //
+ final void switchOut() nothrow @nogc
+ {
+ ThreadBase tobj = ThreadBase.getThis();
+ void** oldp = &m_ctxt.tstack;
+ void* newp = tobj.m_curr.within.tstack;
+
+ // NOTE: The order of operations here is very important. The current
+ // stack top must be stored before m_lock is set, and pushContext
+ // must not be called until after m_lock is set. This process
+ // is intended to prevent a race condition with the suspend
+ // mechanism used for garbage collection. If it is not followed,
+ // a badly timed collection could cause the GC to scan from the
+ // bottom of one stack to the top of another, or to miss scanning
+ // a stack that still contains valid data. The old stack pointer
+ // oldp will be set again before the context switch to guarantee
+ // that it points to exactly the correct stack location so the
+ // successive pop operations will succeed.
+ *oldp = getStackTop();
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, true);
+
+ fiber_switchContext( oldp, newp );
+
+ // NOTE: As above, these operations must be performed in a strict order
+ // to prevent Bad Things from happening.
+ // NOTE: If use of this fiber is multiplexed across threads, the thread
+ // executing here may be different from the one above, so get the
+ // current thread handle before unlocking, etc.
+ tobj = ThreadBase.getThis();
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
+ tobj.m_curr.tstack = tobj.m_curr.bstack;
+ }
+}
+
+///
+unittest {
+ int counter;
+
+ class DerivedFiber : Fiber
+ {
+ this()
+ {
+ super( &run );
+ }
+
+ private :
+ void run()
+ {
+ counter += 2;
+ }
+ }
+
+ void fiberFunc()
+ {
+ counter += 4;
+ Fiber.yield();
+ counter += 8;
+ }
+
+ // create instances of each type
+ Fiber derived = new DerivedFiber();
+ Fiber composed = new Fiber( &fiberFunc );
+
+ assert( counter == 0 );
+
+ derived.call();
+ assert( counter == 2, "Derived fiber increment." );
+
+ composed.call();
+ assert( counter == 6, "First composed fiber increment." );
+
+ counter += 16;
+ assert( counter == 22, "Calling context increment." );
+
+ composed.call();
+ assert( counter == 30, "Second composed fiber increment." );
+
+ // since each fiber has run to completion, each should have state TERM
+ assert( derived.state == Fiber.State.TERM );
+ assert( composed.state == Fiber.State.TERM );
+}
+
+version (unittest)
+{
+ import core.thread.fiber: Fiber;
+}
+
+version (CoreUnittest)
+{
+ class TestFiber : Fiber
+ {
+ this()
+ {
+ super(&run);
+ }
+
+ void run()
+ {
+ foreach (i; 0 .. 1000)
+ {
+ sum += i;
+ Fiber.yield();
+ }
+ }
+
+ enum expSum = 1000 * 999 / 2;
+ size_t sum;
+ }
+
+ void runTen()
+ {
+ TestFiber[10] fibs;
+ foreach (ref fib; fibs)
+ fib = new TestFiber();
+
+ bool cont;
+ do {
+ cont = false;
+ foreach (fib; fibs) {
+ if (fib.state == Fiber.State.HOLD)
+ {
+ fib.call();
+ cont |= fib.state != Fiber.State.TERM;
+ }
+ }
+ } while (cont);
+
+ foreach (fib; fibs)
+ {
+ assert(fib.sum == TestFiber.expSum);
+ }
+ }
+}
+
+
+// Single thread running separate fibers
+unittest
+{
+ runTen();
+}
+
+
+// Multiple threads running separate fibers
+unittest
+{
+ auto group = new ThreadGroup();
+ foreach (_; 0 .. 4)
+ {
+ group.create(&runTen);
+ }
+ group.joinAll();
+}
+
+
+// Multiple threads running shared fibers
+version (PPC) version = UnsafeFiberMigration;
+version (PPC64) version = UnsafeFiberMigration;
+version (OSX)
+{
+ version (X86) version = UnsafeFiberMigration;
+ version (X86_64) version = UnsafeFiberMigration;
+ version (AArch64) version = UnsafeFiberMigration;
+}
+
+version (UnsafeFiberMigration)
+{
+ // XBUG: core.thread fibers are supposed to be safe to migrate across
+ // threads, however, there is a problem: GCC always assumes that the
+ // address of thread-local variables don't change while on a given stack.
+ // In consequence, migrating fibers between threads currently is an unsafe
+ // thing to do, and will break on some targets (possibly PR26461).
+}
+else
+{
+ version = FiberMigrationUnittest;
+}
+
+version (FiberMigrationUnittest)
+unittest
+{
+ shared bool[10] locks;
+ TestFiber[10] fibs;
+
+ void runShared()
+ {
+ bool cont;
+ do {
+ cont = false;
+ foreach (idx; 0 .. 10)
+ {
+ if (cas(&locks[idx], false, true))
+ {
+ if (fibs[idx].state == Fiber.State.HOLD)
+ {
+ fibs[idx].call();
+ cont |= fibs[idx].state != Fiber.State.TERM;
+ }
+ locks[idx] = false;
+ }
+ else
+ {
+ cont = true;
+ }
+ }
+ } while (cont);
+ }
+
+ foreach (ref fib; fibs)
+ {
+ fib = new TestFiber();
+ }
+
+ auto group = new ThreadGroup();
+ foreach (_; 0 .. 4)
+ {
+ group.create(&runShared);
+ }
+ group.joinAll();
+
+ foreach (fib; fibs)
+ {
+ assert(fib.sum == TestFiber.expSum);
+ }
+}
+
+
+// Test exception handling inside fibers.
+unittest
+{
+ enum MSG = "Test message.";
+ string caughtMsg;
+ (new Fiber({
+ try
+ {
+ throw new Exception(MSG);
+ }
+ catch (Exception e)
+ {
+ caughtMsg = e.msg;
+ }
+ })).call();
+ assert(caughtMsg == MSG);
+}
+
+
+unittest
+{
+ int x = 0;
+
+ (new Fiber({
+ x++;
+ })).call();
+ assert( x == 1 );
+}
+
+nothrow unittest
+{
+ new Fiber({}).call!(Fiber.Rethrow.no)();
+}
+
+unittest
+{
+ new Fiber({}).call(Fiber.Rethrow.yes);
+ new Fiber({}).call(Fiber.Rethrow.no);
+}
+
+unittest
+{
+ enum MSG = "Test message.";
+
+ try
+ {
+ (new Fiber(function() {
+ throw new Exception( MSG );
+ })).call();
+ assert( false, "Expected rethrown exception." );
+ }
+ catch ( Throwable t )
+ {
+ assert( t.msg == MSG );
+ }
+}
+
+// Test exception chaining when switching contexts in finally blocks.
+unittest
+{
+ static void throwAndYield(string msg) {
+ try {
+ throw new Exception(msg);
+ } finally {
+ Fiber.yield();
+ }
+ }
+
+ static void fiber(string name) {
+ try {
+ try {
+ throwAndYield(name ~ ".1");
+ } finally {
+ throwAndYield(name ~ ".2");
+ }
+ } catch (Exception e) {
+ assert(e.msg == name ~ ".1");
+ assert(e.next);
+ assert(e.next.msg == name ~ ".2");
+ assert(!e.next.next);
+ }
+ }
+
+ auto first = new Fiber(() => fiber("first"));
+ auto second = new Fiber(() => fiber("second"));
+ first.call();
+ second.call();
+ first.call();
+ second.call();
+ first.call();
+ second.call();
+ assert(first.state == Fiber.State.TERM);
+ assert(second.state == Fiber.State.TERM);
+}
+
+// Test Fiber resetting
+unittest
+{
+ static string method;
+
+ static void foo()
+ {
+ method = "foo";
+ }
+
+ void bar()
+ {
+ method = "bar";
+ }
+
+ static void expect(Fiber fib, string s)
+ {
+ assert(fib.state == Fiber.State.HOLD);
+ fib.call();
+ assert(fib.state == Fiber.State.TERM);
+ assert(method == s); method = null;
+ }
+ auto fib = new Fiber(&foo);
+ expect(fib, "foo");
+
+ fib.reset();
+ expect(fib, "foo");
+
+ fib.reset(&foo);
+ expect(fib, "foo");
+
+ fib.reset(&bar);
+ expect(fib, "bar");
+
+ fib.reset(function void(){method = "function";});
+ expect(fib, "function");
+
+ fib.reset(delegate void(){method = "delegate";});
+ expect(fib, "delegate");
+}
+
+// Test unsafe reset in hold state
+unittest
+{
+ auto fib = new Fiber(function {ubyte[2048] buf = void; Fiber.yield();}, 4096);
+ foreach (_; 0 .. 10)
+ {
+ fib.call();
+ assert(fib.state == Fiber.State.HOLD);
+ fib.reset();
+ }
+}
+
+// stress testing GC stack scanning
+unittest
+{
+ import core.memory;
+ import core.thread.osthread : Thread;
+ import core.time : dur;
+
+ static void unreferencedThreadObject()
+ {
+ static void sleep() { Thread.sleep(dur!"msecs"(100)); }
+ auto thread = new Thread(&sleep).start();
+ }
+ unreferencedThreadObject();
+ GC.collect();
+
+ static class Foo
+ {
+ this(int value)
+ {
+ _value = value;
+ }
+
+ int bar()
+ {
+ return _value;
+ }
+
+ int _value;
+ }
+
+ static void collect()
+ {
+ auto foo = new Foo(2);
+ assert(foo.bar() == 2);
+ GC.collect();
+ Fiber.yield();
+ GC.collect();
+ assert(foo.bar() == 2);
+ }
+
+ auto fiber = new Fiber(&collect);
+
+ fiber.call();
+ GC.collect();
+ fiber.call();
+
+ // thread reference
+ auto foo = new Foo(2);
+
+ void collect2()
+ {
+ assert(foo.bar() == 2);
+ GC.collect();
+ Fiber.yield();
+ GC.collect();
+ assert(foo.bar() == 2);
+ }
+
+ fiber = new Fiber(&collect2);
+
+ fiber.call();
+ GC.collect();
+ fiber.call();
+
+ static void recurse(size_t cnt)
+ {
+ --cnt;
+ Fiber.yield();
+ if (cnt)
+ {
+ auto fib = new Fiber(() { recurse(cnt); });
+ fib.call();
+ GC.collect();
+ fib.call();
+ }
+ }
+ fiber = new Fiber(() { recurse(20); });
+ fiber.call();
+}
diff --git a/libphobos/libdruntime/core/thread/fiber.d b/libphobos/libdruntime/core/thread/fiber/package.d
index e02733bd970..d10a25d683c 100644
--- a/libphobos/libdruntime/core/thread/fiber.d
+++ b/libphobos/libdruntime/core/thread/fiber/package.d
@@ -1,12 +1,12 @@
/**
- * The fiber module provides OS-indepedent lightweight threads aka fibers.
+ * The fiber module provides lightweight threads aka fibers.
*
* Copyright: Copyright Sean Kelly 2005 - 2012.
* License: Distributed under the
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
- * Source: $(DRUNTIMESRC core/thread/fiber.d)
+ * Source: $(DRUNTIMESRC core/thread/fiber/package.d)
*/
/* NOTE: This file has been patched from the original DMD distribution to
@@ -14,10 +14,11 @@
*/
module core.thread.fiber;
+import core.thread.context;
+import core.thread.fiber.base : fiber_entryPoint, FiberBase;
import core.thread.threadbase;
import core.thread.threadgroup;
import core.thread.types;
-import core.thread.context;
import core.memory : pageSize;
@@ -28,7 +29,6 @@ import core.memory : pageSize;
version (GNU)
{
import gcc.builtins;
- import gcc.config;
version (GNU_StackGrowsDown)
version = StackGrowsDown;
}
@@ -40,12 +40,12 @@ else
version (Windows)
{
- import core.stdc.stdlib : malloc, free;
+ import core.stdc.stdlib : free, malloc;
import core.sys.windows.winbase;
import core.sys.windows.winnt;
}
-private
+package
{
version (D_InlineAsm_X86)
{
@@ -208,7 +208,7 @@ private
// a version identifier. Please note that this is considered
// an obsolescent feature according to the POSIX spec, so a
// custom solution is still preferred.
- import core.sys.posix.ucontext;
+ import core.sys.posix.ucontext : getcontext, makecontext, MINSIGSTKSZ, swapcontext, ucontext_t;
}
}
}
@@ -217,46 +217,20 @@ private
// Fiber Entry Point and Context Switch
///////////////////////////////////////////////////////////////////////////////
-private
+package
{
import core.atomic : atomicStore, cas, MemoryOrder;
import core.exception : onOutOfMemoryError;
import core.stdc.stdlib : abort;
- extern (C) void fiber_entryPoint() nothrow
+ // Look above the definition of 'class Fiber' for some information about the implementation of this routine
+ version (AsmExternal)
{
- Fiber obj = Fiber.getThis();
- assert( obj );
-
- assert( ThreadBase.getThis().m_curr is obj.m_ctxt );
- atomicStore!(MemoryOrder.raw)(*cast(shared)&ThreadBase.getThis().m_lock, false);
- obj.m_ctxt.tstack = obj.m_ctxt.bstack;
- obj.m_state = Fiber.State.EXEC;
-
- try
- {
- obj.run();
- }
- catch ( Throwable t )
- {
- obj.m_unhandled = t;
- }
-
- static if ( __traits( compiles, ucontext_t ) )
- obj.m_ucur = &obj.m_utxt;
-
- obj.m_state = Fiber.State.TERM;
- obj.switchOut();
+ extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc;
+ version (AArch64)
+ extern (C) void fiber_trampoline() nothrow;
}
-
- // Look above the definition of 'class Fiber' for some information about the implementation of this routine
- version (AsmExternal)
- {
- extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc;
- version (AArch64)
- extern (C) void fiber_trampoline() nothrow;
- }
- else
+ else
extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc
{
// NOTE: The data pushed and popped in this routine must match the
@@ -602,7 +576,7 @@ private
*
* Authors: Based on a design by Mikola Lysenko.
*/
-class Fiber
+class Fiber : FiberBase
{
///////////////////////////////////////////////////////////////////////////
// Initialization
@@ -644,14 +618,8 @@ class Fiber
*/
this( void function() fn, size_t sz = pageSize * defaultStackPages,
size_t guardPageSize = pageSize ) nothrow
- in
- {
- assert( fn );
- }
- do
{
- allocStack( sz, guardPageSize );
- reset( fn );
+ super( fn, sz, guardPageSize );
}
@@ -673,238 +641,7 @@ class Fiber
this( void delegate() dg, size_t sz = pageSize * defaultStackPages,
size_t guardPageSize = pageSize ) nothrow
{
- allocStack( sz, guardPageSize );
- reset( cast(void delegate() const) dg );
- }
-
-
- /**
- * Cleans up any remaining resources used by this object.
- */
- ~this() nothrow @nogc
- {
- // NOTE: A live reference to this object will exist on its associated
- // stack from the first time its call() method has been called
- // until its execution completes with State.TERM. Thus, the only
- // times this dtor should be called are either if the fiber has
- // terminated (and therefore has no active stack) or if the user
- // explicitly deletes this object. The latter case is an error
- // but is not easily tested for, since State.HOLD may imply that
- // the fiber was just created but has never been run. There is
- // not a compelling case to create a State.INIT just to offer a
- // means of ensuring the user isn't violating this object's
- // contract, so for now this requirement will be enforced by
- // documentation only.
- freeStack();
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // General Actions
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Transfers execution to this fiber object. The calling context will be
- * suspended until the fiber calls Fiber.yield() or until it terminates
- * via an unhandled exception.
- *
- * Params:
- * rethrow = Rethrow any unhandled exception which may have caused this
- * fiber to terminate.
- *
- * In:
- * This fiber must be in state HOLD.
- *
- * Throws:
- * Any exception not handled by the joined thread.
- *
- * Returns:
- * Any exception not handled by this fiber if rethrow = false, null
- * otherwise.
- */
- // Not marked with any attributes, even though `nothrow @nogc` works
- // because it calls arbitrary user code. Most of the implementation
- // is already `@nogc nothrow`, but in order for `Fiber.call` to
- // propagate the attributes of the user's function, the Fiber
- // class needs to be templated.
- final Throwable call( Rethrow rethrow = Rethrow.yes )
- {
- return rethrow ? call!(Rethrow.yes)() : call!(Rethrow.no);
- }
-
- /// ditto
- final Throwable call( Rethrow rethrow )()
- {
- callImpl();
- if ( m_unhandled )
- {
- Throwable t = m_unhandled;
- m_unhandled = null;
- static if ( rethrow )
- throw t;
- else
- return t;
- }
- return null;
- }
-
- private void callImpl() nothrow @nogc
- in
- {
- assert( m_state == State.HOLD );
- }
- do
- {
- Fiber cur = getThis();
-
- static if ( __traits( compiles, ucontext_t ) )
- m_ucur = cur ? &cur.m_utxt : &Fiber.sm_utxt;
-
- setThis( this );
- this.switchIn();
- setThis( cur );
-
- static if ( __traits( compiles, ucontext_t ) )
- m_ucur = null;
-
- // NOTE: If the fiber has terminated then the stack pointers must be
- // reset. This ensures that the stack for this fiber is not
- // scanned if the fiber has terminated. This is necessary to
- // prevent any references lingering on the stack from delaying
- // the collection of otherwise dead objects. The most notable
- // being the current object, which is referenced at the top of
- // fiber_entryPoint.
- if ( m_state == State.TERM )
- {
- m_ctxt.tstack = m_ctxt.bstack;
- }
- }
-
- /// Flag to control rethrow behavior of $(D $(LREF call))
- enum Rethrow : bool { no, yes }
-
- /**
- * Resets this fiber so that it may be re-used, optionally with a
- * new function/delegate. This routine should only be called for
- * fibers that have terminated, as doing otherwise could result in
- * scope-dependent functionality that is not executed.
- * Stack-based classes, for example, may not be cleaned up
- * properly if a fiber is reset before it has terminated.
- *
- * In:
- * This fiber must be in state TERM or HOLD.
- */
- final void reset() nothrow @nogc
- in
- {
- assert( m_state == State.TERM || m_state == State.HOLD );
- }
- do
- {
- m_ctxt.tstack = m_ctxt.bstack;
- m_state = State.HOLD;
- initStack();
- m_unhandled = null;
- }
-
- /// ditto
- final void reset( void function() fn ) nothrow @nogc
- {
- reset();
- m_call = fn;
- }
-
- /// ditto
- final void reset( void delegate() dg ) nothrow @nogc
- {
- reset();
- m_call = dg;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // General Properties
- ///////////////////////////////////////////////////////////////////////////
-
-
- /// A fiber may occupy one of three states: HOLD, EXEC, and TERM.
- enum State
- {
- /** The HOLD state applies to any fiber that is suspended and ready to
- be called. */
- HOLD,
- /** The EXEC state will be set for any fiber that is currently
- executing. */
- EXEC,
- /** The TERM state is set when a fiber terminates. Once a fiber
- terminates, it must be reset before it may be called again. */
- TERM
- }
-
-
- /**
- * Gets the current state of this fiber.
- *
- * Returns:
- * The state of this fiber as an enumerated value.
- */
- final @property State state() const @safe pure nothrow @nogc
- {
- return m_state;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Actions on Calling Fiber
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Forces a context switch to occur away from the calling fiber.
- */
- static void yield() nothrow @nogc
- {
- Fiber cur = getThis();
- assert( cur, "Fiber.yield() called with no active fiber" );
- assert( cur.m_state == State.EXEC );
-
- static if ( __traits( compiles, ucontext_t ) )
- cur.m_ucur = &cur.m_utxt;
-
- cur.m_state = State.HOLD;
- cur.switchOut();
- cur.m_state = State.EXEC;
- }
-
-
- /**
- * Forces a context switch to occur away from the calling fiber and then
- * throws obj in the calling fiber.
- *
- * Params:
- * t = The object to throw.
- *
- * In:
- * t must not be null.
- */
- static void yieldAndThrow( Throwable t ) nothrow @nogc
- in
- {
- assert( t );
- }
- do
- {
- Fiber cur = getThis();
- assert( cur, "Fiber.yield() called with no active fiber" );
- assert( cur.m_state == State.EXEC );
-
- static if ( __traits( compiles, ucontext_t ) )
- cur.m_ucur = &cur.m_utxt;
-
- cur.m_unhandled = t;
- cur.m_state = State.HOLD;
- cur.switchOut();
- cur.m_state = State.EXEC;
+ super( dg, sz, guardPageSize );
}
@@ -923,8 +660,7 @@ class Fiber
*/
static Fiber getThis() @safe nothrow @nogc
{
- version (GNU) pragma(inline, false);
- return sm_this;
+ return cast(Fiber) FiberBase.getThis();
}
@@ -945,27 +681,7 @@ class Fiber
}
}
-private:
-
- //
- // Fiber entry point. Invokes the function or delegate passed on
- // construction (if any).
- //
- final void run()
- {
- m_call();
- }
-
- //
- // Standard fiber data
- //
- Callable m_call;
- bool m_isRunning;
- Throwable m_unhandled;
- State m_state;
-
-
-private:
+protected:
///////////////////////////////////////////////////////////////////////////
// Stack Management
///////////////////////////////////////////////////////////////////////////
@@ -974,7 +690,7 @@ private:
//
// Allocate a new stack for this fiber.
//
- final void allocStack( size_t sz, size_t guardPageSize ) nothrow
+ final override void allocStack( size_t sz, size_t guardPageSize ) nothrow
in
{
assert( !m_pmem && !m_ctxt );
@@ -1043,7 +759,9 @@ private:
}
else
{
- version (Posix) import core.sys.posix.sys.mman; // mmap, MAP_ANON
+ version (Posix) import core.sys.posix.sys.mman : MAP_ANON, MAP_FAILED, MAP_PRIVATE, mmap,
+ mprotect, PROT_NONE, PROT_READ, PROT_WRITE;
+ version (OpenBSD) import core.sys.posix.sys.mman : MAP_STACK;
static if ( __traits( compiles, ucontext_t ) )
{
@@ -1121,7 +839,7 @@ private:
//
// Free this fiber's stack.
//
- final void freeStack() nothrow @nogc
+ final override void freeStack() nothrow @nogc
in(m_pmem)
in(m_ctxt)
{
@@ -1137,7 +855,7 @@ private:
}
else
{
- import core.sys.posix.sys.mman; // munmap
+ import core.sys.posix.sys.mman : mmap, munmap;
static if ( __traits( compiles, mmap ) )
{
@@ -1157,7 +875,7 @@ private:
// Initialize the allocated stack.
// Look above the definition of 'class Fiber' for some information about the implementation of this routine
//
- final void initStack() nothrow @nogc
+ final override void initStack() nothrow @nogc
in
{
assert( m_ctxt.tstack && m_ctxt.tstack == m_ctxt.bstack );
@@ -1232,7 +950,7 @@ private:
}
enum sehChainEnd = cast(EXCEPTION_REGISTRATION*) 0xFFFFFFFF;
- __gshared static fp_t finalHandler = null;
+ __gshared fp_t finalHandler = null;
if ( finalHandler is null )
{
static EXCEPTION_REGISTRATION* fs0() nothrow
@@ -1505,7 +1223,7 @@ private:
// Only need to set return address ($r1). Everything else is fine
// zero initialized.
pstack -= size_t.sizeof * 11; // skip past space reserved for $r21-$r31
- push (cast(size_t) &fiber_entryPoint);
+ push(cast(size_t) &fiber_entryPoint);
pstack += size_t.sizeof; // adjust sp (newp) above lr
}
else version (AsmAArch64_Posix)
@@ -1616,537 +1334,6 @@ private:
else
static assert(0, "Not implemented");
}
-
-
- StackContext* m_ctxt;
- size_t m_size;
- void* m_pmem;
-
- static if ( __traits( compiles, ucontext_t ) )
- {
- // NOTE: The static ucontext instance is used to represent the context
- // of the executing thread.
- static ucontext_t sm_utxt = void;
- ucontext_t m_utxt = void;
- ucontext_t* m_ucur = null;
- }
- else static if (GNU_Enable_CET)
- {
- // When libphobos was built with --enable-cet, these fields need to
- // always be present in the Fiber class layout.
- import core.sys.posix.ucontext;
- static ucontext_t sm_utxt = void;
- ucontext_t m_utxt = void;
- ucontext_t* m_ucur = null;
- }
-
-
-private:
- ///////////////////////////////////////////////////////////////////////////
- // Storage of Active Fiber
- ///////////////////////////////////////////////////////////////////////////
-
-
- //
- // Sets a thread-local reference to the current fiber object.
- //
- static void setThis( Fiber f ) nothrow @nogc
- {
- sm_this = f;
- }
-
- static Fiber sm_this;
-
-
-private:
- ///////////////////////////////////////////////////////////////////////////
- // Context Switching
- ///////////////////////////////////////////////////////////////////////////
-
-
- //
- // Switches into the stack held by this fiber.
- //
- final void switchIn() nothrow @nogc
- {
- ThreadBase tobj = ThreadBase.getThis();
- void** oldp = &tobj.m_curr.tstack;
- void* newp = m_ctxt.tstack;
-
- // NOTE: The order of operations here is very important. The current
- // stack top must be stored before m_lock is set, and pushContext
- // must not be called until after m_lock is set. This process
- // is intended to prevent a race condition with the suspend
- // mechanism used for garbage collection. If it is not followed,
- // a badly timed collection could cause the GC to scan from the
- // bottom of one stack to the top of another, or to miss scanning
- // a stack that still contains valid data. The old stack pointer
- // oldp will be set again before the context switch to guarantee
- // that it points to exactly the correct stack location so the
- // successive pop operations will succeed.
- *oldp = getStackTop();
- atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, true);
- tobj.pushContext( m_ctxt );
-
- fiber_switchContext( oldp, newp );
-
- // NOTE: As above, these operations must be performed in a strict order
- // to prevent Bad Things from happening.
- tobj.popContext();
- atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
- tobj.m_curr.tstack = tobj.m_curr.bstack;
- }
-
-
- //
- // Switches out of the current stack and into the enclosing stack.
- //
- final void switchOut() nothrow @nogc
- {
- ThreadBase tobj = ThreadBase.getThis();
- void** oldp = &m_ctxt.tstack;
- void* newp = tobj.m_curr.within.tstack;
-
- // NOTE: The order of operations here is very important. The current
- // stack top must be stored before m_lock is set, and pushContext
- // must not be called until after m_lock is set. This process
- // is intended to prevent a race condition with the suspend
- // mechanism used for garbage collection. If it is not followed,
- // a badly timed collection could cause the GC to scan from the
- // bottom of one stack to the top of another, or to miss scanning
- // a stack that still contains valid data. The old stack pointer
- // oldp will be set again before the context switch to guarantee
- // that it points to exactly the correct stack location so the
- // successive pop operations will succeed.
- *oldp = getStackTop();
- atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, true);
-
- fiber_switchContext( oldp, newp );
-
- // NOTE: As above, these operations must be performed in a strict order
- // to prevent Bad Things from happening.
- // NOTE: If use of this fiber is multiplexed across threads, the thread
- // executing here may be different from the one above, so get the
- // current thread handle before unlocking, etc.
- tobj = ThreadBase.getThis();
- atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
- tobj.m_curr.tstack = tobj.m_curr.bstack;
- }
-}
-
-///
-unittest {
- int counter;
-
- class DerivedFiber : Fiber
- {
- this()
- {
- super( &run );
- }
-
- private :
- void run()
- {
- counter += 2;
- }
- }
-
- void fiberFunc()
- {
- counter += 4;
- Fiber.yield();
- counter += 8;
- }
-
- // create instances of each type
- Fiber derived = new DerivedFiber();
- Fiber composed = new Fiber( &fiberFunc );
-
- assert( counter == 0 );
-
- derived.call();
- assert( counter == 2, "Derived fiber increment." );
-
- composed.call();
- assert( counter == 6, "First composed fiber increment." );
-
- counter += 16;
- assert( counter == 22, "Calling context increment." );
-
- composed.call();
- assert( counter == 30, "Second composed fiber increment." );
-
- // since each fiber has run to completion, each should have state TERM
- assert( derived.state == Fiber.State.TERM );
- assert( composed.state == Fiber.State.TERM );
-}
-
-version (CoreUnittest)
-{
- class TestFiber : Fiber
- {
- this()
- {
- super(&run);
- }
-
- void run()
- {
- foreach (i; 0 .. 1000)
- {
- sum += i;
- Fiber.yield();
- }
- }
-
- enum expSum = 1000 * 999 / 2;
- size_t sum;
- }
-
- void runTen()
- {
- TestFiber[10] fibs;
- foreach (ref fib; fibs)
- fib = new TestFiber();
-
- bool cont;
- do {
- cont = false;
- foreach (fib; fibs) {
- if (fib.state == Fiber.State.HOLD)
- {
- fib.call();
- cont |= fib.state != Fiber.State.TERM;
- }
- }
- } while (cont);
-
- foreach (fib; fibs)
- {
- assert(fib.sum == TestFiber.expSum);
- }
- }
-}
-
-
-// Single thread running separate fibers
-unittest
-{
- runTen();
-}
-
-
-// Multiple threads running separate fibers
-unittest
-{
- auto group = new ThreadGroup();
- foreach (_; 0 .. 4)
- {
- group.create(&runTen);
- }
- group.joinAll();
-}
-
-
-// Multiple threads running shared fibers
-version (PPC) version = UnsafeFiberMigration;
-version (PPC64) version = UnsafeFiberMigration;
-version (OSX)
-{
- version (X86) version = UnsafeFiberMigration;
- version (X86_64) version = UnsafeFiberMigration;
- version (AArch64) version = UnsafeFiberMigration;
-}
-
-version (UnsafeFiberMigration)
-{
- // XBUG: core.thread fibers are supposed to be safe to migrate across
- // threads, however, there is a problem: GCC always assumes that the
- // address of thread-local variables don't change while on a given stack.
- // In consequence, migrating fibers between threads currently is an unsafe
- // thing to do, and will break on some targets (possibly PR26461).
-}
-else
-{
- version = FiberMigrationUnittest;
-}
-
-version (FiberMigrationUnittest)
-unittest
-{
- shared bool[10] locks;
- TestFiber[10] fibs;
-
- void runShared()
- {
- bool cont;
- do {
- cont = false;
- foreach (idx; 0 .. 10)
- {
- if (cas(&locks[idx], false, true))
- {
- if (fibs[idx].state == Fiber.State.HOLD)
- {
- fibs[idx].call();
- cont |= fibs[idx].state != Fiber.State.TERM;
- }
- locks[idx] = false;
- }
- else
- {
- cont = true;
- }
- }
- } while (cont);
- }
-
- foreach (ref fib; fibs)
- {
- fib = new TestFiber();
- }
-
- auto group = new ThreadGroup();
- foreach (_; 0 .. 4)
- {
- group.create(&runShared);
- }
- group.joinAll();
-
- foreach (fib; fibs)
- {
- assert(fib.sum == TestFiber.expSum);
- }
-}
-
-
-// Test exception handling inside fibers.
-unittest
-{
- enum MSG = "Test message.";
- string caughtMsg;
- (new Fiber({
- try
- {
- throw new Exception(MSG);
- }
- catch (Exception e)
- {
- caughtMsg = e.msg;
- }
- })).call();
- assert(caughtMsg == MSG);
-}
-
-
-unittest
-{
- int x = 0;
-
- (new Fiber({
- x++;
- })).call();
- assert( x == 1 );
-}
-
-nothrow unittest
-{
- new Fiber({}).call!(Fiber.Rethrow.no)();
-}
-
-unittest
-{
- new Fiber({}).call(Fiber.Rethrow.yes);
- new Fiber({}).call(Fiber.Rethrow.no);
-}
-
-unittest
-{
- enum MSG = "Test message.";
-
- try
- {
- (new Fiber(function() {
- throw new Exception( MSG );
- })).call();
- assert( false, "Expected rethrown exception." );
- }
- catch ( Throwable t )
- {
- assert( t.msg == MSG );
- }
-}
-
-// Test exception chaining when switching contexts in finally blocks.
-unittest
-{
- static void throwAndYield(string msg) {
- try {
- throw new Exception(msg);
- } finally {
- Fiber.yield();
- }
- }
-
- static void fiber(string name) {
- try {
- try {
- throwAndYield(name ~ ".1");
- } finally {
- throwAndYield(name ~ ".2");
- }
- } catch (Exception e) {
- assert(e.msg == name ~ ".1");
- assert(e.next);
- assert(e.next.msg == name ~ ".2");
- assert(!e.next.next);
- }
- }
-
- auto first = new Fiber(() => fiber("first"));
- auto second = new Fiber(() => fiber("second"));
- first.call();
- second.call();
- first.call();
- second.call();
- first.call();
- second.call();
- assert(first.state == Fiber.State.TERM);
- assert(second.state == Fiber.State.TERM);
-}
-
-// Test Fiber resetting
-unittest
-{
- static string method;
-
- static void foo()
- {
- method = "foo";
- }
-
- void bar()
- {
- method = "bar";
- }
-
- static void expect(Fiber fib, string s)
- {
- assert(fib.state == Fiber.State.HOLD);
- fib.call();
- assert(fib.state == Fiber.State.TERM);
- assert(method == s); method = null;
- }
- auto fib = new Fiber(&foo);
- expect(fib, "foo");
-
- fib.reset();
- expect(fib, "foo");
-
- fib.reset(&foo);
- expect(fib, "foo");
-
- fib.reset(&bar);
- expect(fib, "bar");
-
- fib.reset(function void(){method = "function";});
- expect(fib, "function");
-
- fib.reset(delegate void(){method = "delegate";});
- expect(fib, "delegate");
-}
-
-// Test unsafe reset in hold state
-unittest
-{
- auto fib = new Fiber(function {ubyte[2048] buf = void; Fiber.yield();}, 4096);
- foreach (_; 0 .. 10)
- {
- fib.call();
- assert(fib.state == Fiber.State.HOLD);
- fib.reset();
- }
-}
-
-// stress testing GC stack scanning
-unittest
-{
- import core.memory;
- import core.thread.osthread : Thread;
- import core.time : dur;
-
- static void unreferencedThreadObject()
- {
- static void sleep() { Thread.sleep(dur!"msecs"(100)); }
- auto thread = new Thread(&sleep).start();
- }
- unreferencedThreadObject();
- GC.collect();
-
- static class Foo
- {
- this(int value)
- {
- _value = value;
- }
-
- int bar()
- {
- return _value;
- }
-
- int _value;
- }
-
- static void collect()
- {
- auto foo = new Foo(2);
- assert(foo.bar() == 2);
- GC.collect();
- Fiber.yield();
- GC.collect();
- assert(foo.bar() == 2);
- }
-
- auto fiber = new Fiber(&collect);
-
- fiber.call();
- GC.collect();
- fiber.call();
-
- // thread reference
- auto foo = new Foo(2);
-
- void collect2()
- {
- assert(foo.bar() == 2);
- GC.collect();
- Fiber.yield();
- GC.collect();
- assert(foo.bar() == 2);
- }
-
- fiber = new Fiber(&collect2);
-
- fiber.call();
- GC.collect();
- fiber.call();
-
- static void recurse(size_t cnt)
- {
- --cnt;
- Fiber.yield();
- if (cnt)
- {
- auto fib = new Fiber(() { recurse(cnt); });
- fib.call();
- GC.collect();
- fib.call();
- }
- }
- fiber = new Fiber(() { recurse(20); });
- fiber.call();
}
diff --git a/libphobos/libdruntime/core/thread/osthread.d b/libphobos/libdruntime/core/thread/osthread.d
index 2379f7925e4..e5f0cadbbf2 100644
--- a/libphobos/libdruntime/core/thread/osthread.d
+++ b/libphobos/libdruntime/core/thread/osthread.d
@@ -15,15 +15,14 @@
*/
module core.thread.osthread;
-import core.thread.threadbase;
-import core.thread.context;
-import core.thread.types;
import core.atomic;
-import core.memory : GC, pageSize;
-import core.time;
import core.exception : onOutOfMemoryError;
import core.internal.traits : externDFunc;
-
+import core.memory : GC, pageSize;
+import core.thread.context;
+import core.thread.threadbase;
+import core.thread.types;
+import core.time;
///////////////////////////////////////////////////////////////////////////////
// Platform Detection and Memory Allocation
@@ -118,7 +117,7 @@ version (Posix)
// a version identifier. Please note that this is considered
// an obsolescent feature according to the POSIX spec, so a
// custom solution is still preferred.
- import core.sys.posix.ucontext;
+ static import core.sys.posix.ucontext;
}
}
@@ -141,25 +140,34 @@ version (Windows)
}
else version (Posix)
{
+ static import core.sys.posix.pthread;
+ static import core.sys.posix.signal;
import core.stdc.errno;
- import core.sys.posix.semaphore;
- import core.sys.posix.stdlib; // for malloc, valloc, free, atexit
- import core.sys.posix.pthread;
- import core.sys.posix.signal;
- import core.sys.posix.time;
+ import core.sys.posix.pthread : pthread_atfork, pthread_attr_destroy, pthread_attr_getstack, pthread_attr_init,
+ pthread_attr_setstacksize, pthread_create, pthread_detach, pthread_getschedparam, pthread_join, pthread_self,
+ pthread_setschedparam, sched_get_priority_max, sched_get_priority_min, sched_param, sched_yield;
+ import core.sys.posix.semaphore : sem_init, sem_post, sem_t, sem_wait;
+ import core.sys.posix.signal : pthread_kill, sigaction, sigaction_t, sigdelset, sigfillset, sigset_t, sigsuspend,
+ SIGUSR1, stack_t;
+ import core.sys.posix.stdlib : free, malloc, realloc;
+ import core.sys.posix.sys.types : pthread_attr_t, pthread_key_t, pthread_t;
+ import core.sys.posix.time : nanosleep, timespec;
version (Darwin)
{
- import core.sys.darwin.mach.thread_act;
+ import core.sys.darwin.mach.kern_return : KERN_SUCCESS;
+ import core.sys.darwin.mach.port : mach_port_t;
+ import core.sys.darwin.mach.thread_act : mach_msg_type_number_t, thread_get_state, thread_resume,
+ thread_suspend, x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT, x86_thread_state64_t;
import core.sys.darwin.pthread : pthread_mach_thread_np;
}
}
version (Solaris)
{
- import core.sys.solaris.sys.priocntl;
- import core.sys.solaris.sys.types;
import core.sys.posix.sys.wait : idtype_t;
+ import core.sys.solaris.sys.priocntl : PC_CLNULL, PC_GETCLINFO, PC_GETPARMS, PC_SETPARMS, pcinfo_t, pcparms_t, priocntl;
+ import core.sys.solaris.sys.types : P_MYID, pri_t;
}
version (GNU)
@@ -869,8 +877,10 @@ class Thread : ThreadBase
}
else version (Posix)
{
- static if (__traits(compiles, pthread_setschedprio))
+ static if (__traits(compiles, core.sys.posix.pthread.pthread_setschedprio))
{
+ import core.sys.posix.pthread : pthread_setschedprio;
+
if (auto err = pthread_setschedprio(m_addr, val))
{
// ignore error if thread is not running => Bugzilla 8960
@@ -1528,13 +1538,11 @@ private extern (D) void scanWindowsOnly(scope ScanAllThreadsTypeFn scan, ThreadB
*/
version (Posix)
{
- import core.sys.posix.unistd;
-
- alias getpid = core.sys.posix.unistd.getpid;
+ alias getpid = imported!"core.sys.posix.unistd".getpid;
}
else version (Windows)
{
- alias getpid = core.sys.windows.winbase.GetCurrentProcessId;
+ alias getpid = imported!"core.sys.windows.winbase".GetCurrentProcessId;
}
extern (C) @nogc nothrow
@@ -1599,7 +1607,7 @@ private extern(D) void* getStackBottom() nothrow @nogc
}
else version (Darwin)
{
- import core.sys.darwin.pthread;
+ import core.sys.darwin.pthread : pthread_get_stackaddr_np;
return pthread_get_stackaddr_np(pthread_self());
}
else version (PThread_Getattr_NP)
@@ -2079,6 +2087,10 @@ extern (C) void thread_init() @nogc nothrow
enum SIGRTMIN = SIGUSR1;
enum SIGRTMAX = 32;
}
+ else
+ {
+ import core.sys.posix.signal : SIGRTMAX, SIGRTMIN;
+ }
if ( suspendSignalNumber == 0 )
{
@@ -2102,8 +2114,12 @@ extern (C) void thread_init() @nogc nothrow
// NOTE: SA_RESTART indicates that system calls should restart if they
// are interrupted by a signal, but this is not available on all
// Posix systems, even those that support multithreading.
- static if ( __traits( compiles, SA_RESTART ) )
+ static if (__traits(compiles, core.sys.posix.signal.SA_RESTART))
+ {
+ import core.sys.posix.signal : SA_RESTART;
+
suspend.sa_flags = SA_RESTART;
+ }
suspend.sa_handler = &thread_suspendHandler;
// NOTE: We want to ignore all signals while in this handler, so fill
@@ -2233,19 +2249,6 @@ else version (Posix)
{
private
{
- import core.stdc.errno;
- import core.sys.posix.semaphore;
- import core.sys.posix.stdlib; // for malloc, valloc, free, atexit
- import core.sys.posix.pthread;
- import core.sys.posix.signal;
- import core.sys.posix.time;
-
- version (Darwin)
- {
- import core.sys.darwin.mach.thread_act;
- import core.sys.darwin.pthread : pthread_mach_thread_np;
- }
-
//
// Entry point for POSIX threads
//
@@ -2308,14 +2311,18 @@ else version (Posix)
// implementation actually requires default initialization
// then pthread_cleanup should be restructured to maintain
// the current lack of a link dependency.
- static if ( __traits( compiles, pthread_cleanup ) )
+ static if (__traits(compiles, core.sys.posix.pthread.pthread_cleanup))
{
+ import core.sys.posix.pthread : pthread_cleanup;
+
pthread_cleanup cleanup = void;
cleanup.push( &thread_cleanupHandler, cast(void*) obj );
}
- else static if ( __traits( compiles, pthread_cleanup_push ) )
+ else static if (__traits(compiles, core.sys.posix.pthread.pthread_cleanup_push))
{
- pthread_cleanup_push( &thread_cleanupHandler, cast(void*) obj );
+ import core.sys.posix.pthread : pthread_cleanup_push;
+
+ pthread_cleanup_push(&thread_cleanupHandler, cast(void*) obj);
}
else
{
@@ -2366,12 +2373,14 @@ else version (Posix)
// NOTE: Normal cleanup is handled by scope(exit).
- static if ( __traits( compiles, pthread_cleanup ) )
+ static if (__traits(compiles, core.sys.posix.pthread.pthread_cleanup))
{
cleanup.pop( 0 );
}
- else static if ( __traits( compiles, pthread_cleanup_push ) )
+ else static if (__traits(compiles, core.sys.posix.pthread.pthread_cleanup_push))
{
+ import core.sys.posix.pthread : pthread_cleanup_pop;
+
pthread_cleanup_pop( 0 );
}
@@ -2558,10 +2567,9 @@ private
// Note: if the DLL is never unloaded, process termination kills all threads
// and signals their handles before unconditionally calling DllMain(DLL_PROCESS_DETACH).
- import core.sys.windows.winbase : FreeLibraryAndExitThread, GetModuleHandleExW,
- GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
- import core.sys.windows.windef : HMODULE;
import core.sys.windows.dll : dll_getRefCount;
+ import core.sys.windows.winbase : FreeLibraryAndExitThread, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, GetModuleHandleExW;
+ import core.sys.windows.windef : HMODULE;
version (CRuntime_Microsoft)
extern(C) extern __gshared ubyte msvcUsesUCRT; // from rt/msvc.d
diff --git a/libphobos/libdruntime/core/thread/threadbase.d b/libphobos/libdruntime/core/thread/threadbase.d
index f3854076b0b..93af3b113d8 100644
--- a/libphobos/libdruntime/core/thread/threadbase.d
+++ b/libphobos/libdruntime/core/thread/threadbase.d
@@ -7,7 +7,7 @@
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
- * Source: $(DRUNTIMESRC core/thread/osthread.d)
+ * Source: $(DRUNTIMESRC core/thread/threadbase.d)
*/
/* NOTE: This file has been patched from the original DMD distribution to
diff --git a/libphobos/libdruntime/core/thread/threadgroup.d b/libphobos/libdruntime/core/thread/threadgroup.d
index d00ce05854d..b2ab9313901 100644
--- a/libphobos/libdruntime/core/thread/threadgroup.d
+++ b/libphobos/libdruntime/core/thread/threadgroup.d
@@ -6,7 +6,7 @@
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
- * Source: $(DRUNTIMESRC core/thread/osthread.d)
+ * Source: $(DRUNTIMESRC core/thread/threadgroup.d)
*/
module core.thread.threadgroup;
diff --git a/libphobos/libdruntime/core/thread/types.d b/libphobos/libdruntime/core/thread/types.d
index 998f610c255..4d0b3649ec7 100644
--- a/libphobos/libdruntime/core/thread/types.d
+++ b/libphobos/libdruntime/core/thread/types.d
@@ -6,7 +6,7 @@
* $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
* (See accompanying file LICENSE)
* Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
- * Source: $(DRUNTIMESRC core/thread/osthread.d)
+ * Source: $(DRUNTIMESRC core/thread/types.d)
*/
module core.thread.types;
@@ -20,7 +20,7 @@ version (Windows)
else
version (Posix)
{
- import core.sys.posix.pthread;
+ import core.sys.posix.sys.types : pthread_t;
alias ThreadID = pthread_t;
}
@@ -55,7 +55,7 @@ shared static this()
{
version (Posix)
{
- import core.sys.posix.unistd;
+ import core.sys.posix.unistd : _SC_THREAD_STACK_MIN, sysconf;
PTHREAD_STACK_MIN = cast(size_t)sysconf(_SC_THREAD_STACK_MIN);
}
diff --git a/libphobos/libdruntime/core/time.d b/libphobos/libdruntime/core/time.d
index dc79141efa7..53a0533f25e 100644
--- a/libphobos/libdruntime/core/time.d
+++ b/libphobos/libdruntime/core/time.d
@@ -66,19 +66,9 @@
module core.time;
import core.exception;
-import core.stdc.time;
-import core.stdc.stdio;
import core.internal.string;
-
-version (Windows)
-{
-import core.sys.windows.winbase /+: QueryPerformanceCounter, QueryPerformanceFrequency+/;
-}
-else version (Posix)
-{
-import core.sys.posix.time;
-import core.sys.posix.sys.time;
-}
+import core.stdc.stdio;
+import core.stdc.time;
version (OSX)
version = Darwin;
@@ -89,12 +79,28 @@ else version (TVOS)
else version (WatchOS)
version = Darwin;
+version (Windows)
+{
+ import core.sys.windows.winbase /+: QueryPerformanceCounter, QueryPerformanceFrequency+/;
+}
+else version (Darwin)
+{
+ import core.sys.posix.sys.time : gettimeofday, timeval;
+ import core.sys.posix.time : timespec;
+}
+else version (Posix)
+{
+ import core.sys.posix.sys.time : gettimeofday, timeval;
+ import core.sys.posix.time : clock_getres, clock_gettime, CLOCK_MONOTONIC, timespec;
+}
+
+
//This probably should be moved somewhere else in druntime which
//is Darwin-specific.
version (Darwin)
{
-public import core.sys.darwin.mach.kern_return;
+import core.sys.darwin.mach.kern_return : kern_return_t;
extern(C) nothrow @nogc
{
@@ -3925,7 +3931,14 @@ version (CoreUnittest) const(char)* numToStringz()(long value) @trusted pure not
}
-import core.internal.traits : AliasSeq;
+/+
+ dmd @@@BUG18223@@@
+ A selective import of `AliasSeq` happens to bleed through and causes symbol clashes downstream.
+ +/
+version (none)
+ import core.internal.traits : AliasSeq;
+else
+ import core.internal.traits;
/+ An adjusted copy of std.exception.assertThrown. +/
diff --git a/libphobos/libdruntime/rt/aApply.d b/libphobos/libdruntime/rt/aApply.d
index c59d9dc1234..b8e575d20fe 100644
--- a/libphobos/libdruntime/rt/aApply.d
+++ b/libphobos/libdruntime/rt/aApply.d
@@ -10,6 +10,8 @@ module rt.aApply;
import core.internal.utf : decode, toUTF8;
+debug (apply) import core.stdc.stdio : printf;
+
/**********************************************/
/* 1 argument versions */
@@ -76,7 +78,7 @@ extern (C) int _aApplycd1(scope const(char)[] aa, dg_t dg)
int result;
size_t len = aa.length;
- debug(apply) printf("_aApplycd1(), len = %d\n", len);
+ debug(apply) printf("_aApplycd1(), len = %zd\n", len);
for (size_t i = 0; i < len; )
{
dchar d = aa[i];
@@ -137,7 +139,7 @@ extern (C) int _aApplywd1(scope const(wchar)[] aa, dg_t dg)
int result;
size_t len = aa.length;
- debug(apply) printf("_aApplywd1(), len = %d\n", len);
+ debug(apply) printf("_aApplywd1(), len = %zd\n", len);
for (size_t i = 0; i < len; )
{
dchar d = aa[i];
@@ -198,7 +200,7 @@ extern (C) int _aApplycw1(scope const(char)[] aa, dg_t dg)
int result;
size_t len = aa.length;
- debug(apply) printf("_aApplycw1(), len = %d\n", len);
+ debug(apply) printf("_aApplycw1(), len = %zd\n", len);
for (size_t i = 0; i < len; )
{
wchar w = aa[i];
@@ -272,7 +274,7 @@ extern (C) int _aApplywc1(scope const(wchar)[] aa, dg_t dg)
int result;
size_t len = aa.length;
- debug(apply) printf("_aApplywc1(), len = %d\n", len);
+ debug(apply) printf("_aApplywc1(), len = %zd\n", len);
for (size_t i = 0; i < len; )
{
wchar w = aa[i];
@@ -351,7 +353,7 @@ extern (C) int _aApplydc1(scope const(dchar)[] aa, dg_t dg)
{
int result;
- debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplydc1(), len = %zd\n", aa.length);
foreach (dchar d; aa)
{
if (d & ~0x7F)
@@ -427,7 +429,7 @@ extern (C) int _aApplydw1(scope const(dchar)[] aa, dg_t dg)
{
int result;
- debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplydw1(), len = %zd\n", aa.length);
foreach (dchar d; aa)
{
wchar w;
@@ -513,7 +515,7 @@ extern (C) int _aApplycd2(scope const(char)[] aa, dg2_t dg)
int result;
size_t len = aa.length;
- debug(apply) printf("_aApplycd2(), len = %d\n", len);
+ debug(apply) printf("_aApplycd2(), len = %zd\n", len);
size_t n;
for (size_t i = 0; i < len; i += n)
{
@@ -581,7 +583,7 @@ extern (C) int _aApplywd2(scope const(wchar)[] aa, dg2_t dg)
int result;
size_t len = aa.length;
- debug(apply) printf("_aApplywd2(), len = %d\n", len);
+ debug(apply) printf("_aApplywd2(), len = %zd\n", len);
size_t n;
for (size_t i = 0; i < len; i += n)
{
@@ -649,7 +651,7 @@ extern (C) int _aApplycw2(scope const(char)[] aa, dg2_t dg)
int result;
size_t len = aa.length;
- debug(apply) printf("_aApplycw2(), len = %d\n", len);
+ debug(apply) printf("_aApplycw2(), len = %zd\n", len);
size_t n;
for (size_t i = 0; i < len; i += n)
{
@@ -728,7 +730,7 @@ extern (C) int _aApplywc2(scope const(wchar)[] aa, dg2_t dg)
int result;
size_t len = aa.length;
- debug(apply) printf("_aApplywc2(), len = %d\n", len);
+ debug(apply) printf("_aApplywc2(), len = %zd\n", len);
size_t n;
for (size_t i = 0; i < len; i += n)
{
@@ -813,7 +815,7 @@ extern (C) int _aApplydc2(scope const(dchar)[] aa, dg2_t dg)
int result;
size_t len = aa.length;
- debug(apply) printf("_aApplydc2(), len = %d\n", len);
+ debug(apply) printf("_aApplydc2(), len = %zd\n", len);
for (size_t i = 0; i < len; i++)
{
dchar d = aa[i];
@@ -891,7 +893,7 @@ unittest
extern (C) int _aApplydw2(scope const(dchar)[] aa, dg2_t dg)
{ int result;
- debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplydw2(), len = %zd\n", aa.length);
foreach (size_t i, dchar d; aa)
{
wchar w;
diff --git a/libphobos/libdruntime/rt/aApplyR.d b/libphobos/libdruntime/rt/aApplyR.d
index 560025c636d..14052dfcd47 100644
--- a/libphobos/libdruntime/rt/aApplyR.d
+++ b/libphobos/libdruntime/rt/aApplyR.d
@@ -10,6 +10,8 @@ module rt.aApplyR;
import core.internal.utf;
+debug (apply) import core.stdc.stdio : printf;
+
/**********************************************/
/* 1 argument versions */
@@ -37,7 +39,7 @@ Returns:
extern (C) int _aApplyRcd1(scope const(char)[] aa, dg_t dg)
{ int result;
- debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRcd1(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d;
@@ -110,7 +112,7 @@ unittest
extern (C) int _aApplyRwd1(scope const(wchar)[] aa, dg_t dg)
{ int result;
- debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRwd1(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d;
@@ -173,7 +175,7 @@ unittest
extern (C) int _aApplyRcw1(scope const(char)[] aa, dg_t dg)
{ int result;
- debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRcw1(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d;
wchar w;
@@ -259,7 +261,7 @@ unittest
extern (C) int _aApplyRwc1(scope const(wchar)[] aa, dg_t dg)
{ int result;
- debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRwc1(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d;
char c;
@@ -343,7 +345,7 @@ unittest
extern (C) int _aApplyRdc1(scope const(dchar)[] aa, dg_t dg)
{ int result;
- debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRdc1(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0;)
{ dchar d = aa[--i];
char c;
@@ -421,7 +423,7 @@ unittest
extern (C) int _aApplyRdw1(scope const(dchar)[] aa, dg_t dg)
{ int result;
- debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRdw1(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d = aa[--i];
wchar w;
@@ -507,7 +509,7 @@ extern (C) int _aApplyRcd2(scope const(char)[] aa, dg2_t dg)
size_t i;
size_t len = aa.length;
- debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
+ debug(apply) printf("_aApplyRcd2(), len = %zd\n", len);
for (i = len; i != 0; )
{ dchar d;
@@ -581,7 +583,7 @@ unittest
extern (C) int _aApplyRwd2(scope const(wchar)[] aa, dg2_t dg)
{ int result;
- debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRwd2(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d;
@@ -646,7 +648,7 @@ unittest
extern (C) int _aApplyRcw2(scope const(char)[] aa, dg2_t dg)
{ int result;
- debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRcw2(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d;
wchar w;
@@ -734,7 +736,7 @@ unittest
extern (C) int _aApplyRwc2(scope const(wchar)[] aa, dg2_t dg)
{ int result;
- debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRwc2(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d;
char c;
@@ -820,7 +822,7 @@ unittest
extern (C) int _aApplyRdc2(scope const(dchar)[] aa, dg2_t dg)
{ int result;
- debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRdc2(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d = aa[--i];
char c;
@@ -899,7 +901,7 @@ unittest
extern (C) int _aApplyRdw2(scope const(dchar)[] aa, dg2_t dg)
{ int result;
- debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
+ debug(apply) printf("_aApplyRdw2(), len = %zd\n", aa.length);
for (size_t i = aa.length; i != 0; )
{ dchar d = aa[--i];
wchar w;
diff --git a/libphobos/libdruntime/rt/adi.d b/libphobos/libdruntime/rt/adi.d
index ea5a78f9c13..ece0f4b9f2e 100644
--- a/libphobos/libdruntime/rt/adi.d
+++ b/libphobos/libdruntime/rt/adi.d
@@ -27,7 +27,7 @@ private
extern (C) int _adEq2(void[] a1, void[] a2, TypeInfo ti)
{
- debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+ debug(adi) printf("_adEq2(a1.length = %zd, a2.length = %zd)\n", a1.length, a2.length);
if (a1.length != a2.length)
return 0; // not equal
if (!ti.equals(&a1, &a2))
diff --git a/libphobos/libdruntime/rt/arraycat.d b/libphobos/libdruntime/rt/arraycat.d
index d8794809af3..0ab785ba3b9 100644
--- a/libphobos/libdruntime/rt/arraycat.d
+++ b/libphobos/libdruntime/rt/arraycat.d
@@ -21,7 +21,7 @@ extern (C) @trusted nothrow:
void[] _d_arraycopy(size_t size, void[] from, void[] to)
{
- debug(PRINTF) printf("f = %p,%d, t = %p,%d, size = %d\n",
+ debug(PRINTF) printf("f = %p,%zd, t = %p,%zd, size = %zd\n",
from.ptr, from.length, to.ptr, to.length, size);
enforceRawArraysConformable("copy", size, from, to);
diff --git a/libphobos/libdruntime/rt/cast_.d b/libphobos/libdruntime/rt/cast_.d
index c7d8bbaab35..cd110bfc2aa 100644
--- a/libphobos/libdruntime/rt/cast_.d
+++ b/libphobos/libdruntime/rt/cast_.d
@@ -14,6 +14,8 @@
*/
module rt.cast_;
+debug(cast_) import core.stdc.stdio : printf;
+
extern (C):
@nogc:
nothrow:
@@ -60,7 +62,7 @@ Object _d_toObject(return scope void* p)
*/
if (pi.offset < 0x10000)
{
- debug(cast_) printf("\tpi.offset = %d\n", pi.offset);
+ debug(cast_) printf("\tpi.offset = %zd\n", pi.offset);
return cast(Object)(p - pi.offset);
}
return o;
@@ -72,19 +74,19 @@ Object _d_toObject(return scope void* p)
*/
void* _d_interface_cast(void* p, ClassInfo c)
{
- debug(cast_) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
+ debug(cast_) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, cast(int) c.name.length, c.name.ptr);
if (!p)
return null;
Interface* pi = **cast(Interface***) p;
- debug(cast_) printf("\tpi.offset = %d\n", pi.offset);
+ debug(cast_) printf("\tpi.offset = %zd\n", pi.offset);
Object o2 = cast(Object)(p - pi.offset);
void* res = null;
size_t offset = 0;
if (o2 && _d_isbaseof2(typeid(o2), c, offset))
{
- debug(cast_) printf("\toffset = %d\n", offset);
+ debug(cast_) printf("\toffset = %zd\n", offset);
res = cast(void*) o2 + offset;
}
debug(cast_) printf("\tresult = %p\n", res);
@@ -101,13 +103,13 @@ void* _d_interface_cast(void* p, ClassInfo c)
*/
void* _d_dynamic_cast(Object o, ClassInfo c)
{
- debug(cast_) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
+ debug(cast_) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, cast(int) c.name.length, c.name.ptr);
void* res = null;
size_t offset = 0;
if (o && _d_isbaseof2(typeid(o), c, offset))
{
- debug(cast_) printf("\toffset = %d\n", offset);
+ debug(cast_) printf("\toffset = %zd\n", offset);
res = cast(void*) o + offset;
}
debug(cast_) printf("\tresult = %p\n", res);
@@ -124,7 +126,7 @@ void* _d_dynamic_cast(Object o, ClassInfo c)
*/
void* _d_class_cast(Object o, ClassInfo c)
{
- debug(cast_) printf("_d_cast_cast(o = %p, c = '%.*s', level %d)\n", o, c.name, level);
+ debug(cast_) printf("_d_cast_cast(o = %p, c = '%.*s')\n", o, cast(int) c.name.length, c.name.ptr);
if (!o)
return null;
diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d
index 7851f664297..dbdfcb0b1f0 100644
--- a/libphobos/libdruntime/rt/lifetime.d
+++ b/libphobos/libdruntime/rt/lifetime.d
@@ -261,7 +261,7 @@ Params:
*/
extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow
{
- debug(PRINTF) printf("_d_arrayshrinkfit, elemsize = %d, arr.ptr = x%x arr.length = %d\n", ti.next.tsize, arr.ptr, arr.length);
+ debug(PRINTF) printf("_d_arrayshrinkfit, elemsize = %zd, arr.ptr = %p arr.length = %zd\n", ti.next.tsize, arr.ptr, arr.length);
auto tinext = unqualify(ti.next);
auto size = tinext.tsize; // array element size
auto reqsize = arr.length * size;
@@ -471,7 +471,7 @@ extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure noth
auto tinext = unqualify(ti.next);
auto size = tinext.tsize;
- debug(PRINTF) printf("_d_newarrayU(length = x%x, size = %d)\n", length, size);
+ debug(PRINTF) printf("_d_newarrayU(length = x%zx, size = %zd)\n", length, size);
if (length == 0 || size == 0)
return null;
@@ -876,7 +876,7 @@ do
{
//printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
if (p)
- printf("\tp.ptr = %p, p.length = %d\n", (*p).ptr, (*p).length);
+ printf("\tp.ptr = %p, p.length = %zd\n", (*p).ptr, (*p).length);
}
if (newlength <= (*p).length)
@@ -925,7 +925,7 @@ do
assert(0);
}
- debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
+ debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength);
const isshared = typeid(ti) is typeid(TypeInfo_Shared);
@@ -998,7 +998,7 @@ do
{
//printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
if (p)
- printf("\tp.ptr = %p, p.length = %d\n", (*p).ptr, (*p).length);
+ printf("\tp.ptr = %p, p.length = %zd\n", (*p).ptr, (*p).length);
}
if (newlength <= (*p).length)
@@ -1047,7 +1047,7 @@ do
assert(0);
}
- debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
+ debug(PRINTF) printf("newsize = %zx, newlength = %zx\n", newsize, newlength);
const isshared = typeid(ti) is typeid(TypeInfo_Shared);
@@ -1184,7 +1184,7 @@ size_t newCapacity(size_t newlength, size_t elemsize)
// ((newlength * mult + 99) / 100) * elemsize
newcap = cast(size_t)((newlength * mult + 127) >> 7) * elemsize;
debug(PRINTF) printf("mult: %2.2f, alloc: %2.2f\n",mult/128.0,newcap / cast(double)elemsize);
- debug(PRINTF) printf("newcap = %d, newlength = %d, elemsize = %d\n", newcap, newlength, elemsize);
+ debug(PRINTF) printf("newcap = %zd, newlength = %zd, elemsize = %zd\n", newcap, newlength, elemsize);
return newcap;
}
@@ -1426,7 +1426,7 @@ void* _d_arrayliteralTX(const TypeInfo ti, size_t length) @weak
auto sizeelem = tinext.tsize; // array element size
void* result;
- debug(PRINTF) printf("_d_arrayliteralTX(sizeelem = %d, length = %d)\n", sizeelem, length);
+ debug(PRINTF) printf("_d_arrayliteralTX(sizeelem = %zd, length = %zd)\n", sizeelem, length);
if (length == 0 || sizeelem == 0)
result = null;
else
diff --git a/libphobos/libdruntime/rt/monitor_.d b/libphobos/libdruntime/rt/monitor_.d
index 3a9c1f7cc2e..5d6c2f8c148 100644
--- a/libphobos/libdruntime/rt/monitor_.d
+++ b/libphobos/libdruntime/rt/monitor_.d
@@ -185,7 +185,10 @@ version (Windows)
}
else version (Posix)
{
- import core.sys.posix.pthread;
+ import core.sys.posix.pthread : pthread_mutex_destroy, pthread_mutex_init, pthread_mutex_lock,
+ PTHREAD_MUTEX_RECURSIVE, pthread_mutex_unlock, pthread_mutexattr_destroy, pthread_mutexattr_init,
+ pthread_mutexattr_settype;
+ import core.sys.posix.sys.types : pthread_mutex_t, pthread_mutexattr_t;
@nogc:
alias Mutex = pthread_mutex_t;