summaryrefslogtreecommitdiff
path: root/libphobos/src
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2021-02-03 19:01:32 +0100
committerIain Buclaw <ibuclaw@gdcproject.org>2021-02-03 22:06:42 +0100
commitb1a207c6df0a9c5555017f65f8731acf8d4c14c2 (patch)
treefca99fd7efdcdf6fc71b042be6df26de755c9468 /libphobos/src
parentb52a1dfe12a6303c7649f3ff5b8dac6c1001d49a (diff)
downloadgcc-b1a207c6df0a9c5555017f65f8731acf8d4c14c2.tar.gz
libphobos: Merge upstream druntime 9d0c8364, phobos 9d575282e.
Druntime changes: - Add platform-specific bindings for stdlib.h and sys/syctl.h. - Add darwin bindings for mach/dyld.h. - Fix solaris bindings for locale.h (PR98910). - Remove deprecated bindings from the module headers. Phobos changes: - Backport platform-specific fixes for std.conv, std.datetime, std.exception, std.experimental.allocator, std.file, std.math, std.parallelism, std.socket, std.stdio, and std.system. Reviewed-on: https://github.com/dlang/druntime/pull/3363 https://github.com/dlang/phobos/pull/7784 libphobos/ChangeLog: PR d/98910 * libdruntime/MERGE: Merge upstream druntime 9d0c8364. * libdruntime/Makefile.am (DRUNTIME_DSOURCES): Add core/internal/attributes.d (DRUNTIME_DSOURCES_BIONIC): Add core/sys/bionic/stdlib.d. (DRUNTIME_DSOURCES_DARWIN): Add core/sys/darwin/stdlib.d, and core/sys/darwin/sys/sysctl.d. (DRUNTIME_DSOURCES_DRAGONFLYBSD): Add core/sys/dragonflybsd/stdlib.d, and core/sys/dragonflybsd/sys/sysctl.d. (DRUNTIME_DSOURCES_FREEBSD): Add core/sys/freebsd/stdlib.d, and core/sys/freebsd/sys/sysctl.d. (DRUNTIME_DSOURCES_NETBSD): Add core/sys/netbsd/stdlib.d, and core/sys/netbsd/sys/sysctl.d. (DRUNTIME_DSOURCES_OPENBSD): Add core/sys/openbsd/stdlib.d, and core/sys/openbsd/sys/sysctl.d. (DRUNTIME_DSOURCES_SOLARIS): Add core/sys/solaris/stdlib.d. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 9d575282e.
Diffstat (limited to 'libphobos/src')
-rw-r--r--libphobos/src/MERGE2
-rw-r--r--libphobos/src/std/conv.d2
-rw-r--r--libphobos/src/std/datetime/systime.d110
-rw-r--r--libphobos/src/std/datetime/timezone.d17
-rw-r--r--libphobos/src/std/exception.d5
-rw-r--r--libphobos/src/std/experimental/allocator/building_blocks/region.d44
-rw-r--r--libphobos/src/std/experimental/allocator/mmap_allocator.d17
-rw-r--r--libphobos/src/std/file.d88
-rw-r--r--libphobos/src/std/math.d33
-rw-r--r--libphobos/src/std/parallelism.d233
-rw-r--r--libphobos/src/std/socket.d4
-rw-r--r--libphobos/src/std/stdio.d9
-rw-r--r--libphobos/src/std/system.d6
13 files changed, 412 insertions, 158 deletions
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE
index 1d8f8dfb46d..6de04b453ff 100644
--- a/libphobos/src/MERGE
+++ b/libphobos/src/MERGE
@@ -1,4 +1,4 @@
-3dd5df6864b3849450d3657e219b90909663a513
+9d575282edeccecbc061e615bf2486fd07e8c084
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
diff --git a/libphobos/src/std/conv.d b/libphobos/src/std/conv.d
index 743d203b2bb..31cc6517173 100644
--- a/libphobos/src/std/conv.d
+++ b/libphobos/src/std/conv.d
@@ -3148,8 +3148,6 @@ if (isInputRange!Source && isSomeChar!(ElementType!Source) && !is(Source == enum
{
version (CRuntime_Microsoft)
ld1 = 0x1.FFFFFFFFFFFFFFFEp-16382L; // strtold currently mapped to strtod
- else version (CRuntime_Bionic)
- ld1 = 0x1.FFFFFFFFFFFFFFFEp-16382L; // strtold currently mapped to strtod
else
ld1 = strtold(s.ptr, null);
}
diff --git a/libphobos/src/std/datetime/systime.d b/libphobos/src/std/datetime/systime.d
index 0b11ed96745..b2291910616 100644
--- a/libphobos/src/std/datetime/systime.d
+++ b/libphobos/src/std/datetime/systime.d
@@ -7,6 +7,15 @@
+/
module std.datetime.systime;
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
import core.time;
import std.datetime.date;
import std.datetime.timezone;
@@ -161,18 +170,19 @@ public:
static import core.stdc.time;
enum hnsecsToUnixEpoch = unixTimeToStdTime(0);
- version (OSX)
+ version (Darwin)
{
static if (clockType == ClockType.second)
return unixTimeToStdTime(core.stdc.time.time(null));
else
{
import core.sys.posix.sys.time : gettimeofday, timeval;
- timeval tv;
- if (gettimeofday(&tv, null) != 0)
- throw new TimeException("Call to gettimeofday() failed");
+ timeval tv = void;
+ // Posix gettimeofday called with a valid timeval address
+ // and a null second parameter doesn't fail.
+ gettimeofday(&tv, null);
return convert!("seconds", "hnsecs")(tv.tv_sec) +
- convert!("usecs", "hnsecs")(tv.tv_usec) +
+ tv.tv_usec * 10 +
hnsecsToUnixEpoch;
}
}
@@ -188,9 +198,16 @@ public:
else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
else static assert(0, "Previous static if is wrong.");
- timespec ts;
- if (clock_gettime(clockArg, &ts) != 0)
- throw new TimeException("Call to clock_gettime() failed");
+ timespec ts = void;
+ immutable error = clock_gettime(clockArg, &ts);
+ // Posix clock_gettime called with a valid address and valid clock_id is only
+ // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
+ // is long or larger overflow won't happen before 292 billion years A.D.
+ static if (ts.tv_sec.max < long.max)
+ {
+ if (error)
+ throw new TimeException("Call to clock_gettime() failed");
+ }
return convert!("seconds", "hnsecs")(ts.tv_sec) +
ts.tv_nsec / 100 +
hnsecsToUnixEpoch;
@@ -205,9 +222,16 @@ public:
else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
else static assert(0, "Previous static if is wrong.");
- timespec ts;
- if (clock_gettime(clockArg, &ts) != 0)
- throw new TimeException("Call to clock_gettime() failed");
+ timespec ts = void;
+ immutable error = clock_gettime(clockArg, &ts);
+ // Posix clock_gettime called with a valid address and valid clock_id is only
+ // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
+ // is long or larger overflow won't happen before 292 billion years A.D.
+ static if (ts.tv_sec.max < long.max)
+ {
+ if (error)
+ throw new TimeException("Call to clock_gettime() failed");
+ }
return convert!("seconds", "hnsecs")(ts.tv_sec) +
ts.tv_nsec / 100 +
hnsecsToUnixEpoch;
@@ -218,12 +242,38 @@ public:
return unixTimeToStdTime(core.stdc.time.time(null));
else
{
- import core.sys.posix.sys.time : gettimeofday, timeval;
- timeval tv;
- if (gettimeofday(&tv, null) != 0)
- throw new TimeException("Call to gettimeofday() failed");
- return convert!("seconds", "hnsecs")(tv.tv_sec) +
- convert!("usecs", "hnsecs")(tv.tv_usec) +
+ import core.sys.netbsd.time : clock_gettime, CLOCK_REALTIME;
+ timespec ts = void;
+ immutable error = clock_gettime(CLOCK_REALTIME, &ts);
+ // Posix clock_gettime called with a valid address and valid clock_id is only
+ // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
+ // is long or larger overflow won't happen before 292 billion years A.D.
+ static if (ts.tv_sec.max < long.max)
+ {
+ if (error)
+ throw new TimeException("Call to clock_gettime() failed");
+ }
+ return convert!("seconds", "hnsecs")(ts.tv_sec) +
+ ts.tv_nsec / 100 +
+ hnsecsToUnixEpoch;
+ }
+ }
+ else version (OpenBSD)
+ {
+ static if (clockType == ClockType.second)
+ return unixTimeToStdTime(core.stdc.time.time(null));
+ else
+ {
+ import core.sys.openbsd.time : clock_gettime, CLOCK_REALTIME;
+ static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME;
+ else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
+ else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
+ else static assert(0, "Previous static if is wrong.");
+ timespec ts;
+ if (clock_gettime(clockArg, &ts) != 0)
+ throw new TimeException("Call to clock_gettime() failed");
+ return convert!("seconds", "hnsecs")(ts.tv_sec) +
+ ts.tv_nsec / 100 +
hnsecsToUnixEpoch;
}
}
@@ -236,9 +286,16 @@ public:
else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
else static assert(0, "Previous static if is wrong.");
- timespec ts;
- if (clock_gettime(clockArg, &ts) != 0)
- throw new TimeException("Call to clock_gettime() failed");
+ timespec ts = void;
+ immutable error = clock_gettime(clockArg, &ts);
+ // Posix clock_gettime called with a valid address and valid clock_id is only
+ // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
+ // is long or larger overflow won't happen before 292 billion years A.D.
+ static if (ts.tv_sec.max < long.max)
+ {
+ if (error)
+ throw new TimeException("Call to clock_gettime() failed");
+ }
return convert!("seconds", "hnsecs")(ts.tv_sec) +
ts.tv_nsec / 100 +
hnsecsToUnixEpoch;
@@ -254,9 +311,16 @@ public:
else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
else static assert(0, "Previous static if is wrong.");
- timespec ts;
- if (clock_gettime(clockArg, &ts) != 0)
- throw new TimeException("Call to clock_gettime() failed");
+ timespec ts = void;
+ immutable error = clock_gettime(clockArg, &ts);
+ // Posix clock_gettime called with a valid address and valid clock_id is only
+ // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
+ // is long or larger overflow won't happen before 292 billion years A.D.
+ static if (ts.tv_sec.max < long.max)
+ {
+ if (error)
+ throw new TimeException("Call to clock_gettime() failed");
+ }
return convert!("seconds", "hnsecs")(ts.tv_sec) +
ts.tv_nsec / 100 +
hnsecsToUnixEpoch;
diff --git a/libphobos/src/std/datetime/timezone.d b/libphobos/src/std/datetime/timezone.d
index 7ae19020243..9b744ff7ab0 100644
--- a/libphobos/src/std/datetime/timezone.d
+++ b/libphobos/src/std/datetime/timezone.d
@@ -14,6 +14,15 @@ import std.exception : enforce;
import std.range.primitives;
import std.traits : isIntegral, isSomeString, Unqual;
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
version (Windows)
{
import core.stdc.time : time_t;
@@ -296,7 +305,7 @@ public:
else version (NetBSD) enum utcZone = "UTC";
else version (DragonFlyBSD) enum utcZone = "UTC";
else version (linux) enum utcZone = "UTC";
- else version (OSX) enum utcZone = "UTC";
+ else version (Darwin) enum utcZone = "UTC";
else version (Solaris) enum utcZone = "UTC";
else static assert(0, "The location of the UTC timezone file on this Posix platform must be set.");
@@ -671,7 +680,11 @@ public:
@safe unittest
{
- assert(LocalTime().dstName !is null);
+ // tzname, called from dstName, isn't set by default for Musl.
+ version (CRuntime_Musl)
+ assert(LocalTime().dstName is null);
+ else
+ assert(LocalTime().dstName !is null);
version (Posix)
{
diff --git a/libphobos/src/std/exception.d b/libphobos/src/std/exception.d
index 73afadc07e0..56133c9ad89 100644
--- a/libphobos/src/std/exception.d
+++ b/libphobos/src/std/exception.d
@@ -1478,10 +1478,13 @@ private bool isUnionAliasedImpl(T)(size_t offset)
static assert( isUnionAliased!(S.A5, 1)); //a5.b1;
}
+version (CRuntime_Glibc) version = GNU_STRERROR;
+version (CRuntime_UClibc) version = GNU_STRERROR;
+
package string errnoString(int errno) nothrow @trusted
{
import core.stdc.string : strlen;
- version (CRuntime_Glibc)
+ version (GNU_STRERROR)
{
import core.stdc.string : strerror_r;
char[1024] buf = void;
diff --git a/libphobos/src/std/experimental/allocator/building_blocks/region.d b/libphobos/src/std/experimental/allocator/building_blocks/region.d
index 835d0937cec..53f5ef988d4 100644
--- a/libphobos/src/std/experimental/allocator/building_blocks/region.d
+++ b/libphobos/src/std/experimental/allocator/building_blocks/region.d
@@ -5,6 +5,15 @@ import std.experimental.allocator.building_blocks.null_allocator;
import std.experimental.allocator.common;
import std.typecons : Flag, Yes, No;
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
/**
A $(D Region) allocator allocates memory straight from one contiguous chunk.
There is no deallocation, and once the region is full, allocation requests
@@ -580,14 +589,26 @@ struct InSituRegion(size_t size, size_t minAlign = platformAlignment)
assert(a.length == 2001);
}
-version(CRuntime_Musl)
+version (CRuntime_Musl)
{
// sbrk and brk are disabled in Musl:
// https://git.musl-libc.org/cgit/musl/commit/?id=7a995fe706e519a4f55399776ef0df9596101f93
// https://git.musl-libc.org/cgit/musl/commit/?id=863d628d93ea341b6a32661a1654320ce69f6a07
-} else:
-private extern(C) void* sbrk(long);
-private extern(C) int brk(shared void*);
+}
+version (DragonFlyBSD)
+{
+ // sbrk is deprecated in favor of mmap (we could implement a mmap + MAP_NORESERVE + PROT_NONE version)
+ // brk has been removed
+ // https://www.dragonflydigest.com/2019/02/22/22586.html
+ // http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/dc676eaefa61b0f47bbea1c53eab86fd5ccd78c6
+ // http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/4b5665564ef37dc939a3a9ffbafaab9894c18885
+ // http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/8618d94a0e2ff8303ad93c123a3fa598c26a116e
+}
+else
+{
+ private extern(C) void* sbrk(long) nothrow @nogc;
+ private extern(C) int brk(shared void*) nothrow @nogc;
+}
/**
@@ -599,11 +620,14 @@ that uncontrolled calls to $(D brk) and $(D sbrk) may affect the workings of $(D
SbrkRegion) adversely.
*/
+version (CRuntime_Musl) {} else
+version (DragonFlyBSD) {} else
version (Posix) struct SbrkRegion(uint minAlign = platformAlignment)
{
import core.sys.posix.pthread : pthread_mutex_init, pthread_mutex_destroy,
pthread_mutex_t, pthread_mutex_lock, pthread_mutex_unlock,
- PTHREAD_MUTEX_INITIALIZER;
+
+ PTHREAD_MUTEX_INITIALIZER;
private static shared pthread_mutex_t sbrkMutex = PTHREAD_MUTEX_INITIALIZER;
import std.typecons : Ternary;
@@ -763,7 +787,9 @@ version (Posix) struct SbrkRegion(uint minAlign = platformAlignment)
}
}
-version (Posix) @system unittest
+version (CRuntime_Musl) {} else
+version (DragonFlyBSD) {} else
+version (Posix) @system nothrow @nogc unittest
{
// Let's test the assumption that sbrk(n) returns the old address
const p1 = sbrk(0);
@@ -775,7 +801,9 @@ version (Posix) @system unittest
sbrk(-4096);
}
-version (Posix) @system unittest
+version (CRuntime_Musl) {} else
+version (DragonFlyBSD) {} else
+version (Posix) @system nothrow @nogc unittest
{
import std.typecons : Ternary;
alias alloc = SbrkRegion!(8).instance;
@@ -786,7 +814,7 @@ version (Posix) @system unittest
assert(alloc.owns(a) == Ternary.yes);
assert(alloc.owns(b) == Ternary.yes);
// reducing the brk does not work on OSX
- version (OSX) {} else
+ version (Darwin) {} else
{
assert(alloc.deallocate(b));
assert(alloc.deallocateAll);
diff --git a/libphobos/src/std/experimental/allocator/mmap_allocator.d b/libphobos/src/std/experimental/allocator/mmap_allocator.d
index 945859b8c56..e07d444c32c 100644
--- a/libphobos/src/std/experimental/allocator/mmap_allocator.d
+++ b/libphobos/src/std/experimental/allocator/mmap_allocator.d
@@ -46,6 +46,21 @@ struct MmapAllocator
if (b.ptr) munmap(b.ptr, b.length) == 0 || assert(0);
return true;
}
+
+ // Anonymous mmap might be zero-filled on all Posix systems but
+ // not all commit to this in the documentation.
+ version (linux)
+ // http://man7.org/linux/man-pages/man2/mmap.2.html
+ package alias allocateZeroed = allocate;
+ else version (NetBSD)
+ // http://netbsd.gw.com/cgi-bin/man-cgi?mmap+2+NetBSD-current
+ package alias allocateZeroed = allocate;
+ else version (Solaris)
+ // https://docs.oracle.com/cd/E88353_01/html/E37841/mmap-2.html
+ package alias allocateZeroed = allocate;
+ else version (AIX)
+ // https://www.ibm.com/support/knowledgecenter/en/ssw_aix_71/com.ibm.aix.basetrf1/mmap.htm
+ package alias allocateZeroed = allocate;
}
else version (Windows)
{
@@ -67,6 +82,8 @@ struct MmapAllocator
{
return b.ptr is null || VirtualFree(b.ptr, 0, MEM_RELEASE) != 0;
}
+
+ package alias allocateZeroed = allocate;
}
}
diff --git a/libphobos/src/std/file.d b/libphobos/src/std/file.d
index 380ecfc2bcd..13a3db0ff66 100644
--- a/libphobos/src/std/file.d
+++ b/libphobos/src/std/file.d
@@ -1490,6 +1490,15 @@ if (isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R))
// vfs.timestamp_precision sysctl to a value greater than zero.
// - OS X, where the native filesystem (HFS+) stores filesystem
// timestamps with 1-second precision.
+//
+// Note: on linux systems, although in theory a change to a file date
+// can be tracked with precision of 4 msecs, this test waits 20 msecs
+// to prevent possible problems relative to the CI services the dlang uses,
+// as they may have the HZ setting that controls the software clock set to 100
+// (instead of the more common 250).
+// see https://man7.org/linux/man-pages/man7/time.7.html
+// https://stackoverflow.com/a/14393315,
+// https://issues.dlang.org/show_bug.cgi?id=21148
version (FreeBSD) {} else
version (DragonFlyBSD) {} else
version (OSX) {} else
@@ -1508,7 +1517,7 @@ version (OSX) {} else
remove(deleteme);
assert(time != lastTime);
lastTime = time;
- Thread.sleep(10.msecs);
+ Thread.sleep(20.msecs);
}
}
@@ -2757,15 +2766,27 @@ else version (NetBSD)
buffer.length *= 2;
}
}
+ else version (DragonFlyBSD)
+ {
+ import core.sys.dragonflybsd.sys.sysctl : sysctl, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME;
+ import std.exception : errnoEnforce, assumeUnique;
+
+ int[4] mib = [CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1];
+ size_t len;
+
+ auto result = sysctl(mib.ptr, mib.length, null, &len, null, 0); // get the length of the path
+ errnoEnforce(result == 0);
+
+ auto buffer = new char[len - 1];
+ result = sysctl(mib.ptr, mib.length, buffer.ptr, &len, null, 0);
+ errnoEnforce(result == 0);
+
+ return buffer.assumeUnique;
+ }
else version (FreeBSD)
{
+ import core.sys.freebsd.sys.sysctl : sysctl, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME;
import std.exception : errnoEnforce, assumeUnique;
- enum
- {
- CTL_KERN = 1,
- KERN_PROC = 14,
- KERN_PROC_PATHNAME = 12
- }
int[4] mib = [CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1];
size_t len;
@@ -2781,11 +2802,58 @@ else version (NetBSD)
}
else version (NetBSD)
{
- return readLink("/proc/self/exe");
+ import core.sys.netbsd.sys.sysctl : sysctl, CTL_KERN, KERN_PROC_ARGS, KERN_PROC_PATHNAME;
+ import std.exception : errnoEnforce, assumeUnique;
+
+ int[4] mib = [CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME];
+ size_t len;
+
+ auto result = sysctl(mib.ptr, mib.length, null, &len, null, 0); // get the length of the path
+ errnoEnforce(result == 0);
+
+ auto buffer = new char[len - 1];
+ result = sysctl(mib.ptr, mib.length, buffer.ptr, &len, null, 0);
+ errnoEnforce(result == 0);
+
+ return buffer.assumeUnique;
}
- else version (DragonFlyBSD)
+ else version (OpenBSD)
{
- return readLink("/proc/curproc/file");
+ import core.sys.openbsd.sys.sysctl : sysctl, CTL_KERN, KERN_PROC_ARGS, KERN_PROC_ARGV;
+ import core.sys.posix.unistd : getpid;
+ import std.conv : to;
+ import std.exception : enforce, errnoEnforce;
+ import std.process : searchPathFor;
+
+ int[4] mib = [CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV];
+ size_t len;
+
+ auto result = sysctl(mib.ptr, mib.length, null, &len, null, 0);
+ errnoEnforce(result == 0);
+
+ auto argv = new char*[len - 1];
+ result = sysctl(mib.ptr, mib.length, argv.ptr, &len, null, 0);
+ errnoEnforce(result == 0);
+
+ auto argv0 = argv[0];
+ if (*argv0 == '/' || *argv0 == '.')
+ {
+ import core.sys.posix.stdlib : realpath;
+ auto absolutePath = realpath(argv0, null);
+ scope (exit)
+ {
+ if (absolutePath)
+ free(absolutePath);
+ }
+ errnoEnforce(absolutePath);
+ return to!(string)(absolutePath);
+ }
+ else
+ {
+ auto absolutePath = searchPathFor(to!string(argv0));
+ errnoEnforce(absolutePath);
+ return absolutePath;
+ }
}
else version (Solaris)
{
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index 3d18cfa528b..ff368b79f9d 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -167,19 +167,14 @@ version (SystemZ) version = IBMZ_Any;
version (RISCV32) version = RISCV_Any;
version (RISCV64) version = RISCV_Any;
-version (D_InlineAsm_X86)
-{
- version = InlineAsm_X86_Any;
-}
-else version (D_InlineAsm_X86_64)
-{
- version = InlineAsm_X86_Any;
-}
+version (D_InlineAsm_X86) version = InlineAsm_X86_Any;
+version (D_InlineAsm_X86_64) version = InlineAsm_X86_Any;
-version (CRuntime_Microsoft)
+version (InlineAsm_X86_Any) version = InlineAsm_X87;
+version (InlineAsm_X87)
{
- version (InlineAsm_X86_Any)
- version = MSVC_InlineAsm;
+ static assert(real.mant_dig == 64);
+ version (CRuntime_Microsoft) version = InlineAsm_X87_MSVC;
}
version (X86_64) version = StaticallyHaveSSE;
@@ -3610,7 +3605,7 @@ real log1p(real x) @safe pure nothrow @nogc
real log2(real x) @safe pure nothrow @nogc
{
version (INLINE_YL2X)
- return core.math.yl2x(x, 1);
+ return core.math.yl2x(x, 1.0L);
else
{
// Special cases are the same as for log.
@@ -4586,19 +4581,21 @@ real round(real x) @trusted nothrow @nogc
* If the fractional part of x is exactly 0.5, the return value is rounded
* away from zero.
*
- * $(BLUE This function is Posix-Only.)
+ * $(BLUE This function is not implemented for Digital Mars C runtime.)
*/
long lround(real x) @trusted nothrow @nogc
{
- version (Posix)
- return core.stdc.math.llroundl(x);
- else
+ version (CRuntime_DigitalMars)
assert(0, "lround not implemented");
+ else
+ return core.stdc.math.llroundl(x);
}
-version (Posix)
+///
+@safe nothrow @nogc unittest
{
- @safe nothrow @nogc unittest
+ version (CRuntime_DigitalMars) {}
+ else
{
assert(lround(0.49) == 0);
assert(lround(0.5) == 1);
diff --git a/libphobos/src/std/parallelism.d b/libphobos/src/std/parallelism.d
index 64fa2f93c7e..43a1ba59527 100644
--- a/libphobos/src/std/parallelism.d
+++ b/libphobos/src/std/parallelism.d
@@ -40,6 +40,15 @@ License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0)
*/
module std.parallelism;
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
///
@system unittest
{
@@ -86,107 +95,82 @@ import std.meta;
import std.range.primitives;
import std.traits;
-version (OSX)
-{
- version = useSysctlbyname;
-}
-else version (FreeBSD)
-{
- version = useSysctlbyname;
-}
-else version (DragonFlyBSD)
-{
- version = useSysctlbyname;
-}
-else version (NetBSD)
-{
- version = useSysctlbyname;
-}
+/*
+(For now public undocumented with reserved name.)
+A lazily initialized global constant. The underlying value is a shared global
+statically initialized to `outOfBandValue` which must not be a legit value of
+the constant. Upon the first call the situation is detected and the global is
+initialized by calling `initializer`. The initializer is assumed to be pure
+(even if not marked as such), i.e. return the same value upon repeated calls.
+For that reason, no special precautions are taken so `initializer` may be called
+more than one time leading to benign races on the cached value.
-version (Windows)
-{
- // BUGS: Only works on Windows 2000 and above.
- shared static this()
- {
- import core.sys.windows.windows : SYSTEM_INFO, GetSystemInfo;
- import std.algorithm.comparison : max;
+In the quiescent state the cost of the function is an atomic load from a global.
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- totalCPUs = max(1, cast(uint) si.dwNumberOfProcessors);
- }
+Params:
+ T = The type of the pseudo-constant (may be qualified)
+ outOfBandValue = A value that cannot be valid, it is used for initialization
+ initializer = The function performing initialization; must be `nothrow`
-}
-else version (linux)
-{
- shared static this()
- {
- import core.sys.posix.unistd : _SC_NPROCESSORS_ONLN, sysconf;
- totalCPUs = cast(uint) sysconf(_SC_NPROCESSORS_ONLN);
- }
-}
-else version (Solaris)
-{
- shared static this()
- {
- import core.sys.posix.unistd : _SC_NPROCESSORS_ONLN, sysconf;
- totalCPUs = cast(uint) sysconf(_SC_NPROCESSORS_ONLN);
- }
-}
-else version (useSysctlbyname)
+Returns:
+ The lazily initialized value
+*/
+@property pure
+T __lazilyInitializedConstant(T, alias outOfBandValue, alias initializer)()
+if (is(Unqual!T : T)
+ && is(typeof(initializer()) : T)
+ && is(typeof(outOfBandValue) : T))
{
- extern(C) int sysctlbyname(
- const char *, void *, size_t *, void *, size_t
- );
-
- shared static this()
- {
- version (OSX)
- {
- auto nameStr = "machdep.cpu.core_count\0".ptr;
- }
- else version (FreeBSD)
+ static T impl() nothrow
+ {
+ // Thread-local cache
+ static Unqual!T tls = outOfBandValue;
+ auto local = tls;
+ // Shortest path, no atomic operations
+ if (local != outOfBandValue) return local;
+ // Process-level cache
+ static shared Unqual!T result = outOfBandValue;
+ // Initialize both process-level cache and tls
+ local = atomicLoad(result);
+ if (local == outOfBandValue)
{
- auto nameStr = "hw.ncpu\0".ptr;
+ local = initializer();
+ atomicStore(result, local);
}
- else version (DragonFlyBSD)
- {
- auto nameStr = "hw.ncpu\0".ptr;
- }
- else version (NetBSD)
- {
- auto nameStr = "hw.ncpu\0".ptr;
- }
-
- uint ans;
- size_t len = uint.sizeof;
- sysctlbyname(nameStr, &ans, &len, null, 0);
- totalCPUs = ans;
+ tls = local;
+ return local;
}
+ import std.traits : SetFunctionAttributes;
+ alias Fun = SetFunctionAttributes!(typeof(&impl), "D",
+ functionAttributes!(typeof(&impl)) | FunctionAttribute.pure_);
+ auto purified = (() @trusted => cast(Fun) &impl)();
+ return purified();
}
-else
-{
- static assert(0, "Don't know how to get N CPUs on this OS.");
-}
-immutable size_t cacheLineSize;
-shared static this()
+// Returns the size of a cache line.
+alias cacheLineSize =
+ __lazilyInitializedConstant!(immutable(size_t), size_t.max, cacheLineSizeImpl);
+
+private size_t cacheLineSizeImpl() @nogc nothrow @trusted
{
+ size_t result = 0;
import core.cpuid : datacache;
- size_t lineSize = 0;
- foreach (cachelevel; datacache)
+ foreach (ref const cachelevel; datacache)
{
- if (cachelevel.lineSize > lineSize && cachelevel.lineSize < uint.max)
+ if (cachelevel.lineSize > result && cachelevel.lineSize < uint.max)
{
- lineSize = cachelevel.lineSize;
+ result = cachelevel.lineSize;
}
}
-
- cacheLineSize = lineSize;
+ return result;
}
+@nogc @safe nothrow unittest
+{
+ assert(cacheLineSize == cacheLineSizeImpl);
+}
/* Atomics code. These forward to core.atomic, but are written like this
for two reasons:
@@ -957,7 +941,81 @@ if (is(typeof(fun(args))) && isSafeTask!F)
The total number of CPU cores available on the current machine, as reported by
the operating system.
*/
-immutable uint totalCPUs;
+alias totalCPUs =
+ __lazilyInitializedConstant!(immutable(uint), uint.max, totalCPUsImpl);
+
+uint totalCPUsImpl() @nogc nothrow @trusted
+{
+ version (Windows)
+ {
+ // BUGS: Only works on Windows 2000 and above.
+ import core.sys.windows.winbase : SYSTEM_INFO, GetSystemInfo;
+ import std.algorithm.comparison : max;
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return max(1, cast(uint) si.dwNumberOfProcessors);
+ }
+ else version (linux)
+ {
+ import core.sys.linux.sched : CPU_COUNT, cpu_set_t, sched_getaffinity;
+ import core.sys.posix.unistd : _SC_NPROCESSORS_ONLN, sysconf;
+
+ cpu_set_t set = void;
+ if (sched_getaffinity(0, cpu_set_t.sizeof, &set) == 0)
+ {
+ int count = CPU_COUNT(&set);
+ if (count > 0)
+ return cast(uint) count;
+ }
+ return cast(uint) sysconf(_SC_NPROCESSORS_ONLN);
+ }
+ else version (Darwin)
+ {
+ import core.sys.darwin.sys.sysctl : sysctlbyname;
+ uint result;
+ size_t len = result.sizeof;
+ sysctlbyname("hw.physicalcpu", &result, &len, null, 0);
+ return result;
+ }
+ else version (DragonFlyBSD)
+ {
+ import core.sys.dragonflybsd.sys.sysctl : sysctlbyname;
+ uint result;
+ size_t len = result.sizeof;
+ sysctlbyname("hw.ncpu", &result, &len, null, 0);
+ return result;
+ }
+ else version (FreeBSD)
+ {
+ import core.sys.freebsd.sys.sysctl : sysctlbyname;
+ uint result;
+ size_t len = result.sizeof;
+ sysctlbyname("hw.ncpu", &result, &len, null, 0);
+ return result;
+ }
+ else version (NetBSD)
+ {
+ import core.sys.netbsd.sys.sysctl : sysctlbyname;
+ uint result;
+ size_t len = result.sizeof;
+ sysctlbyname("hw.ncpu", &result, &len, null, 0);
+ return result;
+ }
+ else version (Solaris)
+ {
+ import core.sys.posix.unistd : _SC_NPROCESSORS_ONLN, sysconf;
+ return cast(uint) sysconf(_SC_NPROCESSORS_ONLN);
+ }
+ else version (OpenBSD)
+ {
+ import core.sys.posix.unistd : _SC_NPROCESSORS_ONLN, sysconf;
+ return cast(uint) sysconf(_SC_NPROCESSORS_ONLN);
+ }
+ else
+ {
+ static assert(0, "Don't know how to get N CPUs on this OS.");
+ }
+}
/*
This class serves two purposes:
@@ -3302,11 +3360,7 @@ terminating the main thread.
}());
}
-private shared uint _defaultPoolThreads;
-shared static this()
-{
- atomicStore(_defaultPoolThreads, totalCPUs - 1);
-}
+private shared uint _defaultPoolThreads = uint.max;
/**
These properties get and set the number of worker threads in the $(D TaskPool)
@@ -3316,7 +3370,8 @@ number of worker threads in the instance returned by $(D taskPool).
*/
@property uint defaultPoolThreads() @trusted
{
- return atomicLoad(_defaultPoolThreads);
+ const local = atomicLoad(_defaultPoolThreads);
+ return local < uint.max ? local : totalCPUs - 1;
}
/// Ditto
diff --git a/libphobos/src/std/socket.d b/libphobos/src/std/socket.d
index a4ba39c8336..ecb2c8b916e 100644
--- a/libphobos/src/std/socket.d
+++ b/libphobos/src/std/socket.d
@@ -146,6 +146,8 @@ class SocketException: Exception
mixin basicExceptionCtors;
}
+version (CRuntime_Glibc) version = GNU_STRERROR;
+version (CRuntime_UClibc) version = GNU_STRERROR;
/*
* Needs to be public so that SocketOSException can be thrown outside of
@@ -159,7 +161,7 @@ string formatSocketError(int err) @trusted
{
char[80] buf;
const(char)* cs;
- version (CRuntime_Glibc)
+ version (GNU_STRERROR)
{
cs = strerror_r(err, buf.ptr, buf.length);
}
diff --git a/libphobos/src/std/stdio.d b/libphobos/src/std/stdio.d
index c59bc4c219b..bbf785773d4 100644
--- a/libphobos/src/std/stdio.d
+++ b/libphobos/src/std/stdio.d
@@ -79,6 +79,10 @@ else version (NetBSD)
{
version = GENERIC_IO;
}
+else version (OpenBSD)
+{
+ version = GENERIC_IO;
+}
else version (DragonFlyBSD)
{
version = GENERIC_IO;
@@ -93,12 +97,11 @@ version (Windows)
{
private alias FSChar = wchar;
}
-else version (Posix)
+else
{
private alias FSChar = char;
}
-else
- static assert(0);
+
version (Windows)
{
diff --git a/libphobos/src/std/system.d b/libphobos/src/std/system.d
index e0b3dee8dae..353d692848a 100644
--- a/libphobos/src/std/system.d
+++ b/libphobos/src/std/system.d
@@ -30,6 +30,9 @@ immutable
win64, /// Microsoft 64 bit Windows systems
linux, /// All Linux Systems, except for Android
osx, /// Mac OS X
+ iOS, /// iOS
+ tvOS, /// tvOS
+ watchOS, /// watchOS
freeBSD, /// FreeBSD
netBSD, /// NetBSD
dragonFlyBSD, /// DragonFlyBSD
@@ -44,6 +47,9 @@ immutable
else version (Android) OS os = OS.android;
else version (linux) OS os = OS.linux;
else version (OSX) OS os = OS.osx;
+ else version (iOS) OS os = OS.iOS;
+ else version (tvOS) OS os = OS.tvOS;
+ else version (watchOS) OS os = OS.watchOS;
else version (FreeBSD) OS os = OS.freeBSD;
else version (NetBSD) OS os = OS.netBSD;
else version (DragonFlyBSD) OS os = OS.dragonFlyBSD;