public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Add more uses of getTargetInfo(osxVersionMin). Implement posix_memalign if missing
@ 2021-10-15 19:33 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-15 19:33 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:63e1b5573457d69d24b2bc60430bef79baa3289d

commit 63e1b5573457d69d24b2bc60430bef79baa3289d
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Dec 6 00:19:39 2020 +0100

    libphobos: Add more uses of getTargetInfo(osxVersionMin).  Implement posix_memalign if missing

Diff:
---
 libphobos/libdruntime/core/stdc/math.d             |  20 +--
 libphobos/libdruntime/core/sys/darwin/config.d     |   8 ++
 libphobos/libdruntime/core/sys/darwin/mach/dyld.d  |  18 ++-
 libphobos/libdruntime/core/sys/darwin/pthread.d    |  35 +++--
 libphobos/libdruntime/core/sys/darwin/string.d     |   8 +-
 libphobos/libdruntime/core/sys/posix/stdio.d       |   4 +-
 libphobos/libdruntime/core/sys/posix/stdlib.d      |   8 +-
 .../src/std/experimental/allocator/mallocator.d    | 141 ++++++++++++++++++---
 8 files changed, 193 insertions(+), 49 deletions(-)

diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index 2de6e579575..7f15d569d0f 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -922,6 +922,8 @@ else version (CRuntime_UClibc)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum
     {
         ///
@@ -968,7 +970,15 @@ else version (Darwin)
     // Support of OSX < 10.8 needs legacy function names without "l" suffix
     // with exception of __signbitl.  Otherwise could use else version like
     // other Darwins
-    version (OSX)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_8)
+    {
+        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
+        pure int __fpclassifyl(real x);
+        pure int __isfinitel(real x);
+        pure int __isinfl(real x);
+        pure int __isnanl(real x);
+    }
+    else
     {
         version (AArch64)
         {
@@ -990,14 +1000,6 @@ else version (Darwin)
             alias __isnanl = __isnan;
         }
     }
-    else
-    {
-        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
-        pure int __fpclassifyl(real x);
-        pure int __isfinitel(real x);
-        pure int __isinfl(real x);
-        pure int __isnanl(real x);
-    }
 
   extern (D)
   {
diff --git a/libphobos/libdruntime/core/sys/darwin/config.d b/libphobos/libdruntime/core/sys/darwin/config.d
index 87f3fd4dae6..a6b94eda157 100644
--- a/libphobos/libdruntime/core/sys/darwin/config.d
+++ b/libphobos/libdruntime/core/sys/darwin/config.d
@@ -19,6 +19,14 @@ version (Darwin):
 
 public import core.sys.posix.config;
 
+// The compiler exposes `__traits(getTargetInfo, "osxVersionMin")` as a way to
+// obtain the lower bound support OSX version. In some compilers this is
+// controlled by a command-line option:
+//  -mmacosx-version-min=   (on OSX).
+//  -miphoneos-version-min= (on iOS)
+//  -mtvos-version-min=     (on TVOS)
+//  -mwatchos-version-min=  (on WatchOS)
+
 enum __MAC_10_0    = 100000;
 enum __MAC_10_1    = 100100;
 enum __MAC_10_2    = 100200;
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
index 6e28bfa655b..02d57433429 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
@@ -28,14 +28,18 @@ nothrow:
 
 public import core.stdc.stdint; // for intptr_t
 public import core.sys.darwin.mach.loader;
+import core.sys.darwin.config;
 
-uint         _dyld_image_count();
-const(char)* _dyld_get_image_name(uint image_index);
-mach_header* _dyld_get_image_header(uint image_index);
-intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
-
-void         _dyld_register_func_for_add_image(void function(const scope mach_header* mh, intptr_t vmaddr_slide));
-void         _dyld_register_func_for_remove_image(void function(const scope mach_header* mh, intptr_t vmaddr_slide));
+// __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_1)
+{
+    uint         _dyld_image_count();
+    const(char)* _dyld_get_image_name(uint image_index);
+    mach_header* _dyld_get_image_header(uint image_index);
+    intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
+    void         _dyld_register_func_for_add_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+    void         _dyld_register_func_for_remove_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+}
 
 int NSVersionOfRunTimeLibrary(const char* libraryPath);
 int NSVersionOfLinkTimeLibrary(const char* libraryPath);
diff --git a/libphobos/libdruntime/core/sys/darwin/pthread.d b/libphobos/libdruntime/core/sys/darwin/pthread.d
index 456cde96cbd..9a1aaafd440 100644
--- a/libphobos/libdruntime/core/sys/darwin/pthread.d
+++ b/libphobos/libdruntime/core/sys/darwin/pthread.d
@@ -29,22 +29,32 @@ nothrow:
 
 public import core.sys.posix.pthread;
 public import core.sys.darwin.mach.port;
+import core.sys.darwin.config;
 
 int pthread_is_threaded_np();
-int pthread_threadid_np(pthread_t, ulong*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
-int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
-int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_threadid_np(pthread_t, ulong*);
+}
+// __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+{
+    int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
+    int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
+}
 int pthread_rwlock_downgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_upgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_tryupgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_held_np(pthread_rwlock_t*);
 int pthread_rwlock_rdheld_np(pthread_rwlock_t*);
 int pthread_rwlock_wrheld_np(pthread_rwlock_t*);
-int pthread_getname_np(pthread_t, char*, size_t);
-int pthread_setname_np(const scope char*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_getname_np(pthread_t, char*, size_t);
+    int pthread_setname_np(in char*);
+}
 int pthread_main_np();
 mach_port_t pthread_mach_thread_np(pthread_t);
 size_t pthread_get_stacksize_np(pthread_t);
@@ -53,8 +63,11 @@ int pthread_cond_signal_thread_np(pthread_cond_t*, pthread_t);
 int pthread_cond_timedwait_relative_np(pthread_cond_t*, pthread_mutex_t*, const scope timespec*);
 int pthread_create_suspended_np(pthread_t*, const scope pthread_attr_t*, void* function(void*), void*);
 int pthread_kill(pthread_t, int);
-pthread_t pthread_from_mach_thread_np(mach_port_t);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
-int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
+// __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    pthread_t pthread_from_mach_thread_np(mach_port_t);
+}
+int pthread_sigmask(int, in sigset_t*, sigset_t*);
 // ^ __DARWIN_ALIAS(pthread_sigmask)
 void pthread_yield_np();
diff --git a/libphobos/libdruntime/core/sys/darwin/string.d b/libphobos/libdruntime/core/sys/darwin/string.d
index bd65fde27bc..20dcd1fdc81 100644
--- a/libphobos/libdruntime/core/sys/darwin/string.d
+++ b/libphobos/libdruntime/core/sys/darwin/string.d
@@ -9,6 +9,7 @@ module core.sys.darwin.string;
 
 public import core.stdc.string;
 import core.sys.darwin.sys.cdefs;
+import core.sys.darwin.config;
 
 version (OSX)
     version = Darwin;
@@ -26,6 +27,9 @@ nothrow:
 
 static if (__DARWIN_C_LEVEL >= __DARWIN_C_FULL)
 {
-    // ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
-    pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    // __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+    {
+        pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    }
 }
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index fcd9fcbc29c..2e38c0c7e2e 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -373,12 +373,14 @@ else version (CRuntime_Bionic)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum L_ctermid = 1024;
 
     int   fseeko(FILE*, off_t, int);
     off_t ftello(FILE*);
 
-    static if (__traits(getTargetInfo, "osxVersionMin") >= 100700)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
     {
         ssize_t getdelim(char**, size_t*, int, FILE*);
         ssize_t getline(char**, size_t*, FILE*);
diff --git a/libphobos/libdruntime/core/sys/posix/stdlib.d b/libphobos/libdruntime/core/sys/posix/stdlib.d
index 4c10d4e0ed5..57e369d41a5 100644
--- a/libphobos/libdruntime/core/sys/posix/stdlib.d
+++ b/libphobos/libdruntime/core/sys/posix/stdlib.d
@@ -119,7 +119,13 @@ else version (Solaris)
 }
 else version (Darwin)
 {
-    int posix_memalign(void**, size_t, size_t);
+    import core.sys.darwin.config;
+
+    // __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+    {
+        int posix_memalign(void**, size_t, size_t);
+    }
 }
 else version (CRuntime_Bionic)
 {
diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d
index 2d1dec39a74..6e1866bc976 100644
--- a/libphobos/src/std/experimental/allocator/mallocator.d
+++ b/libphobos/src/std/experimental/allocator/mallocator.d
@@ -194,6 +194,84 @@ version (Windows)
     }
 }
 
+version (Posix)
+{
+    // Not all platforms have posix_memalign available, supply own implementation
+    // if this is the case.  Avoid calling it posix_memalign because it needs
+    // special handling for realloc and free cases.
+    static if (!__traits(compiles, { import core.sys.posix.stdlib : posix_memalign; }))
+    {
+        // Helper to cast the infos written before the aligned pointer
+        // this header keeps track of the size (required to realloc) and of
+        // the base ptr (required to free).
+        private struct AlignInfo
+        {
+            void* basePtr;
+            size_t size;
+
+            @nogc nothrow
+            static AlignInfo* opCall(void* ptr)
+            {
+                return cast(AlignInfo*) (ptr - AlignInfo.sizeof);
+            }
+        }
+
+        @nogc nothrow
+        private void* _aligned_malloc(size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : malloc;
+            size_t offset = alignment + size_t.sizeof * 2 - 1;
+
+            // unaligned chunk
+            void* basePtr = malloc(size + offset);
+            if (!basePtr) return null;
+
+            // get aligned location within the chunk
+            void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset)
+                & ~(alignment - 1));
+
+            // write the header before the aligned pointer
+            AlignInfo* head = AlignInfo(alignedPtr);
+            head.basePtr = basePtr;
+            head.size = size;
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void* _aligned_realloc(void* ptr, size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : free;
+            import core.stdc.string : memcpy;
+
+            if (!ptr) return _aligned_malloc(size, alignment);
+
+            // gets the header from the exising pointer
+            AlignInfo* head = AlignInfo(ptr);
+
+            // gets a new aligned pointer
+            void* alignedPtr = _aligned_malloc(size, alignment);
+            if (!alignedPtr)
+                return null;
+
+            // copy exising data
+            memcpy(alignedPtr, ptr, head.size);
+            free(head.basePtr);
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void _aligned_free(void *ptr)
+        {
+            import core.stdc.stdlib : free;
+            if (!ptr) return;
+            AlignInfo* head = AlignInfo(ptr);
+            free(head.basePtr);
+        }
+    }
+}
+
 /**
    Aligned allocator using OS-specific primitives, under a uniform API.
  */
@@ -226,24 +304,32 @@ struct AlignedMallocator
     @trusted @nogc nothrow
     void[] alignedAllocate(size_t bytes, uint a) shared
     {
-        import core.stdc.errno : ENOMEM, EINVAL;
-        import core.sys.posix.stdlib : posix_memalign;
-        assert(a.isGoodDynamicAlignment);
-        void* result;
-        auto code = posix_memalign(&result, a, bytes);
-        if (code == ENOMEM)
-            return null;
-
-        else if (code == EINVAL)
+        static if (__traits(compiles, _aligned_malloc))
         {
-            assert(0, "AlignedMallocator.alignment is not a power of two "
-                ~"multiple of (void*).sizeof, according to posix_memalign!");
+            auto result = _aligned_malloc(bytes, a);
+            return result ? result[0 .. bytes] : null;
         }
-        else if (code != 0)
-            assert(0, "posix_memalign returned an unknown code!");
-
         else
-            return result[0 .. bytes];
+        {
+            import core.stdc.errno : ENOMEM, EINVAL;
+            import core.sys.posix.stdlib : posix_memalign;
+            assert(a.isGoodDynamicAlignment);
+            void* result;
+            auto code = posix_memalign(&result, a, bytes);
+            if (code == ENOMEM)
+                return null;
+
+            else if (code == EINVAL)
+            {
+                assert(0, "AlignedMallocator.alignment is not a power of two "
+                    ~"multiple of (void*).sizeof, according to posix_memalign!");
+            }
+            else if (code != 0)
+                assert(0, "posix_memalign returned an unknown code!");
+
+            else
+                return result[0 .. bytes];
+        }
     }
     else version (Windows)
     @trusted @nogc nothrow
@@ -263,8 +349,13 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool deallocate(void[] b) shared
     {
-        import core.stdc.stdlib : free;
-        free(b.ptr);
+        static if (__traits(compiles, _aligned_free))
+            _aligned_free(b.ptr);
+        else
+        {
+            import core.stdc.stdlib : free;
+            free(b.ptr);
+        }
         return true;
     }
     else version (Windows)
@@ -284,7 +375,21 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool reallocate(ref void[] b, size_t newSize) shared
     {
-        return Mallocator.instance.reallocate(b, newSize);
+        static if (__traits(compiles, _aligned_realloc))
+        {
+            if (!newSize)
+            {
+                deallocate(b);
+                b = null;
+                return true;
+            }
+            auto p = cast(ubyte*) _aligned_realloc(b.ptr, newSize, alignment);
+            if (!p) return false;
+            b = p[0 .. newSize];
+            return true;
+        }
+        else
+            return Mallocator.instance.reallocate(b, newSize);
     }
     version (Windows)
     @system @nogc nothrow


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Add more uses of getTargetInfo(osxVersionMin). Implement posix_memalign if missing
@ 2021-10-18 15:54 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-18 15:54 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:20cbdf25bf4b644538347fa0e0e49e0cd53c7d9e

commit 20cbdf25bf4b644538347fa0e0e49e0cd53c7d9e
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Dec 6 00:19:39 2020 +0100

    libphobos: Add more uses of getTargetInfo(osxVersionMin).  Implement posix_memalign if missing

Diff:
---
 libphobos/libdruntime/core/stdc/math.d             |  20 +--
 libphobos/libdruntime/core/sys/darwin/config.d     |   8 ++
 libphobos/libdruntime/core/sys/darwin/mach/dyld.d  |  18 ++-
 libphobos/libdruntime/core/sys/darwin/pthread.d    |  35 +++--
 libphobos/libdruntime/core/sys/darwin/string.d     |   8 +-
 libphobos/libdruntime/core/sys/posix/stdio.d       |   4 +-
 libphobos/libdruntime/core/sys/posix/stdlib.d      |   8 +-
 .../src/std/experimental/allocator/mallocator.d    | 141 ++++++++++++++++++---
 8 files changed, 193 insertions(+), 49 deletions(-)

diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index 2de6e579575..7f15d569d0f 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -922,6 +922,8 @@ else version (CRuntime_UClibc)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum
     {
         ///
@@ -968,7 +970,15 @@ else version (Darwin)
     // Support of OSX < 10.8 needs legacy function names without "l" suffix
     // with exception of __signbitl.  Otherwise could use else version like
     // other Darwins
-    version (OSX)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_8)
+    {
+        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
+        pure int __fpclassifyl(real x);
+        pure int __isfinitel(real x);
+        pure int __isinfl(real x);
+        pure int __isnanl(real x);
+    }
+    else
     {
         version (AArch64)
         {
@@ -990,14 +1000,6 @@ else version (Darwin)
             alias __isnanl = __isnan;
         }
     }
-    else
-    {
-        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
-        pure int __fpclassifyl(real x);
-        pure int __isfinitel(real x);
-        pure int __isinfl(real x);
-        pure int __isnanl(real x);
-    }
 
   extern (D)
   {
diff --git a/libphobos/libdruntime/core/sys/darwin/config.d b/libphobos/libdruntime/core/sys/darwin/config.d
index 87f3fd4dae6..a6b94eda157 100644
--- a/libphobos/libdruntime/core/sys/darwin/config.d
+++ b/libphobos/libdruntime/core/sys/darwin/config.d
@@ -19,6 +19,14 @@ version (Darwin):
 
 public import core.sys.posix.config;
 
+// The compiler exposes `__traits(getTargetInfo, "osxVersionMin")` as a way to
+// obtain the lower bound support OSX version. In some compilers this is
+// controlled by a command-line option:
+//  -mmacosx-version-min=   (on OSX).
+//  -miphoneos-version-min= (on iOS)
+//  -mtvos-version-min=     (on TVOS)
+//  -mwatchos-version-min=  (on WatchOS)
+
 enum __MAC_10_0    = 100000;
 enum __MAC_10_1    = 100100;
 enum __MAC_10_2    = 100200;
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
index 6e28bfa655b..02d57433429 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
@@ -28,14 +28,18 @@ nothrow:
 
 public import core.stdc.stdint; // for intptr_t
 public import core.sys.darwin.mach.loader;
+import core.sys.darwin.config;
 
-uint         _dyld_image_count();
-const(char)* _dyld_get_image_name(uint image_index);
-mach_header* _dyld_get_image_header(uint image_index);
-intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
-
-void         _dyld_register_func_for_add_image(void function(const scope mach_header* mh, intptr_t vmaddr_slide));
-void         _dyld_register_func_for_remove_image(void function(const scope mach_header* mh, intptr_t vmaddr_slide));
+// __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_1)
+{
+    uint         _dyld_image_count();
+    const(char)* _dyld_get_image_name(uint image_index);
+    mach_header* _dyld_get_image_header(uint image_index);
+    intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
+    void         _dyld_register_func_for_add_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+    void         _dyld_register_func_for_remove_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+}
 
 int NSVersionOfRunTimeLibrary(const char* libraryPath);
 int NSVersionOfLinkTimeLibrary(const char* libraryPath);
diff --git a/libphobos/libdruntime/core/sys/darwin/pthread.d b/libphobos/libdruntime/core/sys/darwin/pthread.d
index 456cde96cbd..9a1aaafd440 100644
--- a/libphobos/libdruntime/core/sys/darwin/pthread.d
+++ b/libphobos/libdruntime/core/sys/darwin/pthread.d
@@ -29,22 +29,32 @@ nothrow:
 
 public import core.sys.posix.pthread;
 public import core.sys.darwin.mach.port;
+import core.sys.darwin.config;
 
 int pthread_is_threaded_np();
-int pthread_threadid_np(pthread_t, ulong*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
-int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
-int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_threadid_np(pthread_t, ulong*);
+}
+// __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+{
+    int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
+    int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
+}
 int pthread_rwlock_downgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_upgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_tryupgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_held_np(pthread_rwlock_t*);
 int pthread_rwlock_rdheld_np(pthread_rwlock_t*);
 int pthread_rwlock_wrheld_np(pthread_rwlock_t*);
-int pthread_getname_np(pthread_t, char*, size_t);
-int pthread_setname_np(const scope char*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_getname_np(pthread_t, char*, size_t);
+    int pthread_setname_np(in char*);
+}
 int pthread_main_np();
 mach_port_t pthread_mach_thread_np(pthread_t);
 size_t pthread_get_stacksize_np(pthread_t);
@@ -53,8 +63,11 @@ int pthread_cond_signal_thread_np(pthread_cond_t*, pthread_t);
 int pthread_cond_timedwait_relative_np(pthread_cond_t*, pthread_mutex_t*, const scope timespec*);
 int pthread_create_suspended_np(pthread_t*, const scope pthread_attr_t*, void* function(void*), void*);
 int pthread_kill(pthread_t, int);
-pthread_t pthread_from_mach_thread_np(mach_port_t);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
-int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
+// __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    pthread_t pthread_from_mach_thread_np(mach_port_t);
+}
+int pthread_sigmask(int, in sigset_t*, sigset_t*);
 // ^ __DARWIN_ALIAS(pthread_sigmask)
 void pthread_yield_np();
diff --git a/libphobos/libdruntime/core/sys/darwin/string.d b/libphobos/libdruntime/core/sys/darwin/string.d
index bd65fde27bc..20dcd1fdc81 100644
--- a/libphobos/libdruntime/core/sys/darwin/string.d
+++ b/libphobos/libdruntime/core/sys/darwin/string.d
@@ -9,6 +9,7 @@ module core.sys.darwin.string;
 
 public import core.stdc.string;
 import core.sys.darwin.sys.cdefs;
+import core.sys.darwin.config;
 
 version (OSX)
     version = Darwin;
@@ -26,6 +27,9 @@ nothrow:
 
 static if (__DARWIN_C_LEVEL >= __DARWIN_C_FULL)
 {
-    // ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
-    pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    // __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+    {
+        pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    }
 }
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index fcd9fcbc29c..2e38c0c7e2e 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -373,12 +373,14 @@ else version (CRuntime_Bionic)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum L_ctermid = 1024;
 
     int   fseeko(FILE*, off_t, int);
     off_t ftello(FILE*);
 
-    static if (__traits(getTargetInfo, "osxVersionMin") >= 100700)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
     {
         ssize_t getdelim(char**, size_t*, int, FILE*);
         ssize_t getline(char**, size_t*, FILE*);
diff --git a/libphobos/libdruntime/core/sys/posix/stdlib.d b/libphobos/libdruntime/core/sys/posix/stdlib.d
index 4c10d4e0ed5..57e369d41a5 100644
--- a/libphobos/libdruntime/core/sys/posix/stdlib.d
+++ b/libphobos/libdruntime/core/sys/posix/stdlib.d
@@ -119,7 +119,13 @@ else version (Solaris)
 }
 else version (Darwin)
 {
-    int posix_memalign(void**, size_t, size_t);
+    import core.sys.darwin.config;
+
+    // __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+    {
+        int posix_memalign(void**, size_t, size_t);
+    }
 }
 else version (CRuntime_Bionic)
 {
diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d
index 2d1dec39a74..6e1866bc976 100644
--- a/libphobos/src/std/experimental/allocator/mallocator.d
+++ b/libphobos/src/std/experimental/allocator/mallocator.d
@@ -194,6 +194,84 @@ version (Windows)
     }
 }
 
+version (Posix)
+{
+    // Not all platforms have posix_memalign available, supply own implementation
+    // if this is the case.  Avoid calling it posix_memalign because it needs
+    // special handling for realloc and free cases.
+    static if (!__traits(compiles, { import core.sys.posix.stdlib : posix_memalign; }))
+    {
+        // Helper to cast the infos written before the aligned pointer
+        // this header keeps track of the size (required to realloc) and of
+        // the base ptr (required to free).
+        private struct AlignInfo
+        {
+            void* basePtr;
+            size_t size;
+
+            @nogc nothrow
+            static AlignInfo* opCall(void* ptr)
+            {
+                return cast(AlignInfo*) (ptr - AlignInfo.sizeof);
+            }
+        }
+
+        @nogc nothrow
+        private void* _aligned_malloc(size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : malloc;
+            size_t offset = alignment + size_t.sizeof * 2 - 1;
+
+            // unaligned chunk
+            void* basePtr = malloc(size + offset);
+            if (!basePtr) return null;
+
+            // get aligned location within the chunk
+            void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset)
+                & ~(alignment - 1));
+
+            // write the header before the aligned pointer
+            AlignInfo* head = AlignInfo(alignedPtr);
+            head.basePtr = basePtr;
+            head.size = size;
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void* _aligned_realloc(void* ptr, size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : free;
+            import core.stdc.string : memcpy;
+
+            if (!ptr) return _aligned_malloc(size, alignment);
+
+            // gets the header from the exising pointer
+            AlignInfo* head = AlignInfo(ptr);
+
+            // gets a new aligned pointer
+            void* alignedPtr = _aligned_malloc(size, alignment);
+            if (!alignedPtr)
+                return null;
+
+            // copy exising data
+            memcpy(alignedPtr, ptr, head.size);
+            free(head.basePtr);
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void _aligned_free(void *ptr)
+        {
+            import core.stdc.stdlib : free;
+            if (!ptr) return;
+            AlignInfo* head = AlignInfo(ptr);
+            free(head.basePtr);
+        }
+    }
+}
+
 /**
    Aligned allocator using OS-specific primitives, under a uniform API.
  */
@@ -226,24 +304,32 @@ struct AlignedMallocator
     @trusted @nogc nothrow
     void[] alignedAllocate(size_t bytes, uint a) shared
     {
-        import core.stdc.errno : ENOMEM, EINVAL;
-        import core.sys.posix.stdlib : posix_memalign;
-        assert(a.isGoodDynamicAlignment);
-        void* result;
-        auto code = posix_memalign(&result, a, bytes);
-        if (code == ENOMEM)
-            return null;
-
-        else if (code == EINVAL)
+        static if (__traits(compiles, _aligned_malloc))
         {
-            assert(0, "AlignedMallocator.alignment is not a power of two "
-                ~"multiple of (void*).sizeof, according to posix_memalign!");
+            auto result = _aligned_malloc(bytes, a);
+            return result ? result[0 .. bytes] : null;
         }
-        else if (code != 0)
-            assert(0, "posix_memalign returned an unknown code!");
-
         else
-            return result[0 .. bytes];
+        {
+            import core.stdc.errno : ENOMEM, EINVAL;
+            import core.sys.posix.stdlib : posix_memalign;
+            assert(a.isGoodDynamicAlignment);
+            void* result;
+            auto code = posix_memalign(&result, a, bytes);
+            if (code == ENOMEM)
+                return null;
+
+            else if (code == EINVAL)
+            {
+                assert(0, "AlignedMallocator.alignment is not a power of two "
+                    ~"multiple of (void*).sizeof, according to posix_memalign!");
+            }
+            else if (code != 0)
+                assert(0, "posix_memalign returned an unknown code!");
+
+            else
+                return result[0 .. bytes];
+        }
     }
     else version (Windows)
     @trusted @nogc nothrow
@@ -263,8 +349,13 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool deallocate(void[] b) shared
     {
-        import core.stdc.stdlib : free;
-        free(b.ptr);
+        static if (__traits(compiles, _aligned_free))
+            _aligned_free(b.ptr);
+        else
+        {
+            import core.stdc.stdlib : free;
+            free(b.ptr);
+        }
         return true;
     }
     else version (Windows)
@@ -284,7 +375,21 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool reallocate(ref void[] b, size_t newSize) shared
     {
-        return Mallocator.instance.reallocate(b, newSize);
+        static if (__traits(compiles, _aligned_realloc))
+        {
+            if (!newSize)
+            {
+                deallocate(b);
+                b = null;
+                return true;
+            }
+            auto p = cast(ubyte*) _aligned_realloc(b.ptr, newSize, alignment);
+            if (!p) return false;
+            b = p[0 .. newSize];
+            return true;
+        }
+        else
+            return Mallocator.instance.reallocate(b, newSize);
     }
     version (Windows)
     @system @nogc nothrow


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Add more uses of getTargetInfo(osxVersionMin). Implement posix_memalign if missing
@ 2021-10-13  8:30 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-13  8:30 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:5a4be72ce6dc8a6f0f332c0825a6615db6d5e0b4

commit 5a4be72ce6dc8a6f0f332c0825a6615db6d5e0b4
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Dec 6 00:19:39 2020 +0100

    libphobos: Add more uses of getTargetInfo(osxVersionMin).  Implement posix_memalign if missing

Diff:
---
 libphobos/libdruntime/core/stdc/math.d             |  20 +--
 libphobos/libdruntime/core/sys/darwin/config.d     |   8 ++
 libphobos/libdruntime/core/sys/darwin/mach/dyld.d  |  18 ++-
 libphobos/libdruntime/core/sys/darwin/pthread.d    |  35 +++--
 libphobos/libdruntime/core/sys/darwin/string.d     |   8 +-
 libphobos/libdruntime/core/sys/posix/stdio.d       |   4 +-
 libphobos/libdruntime/core/sys/posix/stdlib.d      |   8 +-
 .../src/std/experimental/allocator/mallocator.d    | 141 ++++++++++++++++++---
 8 files changed, 193 insertions(+), 49 deletions(-)

diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index 2de6e579575..7f15d569d0f 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -922,6 +922,8 @@ else version (CRuntime_UClibc)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum
     {
         ///
@@ -968,7 +970,15 @@ else version (Darwin)
     // Support of OSX < 10.8 needs legacy function names without "l" suffix
     // with exception of __signbitl.  Otherwise could use else version like
     // other Darwins
-    version (OSX)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_8)
+    {
+        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
+        pure int __fpclassifyl(real x);
+        pure int __isfinitel(real x);
+        pure int __isinfl(real x);
+        pure int __isnanl(real x);
+    }
+    else
     {
         version (AArch64)
         {
@@ -990,14 +1000,6 @@ else version (Darwin)
             alias __isnanl = __isnan;
         }
     }
-    else
-    {
-        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
-        pure int __fpclassifyl(real x);
-        pure int __isfinitel(real x);
-        pure int __isinfl(real x);
-        pure int __isnanl(real x);
-    }
 
   extern (D)
   {
diff --git a/libphobos/libdruntime/core/sys/darwin/config.d b/libphobos/libdruntime/core/sys/darwin/config.d
index 87f3fd4dae6..a6b94eda157 100644
--- a/libphobos/libdruntime/core/sys/darwin/config.d
+++ b/libphobos/libdruntime/core/sys/darwin/config.d
@@ -19,6 +19,14 @@ version (Darwin):
 
 public import core.sys.posix.config;
 
+// The compiler exposes `__traits(getTargetInfo, "osxVersionMin")` as a way to
+// obtain the lower bound support OSX version. In some compilers this is
+// controlled by a command-line option:
+//  -mmacosx-version-min=   (on OSX).
+//  -miphoneos-version-min= (on iOS)
+//  -mtvos-version-min=     (on TVOS)
+//  -mwatchos-version-min=  (on WatchOS)
+
 enum __MAC_10_0    = 100000;
 enum __MAC_10_1    = 100100;
 enum __MAC_10_2    = 100200;
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
index 6e28bfa655b..02d57433429 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
@@ -28,14 +28,18 @@ nothrow:
 
 public import core.stdc.stdint; // for intptr_t
 public import core.sys.darwin.mach.loader;
+import core.sys.darwin.config;
 
-uint         _dyld_image_count();
-const(char)* _dyld_get_image_name(uint image_index);
-mach_header* _dyld_get_image_header(uint image_index);
-intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
-
-void         _dyld_register_func_for_add_image(void function(const scope mach_header* mh, intptr_t vmaddr_slide));
-void         _dyld_register_func_for_remove_image(void function(const scope mach_header* mh, intptr_t vmaddr_slide));
+// __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_1)
+{
+    uint         _dyld_image_count();
+    const(char)* _dyld_get_image_name(uint image_index);
+    mach_header* _dyld_get_image_header(uint image_index);
+    intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
+    void         _dyld_register_func_for_add_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+    void         _dyld_register_func_for_remove_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+}
 
 int NSVersionOfRunTimeLibrary(const char* libraryPath);
 int NSVersionOfLinkTimeLibrary(const char* libraryPath);
diff --git a/libphobos/libdruntime/core/sys/darwin/pthread.d b/libphobos/libdruntime/core/sys/darwin/pthread.d
index 456cde96cbd..9a1aaafd440 100644
--- a/libphobos/libdruntime/core/sys/darwin/pthread.d
+++ b/libphobos/libdruntime/core/sys/darwin/pthread.d
@@ -29,22 +29,32 @@ nothrow:
 
 public import core.sys.posix.pthread;
 public import core.sys.darwin.mach.port;
+import core.sys.darwin.config;
 
 int pthread_is_threaded_np();
-int pthread_threadid_np(pthread_t, ulong*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
-int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
-int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_threadid_np(pthread_t, ulong*);
+}
+// __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+{
+    int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
+    int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
+}
 int pthread_rwlock_downgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_upgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_tryupgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_held_np(pthread_rwlock_t*);
 int pthread_rwlock_rdheld_np(pthread_rwlock_t*);
 int pthread_rwlock_wrheld_np(pthread_rwlock_t*);
-int pthread_getname_np(pthread_t, char*, size_t);
-int pthread_setname_np(const scope char*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_getname_np(pthread_t, char*, size_t);
+    int pthread_setname_np(in char*);
+}
 int pthread_main_np();
 mach_port_t pthread_mach_thread_np(pthread_t);
 size_t pthread_get_stacksize_np(pthread_t);
@@ -53,8 +63,11 @@ int pthread_cond_signal_thread_np(pthread_cond_t*, pthread_t);
 int pthread_cond_timedwait_relative_np(pthread_cond_t*, pthread_mutex_t*, const scope timespec*);
 int pthread_create_suspended_np(pthread_t*, const scope pthread_attr_t*, void* function(void*), void*);
 int pthread_kill(pthread_t, int);
-pthread_t pthread_from_mach_thread_np(mach_port_t);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
-int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
+// __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    pthread_t pthread_from_mach_thread_np(mach_port_t);
+}
+int pthread_sigmask(int, in sigset_t*, sigset_t*);
 // ^ __DARWIN_ALIAS(pthread_sigmask)
 void pthread_yield_np();
diff --git a/libphobos/libdruntime/core/sys/darwin/string.d b/libphobos/libdruntime/core/sys/darwin/string.d
index bd65fde27bc..20dcd1fdc81 100644
--- a/libphobos/libdruntime/core/sys/darwin/string.d
+++ b/libphobos/libdruntime/core/sys/darwin/string.d
@@ -9,6 +9,7 @@ module core.sys.darwin.string;
 
 public import core.stdc.string;
 import core.sys.darwin.sys.cdefs;
+import core.sys.darwin.config;
 
 version (OSX)
     version = Darwin;
@@ -26,6 +27,9 @@ nothrow:
 
 static if (__DARWIN_C_LEVEL >= __DARWIN_C_FULL)
 {
-    // ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
-    pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    // __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+    {
+        pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    }
 }
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index fcd9fcbc29c..2e38c0c7e2e 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -373,12 +373,14 @@ else version (CRuntime_Bionic)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum L_ctermid = 1024;
 
     int   fseeko(FILE*, off_t, int);
     off_t ftello(FILE*);
 
-    static if (__traits(getTargetInfo, "osxVersionMin") >= 100700)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
     {
         ssize_t getdelim(char**, size_t*, int, FILE*);
         ssize_t getline(char**, size_t*, FILE*);
diff --git a/libphobos/libdruntime/core/sys/posix/stdlib.d b/libphobos/libdruntime/core/sys/posix/stdlib.d
index 4c10d4e0ed5..57e369d41a5 100644
--- a/libphobos/libdruntime/core/sys/posix/stdlib.d
+++ b/libphobos/libdruntime/core/sys/posix/stdlib.d
@@ -119,7 +119,13 @@ else version (Solaris)
 }
 else version (Darwin)
 {
-    int posix_memalign(void**, size_t, size_t);
+    import core.sys.darwin.config;
+
+    // __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+    {
+        int posix_memalign(void**, size_t, size_t);
+    }
 }
 else version (CRuntime_Bionic)
 {
diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d
index 2d1dec39a74..6e1866bc976 100644
--- a/libphobos/src/std/experimental/allocator/mallocator.d
+++ b/libphobos/src/std/experimental/allocator/mallocator.d
@@ -194,6 +194,84 @@ version (Windows)
     }
 }
 
+version (Posix)
+{
+    // Not all platforms have posix_memalign available, supply own implementation
+    // if this is the case.  Avoid calling it posix_memalign because it needs
+    // special handling for realloc and free cases.
+    static if (!__traits(compiles, { import core.sys.posix.stdlib : posix_memalign; }))
+    {
+        // Helper to cast the infos written before the aligned pointer
+        // this header keeps track of the size (required to realloc) and of
+        // the base ptr (required to free).
+        private struct AlignInfo
+        {
+            void* basePtr;
+            size_t size;
+
+            @nogc nothrow
+            static AlignInfo* opCall(void* ptr)
+            {
+                return cast(AlignInfo*) (ptr - AlignInfo.sizeof);
+            }
+        }
+
+        @nogc nothrow
+        private void* _aligned_malloc(size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : malloc;
+            size_t offset = alignment + size_t.sizeof * 2 - 1;
+
+            // unaligned chunk
+            void* basePtr = malloc(size + offset);
+            if (!basePtr) return null;
+
+            // get aligned location within the chunk
+            void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset)
+                & ~(alignment - 1));
+
+            // write the header before the aligned pointer
+            AlignInfo* head = AlignInfo(alignedPtr);
+            head.basePtr = basePtr;
+            head.size = size;
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void* _aligned_realloc(void* ptr, size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : free;
+            import core.stdc.string : memcpy;
+
+            if (!ptr) return _aligned_malloc(size, alignment);
+
+            // gets the header from the exising pointer
+            AlignInfo* head = AlignInfo(ptr);
+
+            // gets a new aligned pointer
+            void* alignedPtr = _aligned_malloc(size, alignment);
+            if (!alignedPtr)
+                return null;
+
+            // copy exising data
+            memcpy(alignedPtr, ptr, head.size);
+            free(head.basePtr);
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void _aligned_free(void *ptr)
+        {
+            import core.stdc.stdlib : free;
+            if (!ptr) return;
+            AlignInfo* head = AlignInfo(ptr);
+            free(head.basePtr);
+        }
+    }
+}
+
 /**
    Aligned allocator using OS-specific primitives, under a uniform API.
  */
@@ -226,24 +304,32 @@ struct AlignedMallocator
     @trusted @nogc nothrow
     void[] alignedAllocate(size_t bytes, uint a) shared
     {
-        import core.stdc.errno : ENOMEM, EINVAL;
-        import core.sys.posix.stdlib : posix_memalign;
-        assert(a.isGoodDynamicAlignment);
-        void* result;
-        auto code = posix_memalign(&result, a, bytes);
-        if (code == ENOMEM)
-            return null;
-
-        else if (code == EINVAL)
+        static if (__traits(compiles, _aligned_malloc))
         {
-            assert(0, "AlignedMallocator.alignment is not a power of two "
-                ~"multiple of (void*).sizeof, according to posix_memalign!");
+            auto result = _aligned_malloc(bytes, a);
+            return result ? result[0 .. bytes] : null;
         }
-        else if (code != 0)
-            assert(0, "posix_memalign returned an unknown code!");
-
         else
-            return result[0 .. bytes];
+        {
+            import core.stdc.errno : ENOMEM, EINVAL;
+            import core.sys.posix.stdlib : posix_memalign;
+            assert(a.isGoodDynamicAlignment);
+            void* result;
+            auto code = posix_memalign(&result, a, bytes);
+            if (code == ENOMEM)
+                return null;
+
+            else if (code == EINVAL)
+            {
+                assert(0, "AlignedMallocator.alignment is not a power of two "
+                    ~"multiple of (void*).sizeof, according to posix_memalign!");
+            }
+            else if (code != 0)
+                assert(0, "posix_memalign returned an unknown code!");
+
+            else
+                return result[0 .. bytes];
+        }
     }
     else version (Windows)
     @trusted @nogc nothrow
@@ -263,8 +349,13 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool deallocate(void[] b) shared
     {
-        import core.stdc.stdlib : free;
-        free(b.ptr);
+        static if (__traits(compiles, _aligned_free))
+            _aligned_free(b.ptr);
+        else
+        {
+            import core.stdc.stdlib : free;
+            free(b.ptr);
+        }
         return true;
     }
     else version (Windows)
@@ -284,7 +375,21 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool reallocate(ref void[] b, size_t newSize) shared
     {
-        return Mallocator.instance.reallocate(b, newSize);
+        static if (__traits(compiles, _aligned_realloc))
+        {
+            if (!newSize)
+            {
+                deallocate(b);
+                b = null;
+                return true;
+            }
+            auto p = cast(ubyte*) _aligned_realloc(b.ptr, newSize, alignment);
+            if (!p) return false;
+            b = p[0 .. newSize];
+            return true;
+        }
+        else
+            return Mallocator.instance.reallocate(b, newSize);
     }
     version (Windows)
     @system @nogc nothrow


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Add more uses of getTargetInfo(osxVersionMin). Implement posix_memalign if missing
@ 2021-10-11 20:35 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2021-10-11 20:35 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:203974b454a9f6698628e992f327865f3e8c6e3a

commit 203974b454a9f6698628e992f327865f3e8c6e3a
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Dec 6 00:19:39 2020 +0100

    libphobos: Add more uses of getTargetInfo(osxVersionMin).  Implement posix_memalign if missing

Diff:
---
 libphobos/libdruntime/core/stdc/math.d             |  20 +--
 libphobos/libdruntime/core/sys/darwin/config.d     |   8 ++
 libphobos/libdruntime/core/sys/darwin/mach/dyld.d  |  18 ++-
 libphobos/libdruntime/core/sys/darwin/pthread.d    |  35 +++--
 libphobos/libdruntime/core/sys/darwin/string.d     |   8 +-
 libphobos/libdruntime/core/sys/posix/stdio.d       |   4 +-
 libphobos/libdruntime/core/sys/posix/stdlib.d      |   8 +-
 .../src/std/experimental/allocator/mallocator.d    | 141 ++++++++++++++++++---
 8 files changed, 193 insertions(+), 49 deletions(-)

diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index 2de6e579575..7f15d569d0f 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -922,6 +922,8 @@ else version (CRuntime_UClibc)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum
     {
         ///
@@ -968,7 +970,15 @@ else version (Darwin)
     // Support of OSX < 10.8 needs legacy function names without "l" suffix
     // with exception of __signbitl.  Otherwise could use else version like
     // other Darwins
-    version (OSX)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_8)
+    {
+        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
+        pure int __fpclassifyl(real x);
+        pure int __isfinitel(real x);
+        pure int __isinfl(real x);
+        pure int __isnanl(real x);
+    }
+    else
     {
         version (AArch64)
         {
@@ -990,14 +1000,6 @@ else version (Darwin)
             alias __isnanl = __isnan;
         }
     }
-    else
-    {
-        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
-        pure int __fpclassifyl(real x);
-        pure int __isfinitel(real x);
-        pure int __isinfl(real x);
-        pure int __isnanl(real x);
-    }
 
   extern (D)
   {
diff --git a/libphobos/libdruntime/core/sys/darwin/config.d b/libphobos/libdruntime/core/sys/darwin/config.d
index 87f3fd4dae6..a6b94eda157 100644
--- a/libphobos/libdruntime/core/sys/darwin/config.d
+++ b/libphobos/libdruntime/core/sys/darwin/config.d
@@ -19,6 +19,14 @@ version (Darwin):
 
 public import core.sys.posix.config;
 
+// The compiler exposes `__traits(getTargetInfo, "osxVersionMin")` as a way to
+// obtain the lower bound support OSX version. In some compilers this is
+// controlled by a command-line option:
+//  -mmacosx-version-min=   (on OSX).
+//  -miphoneos-version-min= (on iOS)
+//  -mtvos-version-min=     (on TVOS)
+//  -mwatchos-version-min=  (on WatchOS)
+
 enum __MAC_10_0    = 100000;
 enum __MAC_10_1    = 100100;
 enum __MAC_10_2    = 100200;
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
index 6e28bfa655b..02d57433429 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
@@ -28,14 +28,18 @@ nothrow:
 
 public import core.stdc.stdint; // for intptr_t
 public import core.sys.darwin.mach.loader;
+import core.sys.darwin.config;
 
-uint         _dyld_image_count();
-const(char)* _dyld_get_image_name(uint image_index);
-mach_header* _dyld_get_image_header(uint image_index);
-intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
-
-void         _dyld_register_func_for_add_image(void function(const scope mach_header* mh, intptr_t vmaddr_slide));
-void         _dyld_register_func_for_remove_image(void function(const scope mach_header* mh, intptr_t vmaddr_slide));
+// __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_1)
+{
+    uint         _dyld_image_count();
+    const(char)* _dyld_get_image_name(uint image_index);
+    mach_header* _dyld_get_image_header(uint image_index);
+    intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
+    void         _dyld_register_func_for_add_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+    void         _dyld_register_func_for_remove_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+}
 
 int NSVersionOfRunTimeLibrary(const char* libraryPath);
 int NSVersionOfLinkTimeLibrary(const char* libraryPath);
diff --git a/libphobos/libdruntime/core/sys/darwin/pthread.d b/libphobos/libdruntime/core/sys/darwin/pthread.d
index 456cde96cbd..9a1aaafd440 100644
--- a/libphobos/libdruntime/core/sys/darwin/pthread.d
+++ b/libphobos/libdruntime/core/sys/darwin/pthread.d
@@ -29,22 +29,32 @@ nothrow:
 
 public import core.sys.posix.pthread;
 public import core.sys.darwin.mach.port;
+import core.sys.darwin.config;
 
 int pthread_is_threaded_np();
-int pthread_threadid_np(pthread_t, ulong*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
-int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
-int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_threadid_np(pthread_t, ulong*);
+}
+// __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+{
+    int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
+    int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
+}
 int pthread_rwlock_downgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_upgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_tryupgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_held_np(pthread_rwlock_t*);
 int pthread_rwlock_rdheld_np(pthread_rwlock_t*);
 int pthread_rwlock_wrheld_np(pthread_rwlock_t*);
-int pthread_getname_np(pthread_t, char*, size_t);
-int pthread_setname_np(const scope char*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_getname_np(pthread_t, char*, size_t);
+    int pthread_setname_np(in char*);
+}
 int pthread_main_np();
 mach_port_t pthread_mach_thread_np(pthread_t);
 size_t pthread_get_stacksize_np(pthread_t);
@@ -53,8 +63,11 @@ int pthread_cond_signal_thread_np(pthread_cond_t*, pthread_t);
 int pthread_cond_timedwait_relative_np(pthread_cond_t*, pthread_mutex_t*, const scope timespec*);
 int pthread_create_suspended_np(pthread_t*, const scope pthread_attr_t*, void* function(void*), void*);
 int pthread_kill(pthread_t, int);
-pthread_t pthread_from_mach_thread_np(mach_port_t);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
-int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
+// __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    pthread_t pthread_from_mach_thread_np(mach_port_t);
+}
+int pthread_sigmask(int, in sigset_t*, sigset_t*);
 // ^ __DARWIN_ALIAS(pthread_sigmask)
 void pthread_yield_np();
diff --git a/libphobos/libdruntime/core/sys/darwin/string.d b/libphobos/libdruntime/core/sys/darwin/string.d
index bd65fde27bc..20dcd1fdc81 100644
--- a/libphobos/libdruntime/core/sys/darwin/string.d
+++ b/libphobos/libdruntime/core/sys/darwin/string.d
@@ -9,6 +9,7 @@ module core.sys.darwin.string;
 
 public import core.stdc.string;
 import core.sys.darwin.sys.cdefs;
+import core.sys.darwin.config;
 
 version (OSX)
     version = Darwin;
@@ -26,6 +27,9 @@ nothrow:
 
 static if (__DARWIN_C_LEVEL >= __DARWIN_C_FULL)
 {
-    // ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
-    pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    // __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+    {
+        pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    }
 }
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index fcd9fcbc29c..2e38c0c7e2e 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -373,12 +373,14 @@ else version (CRuntime_Bionic)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum L_ctermid = 1024;
 
     int   fseeko(FILE*, off_t, int);
     off_t ftello(FILE*);
 
-    static if (__traits(getTargetInfo, "osxVersionMin") >= 100700)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
     {
         ssize_t getdelim(char**, size_t*, int, FILE*);
         ssize_t getline(char**, size_t*, FILE*);
diff --git a/libphobos/libdruntime/core/sys/posix/stdlib.d b/libphobos/libdruntime/core/sys/posix/stdlib.d
index 4c10d4e0ed5..57e369d41a5 100644
--- a/libphobos/libdruntime/core/sys/posix/stdlib.d
+++ b/libphobos/libdruntime/core/sys/posix/stdlib.d
@@ -119,7 +119,13 @@ else version (Solaris)
 }
 else version (Darwin)
 {
-    int posix_memalign(void**, size_t, size_t);
+    import core.sys.darwin.config;
+
+    // __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+    {
+        int posix_memalign(void**, size_t, size_t);
+    }
 }
 else version (CRuntime_Bionic)
 {
diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d
index 2d1dec39a74..6e1866bc976 100644
--- a/libphobos/src/std/experimental/allocator/mallocator.d
+++ b/libphobos/src/std/experimental/allocator/mallocator.d
@@ -194,6 +194,84 @@ version (Windows)
     }
 }
 
+version (Posix)
+{
+    // Not all platforms have posix_memalign available, supply own implementation
+    // if this is the case.  Avoid calling it posix_memalign because it needs
+    // special handling for realloc and free cases.
+    static if (!__traits(compiles, { import core.sys.posix.stdlib : posix_memalign; }))
+    {
+        // Helper to cast the infos written before the aligned pointer
+        // this header keeps track of the size (required to realloc) and of
+        // the base ptr (required to free).
+        private struct AlignInfo
+        {
+            void* basePtr;
+            size_t size;
+
+            @nogc nothrow
+            static AlignInfo* opCall(void* ptr)
+            {
+                return cast(AlignInfo*) (ptr - AlignInfo.sizeof);
+            }
+        }
+
+        @nogc nothrow
+        private void* _aligned_malloc(size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : malloc;
+            size_t offset = alignment + size_t.sizeof * 2 - 1;
+
+            // unaligned chunk
+            void* basePtr = malloc(size + offset);
+            if (!basePtr) return null;
+
+            // get aligned location within the chunk
+            void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset)
+                & ~(alignment - 1));
+
+            // write the header before the aligned pointer
+            AlignInfo* head = AlignInfo(alignedPtr);
+            head.basePtr = basePtr;
+            head.size = size;
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void* _aligned_realloc(void* ptr, size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : free;
+            import core.stdc.string : memcpy;
+
+            if (!ptr) return _aligned_malloc(size, alignment);
+
+            // gets the header from the exising pointer
+            AlignInfo* head = AlignInfo(ptr);
+
+            // gets a new aligned pointer
+            void* alignedPtr = _aligned_malloc(size, alignment);
+            if (!alignedPtr)
+                return null;
+
+            // copy exising data
+            memcpy(alignedPtr, ptr, head.size);
+            free(head.basePtr);
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void _aligned_free(void *ptr)
+        {
+            import core.stdc.stdlib : free;
+            if (!ptr) return;
+            AlignInfo* head = AlignInfo(ptr);
+            free(head.basePtr);
+        }
+    }
+}
+
 /**
    Aligned allocator using OS-specific primitives, under a uniform API.
  */
@@ -226,24 +304,32 @@ struct AlignedMallocator
     @trusted @nogc nothrow
     void[] alignedAllocate(size_t bytes, uint a) shared
     {
-        import core.stdc.errno : ENOMEM, EINVAL;
-        import core.sys.posix.stdlib : posix_memalign;
-        assert(a.isGoodDynamicAlignment);
-        void* result;
-        auto code = posix_memalign(&result, a, bytes);
-        if (code == ENOMEM)
-            return null;
-
-        else if (code == EINVAL)
+        static if (__traits(compiles, _aligned_malloc))
         {
-            assert(0, "AlignedMallocator.alignment is not a power of two "
-                ~"multiple of (void*).sizeof, according to posix_memalign!");
+            auto result = _aligned_malloc(bytes, a);
+            return result ? result[0 .. bytes] : null;
         }
-        else if (code != 0)
-            assert(0, "posix_memalign returned an unknown code!");
-
         else
-            return result[0 .. bytes];
+        {
+            import core.stdc.errno : ENOMEM, EINVAL;
+            import core.sys.posix.stdlib : posix_memalign;
+            assert(a.isGoodDynamicAlignment);
+            void* result;
+            auto code = posix_memalign(&result, a, bytes);
+            if (code == ENOMEM)
+                return null;
+
+            else if (code == EINVAL)
+            {
+                assert(0, "AlignedMallocator.alignment is not a power of two "
+                    ~"multiple of (void*).sizeof, according to posix_memalign!");
+            }
+            else if (code != 0)
+                assert(0, "posix_memalign returned an unknown code!");
+
+            else
+                return result[0 .. bytes];
+        }
     }
     else version (Windows)
     @trusted @nogc nothrow
@@ -263,8 +349,13 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool deallocate(void[] b) shared
     {
-        import core.stdc.stdlib : free;
-        free(b.ptr);
+        static if (__traits(compiles, _aligned_free))
+            _aligned_free(b.ptr);
+        else
+        {
+            import core.stdc.stdlib : free;
+            free(b.ptr);
+        }
         return true;
     }
     else version (Windows)
@@ -284,7 +375,21 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool reallocate(ref void[] b, size_t newSize) shared
     {
-        return Mallocator.instance.reallocate(b, newSize);
+        static if (__traits(compiles, _aligned_realloc))
+        {
+            if (!newSize)
+            {
+                deallocate(b);
+                b = null;
+                return true;
+            }
+            auto p = cast(ubyte*) _aligned_realloc(b.ptr, newSize, alignment);
+            if (!p) return false;
+            b = p[0 .. newSize];
+            return true;
+        }
+        else
+            return Mallocator.instance.reallocate(b, newSize);
     }
     version (Windows)
     @system @nogc nothrow


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Add more uses of getTargetInfo(osxVersionMin). Implement posix_memalign if missing
@ 2020-12-21 20:36 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2020-12-21 20:36 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:f229f836074315239753ca8e34b55ae0212b8abe

commit f229f836074315239753ca8e34b55ae0212b8abe
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Dec 6 00:19:39 2020 +0100

    libphobos: Add more uses of getTargetInfo(osxVersionMin).  Implement posix_memalign if missing

Diff:
---
 libphobos/libdruntime/Makefile.am                  |  18 +--
 libphobos/libdruntime/core/stdc/math.d             |  20 +--
 libphobos/libdruntime/core/sys/darwin/config.d     |  61 +++++++++
 libphobos/libdruntime/core/sys/darwin/mach/dyld.d  |  19 +--
 libphobos/libdruntime/core/sys/darwin/pthread.d    |  33 +++--
 libphobos/libdruntime/core/sys/darwin/string.d     |   8 +-
 libphobos/libdruntime/core/sys/posix/stdio.d       |   4 +-
 libphobos/libdruntime/core/sys/posix/stdlib.d      |   8 +-
 .../src/std/experimental/allocator/mallocator.d    | 141 ++++++++++++++++++---
 9 files changed, 254 insertions(+), 58 deletions(-)

diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 1ebc97af39d..124d5b049d0 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -215,15 +215,15 @@ DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
 DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/fcntl.d \
 	core/sys/bionic/string.d core/sys/bionic/unistd.d
 
-DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
-	core/sys/darwin/dlfcn.d core/sys/darwin/execinfo.d \
-	core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
-	core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
-	core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
-	core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
-	core/sys/darwin/pthread.d core/sys/darwin/string.d \
-	core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
-	core/sys/darwin/sys/mman.d
+DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/config.d \
+	core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d \
+	core/sys/darwin/execinfo.d core/sys/darwin/mach/dyld.d \
+	core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
+	core/sys/darwin/mach/loader.d core/sys/darwin/mach/port.d \
+	core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/thread_act.d \
+	core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
+	core/sys/darwin/string.d core/sys/darwin/sys/cdefs.d \
+	core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d
 
 DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
 	core/sys/dragonflybsd/execinfo.d core/sys/dragonflybsd/netinet/in_.d \
diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index 492978939d8..5578cfddd97 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -989,6 +989,8 @@ else version (MinGW)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum
     {
         ///
@@ -1035,7 +1037,15 @@ else version (Darwin)
     // Support of OSX < 10.8 needs legacy function names without "l" suffix
     // with exception of __signbitl.  Otherwise could use else version like
     // other Darwins
-    version (OSX)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_8)
+    {
+        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
+        pure int __fpclassifyl(real x);
+        pure int __isfinitel(real x);
+        pure int __isinfl(real x);
+        pure int __isnanl(real x);
+    }
+    else
     {
         pure int __fpclassify(real x);
         pure int __isfinite(real x);
@@ -1046,14 +1056,6 @@ else version (Darwin)
         alias __isinfl = __isinf;
         alias __isnanl = __isnan;
     }
-    else
-    {
-        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
-        pure int __fpclassifyl(real x);
-        pure int __isfinitel(real x);
-        pure int __isinfl(real x);
-        pure int __isnanl(real x);
-    }
 
   extern (D)
   {
diff --git a/libphobos/libdruntime/core/sys/darwin/config.d b/libphobos/libdruntime/core/sys/darwin/config.d
new file mode 100644
index 00000000000..347aea41f6b
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/darwin/config.d
@@ -0,0 +1,61 @@
+/**
+ * D header file for Darwin.
+ *
+ * Copyright: Copyright (c) 2020 D Language Foundation
+ * Authors: Iain Buclaw
+ */
+module core.sys.darwin.config;
+
+version (OSX)
+    version = Darwin;
+else version (iOS)
+    version = Darwin;
+else version (TVOS)
+    version = Darwin;
+else version (WatchOS)
+    version = Darwin;
+
+version (Darwin):
+
+public import core.sys.posix.config;
+
+// The compiler exposes `__traits(getTargetInfo, "osxVersionMin")` as a way to
+// obtain the lower bound support OSX version. In some compilers this is
+// controlled by a command-line option:
+//  -mmacosx-version-min=   (on OSX).
+//  -miphoneos-version-min= (on iOS)
+//  -mtvos-version-min=     (on TVOS)
+//  -mwatchos-version-min=  (on WatchOS)
+
+enum __MAC_10_0    = 100000;
+enum __MAC_10_1    = 100100;
+enum __MAC_10_2    = 100200;
+enum __MAC_10_3    = 100300;
+enum __MAC_10_4    = 100400;
+enum __MAC_10_5    = 100500;
+enum __MAC_10_6    = 100600;
+enum __MAC_10_7    = 100700;
+enum __MAC_10_8    = 100800;
+enum __MAC_10_9    = 100900;
+enum __MAC_10_10   = 101000;
+enum __MAC_10_10_2 = 101002;
+enum __MAC_10_10_3 = 101003;
+enum __MAC_10_11   = 101100;
+enum __MAC_10_11_2 = 101102;
+enum __MAC_10_11_3 = 101103;
+enum __MAC_10_11_4 = 101104;
+enum __MAC_10_12   = 101200;
+enum __MAC_10_12_1 = 101201;
+enum __MAC_10_12_2 = 101202;
+enum __MAC_10_12_4 = 101204;
+enum __MAC_10_13   = 101300;
+enum __MAC_10_13_1 = 101301;
+enum __MAC_10_13_2 = 101302;
+enum __MAC_10_13_4 = 101304;
+enum __MAC_10_14   = 101400;
+enum __MAC_10_14_1 = 101401;
+enum __MAC_10_14_4 = 101404;
+enum __MAC_10_15   = 101500;
+enum __MAC_10_15_1 = 101501;
+enum __MAC_10_16   = 101501;
+enum __MAC_11_0    = 110000;
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
index 5bf5609a203..cfb333559f5 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
@@ -28,12 +28,15 @@ nothrow:
 
 public import core.stdc.stdint; // for intptr_t
 public import core.sys.darwin.mach.loader;
+import core.sys.darwin.config;
 
-uint         _dyld_image_count();
-const(char)* _dyld_get_image_name(uint image_index);
-mach_header* _dyld_get_image_header(uint image_index);
-intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
-void         _dyld_register_func_for_add_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
-void         _dyld_register_func_for_remove_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
-
-
+// __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_1)
+{
+    uint         _dyld_image_count();
+    const(char)* _dyld_get_image_name(uint image_index);
+    mach_header* _dyld_get_image_header(uint image_index);
+    intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
+    void         _dyld_register_func_for_add_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+    void         _dyld_register_func_for_remove_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+}
diff --git a/libphobos/libdruntime/core/sys/darwin/pthread.d b/libphobos/libdruntime/core/sys/darwin/pthread.d
index 786d9f2833d..d70ab58e54a 100644
--- a/libphobos/libdruntime/core/sys/darwin/pthread.d
+++ b/libphobos/libdruntime/core/sys/darwin/pthread.d
@@ -29,22 +29,32 @@ nothrow:
 
 public import core.sys.posix.pthread;
 public import core.sys.darwin.mach.port;
+import core.sys.darwin.config;
 
 int pthread_is_threaded_np();
-int pthread_threadid_np(pthread_t, ulong*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
-int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
-int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_threadid_np(pthread_t, ulong*);
+}
+// __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+{
+    int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
+    int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
+}
 int pthread_rwlock_downgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_upgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_tryupgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_held_np(pthread_rwlock_t*);
 int pthread_rwlock_rdheld_np(pthread_rwlock_t*);
 int pthread_rwlock_wrheld_np(pthread_rwlock_t*);
-int pthread_getname_np(pthread_t, char*, size_t);
-int pthread_setname_np(in char*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_getname_np(pthread_t, char*, size_t);
+    int pthread_setname_np(in char*);
+}
 int pthread_main_np();
 mach_port_t pthread_mach_thread_np(pthread_t);
 size_t pthread_get_stacksize_np(pthread_t);
@@ -53,8 +63,11 @@ int pthread_cond_signal_thread_np(pthread_cond_t*, pthread_t);
 int pthread_cond_timedwait_relative_np(pthread_cond_t*, pthread_mutex_t*, in timespec*);
 int pthread_create_suspended_np(pthread_t*, in pthread_attr_t*, void* function(void*), void*);
 int pthread_kill(pthread_t, int);
-pthread_t pthread_from_mach_thread_np(mach_port_t);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
+// __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    pthread_t pthread_from_mach_thread_np(mach_port_t);
+}
 int pthread_sigmask(int, in sigset_t*, sigset_t*);
 // ^ __DARWIN_ALIAS(pthread_sigmask)
 void pthread_yield_np();
diff --git a/libphobos/libdruntime/core/sys/darwin/string.d b/libphobos/libdruntime/core/sys/darwin/string.d
index bd65fde27bc..20dcd1fdc81 100644
--- a/libphobos/libdruntime/core/sys/darwin/string.d
+++ b/libphobos/libdruntime/core/sys/darwin/string.d
@@ -9,6 +9,7 @@ module core.sys.darwin.string;
 
 public import core.stdc.string;
 import core.sys.darwin.sys.cdefs;
+import core.sys.darwin.config;
 
 version (OSX)
     version = Darwin;
@@ -26,6 +27,9 @@ nothrow:
 
 static if (__DARWIN_C_LEVEL >= __DARWIN_C_FULL)
 {
-    // ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
-    pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    // __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+    {
+        pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    }
 }
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index 0b3f8436254..932923321f9 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -372,12 +372,14 @@ else version (CRuntime_Bionic)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum L_ctermid = 1024;
 
     int   fseeko(FILE*, off_t, int);
     off_t ftello(FILE*);
 
-    static if (__traits(getTargetInfo, "osxVersionMin") >= 100700)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
     {
         ssize_t getdelim(char**, size_t*, int, FILE*);
         ssize_t getline(char**, size_t*, FILE*);
diff --git a/libphobos/libdruntime/core/sys/posix/stdlib.d b/libphobos/libdruntime/core/sys/posix/stdlib.d
index a218f958077..e7c09f640c1 100644
--- a/libphobos/libdruntime/core/sys/posix/stdlib.d
+++ b/libphobos/libdruntime/core/sys/posix/stdlib.d
@@ -118,7 +118,13 @@ else version (Solaris)
 }
 else version (Darwin)
 {
-    int posix_memalign(void**, size_t, size_t);
+    import core.sys.darwin.config;
+
+    // __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+    {
+        int posix_memalign(void**, size_t, size_t);
+    }
 }
 else version (CRuntime_Bionic)
 {
diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d
index 2d1dec39a74..6e1866bc976 100644
--- a/libphobos/src/std/experimental/allocator/mallocator.d
+++ b/libphobos/src/std/experimental/allocator/mallocator.d
@@ -194,6 +194,84 @@ version (Windows)
     }
 }
 
+version (Posix)
+{
+    // Not all platforms have posix_memalign available, supply own implementation
+    // if this is the case.  Avoid calling it posix_memalign because it needs
+    // special handling for realloc and free cases.
+    static if (!__traits(compiles, { import core.sys.posix.stdlib : posix_memalign; }))
+    {
+        // Helper to cast the infos written before the aligned pointer
+        // this header keeps track of the size (required to realloc) and of
+        // the base ptr (required to free).
+        private struct AlignInfo
+        {
+            void* basePtr;
+            size_t size;
+
+            @nogc nothrow
+            static AlignInfo* opCall(void* ptr)
+            {
+                return cast(AlignInfo*) (ptr - AlignInfo.sizeof);
+            }
+        }
+
+        @nogc nothrow
+        private void* _aligned_malloc(size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : malloc;
+            size_t offset = alignment + size_t.sizeof * 2 - 1;
+
+            // unaligned chunk
+            void* basePtr = malloc(size + offset);
+            if (!basePtr) return null;
+
+            // get aligned location within the chunk
+            void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset)
+                & ~(alignment - 1));
+
+            // write the header before the aligned pointer
+            AlignInfo* head = AlignInfo(alignedPtr);
+            head.basePtr = basePtr;
+            head.size = size;
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void* _aligned_realloc(void* ptr, size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : free;
+            import core.stdc.string : memcpy;
+
+            if (!ptr) return _aligned_malloc(size, alignment);
+
+            // gets the header from the exising pointer
+            AlignInfo* head = AlignInfo(ptr);
+
+            // gets a new aligned pointer
+            void* alignedPtr = _aligned_malloc(size, alignment);
+            if (!alignedPtr)
+                return null;
+
+            // copy exising data
+            memcpy(alignedPtr, ptr, head.size);
+            free(head.basePtr);
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void _aligned_free(void *ptr)
+        {
+            import core.stdc.stdlib : free;
+            if (!ptr) return;
+            AlignInfo* head = AlignInfo(ptr);
+            free(head.basePtr);
+        }
+    }
+}
+
 /**
    Aligned allocator using OS-specific primitives, under a uniform API.
  */
@@ -226,24 +304,32 @@ struct AlignedMallocator
     @trusted @nogc nothrow
     void[] alignedAllocate(size_t bytes, uint a) shared
     {
-        import core.stdc.errno : ENOMEM, EINVAL;
-        import core.sys.posix.stdlib : posix_memalign;
-        assert(a.isGoodDynamicAlignment);
-        void* result;
-        auto code = posix_memalign(&result, a, bytes);
-        if (code == ENOMEM)
-            return null;
-
-        else if (code == EINVAL)
+        static if (__traits(compiles, _aligned_malloc))
         {
-            assert(0, "AlignedMallocator.alignment is not a power of two "
-                ~"multiple of (void*).sizeof, according to posix_memalign!");
+            auto result = _aligned_malloc(bytes, a);
+            return result ? result[0 .. bytes] : null;
         }
-        else if (code != 0)
-            assert(0, "posix_memalign returned an unknown code!");
-
         else
-            return result[0 .. bytes];
+        {
+            import core.stdc.errno : ENOMEM, EINVAL;
+            import core.sys.posix.stdlib : posix_memalign;
+            assert(a.isGoodDynamicAlignment);
+            void* result;
+            auto code = posix_memalign(&result, a, bytes);
+            if (code == ENOMEM)
+                return null;
+
+            else if (code == EINVAL)
+            {
+                assert(0, "AlignedMallocator.alignment is not a power of two "
+                    ~"multiple of (void*).sizeof, according to posix_memalign!");
+            }
+            else if (code != 0)
+                assert(0, "posix_memalign returned an unknown code!");
+
+            else
+                return result[0 .. bytes];
+        }
     }
     else version (Windows)
     @trusted @nogc nothrow
@@ -263,8 +349,13 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool deallocate(void[] b) shared
     {
-        import core.stdc.stdlib : free;
-        free(b.ptr);
+        static if (__traits(compiles, _aligned_free))
+            _aligned_free(b.ptr);
+        else
+        {
+            import core.stdc.stdlib : free;
+            free(b.ptr);
+        }
         return true;
     }
     else version (Windows)
@@ -284,7 +375,21 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool reallocate(ref void[] b, size_t newSize) shared
     {
-        return Mallocator.instance.reallocate(b, newSize);
+        static if (__traits(compiles, _aligned_realloc))
+        {
+            if (!newSize)
+            {
+                deallocate(b);
+                b = null;
+                return true;
+            }
+            auto p = cast(ubyte*) _aligned_realloc(b.ptr, newSize, alignment);
+            if (!p) return false;
+            b = p[0 .. newSize];
+            return true;
+        }
+        else
+            return Mallocator.instance.reallocate(b, newSize);
     }
     version (Windows)
     @system @nogc nothrow


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Add more uses of getTargetInfo(osxVersionMin). Implement posix_memalign if missing
@ 2020-12-13 17:43 Iain D Sandoe
  0 siblings, 0 replies; 6+ messages in thread
From: Iain D Sandoe @ 2020-12-13 17:43 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:3b8c2098450ad985c03f3111200c725d31dc47e4

commit 3b8c2098450ad985c03f3111200c725d31dc47e4
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Sun Dec 6 00:19:39 2020 +0100

    libphobos: Add more uses of getTargetInfo(osxVersionMin).  Implement posix_memalign if missing

Diff:
---
 libphobos/libdruntime/Makefile.am                  |  18 +--
 libphobos/libdruntime/core/stdc/math.d             |  20 +--
 libphobos/libdruntime/core/sys/darwin/config.d     |  61 +++++++++
 libphobos/libdruntime/core/sys/darwin/mach/dyld.d  |  19 +--
 libphobos/libdruntime/core/sys/darwin/pthread.d    |  33 +++--
 libphobos/libdruntime/core/sys/darwin/string.d     |   8 +-
 libphobos/libdruntime/core/sys/posix/stdio.d       |   4 +-
 libphobos/libdruntime/core/sys/posix/stdlib.d      |   8 +-
 .../src/std/experimental/allocator/mallocator.d    | 141 ++++++++++++++++++---
 9 files changed, 254 insertions(+), 58 deletions(-)

diff --git a/libphobos/libdruntime/Makefile.am b/libphobos/libdruntime/Makefile.am
index 1ebc97af39d..124d5b049d0 100644
--- a/libphobos/libdruntime/Makefile.am
+++ b/libphobos/libdruntime/Makefile.am
@@ -215,15 +215,15 @@ DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
 DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/fcntl.d \
 	core/sys/bionic/string.d core/sys/bionic/unistd.d
 
-DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/crt_externs.d \
-	core/sys/darwin/dlfcn.d core/sys/darwin/execinfo.d \
-	core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d \
-	core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d \
-	core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d \
-	core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d \
-	core/sys/darwin/pthread.d core/sys/darwin/string.d \
-	core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d \
-	core/sys/darwin/sys/mman.d
+DRUNTIME_DSOURCES_DARWIN = core/sys/darwin/config.d \
+	core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d \
+	core/sys/darwin/execinfo.d core/sys/darwin/mach/dyld.d \
+	core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d \
+	core/sys/darwin/mach/loader.d core/sys/darwin/mach/port.d \
+	core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/thread_act.d \
+	core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d \
+	core/sys/darwin/string.d core/sys/darwin/sys/cdefs.d \
+	core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d
 
 DRUNTIME_DSOURCES_DRAGONFLYBSD = core/sys/dragonflybsd/dlfcn.d \
 	core/sys/dragonflybsd/execinfo.d core/sys/dragonflybsd/netinet/in_.d \
diff --git a/libphobos/libdruntime/core/stdc/math.d b/libphobos/libdruntime/core/stdc/math.d
index 492978939d8..5578cfddd97 100644
--- a/libphobos/libdruntime/core/stdc/math.d
+++ b/libphobos/libdruntime/core/stdc/math.d
@@ -989,6 +989,8 @@ else version (MinGW)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum
     {
         ///
@@ -1035,7 +1037,15 @@ else version (Darwin)
     // Support of OSX < 10.8 needs legacy function names without "l" suffix
     // with exception of __signbitl.  Otherwise could use else version like
     // other Darwins
-    version (OSX)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_8)
+    {
+        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
+        pure int __fpclassifyl(real x);
+        pure int __isfinitel(real x);
+        pure int __isinfl(real x);
+        pure int __isnanl(real x);
+    }
+    else
     {
         pure int __fpclassify(real x);
         pure int __isfinite(real x);
@@ -1046,14 +1056,6 @@ else version (Darwin)
         alias __isinfl = __isinf;
         alias __isnanl = __isnan;
     }
-    else
-    {
-        // Available OSX >= 10.8, iOS >= 6.0, all TVOS and WatchOS
-        pure int __fpclassifyl(real x);
-        pure int __isfinitel(real x);
-        pure int __isinfl(real x);
-        pure int __isnanl(real x);
-    }
 
   extern (D)
   {
diff --git a/libphobos/libdruntime/core/sys/darwin/config.d b/libphobos/libdruntime/core/sys/darwin/config.d
new file mode 100644
index 00000000000..347aea41f6b
--- /dev/null
+++ b/libphobos/libdruntime/core/sys/darwin/config.d
@@ -0,0 +1,61 @@
+/**
+ * D header file for Darwin.
+ *
+ * Copyright: Copyright (c) 2020 D Language Foundation
+ * Authors: Iain Buclaw
+ */
+module core.sys.darwin.config;
+
+version (OSX)
+    version = Darwin;
+else version (iOS)
+    version = Darwin;
+else version (TVOS)
+    version = Darwin;
+else version (WatchOS)
+    version = Darwin;
+
+version (Darwin):
+
+public import core.sys.posix.config;
+
+// The compiler exposes `__traits(getTargetInfo, "osxVersionMin")` as a way to
+// obtain the lower bound support OSX version. In some compilers this is
+// controlled by a command-line option:
+//  -mmacosx-version-min=   (on OSX).
+//  -miphoneos-version-min= (on iOS)
+//  -mtvos-version-min=     (on TVOS)
+//  -mwatchos-version-min=  (on WatchOS)
+
+enum __MAC_10_0    = 100000;
+enum __MAC_10_1    = 100100;
+enum __MAC_10_2    = 100200;
+enum __MAC_10_3    = 100300;
+enum __MAC_10_4    = 100400;
+enum __MAC_10_5    = 100500;
+enum __MAC_10_6    = 100600;
+enum __MAC_10_7    = 100700;
+enum __MAC_10_8    = 100800;
+enum __MAC_10_9    = 100900;
+enum __MAC_10_10   = 101000;
+enum __MAC_10_10_2 = 101002;
+enum __MAC_10_10_3 = 101003;
+enum __MAC_10_11   = 101100;
+enum __MAC_10_11_2 = 101102;
+enum __MAC_10_11_3 = 101103;
+enum __MAC_10_11_4 = 101104;
+enum __MAC_10_12   = 101200;
+enum __MAC_10_12_1 = 101201;
+enum __MAC_10_12_2 = 101202;
+enum __MAC_10_12_4 = 101204;
+enum __MAC_10_13   = 101300;
+enum __MAC_10_13_1 = 101301;
+enum __MAC_10_13_2 = 101302;
+enum __MAC_10_13_4 = 101304;
+enum __MAC_10_14   = 101400;
+enum __MAC_10_14_1 = 101401;
+enum __MAC_10_14_4 = 101404;
+enum __MAC_10_15   = 101500;
+enum __MAC_10_15_1 = 101501;
+enum __MAC_10_16   = 101501;
+enum __MAC_11_0    = 110000;
diff --git a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
index 5bf5609a203..cfb333559f5 100644
--- a/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
+++ b/libphobos/libdruntime/core/sys/darwin/mach/dyld.d
@@ -28,12 +28,15 @@ nothrow:
 
 public import core.stdc.stdint; // for intptr_t
 public import core.sys.darwin.mach.loader;
+import core.sys.darwin.config;
 
-uint         _dyld_image_count();
-const(char)* _dyld_get_image_name(uint image_index);
-mach_header* _dyld_get_image_header(uint image_index);
-intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
-void         _dyld_register_func_for_add_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
-void         _dyld_register_func_for_remove_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
-
-
+// __OSX_AVAILABLE_STARTING(__MAC_10_1, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_1)
+{
+    uint         _dyld_image_count();
+    const(char)* _dyld_get_image_name(uint image_index);
+    mach_header* _dyld_get_image_header(uint image_index);
+    intptr_t     _dyld_get_image_vmaddr_slide(uint image_index);
+    void         _dyld_register_func_for_add_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+    void         _dyld_register_func_for_remove_image(void function(in mach_header* mh, intptr_t vmaddr_slide));
+}
diff --git a/libphobos/libdruntime/core/sys/darwin/pthread.d b/libphobos/libdruntime/core/sys/darwin/pthread.d
index 786d9f2833d..d70ab58e54a 100644
--- a/libphobos/libdruntime/core/sys/darwin/pthread.d
+++ b/libphobos/libdruntime/core/sys/darwin/pthread.d
@@ -29,22 +29,32 @@ nothrow:
 
 public import core.sys.posix.pthread;
 public import core.sys.darwin.mach.port;
+import core.sys.darwin.config;
 
 int pthread_is_threaded_np();
-int pthread_threadid_np(pthread_t, ulong*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
-int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
-int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_threadid_np(pthread_t, ulong*);
+}
+// __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+{
+    int pthread_rwlock_longrdlock_np(pthread_rwlock_t*);
+    int pthread_rwlock_yieldwrlock_np(pthread_rwlock_t*);
+}
 int pthread_rwlock_downgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_upgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_tryupgrade_np(pthread_rwlock_t*);
 int pthread_rwlock_held_np(pthread_rwlock_t*);
 int pthread_rwlock_rdheld_np(pthread_rwlock_t*);
 int pthread_rwlock_wrheld_np(pthread_rwlock_t*);
-int pthread_getname_np(pthread_t, char*, size_t);
-int pthread_setname_np(in char*);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+// __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+{
+    int pthread_getname_np(pthread_t, char*, size_t);
+    int pthread_setname_np(in char*);
+}
 int pthread_main_np();
 mach_port_t pthread_mach_thread_np(pthread_t);
 size_t pthread_get_stacksize_np(pthread_t);
@@ -53,8 +63,11 @@ int pthread_cond_signal_thread_np(pthread_cond_t*, pthread_t);
 int pthread_cond_timedwait_relative_np(pthread_cond_t*, pthread_mutex_t*, in timespec*);
 int pthread_create_suspended_np(pthread_t*, in pthread_attr_t*, void* function(void*), void*);
 int pthread_kill(pthread_t, int);
-pthread_t pthread_from_mach_thread_np(mach_port_t);
-// ^ __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
+// __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0)
+static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_5)
+{
+    pthread_t pthread_from_mach_thread_np(mach_port_t);
+}
 int pthread_sigmask(int, in sigset_t*, sigset_t*);
 // ^ __DARWIN_ALIAS(pthread_sigmask)
 void pthread_yield_np();
diff --git a/libphobos/libdruntime/core/sys/darwin/string.d b/libphobos/libdruntime/core/sys/darwin/string.d
index bd65fde27bc..20dcd1fdc81 100644
--- a/libphobos/libdruntime/core/sys/darwin/string.d
+++ b/libphobos/libdruntime/core/sys/darwin/string.d
@@ -9,6 +9,7 @@ module core.sys.darwin.string;
 
 public import core.stdc.string;
 import core.sys.darwin.sys.cdefs;
+import core.sys.darwin.config;
 
 version (OSX)
     version = Darwin;
@@ -26,6 +27,9 @@ nothrow:
 
 static if (__DARWIN_C_LEVEL >= __DARWIN_C_FULL)
 {
-    // ^ __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
-    pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    // __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
+    {
+        pure void* memmem(return const void* haystack, size_t haystacklen, scope const void* needle, size_t needlelen);
+    }
 }
diff --git a/libphobos/libdruntime/core/sys/posix/stdio.d b/libphobos/libdruntime/core/sys/posix/stdio.d
index 0b3f8436254..932923321f9 100644
--- a/libphobos/libdruntime/core/sys/posix/stdio.d
+++ b/libphobos/libdruntime/core/sys/posix/stdio.d
@@ -372,12 +372,14 @@ else version (CRuntime_Bionic)
 }
 else version (Darwin)
 {
+    import core.sys.darwin.config;
+
     enum L_ctermid = 1024;
 
     int   fseeko(FILE*, off_t, int);
     off_t ftello(FILE*);
 
-    static if (__traits(getTargetInfo, "osxVersionMin") >= 100700)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_7)
     {
         ssize_t getdelim(char**, size_t*, int, FILE*);
         ssize_t getline(char**, size_t*, FILE*);
diff --git a/libphobos/libdruntime/core/sys/posix/stdlib.d b/libphobos/libdruntime/core/sys/posix/stdlib.d
index a218f958077..e7c09f640c1 100644
--- a/libphobos/libdruntime/core/sys/posix/stdlib.d
+++ b/libphobos/libdruntime/core/sys/posix/stdlib.d
@@ -118,7 +118,13 @@ else version (Solaris)
 }
 else version (Darwin)
 {
-    int posix_memalign(void**, size_t, size_t);
+    import core.sys.darwin.config;
+
+    // __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
+    static if (__traits(getTargetInfo, "osxVersionMin") >= __MAC_10_6)
+    {
+        int posix_memalign(void**, size_t, size_t);
+    }
 }
 else version (CRuntime_Bionic)
 {
diff --git a/libphobos/src/std/experimental/allocator/mallocator.d b/libphobos/src/std/experimental/allocator/mallocator.d
index 2d1dec39a74..6e1866bc976 100644
--- a/libphobos/src/std/experimental/allocator/mallocator.d
+++ b/libphobos/src/std/experimental/allocator/mallocator.d
@@ -194,6 +194,84 @@ version (Windows)
     }
 }
 
+version (Posix)
+{
+    // Not all platforms have posix_memalign available, supply own implementation
+    // if this is the case.  Avoid calling it posix_memalign because it needs
+    // special handling for realloc and free cases.
+    static if (!__traits(compiles, { import core.sys.posix.stdlib : posix_memalign; }))
+    {
+        // Helper to cast the infos written before the aligned pointer
+        // this header keeps track of the size (required to realloc) and of
+        // the base ptr (required to free).
+        private struct AlignInfo
+        {
+            void* basePtr;
+            size_t size;
+
+            @nogc nothrow
+            static AlignInfo* opCall(void* ptr)
+            {
+                return cast(AlignInfo*) (ptr - AlignInfo.sizeof);
+            }
+        }
+
+        @nogc nothrow
+        private void* _aligned_malloc(size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : malloc;
+            size_t offset = alignment + size_t.sizeof * 2 - 1;
+
+            // unaligned chunk
+            void* basePtr = malloc(size + offset);
+            if (!basePtr) return null;
+
+            // get aligned location within the chunk
+            void* alignedPtr = cast(void**)((cast(size_t)(basePtr) + offset)
+                & ~(alignment - 1));
+
+            // write the header before the aligned pointer
+            AlignInfo* head = AlignInfo(alignedPtr);
+            head.basePtr = basePtr;
+            head.size = size;
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void* _aligned_realloc(void* ptr, size_t size, size_t alignment)
+        {
+            import core.stdc.stdlib : free;
+            import core.stdc.string : memcpy;
+
+            if (!ptr) return _aligned_malloc(size, alignment);
+
+            // gets the header from the exising pointer
+            AlignInfo* head = AlignInfo(ptr);
+
+            // gets a new aligned pointer
+            void* alignedPtr = _aligned_malloc(size, alignment);
+            if (!alignedPtr)
+                return null;
+
+            // copy exising data
+            memcpy(alignedPtr, ptr, head.size);
+            free(head.basePtr);
+
+            return alignedPtr;
+        }
+
+        @nogc nothrow
+        private void _aligned_free(void *ptr)
+        {
+            import core.stdc.stdlib : free;
+            if (!ptr) return;
+            AlignInfo* head = AlignInfo(ptr);
+            free(head.basePtr);
+        }
+    }
+}
+
 /**
    Aligned allocator using OS-specific primitives, under a uniform API.
  */
@@ -226,24 +304,32 @@ struct AlignedMallocator
     @trusted @nogc nothrow
     void[] alignedAllocate(size_t bytes, uint a) shared
     {
-        import core.stdc.errno : ENOMEM, EINVAL;
-        import core.sys.posix.stdlib : posix_memalign;
-        assert(a.isGoodDynamicAlignment);
-        void* result;
-        auto code = posix_memalign(&result, a, bytes);
-        if (code == ENOMEM)
-            return null;
-
-        else if (code == EINVAL)
+        static if (__traits(compiles, _aligned_malloc))
         {
-            assert(0, "AlignedMallocator.alignment is not a power of two "
-                ~"multiple of (void*).sizeof, according to posix_memalign!");
+            auto result = _aligned_malloc(bytes, a);
+            return result ? result[0 .. bytes] : null;
         }
-        else if (code != 0)
-            assert(0, "posix_memalign returned an unknown code!");
-
         else
-            return result[0 .. bytes];
+        {
+            import core.stdc.errno : ENOMEM, EINVAL;
+            import core.sys.posix.stdlib : posix_memalign;
+            assert(a.isGoodDynamicAlignment);
+            void* result;
+            auto code = posix_memalign(&result, a, bytes);
+            if (code == ENOMEM)
+                return null;
+
+            else if (code == EINVAL)
+            {
+                assert(0, "AlignedMallocator.alignment is not a power of two "
+                    ~"multiple of (void*).sizeof, according to posix_memalign!");
+            }
+            else if (code != 0)
+                assert(0, "posix_memalign returned an unknown code!");
+
+            else
+                return result[0 .. bytes];
+        }
     }
     else version (Windows)
     @trusted @nogc nothrow
@@ -263,8 +349,13 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool deallocate(void[] b) shared
     {
-        import core.stdc.stdlib : free;
-        free(b.ptr);
+        static if (__traits(compiles, _aligned_free))
+            _aligned_free(b.ptr);
+        else
+        {
+            import core.stdc.stdlib : free;
+            free(b.ptr);
+        }
         return true;
     }
     else version (Windows)
@@ -284,7 +375,21 @@ struct AlignedMallocator
     @system @nogc nothrow
     bool reallocate(ref void[] b, size_t newSize) shared
     {
-        return Mallocator.instance.reallocate(b, newSize);
+        static if (__traits(compiles, _aligned_realloc))
+        {
+            if (!newSize)
+            {
+                deallocate(b);
+                b = null;
+                return true;
+            }
+            auto p = cast(ubyte*) _aligned_realloc(b.ptr, newSize, alignment);
+            if (!p) return false;
+            b = p[0 .. newSize];
+            return true;
+        }
+        else
+            return Mallocator.instance.reallocate(b, newSize);
     }
     version (Windows)
     @system @nogc nothrow


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-10-18 15:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-15 19:33 [gcc(refs/users/iains/heads/d-for-darwin)] libphobos: Add more uses of getTargetInfo(osxVersionMin). Implement posix_memalign if missing Iain D Sandoe
  -- strict thread matches above, loose matches on Subject: below --
2021-10-18 15:54 Iain D Sandoe
2021-10-13  8:30 Iain D Sandoe
2021-10-11 20:35 Iain D Sandoe
2020-12-21 20:36 Iain D Sandoe
2020-12-13 17:43 Iain D Sandoe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).