void function(void*) xdtor;
void function(void*) xpostblit;
uint m_align;
- version (X86_64)
- TypeInfo m_arg1;
- TypeInfo m_arg2;
immutable(void)* xgetRTInfo; */
void visit (TypeInfoStructDeclaration *d)
/* uint m_align; */
this->layout_field (build_integer_cst (ti->alignsize (), d_uint_type));
- if (global.params.is64bit)
- {
- /* TypeInfo m_arg1; */
- tree arg1type = (sd->arg1type) ? build_typeinfo (d->loc, sd->arg1type)
- : null_pointer_node;
- this->layout_field (arg1type);
-
- /* TypeInfo m_arg2; */
- tree arg2type = (sd->arg2type) ? build_typeinfo (d->loc, sd->arg2type)
- : null_pointer_node;
- this->layout_field (arg2type);
- }
-
/* immutable(void)* xgetRTInfo; */
if (sd->getRTInfo)
this->layout_field (build_expr (sd->getRTInfo, true));
@SET_MAKE@
# Makefile for the toplevel directory of the D Standard library.
-# Copyright (C) 2006-2020 Free Software Foundation, Inc.
+# Copyright (C) 2006-2021 Free Software Foundation, Inc.
#
# GCC is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11759 "configure"
+#line 11749 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11865 "configure"
+#line 11855 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
-0fe7974cf53b75db59461de2a3d6e53ce933d297
+e4aae28e36c118f13e346a61af6c413aadd8e838
The first line of this file holds the git revision number of the last
merge done from the dlang/druntime repository.
core/stdc/tgmath.d core/stdc/time.d core/stdc/wchar_.d \
core/stdc/wctype.d core/sync/barrier.d core/sync/condition.d \
core/sync/config.d core/sync/exception.d core/sync/mutex.d \
- core/sync/rwmutex.d core/sync/semaphore.d core/thread.d core/time.d \
- core/vararg.d gc/bits.d gc/config.d gc/gcinterface.d \
+ core/sync/rwmutex.d core/sync/semaphore.d core/thread/context.d \
+ core/thread/fiber.d core/thread/osthread.d core/thread/package.d \
+ core/thread/threadbase.d core/thread/threadgroup.d core/thread/types.d \
+ core/time.d core/vararg.d gc/bits.d gc/config.d gc/gcinterface.d \
gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
rt/cast_.d rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d \
rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \
rt/obj.d rt/qsort.d rt/sections.d rt/switch_.d rt/tlsgc.d \
- rt/typeinfo/ti_Acdouble.d rt/typeinfo/ti_Acfloat.d \
- rt/typeinfo/ti_Acreal.d rt/typeinfo/ti_Adouble.d \
- rt/typeinfo/ti_Afloat.d rt/typeinfo/ti_Ag.d rt/typeinfo/ti_Aint.d \
- rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
- rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
- rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
- rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
- rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
- rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
- rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
- rt/typeinfo/ti_long.d rt/typeinfo/ti_n.d rt/typeinfo/ti_ptr.d \
- rt/typeinfo/ti_real.d rt/typeinfo/ti_short.d rt/typeinfo/ti_ubyte.d \
- rt/typeinfo/ti_ucent.d rt/typeinfo/ti_uint.d rt/typeinfo/ti_ulong.d \
- rt/typeinfo/ti_ushort.d rt/typeinfo/ti_void.d rt/typeinfo/ti_wchar.d \
rt/util/array.d rt/util/container/array.d rt/util/container/common.d \
rt/util/container/hashtab.d rt/util/container/treap.d rt/util/random.d \
rt/util/typeinfo.d rt/util/utf.d
DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
core/stdcpp/typeinfo.d
-DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/fcntl.d \
- core/sys/bionic/string.d core/sys/bionic/unistd.d
+DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \
+ 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/dlfcn.d core/sys/darwin/err.d \
+ core/sys/darwin/execinfo.d core/sys/darwin/ifaddrs.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/nlist.d core/sys/darwin/mach/port.d \
+ core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.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
+ core/sys/darwin/sys/attr.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 \
- core/sys/dragonflybsd/pthread_np.d core/sys/dragonflybsd/string.d \
- core/sys/dragonflybsd/sys/_bitset.d \
+ core/sys/dragonflybsd/err.d core/sys/dragonflybsd/execinfo.d \
+ core/sys/dragonflybsd/netinet/in_.d core/sys/dragonflybsd/pthread_np.d \
+ core/sys/dragonflybsd/string.d core/sys/dragonflybsd/sys/_bitset.d \
core/sys/dragonflybsd/sys/_cpuset.d core/sys/dragonflybsd/sys/cdefs.d \
core/sys/dragonflybsd/sys/elf.d core/sys/dragonflybsd/sys/elf32.d \
core/sys/dragonflybsd/sys/elf64.d \
core/sys/dragonflybsd/time.d
DRUNTIME_DSOURCES_FREEBSD = core/sys/freebsd/config.d \
- core/sys/freebsd/dlfcn.d core/sys/freebsd/execinfo.d \
- core/sys/freebsd/netinet/in_.d core/sys/freebsd/pthread_np.d \
- core/sys/freebsd/string.d core/sys/freebsd/sys/_bitset.d \
- core/sys/freebsd/sys/_cpuset.d core/sys/freebsd/sys/cdefs.d \
- core/sys/freebsd/sys/elf.d core/sys/freebsd/sys/elf32.d \
- core/sys/freebsd/sys/elf64.d core/sys/freebsd/sys/elf_common.d \
- core/sys/freebsd/sys/event.d core/sys/freebsd/sys/link_elf.d \
- core/sys/freebsd/sys/mman.d core/sys/freebsd/sys/mount.d \
- core/sys/freebsd/time.d core/sys/freebsd/unistd.d
+ core/sys/freebsd/dlfcn.d core/sys/freebsd/err.d \
+ core/sys/freebsd/execinfo.d core/sys/freebsd/netinet/in_.d \
+ core/sys/freebsd/pthread_np.d core/sys/freebsd/string.d \
+ core/sys/freebsd/sys/_bitset.d core/sys/freebsd/sys/_cpuset.d \
+ core/sys/freebsd/sys/cdefs.d core/sys/freebsd/sys/elf.d \
+ core/sys/freebsd/sys/elf32.d core/sys/freebsd/sys/elf64.d \
+ core/sys/freebsd/sys/elf_common.d core/sys/freebsd/sys/event.d \
+ core/sys/freebsd/sys/link_elf.d core/sys/freebsd/sys/mman.d \
+ core/sys/freebsd/sys/mount.d core/sys/freebsd/time.d \
+ core/sys/freebsd/unistd.d
DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \
- core/sys/linux/errno.d core/sys/linux/execinfo.d \
+ core/sys/linux/err.d core/sys/linux/errno.d core/sys/linux/execinfo.d \
core/sys/linux/fcntl.d core/sys/linux/ifaddrs.d core/sys/linux/link.d \
core/sys/linux/netinet/in_.d core/sys/linux/netinet/tcp.d \
core/sys/linux/sched.d core/sys/linux/stdio.d core/sys/linux/string.d \
core/sys/linux/unistd.d
DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \
- core/sys/netbsd/execinfo.d core/sys/netbsd/string.d \
- core/sys/netbsd/sys/elf.d core/sys/netbsd/sys/elf32.d \
- core/sys/netbsd/sys/elf64.d core/sys/netbsd/sys/elf_common.d \
- core/sys/netbsd/sys/event.d core/sys/netbsd/sys/featuretest.d \
- core/sys/netbsd/sys/link_elf.d core/sys/netbsd/sys/mman.d \
- core/sys/netbsd/time.d
+ core/sys/netbsd/err.d core/sys/netbsd/execinfo.d \
+ core/sys/netbsd/string.d core/sys/netbsd/sys/elf.d \
+ core/sys/netbsd/sys/elf32.d core/sys/netbsd/sys/elf64.d \
+ core/sys/netbsd/sys/elf_common.d core/sys/netbsd/sys/event.d \
+ core/sys/netbsd/sys/featuretest.d core/sys/netbsd/sys/link_elf.d \
+ core/sys/netbsd/sys/mman.d core/sys/netbsd/time.d
DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.d \
- core/sys/openbsd/string.d core/sys/openbsd/sys/cdefs.d \
- core/sys/openbsd/sys/elf.d core/sys/openbsd/sys/elf32.d \
- core/sys/openbsd/sys/elf64.d core/sys/openbsd/sys/elf_common.d \
- core/sys/openbsd/sys/link_elf.d core/sys/openbsd/sys/mman.d \
- core/sys/openbsd/time.d
+ core/sys/openbsd/err.d core/sys/openbsd/string.d \
+ core/sys/openbsd/sys/cdefs.d core/sys/openbsd/sys/elf.d \
+ core/sys/openbsd/sys/elf32.d core/sys/openbsd/sys/elf64.d \
+ core/sys/openbsd/sys/elf_common.d core/sys/openbsd/sys/link_elf.d \
+ core/sys/openbsd/sys/mman.d core/sys/openbsd/time.d
DRUNTIME_DSOURCES_POSIX = core/sys/posix/aio.d \
core/sys/posix/arpa/inet.d core/sys/posix/config.d \
core/sys/posix/dirent.d core/sys/posix/dlfcn.d core/sys/posix/fcntl.d \
core/sys/posix/grp.d core/sys/posix/iconv.d core/sys/posix/inttypes.d \
- core/sys/posix/libgen.d core/sys/posix/mqueue.d \
- core/sys/posix/net/if_.d core/sys/posix/netdb.d \
- core/sys/posix/netinet/in_.d core/sys/posix/netinet/tcp.d \
- core/sys/posix/poll.d core/sys/posix/pthread.d core/sys/posix/pwd.d \
- core/sys/posix/sched.d core/sys/posix/semaphore.d \
- core/sys/posix/setjmp.d core/sys/posix/signal.d core/sys/posix/spawn.d \
- core/sys/posix/stdio.d core/sys/posix/stdlib.d \
- core/sys/posix/sys/filio.d core/sys/posix/sys/ioccom.d \
- core/sys/posix/sys/ioctl.d core/sys/posix/sys/ipc.d \
- core/sys/posix/sys/mman.d core/sys/posix/sys/msg.d \
- core/sys/posix/sys/resource.d core/sys/posix/sys/select.d \
- core/sys/posix/sys/shm.d core/sys/posix/sys/socket.d \
- core/sys/posix/sys/stat.d core/sys/posix/sys/statvfs.d \
- core/sys/posix/sys/time.d core/sys/posix/sys/ttycom.d \
- core/sys/posix/sys/types.d core/sys/posix/sys/uio.d \
- core/sys/posix/sys/un.d core/sys/posix/sys/utsname.d \
- core/sys/posix/sys/wait.d core/sys/posix/syslog.d \
- core/sys/posix/termios.d core/sys/posix/time.d \
+ core/sys/posix/libgen.d core/sys/posix/locale.d \
+ core/sys/posix/mqueue.d core/sys/posix/net/if_.d \
+ core/sys/posix/netdb.d core/sys/posix/netinet/in_.d \
+ core/sys/posix/netinet/tcp.d core/sys/posix/poll.d \
+ core/sys/posix/pthread.d core/sys/posix/pwd.d core/sys/posix/sched.d \
+ core/sys/posix/semaphore.d core/sys/posix/setjmp.d \
+ core/sys/posix/signal.d core/sys/posix/spawn.d \
+ core/sys/posix/stdc/time.d core/sys/posix/stdio.d \
+ core/sys/posix/stdlib.d core/sys/posix/string.d \
+ core/sys/posix/strings.d core/sys/posix/sys/filio.d \
+ core/sys/posix/sys/ioccom.d core/sys/posix/sys/ioctl.d \
+ core/sys/posix/sys/ipc.d core/sys/posix/sys/mman.d \
+ core/sys/posix/sys/msg.d core/sys/posix/sys/resource.d \
+ core/sys/posix/sys/select.d core/sys/posix/sys/shm.d \
+ core/sys/posix/sys/socket.d core/sys/posix/sys/stat.d \
+ core/sys/posix/sys/statvfs.d core/sys/posix/sys/time.d \
+ core/sys/posix/sys/ttycom.d core/sys/posix/sys/types.d \
+ core/sys/posix/sys/uio.d core/sys/posix/sys/un.d \
+ core/sys/posix/sys/utsname.d core/sys/posix/sys/wait.d \
+ core/sys/posix/syslog.d core/sys/posix/termios.d core/sys/posix/time.d \
core/sys/posix/ucontext.d core/sys/posix/unistd.d \
core/sys/posix/utime.d
DRUNTIME_DSOURCES_SOLARIS = core/sys/solaris/dlfcn.d \
- core/sys/solaris/elf.d core/sys/solaris/execinfo.d \
- core/sys/solaris/libelf.d core/sys/solaris/link.d \
- core/sys/solaris/sys/elf.d core/sys/solaris/sys/elf_386.d \
- core/sys/solaris/sys/elf_SPARC.d core/sys/solaris/sys/elf_amd64.d \
- core/sys/solaris/sys/elf_notes.d core/sys/solaris/sys/elftypes.d \
- core/sys/solaris/sys/link.d core/sys/solaris/sys/priocntl.d \
- core/sys/solaris/sys/procset.d core/sys/solaris/sys/types.d \
- core/sys/solaris/time.d
+ core/sys/solaris/elf.d core/sys/solaris/err.d \
+ core/sys/solaris/execinfo.d core/sys/solaris/libelf.d \
+ core/sys/solaris/link.d core/sys/solaris/sys/elf.d \
+ core/sys/solaris/sys/elf_386.d core/sys/solaris/sys/elf_SPARC.d \
+ core/sys/solaris/sys/elf_amd64.d core/sys/solaris/sys/elf_notes.d \
+ core/sys/solaris/sys/elftypes.d core/sys/solaris/sys/link.d \
+ core/sys/solaris/sys/priocntl.d core/sys/solaris/sys/procset.d \
+ core/sys/solaris/sys/types.d core/sys/solaris/time.d
DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \
core/sys/windows/aclapi.d core/sys/windows/aclui.d \
core/sys/windows/rpcdcep.d core/sys/windows/rpcndr.d \
core/sys/windows/rpcnsi.d core/sys/windows/rpcnsip.d \
core/sys/windows/rpcnterr.d core/sys/windows/schannel.d \
- core/sys/windows/secext.d core/sys/windows/security.d \
- core/sys/windows/servprov.d core/sys/windows/setupapi.d \
- core/sys/windows/shellapi.d core/sys/windows/shldisp.d \
- core/sys/windows/shlguid.d core/sys/windows/shlobj.d \
- core/sys/windows/shlwapi.d core/sys/windows/snmp.d \
- core/sys/windows/sql.d core/sys/windows/sqlext.d \
- core/sys/windows/sqltypes.d core/sys/windows/sqlucode.d \
- core/sys/windows/sspi.d core/sys/windows/stacktrace.d \
- core/sys/windows/stat.d core/sys/windows/subauth.d \
+ core/sys/windows/sdkddkver.d core/sys/windows/secext.d \
+ core/sys/windows/security.d core/sys/windows/servprov.d \
+ core/sys/windows/setupapi.d core/sys/windows/shellapi.d \
+ core/sys/windows/shldisp.d core/sys/windows/shlguid.d \
+ core/sys/windows/shlobj.d core/sys/windows/shlwapi.d \
+ core/sys/windows/snmp.d core/sys/windows/sql.d \
+ core/sys/windows/sqlext.d core/sys/windows/sqltypes.d \
+ core/sys/windows/sqlucode.d core/sys/windows/sspi.d \
+ core/sys/windows/stacktrace.d core/sys/windows/stat.d \
+ core/sys/windows/stdc/time.d core/sys/windows/subauth.d \
core/sys/windows/threadaux.d core/sys/windows/tlhelp32.d \
core/sys/windows/tmschema.d core/sys/windows/unknwn.d \
core/sys/windows/uuid.d core/sys/windows/vfw.d \
@SET_MAKE@
# Makefile for the D runtime library.
-# Copyright (C) 2012-2020 Free Software Foundation, Inc.
+# Copyright (C) 2012-2021 Free Software Foundation, Inc.
#
# GCC is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
core/stdc/wctype.lo core/sync/barrier.lo \
core/sync/condition.lo core/sync/config.lo \
core/sync/exception.lo core/sync/mutex.lo core/sync/rwmutex.lo \
- core/sync/semaphore.lo core/thread.lo core/time.lo \
+ core/sync/semaphore.lo core/thread/context.lo \
+ core/thread/fiber.lo core/thread/osthread.lo \
+ core/thread/package.lo core/thread/threadbase.lo \
+ core/thread/threadgroup.lo core/thread/types.lo core/time.lo \
core/vararg.lo gc/bits.lo gc/config.lo gc/gcinterface.lo \
gc/impl/conservative/gc.lo gc/impl/manual/gc.lo gc/os.lo \
gc/pooltable.lo gc/proxy.lo gcc/attribute.lo gcc/backtrace.lo \
rt/config.lo rt/critical_.lo rt/deh.lo rt/dmain2.lo \
rt/invariant.lo rt/lifetime.lo rt/memory.lo rt/minfo.lo \
rt/monitor_.lo rt/obj.lo rt/qsort.lo rt/sections.lo \
- rt/switch_.lo rt/tlsgc.lo rt/typeinfo/ti_Acdouble.lo \
- rt/typeinfo/ti_Acfloat.lo rt/typeinfo/ti_Acreal.lo \
- rt/typeinfo/ti_Adouble.lo rt/typeinfo/ti_Afloat.lo \
- rt/typeinfo/ti_Ag.lo rt/typeinfo/ti_Aint.lo \
- rt/typeinfo/ti_Along.lo rt/typeinfo/ti_Areal.lo \
- rt/typeinfo/ti_Ashort.lo rt/typeinfo/ti_C.lo \
- rt/typeinfo/ti_byte.lo rt/typeinfo/ti_cdouble.lo \
- rt/typeinfo/ti_cent.lo rt/typeinfo/ti_cfloat.lo \
- rt/typeinfo/ti_char.lo rt/typeinfo/ti_creal.lo \
- rt/typeinfo/ti_dchar.lo rt/typeinfo/ti_delegate.lo \
- rt/typeinfo/ti_double.lo rt/typeinfo/ti_float.lo \
- rt/typeinfo/ti_idouble.lo rt/typeinfo/ti_ifloat.lo \
- rt/typeinfo/ti_int.lo rt/typeinfo/ti_ireal.lo \
- rt/typeinfo/ti_long.lo rt/typeinfo/ti_n.lo \
- rt/typeinfo/ti_ptr.lo rt/typeinfo/ti_real.lo \
- rt/typeinfo/ti_short.lo rt/typeinfo/ti_ubyte.lo \
- rt/typeinfo/ti_ucent.lo rt/typeinfo/ti_uint.lo \
- rt/typeinfo/ti_ulong.lo rt/typeinfo/ti_ushort.lo \
- rt/typeinfo/ti_void.lo rt/typeinfo/ti_wchar.lo \
- rt/util/array.lo rt/util/container/array.lo \
- rt/util/container/common.lo rt/util/container/hashtab.lo \
- rt/util/container/treap.lo rt/util/random.lo \
- rt/util/typeinfo.lo rt/util/utf.lo
+ rt/switch_.lo rt/tlsgc.lo rt/util/array.lo \
+ rt/util/container/array.lo rt/util/container/common.lo \
+ rt/util/container/hashtab.lo rt/util/container/treap.lo \
+ rt/util/random.lo rt/util/typeinfo.lo rt/util/utf.lo
am__objects_2 = core/stdc/libgdruntime_la-errno_.lo
am__objects_3 = core/sys/posix/aio.lo core/sys/posix/arpa/inet.lo \
core/sys/posix/config.lo core/sys/posix/dirent.lo \
core/sys/posix/dlfcn.lo core/sys/posix/fcntl.lo \
core/sys/posix/grp.lo core/sys/posix/iconv.lo \
core/sys/posix/inttypes.lo core/sys/posix/libgen.lo \
- core/sys/posix/mqueue.lo core/sys/posix/net/if_.lo \
- core/sys/posix/netdb.lo core/sys/posix/netinet/in_.lo \
- core/sys/posix/netinet/tcp.lo core/sys/posix/poll.lo \
- core/sys/posix/pthread.lo core/sys/posix/pwd.lo \
- core/sys/posix/sched.lo core/sys/posix/semaphore.lo \
- core/sys/posix/setjmp.lo core/sys/posix/signal.lo \
- core/sys/posix/spawn.lo core/sys/posix/stdio.lo \
- core/sys/posix/stdlib.lo core/sys/posix/sys/filio.lo \
+ core/sys/posix/locale.lo core/sys/posix/mqueue.lo \
+ core/sys/posix/net/if_.lo core/sys/posix/netdb.lo \
+ core/sys/posix/netinet/in_.lo core/sys/posix/netinet/tcp.lo \
+ core/sys/posix/poll.lo core/sys/posix/pthread.lo \
+ core/sys/posix/pwd.lo core/sys/posix/sched.lo \
+ core/sys/posix/semaphore.lo core/sys/posix/setjmp.lo \
+ core/sys/posix/signal.lo core/sys/posix/spawn.lo \
+ core/sys/posix/stdc/time.lo core/sys/posix/stdio.lo \
+ core/sys/posix/stdlib.lo core/sys/posix/string.lo \
+ core/sys/posix/strings.lo core/sys/posix/sys/filio.lo \
core/sys/posix/sys/ioccom.lo core/sys/posix/sys/ioctl.lo \
core/sys/posix/sys/ipc.lo core/sys/posix/sys/mman.lo \
core/sys/posix/sys/msg.lo core/sys/posix/sys/resource.lo \
core/sys/posix/unistd.lo core/sys/posix/utime.lo
@DRUNTIME_OS_POSIX_TRUE@am__objects_4 = $(am__objects_3)
am__objects_5 = core/sys/darwin/crt_externs.lo \
- core/sys/darwin/dlfcn.lo core/sys/darwin/execinfo.lo \
+ core/sys/darwin/dlfcn.lo core/sys/darwin/err.lo \
+ core/sys/darwin/execinfo.lo core/sys/darwin/ifaddrs.lo \
core/sys/darwin/mach/dyld.lo core/sys/darwin/mach/getsect.lo \
core/sys/darwin/mach/kern_return.lo \
- core/sys/darwin/mach/loader.lo core/sys/darwin/mach/port.lo \
- core/sys/darwin/mach/semaphore.lo \
+ core/sys/darwin/mach/loader.lo core/sys/darwin/mach/nlist.lo \
+ core/sys/darwin/mach/port.lo core/sys/darwin/mach/semaphore.lo \
+ core/sys/darwin/mach/stab.lo \
core/sys/darwin/mach/thread_act.lo \
core/sys/darwin/netinet/in_.lo core/sys/darwin/pthread.lo \
- core/sys/darwin/string.lo core/sys/darwin/sys/cdefs.lo \
- core/sys/darwin/sys/event.lo core/sys/darwin/sys/mman.lo
+ core/sys/darwin/string.lo core/sys/darwin/sys/attr.lo \
+ core/sys/darwin/sys/cdefs.lo core/sys/darwin/sys/event.lo \
+ core/sys/darwin/sys/mman.lo
@DRUNTIME_OS_DARWIN_TRUE@am__objects_6 = $(am__objects_5)
am__objects_7 = core/sys/dragonflybsd/dlfcn.lo \
- core/sys/dragonflybsd/execinfo.lo \
+ core/sys/dragonflybsd/err.lo core/sys/dragonflybsd/execinfo.lo \
core/sys/dragonflybsd/netinet/in_.lo \
core/sys/dragonflybsd/pthread_np.lo \
core/sys/dragonflybsd/string.lo \
core/sys/dragonflybsd/sys/socket.lo \
core/sys/dragonflybsd/time.lo
@DRUNTIME_OS_DRAGONFLYBSD_TRUE@am__objects_8 = $(am__objects_7)
-am__objects_9 = core/sys/bionic/fcntl.lo core/sys/bionic/string.lo \
- core/sys/bionic/unistd.lo
+am__objects_9 = core/sys/bionic/err.lo core/sys/bionic/fcntl.lo \
+ core/sys/bionic/string.lo core/sys/bionic/unistd.lo
@DRUNTIME_OS_ANDROID_TRUE@am__objects_10 = $(am__objects_9)
am__objects_11 = core/sys/freebsd/config.lo core/sys/freebsd/dlfcn.lo \
- core/sys/freebsd/execinfo.lo core/sys/freebsd/netinet/in_.lo \
- core/sys/freebsd/pthread_np.lo core/sys/freebsd/string.lo \
- core/sys/freebsd/sys/_bitset.lo \
+ core/sys/freebsd/err.lo core/sys/freebsd/execinfo.lo \
+ core/sys/freebsd/netinet/in_.lo core/sys/freebsd/pthread_np.lo \
+ core/sys/freebsd/string.lo core/sys/freebsd/sys/_bitset.lo \
core/sys/freebsd/sys/_cpuset.lo core/sys/freebsd/sys/cdefs.lo \
core/sys/freebsd/sys/elf.lo core/sys/freebsd/sys/elf32.lo \
core/sys/freebsd/sys/elf64.lo \
core/sys/freebsd/sys/mman.lo core/sys/freebsd/sys/mount.lo \
core/sys/freebsd/time.lo core/sys/freebsd/unistd.lo
@DRUNTIME_OS_FREEBSD_TRUE@am__objects_12 = $(am__objects_11)
-am__objects_13 = core/sys/netbsd/dlfcn.lo core/sys/netbsd/execinfo.lo \
- core/sys/netbsd/string.lo core/sys/netbsd/sys/elf.lo \
- core/sys/netbsd/sys/elf32.lo core/sys/netbsd/sys/elf64.lo \
- core/sys/netbsd/sys/elf_common.lo core/sys/netbsd/sys/event.lo \
+am__objects_13 = core/sys/netbsd/dlfcn.lo core/sys/netbsd/err.lo \
+ core/sys/netbsd/execinfo.lo core/sys/netbsd/string.lo \
+ core/sys/netbsd/sys/elf.lo core/sys/netbsd/sys/elf32.lo \
+ core/sys/netbsd/sys/elf64.lo core/sys/netbsd/sys/elf_common.lo \
+ core/sys/netbsd/sys/event.lo \
core/sys/netbsd/sys/featuretest.lo \
core/sys/netbsd/sys/link_elf.lo core/sys/netbsd/sys/mman.lo \
core/sys/netbsd/time.lo
@DRUNTIME_OS_NETBSD_TRUE@am__objects_14 = $(am__objects_13)
-am__objects_15 = core/sys/openbsd/dlfcn.lo core/sys/openbsd/string.lo \
- core/sys/openbsd/sys/cdefs.lo core/sys/openbsd/sys/elf.lo \
- core/sys/openbsd/sys/elf32.lo core/sys/openbsd/sys/elf64.lo \
+am__objects_15 = core/sys/openbsd/dlfcn.lo core/sys/openbsd/err.lo \
+ core/sys/openbsd/string.lo core/sys/openbsd/sys/cdefs.lo \
+ core/sys/openbsd/sys/elf.lo core/sys/openbsd/sys/elf32.lo \
+ core/sys/openbsd/sys/elf64.lo \
core/sys/openbsd/sys/elf_common.lo \
core/sys/openbsd/sys/link_elf.lo core/sys/openbsd/sys/mman.lo \
core/sys/openbsd/time.lo
@DRUNTIME_OS_OPENBSD_TRUE@am__objects_16 = $(am__objects_15)
am__objects_17 = core/sys/linux/config.lo core/sys/linux/dlfcn.lo \
core/sys/linux/elf.lo core/sys/linux/epoll.lo \
- core/sys/linux/errno.lo core/sys/linux/execinfo.lo \
- core/sys/linux/fcntl.lo core/sys/linux/ifaddrs.lo \
- core/sys/linux/link.lo core/sys/linux/netinet/in_.lo \
- core/sys/linux/netinet/tcp.lo core/sys/linux/sched.lo \
- core/sys/linux/stdio.lo core/sys/linux/string.lo \
- core/sys/linux/sys/auxv.lo core/sys/linux/sys/eventfd.lo \
- core/sys/linux/sys/file.lo core/sys/linux/sys/inotify.lo \
- core/sys/linux/sys/mman.lo core/sys/linux/sys/prctl.lo \
- core/sys/linux/sys/signalfd.lo core/sys/linux/sys/socket.lo \
- core/sys/linux/sys/sysinfo.lo core/sys/linux/sys/time.lo \
- core/sys/linux/sys/xattr.lo core/sys/linux/termios.lo \
- core/sys/linux/time.lo core/sys/linux/timerfd.lo \
- core/sys/linux/tipc.lo core/sys/linux/unistd.lo
+ core/sys/linux/err.lo core/sys/linux/errno.lo \
+ core/sys/linux/execinfo.lo core/sys/linux/fcntl.lo \
+ core/sys/linux/ifaddrs.lo core/sys/linux/link.lo \
+ core/sys/linux/netinet/in_.lo core/sys/linux/netinet/tcp.lo \
+ core/sys/linux/sched.lo core/sys/linux/stdio.lo \
+ core/sys/linux/string.lo core/sys/linux/sys/auxv.lo \
+ core/sys/linux/sys/eventfd.lo core/sys/linux/sys/file.lo \
+ core/sys/linux/sys/inotify.lo core/sys/linux/sys/mman.lo \
+ core/sys/linux/sys/prctl.lo core/sys/linux/sys/signalfd.lo \
+ core/sys/linux/sys/socket.lo core/sys/linux/sys/sysinfo.lo \
+ core/sys/linux/sys/time.lo core/sys/linux/sys/xattr.lo \
+ core/sys/linux/termios.lo core/sys/linux/time.lo \
+ core/sys/linux/timerfd.lo core/sys/linux/tipc.lo \
+ core/sys/linux/unistd.lo
@DRUNTIME_OS_LINUX_TRUE@am__objects_18 = $(am__objects_17)
am__objects_19 = core/sys/windows/accctrl.lo \
core/sys/windows/aclapi.lo core/sys/windows/aclui.lo \
core/sys/windows/rpcdce2.lo core/sys/windows/rpcdcep.lo \
core/sys/windows/rpcndr.lo core/sys/windows/rpcnsi.lo \
core/sys/windows/rpcnsip.lo core/sys/windows/rpcnterr.lo \
- core/sys/windows/schannel.lo core/sys/windows/secext.lo \
- core/sys/windows/security.lo core/sys/windows/servprov.lo \
- core/sys/windows/setupapi.lo core/sys/windows/shellapi.lo \
- core/sys/windows/shldisp.lo core/sys/windows/shlguid.lo \
- core/sys/windows/shlobj.lo core/sys/windows/shlwapi.lo \
- core/sys/windows/snmp.lo core/sys/windows/sql.lo \
- core/sys/windows/sqlext.lo core/sys/windows/sqltypes.lo \
- core/sys/windows/sqlucode.lo core/sys/windows/sspi.lo \
- core/sys/windows/stacktrace.lo core/sys/windows/stat.lo \
+ core/sys/windows/schannel.lo core/sys/windows/sdkddkver.lo \
+ core/sys/windows/secext.lo core/sys/windows/security.lo \
+ core/sys/windows/servprov.lo core/sys/windows/setupapi.lo \
+ core/sys/windows/shellapi.lo core/sys/windows/shldisp.lo \
+ core/sys/windows/shlguid.lo core/sys/windows/shlobj.lo \
+ core/sys/windows/shlwapi.lo core/sys/windows/snmp.lo \
+ core/sys/windows/sql.lo core/sys/windows/sqlext.lo \
+ core/sys/windows/sqltypes.lo core/sys/windows/sqlucode.lo \
+ core/sys/windows/sspi.lo core/sys/windows/stacktrace.lo \
+ core/sys/windows/stat.lo core/sys/windows/stdc/time.lo \
core/sys/windows/subauth.lo core/sys/windows/threadaux.lo \
core/sys/windows/tlhelp32.lo core/sys/windows/tmschema.lo \
core/sys/windows/unknwn.lo core/sys/windows/uuid.lo \
core/sys/windows/wtsapi32.lo core/sys/windows/wtypes.lo
@DRUNTIME_OS_MINGW_TRUE@am__objects_20 = $(am__objects_19)
am__objects_21 = core/sys/solaris/dlfcn.lo core/sys/solaris/elf.lo \
- core/sys/solaris/execinfo.lo core/sys/solaris/libelf.lo \
- core/sys/solaris/link.lo core/sys/solaris/sys/elf.lo \
- core/sys/solaris/sys/elf_386.lo \
+ core/sys/solaris/err.lo core/sys/solaris/execinfo.lo \
+ core/sys/solaris/libelf.lo core/sys/solaris/link.lo \
+ core/sys/solaris/sys/elf.lo core/sys/solaris/sys/elf_386.lo \
core/sys/solaris/sys/elf_SPARC.lo \
core/sys/solaris/sys/elf_amd64.lo \
core/sys/solaris/sys/elf_notes.lo \
core/stdc/tgmath.d core/stdc/time.d core/stdc/wchar_.d \
core/stdc/wctype.d core/sync/barrier.d core/sync/condition.d \
core/sync/config.d core/sync/exception.d core/sync/mutex.d \
- core/sync/rwmutex.d core/sync/semaphore.d core/thread.d core/time.d \
- core/vararg.d gc/bits.d gc/config.d gc/gcinterface.d \
+ core/sync/rwmutex.d core/sync/semaphore.d core/thread/context.d \
+ core/thread/fiber.d core/thread/osthread.d core/thread/package.d \
+ core/thread/threadbase.d core/thread/threadgroup.d core/thread/types.d \
+ core/time.d core/vararg.d gc/bits.d gc/config.d gc/gcinterface.d \
gc/impl/conservative/gc.d gc/impl/manual/gc.d gc/os.d gc/pooltable.d \
gc/proxy.d gcc/attribute.d gcc/backtrace.d gcc/builtins.d gcc/deh.d \
gcc/emutls.d gcc/gthread.d gcc/sections/android.d \
rt/cast_.d rt/config.d rt/critical_.d rt/deh.d rt/dmain2.d \
rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d \
rt/obj.d rt/qsort.d rt/sections.d rt/switch_.d rt/tlsgc.d \
- rt/typeinfo/ti_Acdouble.d rt/typeinfo/ti_Acfloat.d \
- rt/typeinfo/ti_Acreal.d rt/typeinfo/ti_Adouble.d \
- rt/typeinfo/ti_Afloat.d rt/typeinfo/ti_Ag.d rt/typeinfo/ti_Aint.d \
- rt/typeinfo/ti_Along.d rt/typeinfo/ti_Areal.d rt/typeinfo/ti_Ashort.d \
- rt/typeinfo/ti_C.d rt/typeinfo/ti_byte.d rt/typeinfo/ti_cdouble.d \
- rt/typeinfo/ti_cent.d rt/typeinfo/ti_cfloat.d rt/typeinfo/ti_char.d \
- rt/typeinfo/ti_creal.d rt/typeinfo/ti_dchar.d \
- rt/typeinfo/ti_delegate.d rt/typeinfo/ti_double.d \
- rt/typeinfo/ti_float.d rt/typeinfo/ti_idouble.d \
- rt/typeinfo/ti_ifloat.d rt/typeinfo/ti_int.d rt/typeinfo/ti_ireal.d \
- rt/typeinfo/ti_long.d rt/typeinfo/ti_n.d rt/typeinfo/ti_ptr.d \
- rt/typeinfo/ti_real.d rt/typeinfo/ti_short.d rt/typeinfo/ti_ubyte.d \
- rt/typeinfo/ti_ucent.d rt/typeinfo/ti_uint.d rt/typeinfo/ti_ulong.d \
- rt/typeinfo/ti_ushort.d rt/typeinfo/ti_void.d rt/typeinfo/ti_wchar.d \
rt/util/array.d rt/util/container/array.d rt/util/container/common.d \
rt/util/container/hashtab.d rt/util/container/treap.d rt/util/random.d \
rt/util/typeinfo.d rt/util/utf.d
DRUNTIME_DSOURCES_STDCXX = core/stdcpp/exception.d \
core/stdcpp/typeinfo.d
-DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/fcntl.d \
- core/sys/bionic/string.d core/sys/bionic/unistd.d
+DRUNTIME_DSOURCES_BIONIC = core/sys/bionic/err.d \
+ 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/dlfcn.d core/sys/darwin/err.d \
+ core/sys/darwin/execinfo.d core/sys/darwin/ifaddrs.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/nlist.d core/sys/darwin/mach/port.d \
+ core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.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
+ core/sys/darwin/sys/attr.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 \
- core/sys/dragonflybsd/pthread_np.d core/sys/dragonflybsd/string.d \
- core/sys/dragonflybsd/sys/_bitset.d \
+ core/sys/dragonflybsd/err.d core/sys/dragonflybsd/execinfo.d \
+ core/sys/dragonflybsd/netinet/in_.d core/sys/dragonflybsd/pthread_np.d \
+ core/sys/dragonflybsd/string.d core/sys/dragonflybsd/sys/_bitset.d \
core/sys/dragonflybsd/sys/_cpuset.d core/sys/dragonflybsd/sys/cdefs.d \
core/sys/dragonflybsd/sys/elf.d core/sys/dragonflybsd/sys/elf32.d \
core/sys/dragonflybsd/sys/elf64.d \
core/sys/dragonflybsd/time.d
DRUNTIME_DSOURCES_FREEBSD = core/sys/freebsd/config.d \
- core/sys/freebsd/dlfcn.d core/sys/freebsd/execinfo.d \
- core/sys/freebsd/netinet/in_.d core/sys/freebsd/pthread_np.d \
- core/sys/freebsd/string.d core/sys/freebsd/sys/_bitset.d \
- core/sys/freebsd/sys/_cpuset.d core/sys/freebsd/sys/cdefs.d \
- core/sys/freebsd/sys/elf.d core/sys/freebsd/sys/elf32.d \
- core/sys/freebsd/sys/elf64.d core/sys/freebsd/sys/elf_common.d \
- core/sys/freebsd/sys/event.d core/sys/freebsd/sys/link_elf.d \
- core/sys/freebsd/sys/mman.d core/sys/freebsd/sys/mount.d \
- core/sys/freebsd/time.d core/sys/freebsd/unistd.d
+ core/sys/freebsd/dlfcn.d core/sys/freebsd/err.d \
+ core/sys/freebsd/execinfo.d core/sys/freebsd/netinet/in_.d \
+ core/sys/freebsd/pthread_np.d core/sys/freebsd/string.d \
+ core/sys/freebsd/sys/_bitset.d core/sys/freebsd/sys/_cpuset.d \
+ core/sys/freebsd/sys/cdefs.d core/sys/freebsd/sys/elf.d \
+ core/sys/freebsd/sys/elf32.d core/sys/freebsd/sys/elf64.d \
+ core/sys/freebsd/sys/elf_common.d core/sys/freebsd/sys/event.d \
+ core/sys/freebsd/sys/link_elf.d core/sys/freebsd/sys/mman.d \
+ core/sys/freebsd/sys/mount.d core/sys/freebsd/time.d \
+ core/sys/freebsd/unistd.d
DRUNTIME_DSOURCES_LINUX = core/sys/linux/config.d \
core/sys/linux/dlfcn.d core/sys/linux/elf.d core/sys/linux/epoll.d \
- core/sys/linux/errno.d core/sys/linux/execinfo.d \
+ core/sys/linux/err.d core/sys/linux/errno.d core/sys/linux/execinfo.d \
core/sys/linux/fcntl.d core/sys/linux/ifaddrs.d core/sys/linux/link.d \
core/sys/linux/netinet/in_.d core/sys/linux/netinet/tcp.d \
core/sys/linux/sched.d core/sys/linux/stdio.d core/sys/linux/string.d \
core/sys/linux/unistd.d
DRUNTIME_DSOURCES_NETBSD = core/sys/netbsd/dlfcn.d \
- core/sys/netbsd/execinfo.d core/sys/netbsd/string.d \
- core/sys/netbsd/sys/elf.d core/sys/netbsd/sys/elf32.d \
- core/sys/netbsd/sys/elf64.d core/sys/netbsd/sys/elf_common.d \
- core/sys/netbsd/sys/event.d core/sys/netbsd/sys/featuretest.d \
- core/sys/netbsd/sys/link_elf.d core/sys/netbsd/sys/mman.d \
- core/sys/netbsd/time.d
+ core/sys/netbsd/err.d core/sys/netbsd/execinfo.d \
+ core/sys/netbsd/string.d core/sys/netbsd/sys/elf.d \
+ core/sys/netbsd/sys/elf32.d core/sys/netbsd/sys/elf64.d \
+ core/sys/netbsd/sys/elf_common.d core/sys/netbsd/sys/event.d \
+ core/sys/netbsd/sys/featuretest.d core/sys/netbsd/sys/link_elf.d \
+ core/sys/netbsd/sys/mman.d core/sys/netbsd/time.d
DRUNTIME_DSOURCES_OPENBSD = core/sys/openbsd/dlfcn.d \
- core/sys/openbsd/string.d core/sys/openbsd/sys/cdefs.d \
- core/sys/openbsd/sys/elf.d core/sys/openbsd/sys/elf32.d \
- core/sys/openbsd/sys/elf64.d core/sys/openbsd/sys/elf_common.d \
- core/sys/openbsd/sys/link_elf.d core/sys/openbsd/sys/mman.d \
- core/sys/openbsd/time.d
+ core/sys/openbsd/err.d core/sys/openbsd/string.d \
+ core/sys/openbsd/sys/cdefs.d core/sys/openbsd/sys/elf.d \
+ core/sys/openbsd/sys/elf32.d core/sys/openbsd/sys/elf64.d \
+ core/sys/openbsd/sys/elf_common.d core/sys/openbsd/sys/link_elf.d \
+ core/sys/openbsd/sys/mman.d core/sys/openbsd/time.d
DRUNTIME_DSOURCES_POSIX = core/sys/posix/aio.d \
core/sys/posix/arpa/inet.d core/sys/posix/config.d \
core/sys/posix/dirent.d core/sys/posix/dlfcn.d core/sys/posix/fcntl.d \
core/sys/posix/grp.d core/sys/posix/iconv.d core/sys/posix/inttypes.d \
- core/sys/posix/libgen.d core/sys/posix/mqueue.d \
- core/sys/posix/net/if_.d core/sys/posix/netdb.d \
- core/sys/posix/netinet/in_.d core/sys/posix/netinet/tcp.d \
- core/sys/posix/poll.d core/sys/posix/pthread.d core/sys/posix/pwd.d \
- core/sys/posix/sched.d core/sys/posix/semaphore.d \
- core/sys/posix/setjmp.d core/sys/posix/signal.d core/sys/posix/spawn.d \
- core/sys/posix/stdio.d core/sys/posix/stdlib.d \
- core/sys/posix/sys/filio.d core/sys/posix/sys/ioccom.d \
- core/sys/posix/sys/ioctl.d core/sys/posix/sys/ipc.d \
- core/sys/posix/sys/mman.d core/sys/posix/sys/msg.d \
- core/sys/posix/sys/resource.d core/sys/posix/sys/select.d \
- core/sys/posix/sys/shm.d core/sys/posix/sys/socket.d \
- core/sys/posix/sys/stat.d core/sys/posix/sys/statvfs.d \
- core/sys/posix/sys/time.d core/sys/posix/sys/ttycom.d \
- core/sys/posix/sys/types.d core/sys/posix/sys/uio.d \
- core/sys/posix/sys/un.d core/sys/posix/sys/utsname.d \
- core/sys/posix/sys/wait.d core/sys/posix/syslog.d \
- core/sys/posix/termios.d core/sys/posix/time.d \
+ core/sys/posix/libgen.d core/sys/posix/locale.d \
+ core/sys/posix/mqueue.d core/sys/posix/net/if_.d \
+ core/sys/posix/netdb.d core/sys/posix/netinet/in_.d \
+ core/sys/posix/netinet/tcp.d core/sys/posix/poll.d \
+ core/sys/posix/pthread.d core/sys/posix/pwd.d core/sys/posix/sched.d \
+ core/sys/posix/semaphore.d core/sys/posix/setjmp.d \
+ core/sys/posix/signal.d core/sys/posix/spawn.d \
+ core/sys/posix/stdc/time.d core/sys/posix/stdio.d \
+ core/sys/posix/stdlib.d core/sys/posix/string.d \
+ core/sys/posix/strings.d core/sys/posix/sys/filio.d \
+ core/sys/posix/sys/ioccom.d core/sys/posix/sys/ioctl.d \
+ core/sys/posix/sys/ipc.d core/sys/posix/sys/mman.d \
+ core/sys/posix/sys/msg.d core/sys/posix/sys/resource.d \
+ core/sys/posix/sys/select.d core/sys/posix/sys/shm.d \
+ core/sys/posix/sys/socket.d core/sys/posix/sys/stat.d \
+ core/sys/posix/sys/statvfs.d core/sys/posix/sys/time.d \
+ core/sys/posix/sys/ttycom.d core/sys/posix/sys/types.d \
+ core/sys/posix/sys/uio.d core/sys/posix/sys/un.d \
+ core/sys/posix/sys/utsname.d core/sys/posix/sys/wait.d \
+ core/sys/posix/syslog.d core/sys/posix/termios.d core/sys/posix/time.d \
core/sys/posix/ucontext.d core/sys/posix/unistd.d \
core/sys/posix/utime.d
DRUNTIME_DSOURCES_SOLARIS = core/sys/solaris/dlfcn.d \
- core/sys/solaris/elf.d core/sys/solaris/execinfo.d \
- core/sys/solaris/libelf.d core/sys/solaris/link.d \
- core/sys/solaris/sys/elf.d core/sys/solaris/sys/elf_386.d \
- core/sys/solaris/sys/elf_SPARC.d core/sys/solaris/sys/elf_amd64.d \
- core/sys/solaris/sys/elf_notes.d core/sys/solaris/sys/elftypes.d \
- core/sys/solaris/sys/link.d core/sys/solaris/sys/priocntl.d \
- core/sys/solaris/sys/procset.d core/sys/solaris/sys/types.d \
- core/sys/solaris/time.d
+ core/sys/solaris/elf.d core/sys/solaris/err.d \
+ core/sys/solaris/execinfo.d core/sys/solaris/libelf.d \
+ core/sys/solaris/link.d core/sys/solaris/sys/elf.d \
+ core/sys/solaris/sys/elf_386.d core/sys/solaris/sys/elf_SPARC.d \
+ core/sys/solaris/sys/elf_amd64.d core/sys/solaris/sys/elf_notes.d \
+ core/sys/solaris/sys/elftypes.d core/sys/solaris/sys/link.d \
+ core/sys/solaris/sys/priocntl.d core/sys/solaris/sys/procset.d \
+ core/sys/solaris/sys/types.d core/sys/solaris/time.d
DRUNTIME_DSOURCES_WINDOWS = core/sys/windows/accctrl.d \
core/sys/windows/aclapi.d core/sys/windows/aclui.d \
core/sys/windows/rpcdcep.d core/sys/windows/rpcndr.d \
core/sys/windows/rpcnsi.d core/sys/windows/rpcnsip.d \
core/sys/windows/rpcnterr.d core/sys/windows/schannel.d \
- core/sys/windows/secext.d core/sys/windows/security.d \
- core/sys/windows/servprov.d core/sys/windows/setupapi.d \
- core/sys/windows/shellapi.d core/sys/windows/shldisp.d \
- core/sys/windows/shlguid.d core/sys/windows/shlobj.d \
- core/sys/windows/shlwapi.d core/sys/windows/snmp.d \
- core/sys/windows/sql.d core/sys/windows/sqlext.d \
- core/sys/windows/sqltypes.d core/sys/windows/sqlucode.d \
- core/sys/windows/sspi.d core/sys/windows/stacktrace.d \
- core/sys/windows/stat.d core/sys/windows/subauth.d \
+ core/sys/windows/sdkddkver.d core/sys/windows/secext.d \
+ core/sys/windows/security.d core/sys/windows/servprov.d \
+ core/sys/windows/setupapi.d core/sys/windows/shellapi.d \
+ core/sys/windows/shldisp.d core/sys/windows/shlguid.d \
+ core/sys/windows/shlobj.d core/sys/windows/shlwapi.d \
+ core/sys/windows/snmp.d core/sys/windows/sql.d \
+ core/sys/windows/sqlext.d core/sys/windows/sqltypes.d \
+ core/sys/windows/sqlucode.d core/sys/windows/sspi.d \
+ core/sys/windows/stacktrace.d core/sys/windows/stat.d \
+ core/sys/windows/stdc/time.d core/sys/windows/subauth.d \
core/sys/windows/threadaux.d core/sys/windows/tlhelp32.d \
core/sys/windows/tmschema.d core/sys/windows/unknwn.d \
core/sys/windows/uuid.d core/sys/windows/vfw.d \
core/sync/mutex.lo: core/sync/$(am__dirstamp)
core/sync/rwmutex.lo: core/sync/$(am__dirstamp)
core/sync/semaphore.lo: core/sync/$(am__dirstamp)
-core/thread.lo: core/$(am__dirstamp)
+core/thread/$(am__dirstamp):
+ @$(MKDIR_P) core/thread
+ @: > core/thread/$(am__dirstamp)
+core/thread/context.lo: core/thread/$(am__dirstamp)
+core/thread/fiber.lo: core/thread/$(am__dirstamp)
+core/thread/osthread.lo: core/thread/$(am__dirstamp)
+core/thread/package.lo: core/thread/$(am__dirstamp)
+core/thread/threadbase.lo: core/thread/$(am__dirstamp)
+core/thread/threadgroup.lo: core/thread/$(am__dirstamp)
+core/thread/types.lo: core/thread/$(am__dirstamp)
core/time.lo: core/$(am__dirstamp)
core/vararg.lo: core/$(am__dirstamp)
gc/$(am__dirstamp):
rt/sections.lo: rt/$(am__dirstamp)
rt/switch_.lo: rt/$(am__dirstamp)
rt/tlsgc.lo: rt/$(am__dirstamp)
-rt/typeinfo/$(am__dirstamp):
- @$(MKDIR_P) rt/typeinfo
- @: > rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Acdouble.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Acfloat.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Acreal.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Adouble.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Afloat.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Ag.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Aint.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Along.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Areal.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_Ashort.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_C.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_byte.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_cdouble.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_cent.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_cfloat.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_char.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_creal.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_dchar.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_delegate.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_double.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_float.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_idouble.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_ifloat.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_int.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_ireal.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_long.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_n.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_ptr.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_real.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_short.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_ubyte.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_ucent.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_uint.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_ulong.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_ushort.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_void.lo: rt/typeinfo/$(am__dirstamp)
-rt/typeinfo/ti_wchar.lo: rt/typeinfo/$(am__dirstamp)
rt/util/$(am__dirstamp):
@$(MKDIR_P) rt/util
@: > rt/util/$(am__dirstamp)
core/sys/posix/iconv.lo: core/sys/posix/$(am__dirstamp)
core/sys/posix/inttypes.lo: core/sys/posix/$(am__dirstamp)
core/sys/posix/libgen.lo: core/sys/posix/$(am__dirstamp)
+core/sys/posix/locale.lo: core/sys/posix/$(am__dirstamp)
core/sys/posix/mqueue.lo: core/sys/posix/$(am__dirstamp)
core/sys/posix/net/$(am__dirstamp):
@$(MKDIR_P) core/sys/posix/net
core/sys/posix/setjmp.lo: core/sys/posix/$(am__dirstamp)
core/sys/posix/signal.lo: core/sys/posix/$(am__dirstamp)
core/sys/posix/spawn.lo: core/sys/posix/$(am__dirstamp)
+core/sys/posix/stdc/$(am__dirstamp):
+ @$(MKDIR_P) core/sys/posix/stdc
+ @: > core/sys/posix/stdc/$(am__dirstamp)
+core/sys/posix/stdc/time.lo: core/sys/posix/stdc/$(am__dirstamp)
core/sys/posix/stdio.lo: core/sys/posix/$(am__dirstamp)
core/sys/posix/stdlib.lo: core/sys/posix/$(am__dirstamp)
+core/sys/posix/string.lo: core/sys/posix/$(am__dirstamp)
+core/sys/posix/strings.lo: core/sys/posix/$(am__dirstamp)
core/sys/posix/sys/$(am__dirstamp):
@$(MKDIR_P) core/sys/posix/sys
@: > core/sys/posix/sys/$(am__dirstamp)
@: > core/sys/darwin/$(am__dirstamp)
core/sys/darwin/crt_externs.lo: core/sys/darwin/$(am__dirstamp)
core/sys/darwin/dlfcn.lo: core/sys/darwin/$(am__dirstamp)
+core/sys/darwin/err.lo: core/sys/darwin/$(am__dirstamp)
core/sys/darwin/execinfo.lo: core/sys/darwin/$(am__dirstamp)
+core/sys/darwin/ifaddrs.lo: core/sys/darwin/$(am__dirstamp)
core/sys/darwin/mach/$(am__dirstamp):
@$(MKDIR_P) core/sys/darwin/mach
@: > core/sys/darwin/mach/$(am__dirstamp)
core/sys/darwin/mach/kern_return.lo: \
core/sys/darwin/mach/$(am__dirstamp)
core/sys/darwin/mach/loader.lo: core/sys/darwin/mach/$(am__dirstamp)
+core/sys/darwin/mach/nlist.lo: core/sys/darwin/mach/$(am__dirstamp)
core/sys/darwin/mach/port.lo: core/sys/darwin/mach/$(am__dirstamp)
core/sys/darwin/mach/semaphore.lo: \
core/sys/darwin/mach/$(am__dirstamp)
+core/sys/darwin/mach/stab.lo: core/sys/darwin/mach/$(am__dirstamp)
core/sys/darwin/mach/thread_act.lo: \
core/sys/darwin/mach/$(am__dirstamp)
core/sys/darwin/netinet/$(am__dirstamp):
core/sys/darwin/sys/$(am__dirstamp):
@$(MKDIR_P) core/sys/darwin/sys
@: > core/sys/darwin/sys/$(am__dirstamp)
+core/sys/darwin/sys/attr.lo: core/sys/darwin/sys/$(am__dirstamp)
core/sys/darwin/sys/cdefs.lo: core/sys/darwin/sys/$(am__dirstamp)
core/sys/darwin/sys/event.lo: core/sys/darwin/sys/$(am__dirstamp)
core/sys/darwin/sys/mman.lo: core/sys/darwin/sys/$(am__dirstamp)
@$(MKDIR_P) core/sys/dragonflybsd
@: > core/sys/dragonflybsd/$(am__dirstamp)
core/sys/dragonflybsd/dlfcn.lo: core/sys/dragonflybsd/$(am__dirstamp)
+core/sys/dragonflybsd/err.lo: core/sys/dragonflybsd/$(am__dirstamp)
core/sys/dragonflybsd/execinfo.lo: \
core/sys/dragonflybsd/$(am__dirstamp)
core/sys/dragonflybsd/netinet/$(am__dirstamp):
core/sys/bionic/$(am__dirstamp):
@$(MKDIR_P) core/sys/bionic
@: > core/sys/bionic/$(am__dirstamp)
+core/sys/bionic/err.lo: core/sys/bionic/$(am__dirstamp)
core/sys/bionic/fcntl.lo: core/sys/bionic/$(am__dirstamp)
core/sys/bionic/string.lo: core/sys/bionic/$(am__dirstamp)
core/sys/bionic/unistd.lo: core/sys/bionic/$(am__dirstamp)
@: > core/sys/freebsd/$(am__dirstamp)
core/sys/freebsd/config.lo: core/sys/freebsd/$(am__dirstamp)
core/sys/freebsd/dlfcn.lo: core/sys/freebsd/$(am__dirstamp)
+core/sys/freebsd/err.lo: core/sys/freebsd/$(am__dirstamp)
core/sys/freebsd/execinfo.lo: core/sys/freebsd/$(am__dirstamp)
core/sys/freebsd/netinet/$(am__dirstamp):
@$(MKDIR_P) core/sys/freebsd/netinet
@$(MKDIR_P) core/sys/netbsd
@: > core/sys/netbsd/$(am__dirstamp)
core/sys/netbsd/dlfcn.lo: core/sys/netbsd/$(am__dirstamp)
+core/sys/netbsd/err.lo: core/sys/netbsd/$(am__dirstamp)
core/sys/netbsd/execinfo.lo: core/sys/netbsd/$(am__dirstamp)
core/sys/netbsd/string.lo: core/sys/netbsd/$(am__dirstamp)
core/sys/netbsd/sys/$(am__dirstamp):
@$(MKDIR_P) core/sys/openbsd
@: > core/sys/openbsd/$(am__dirstamp)
core/sys/openbsd/dlfcn.lo: core/sys/openbsd/$(am__dirstamp)
+core/sys/openbsd/err.lo: core/sys/openbsd/$(am__dirstamp)
core/sys/openbsd/string.lo: core/sys/openbsd/$(am__dirstamp)
core/sys/openbsd/sys/$(am__dirstamp):
@$(MKDIR_P) core/sys/openbsd/sys
core/sys/linux/dlfcn.lo: core/sys/linux/$(am__dirstamp)
core/sys/linux/elf.lo: core/sys/linux/$(am__dirstamp)
core/sys/linux/epoll.lo: core/sys/linux/$(am__dirstamp)
+core/sys/linux/err.lo: core/sys/linux/$(am__dirstamp)
core/sys/linux/errno.lo: core/sys/linux/$(am__dirstamp)
core/sys/linux/execinfo.lo: core/sys/linux/$(am__dirstamp)
core/sys/linux/fcntl.lo: core/sys/linux/$(am__dirstamp)
core/sys/windows/rpcnsip.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/rpcnterr.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/schannel.lo: core/sys/windows/$(am__dirstamp)
+core/sys/windows/sdkddkver.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/secext.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/security.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/servprov.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/sspi.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/stacktrace.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/stat.lo: core/sys/windows/$(am__dirstamp)
+core/sys/windows/stdc/$(am__dirstamp):
+ @$(MKDIR_P) core/sys/windows/stdc
+ @: > core/sys/windows/stdc/$(am__dirstamp)
+core/sys/windows/stdc/time.lo: core/sys/windows/stdc/$(am__dirstamp)
core/sys/windows/subauth.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/threadaux.lo: core/sys/windows/$(am__dirstamp)
core/sys/windows/tlhelp32.lo: core/sys/windows/$(am__dirstamp)
@: > core/sys/solaris/$(am__dirstamp)
core/sys/solaris/dlfcn.lo: core/sys/solaris/$(am__dirstamp)
core/sys/solaris/elf.lo: core/sys/solaris/$(am__dirstamp)
+core/sys/solaris/err.lo: core/sys/solaris/$(am__dirstamp)
core/sys/solaris/execinfo.lo: core/sys/solaris/$(am__dirstamp)
core/sys/solaris/libelf.lo: core/sys/solaris/$(am__dirstamp)
core/sys/solaris/link.lo: core/sys/solaris/$(am__dirstamp)
-rm -f core/sys/posix/net/*.lo
-rm -f core/sys/posix/netinet/*.$(OBJEXT)
-rm -f core/sys/posix/netinet/*.lo
+ -rm -f core/sys/posix/stdc/*.$(OBJEXT)
+ -rm -f core/sys/posix/stdc/*.lo
-rm -f core/sys/posix/sys/*.$(OBJEXT)
-rm -f core/sys/posix/sys/*.lo
-rm -f core/sys/solaris/*.$(OBJEXT)
-rm -f core/sys/solaris/sys/*.lo
-rm -f core/sys/windows/*.$(OBJEXT)
-rm -f core/sys/windows/*.lo
+ -rm -f core/sys/windows/stdc/*.$(OBJEXT)
+ -rm -f core/sys/windows/stdc/*.lo
+ -rm -f core/thread/*.$(OBJEXT)
+ -rm -f core/thread/*.lo
-rm -f gc/*.$(OBJEXT)
-rm -f gc/*.lo
-rm -f gc/impl/conservative/*.$(OBJEXT)
-rm -f gcc/unwind/*.lo
-rm -f rt/*.$(OBJEXT)
-rm -f rt/*.lo
- -rm -f rt/typeinfo/*.$(OBJEXT)
- -rm -f rt/typeinfo/*.lo
-rm -f rt/util/*.$(OBJEXT)
-rm -f rt/util/*.lo
-rm -f rt/util/container/*.$(OBJEXT)
-rm -rf core/sys/posix/arpa/.libs core/sys/posix/arpa/_libs
-rm -rf core/sys/posix/net/.libs core/sys/posix/net/_libs
-rm -rf core/sys/posix/netinet/.libs core/sys/posix/netinet/_libs
+ -rm -rf core/sys/posix/stdc/.libs core/sys/posix/stdc/_libs
-rm -rf core/sys/posix/sys/.libs core/sys/posix/sys/_libs
-rm -rf core/sys/solaris/.libs core/sys/solaris/_libs
-rm -rf core/sys/solaris/sys/.libs core/sys/solaris/sys/_libs
-rm -rf core/sys/windows/.libs core/sys/windows/_libs
+ -rm -rf core/sys/windows/stdc/.libs core/sys/windows/stdc/_libs
+ -rm -rf core/thread/.libs core/thread/_libs
-rm -rf gc/.libs gc/_libs
-rm -rf gc/impl/conservative/.libs gc/impl/conservative/_libs
-rm -rf gc/impl/manual/.libs gc/impl/manual/_libs
-rm -rf gcc/sections/.libs gcc/sections/_libs
-rm -rf gcc/unwind/.libs gcc/unwind/_libs
-rm -rf rt/.libs rt/_libs
- -rm -rf rt/typeinfo/.libs rt/typeinfo/_libs
-rm -rf rt/util/.libs rt/util/_libs
-rm -rf rt/util/container/.libs rt/util/container/_libs
install-toolexeclibDATA: $(toolexeclib_DATA)
-rm -f core/sys/posix/arpa/$(am__dirstamp)
-rm -f core/sys/posix/net/$(am__dirstamp)
-rm -f core/sys/posix/netinet/$(am__dirstamp)
+ -rm -f core/sys/posix/stdc/$(am__dirstamp)
-rm -f core/sys/posix/sys/$(am__dirstamp)
-rm -f core/sys/solaris/$(am__dirstamp)
-rm -f core/sys/solaris/sys/$(am__dirstamp)
-rm -f core/sys/windows/$(am__dirstamp)
+ -rm -f core/sys/windows/stdc/$(am__dirstamp)
+ -rm -f core/thread/$(am__dirstamp)
-rm -f gc/$(am__dirstamp)
-rm -f gc/impl/conservative/$(am__dirstamp)
-rm -f gc/impl/manual/$(am__dirstamp)
-rm -f gcc/sections/$(am__dirstamp)
-rm -f gcc/unwind/$(am__dirstamp)
-rm -f rt/$(am__dirstamp)
- -rm -f rt/typeinfo/$(am__dirstamp)
-rm -f rt/util/$(am__dirstamp)
-rm -f rt/util/container/$(am__dirstamp)
* Use instead of assert(0, msg), since this does not print a message for -release compiled
* code, and druntime is -release compiled.
*/
-void abort(string msg, string filename = __FILE__, size_t line = __LINE__) @nogc nothrow @safe
+void abort(scope string msg, scope string filename = __FILE__, size_t line = __LINE__) @nogc nothrow @safe
{
import core.stdc.stdlib: c_abort = abort;
// use available OS system calls to print the message to stderr
///
real cargl(creal z);
- ///
- double cimag(cdouble z);
- ///
- float cimagf(cfloat z);
- ///
- real cimagl(creal z);
+///
+pragma(inline, true) double cimag(cdouble z) { return z.im; }
+///
+pragma(inline, true) float cimagf(cfloat z) { return z.im; }
+///
+pragma(inline, true) real cimagl(creal z) { return z.im; }
- ///
+///
cdouble conj(cdouble z);
///
cfloat conjf(cfloat z);
///
creal cprojl(creal z);
-// double creal(cdouble z);
+// Note: `creal` is a keyword in D and so this function is inaccessible, use `creald` instead
+//pragma(inline, true) double creal(cdouble z) { return z.re; }
+
///
- float crealf(cfloat z);
- ///
- real creall(creal z);
+pragma(inline, true) double creald(cdouble z) { return z.re; }
+///
+pragma(inline, true) float crealf(cfloat z) { return z.re; }
+///
+pragma(inline, true) real creall(creal z) { return z.re; }
}
else version (Solaris)
{
- enum EPERM = 1 /** Not super-user */;
- enum ENOENT = 2 /** No such file or directory */;
- enum ESRCH = 3 /** No such process */;
- enum EINTR = 4 /** interrupted system call */;
- enum EIO = 5 /** I/O error */;
- enum ENXIO = 6 /** No such device or address */;
- enum E2BIG = 7 /** Arg list too long */;
- enum ENOEXEC = 8 /** Exec format error */;
- enum EBADF = 9 /** Bad file number */;
- enum ECHILD = 10 /** No children */;
- enum EAGAIN = 11 /** Resource temporarily unavailable */;
- enum ENOMEM = 12 /** Not enough core */;
- enum EACCES = 13 /** Permission denied */;
- enum EFAULT = 14 /** Bad address */;
- enum ENOTBLK = 15 /** Block device required */;
- enum EBUSY = 16 /** Mount device busy */;
- enum EEXIST = 17 /** File exists */;
- enum EXDEV = 18 /** Cross-device link */;
- enum ENODEV = 19 /** No such device */;
- enum ENOTDIR = 20 /** Not a directory */;
- enum EISDIR = 21 /** Is a directory */;
- enum EINVAL = 22 /** Invalid argument */;
- enum ENFILE = 23 /** File table overflow */;
- enum EMFILE = 24 /** Too many open files */;
- enum ENOTTY = 25 /** Inappropriate ioctl for device */;
- enum ETXTBSY = 26 /** Text file busy */;
- enum EFBIG = 27 /** File too large */;
- enum ENOSPC = 28 /** No space left on device */;
- enum ESPIPE = 29 /** Illegal seek */;
- enum EROFS = 30 /** Read only file system */;
- enum EMLINK = 31 /** Too many links */;
- enum EPIPE = 32 /** Broken pipe */;
- enum EDOM = 33 /** Math arg out of domain of func */;
- enum ERANGE = 34 /** Math result not representable */;
- enum ENOMSG = 35 /** No message of desired type */;
- enum EIDRM = 36 /** Identifier removed */;
- enum ECHRNG = 37 /** Channel number out of range */;
- enum EL2NSYNC = 38 /** Level 2 not synchronized */;
- enum EL3HLT = 39 /** Level 3 halted */;
- enum EL3RST = 40 /** Level 3 reset */;
- enum ELNRNG = 41 /** Link number out of range */;
- enum EUNATCH = 42 /** Protocol driver not attached */;
- enum ENOCSI = 43 /** No CSI structure available */;
- enum EL2HLT = 44 /** Level 2 halted */;
- enum EDEADLK = 45 /** Deadlock condition. */;
- enum ENOLCK = 46 /** No record locks available. */;
- enum ECANCELED = 47 /** Operation canceled */;
- enum ENOTSUP = 48 /** Operation not supported */;
- enum EDQUOT = 49 /** Disc quota exceeded */;
- enum EBADE = 50 /** invalid exchange */;
- enum EBADR = 51 /** invalid request descriptor */;
- enum EXFULL = 52 /** exchange full */;
- enum ENOANO = 53 /** no anode */;
- enum EBADRQC = 54 /** invalid request code */;
- enum EBADSLT = 55 /** invalid slot */;
- enum EDEADLOCK = 56 /** file locking deadlock error */;
- enum EBFONT = 57 /** bad font file fmt */;
- enum EOWNERDEAD = 58 /** process died with the lock */;
- enum ENOTRECOVERABLE = 59 /** lock is not recoverable */;
- enum ENOSTR = 60 /** Device not a stream */;
- enum ENODATA = 61 /** no data (for no delay io) */;
- enum ETIME = 62 /** timer expired */;
- enum ENOSR = 63 /** out of streams resources */;
- enum ENONET = 64 /** Machine is not on the network */;
- enum ENOPKG = 65 /** Package not installed */;
- enum EREMOTE = 66 /** The object is remote */;
- enum ENOLINK = 67 /** the link has been severed */;
- enum EADV = 68 /** advertise error */;
- enum ESRMNT = 69 /** srmount error */;
- enum ECOMM = 70 /** Communication error on send */;
- enum EPROTO = 71 /** Protocol error */;
- enum ELOCKUNMAPPED = 72 /** locked lock was unmapped */;
- enum ENOTACTIVE = 73 /** Facility is not active */;
- enum EMULTIHOP = 74 /** multihop attempted */;
- enum EBADMSG = 77 /** trying to read unreadable message */;
- enum ENAMETOOLONG = 78 /** path name is too long */;
- enum EOVERFLOW = 79 /** value too large to be stored in data type */;
- enum ENOTUNIQ = 80 /** given log. name not unique */;
- enum EBADFD = 81 /** f.d. invalid for this operation */;
- enum EREMCHG = 82 /** Remote address changed */;
- enum ELIBACC = 83 /** Can't access a needed shared lib. */;
- enum ELIBBAD = 84 /** Accessing a corrupted shared lib. */;
- enum ELIBSCN = 85 /** .lib section in a.out corrupted. */;
- enum ELIBMAX = 86 /** Attempting to link in too many libs. */;
- enum ELIBEXEC = 87 /** Attempting to exec a shared library. */;
- enum EILSEQ = 88 /** Illegal byte sequence. */;
- enum ENOSYS = 89 /** Unsupported file system operation */;
- enum ELOOP = 90 /** Symbolic link loop */;
- enum ERESTART = 91 /** Restartable system call */;
- enum ESTRPIPE = 92 /** if pipe/FIFO, don't sleep in stream head */;
- enum ENOTEMPTY = 93 /** directory not empty */;
- enum EUSERS = 94 /** Too many users (for UFS) */;
- enum ENOTSOCK = 95 /** Socket operation on non-socket */;
- enum EDESTADDRREQ = 96 /** Destination address required */;
- enum EMSGSIZE = 97 /** Message too long */;
- enum EPROTOTYPE = 98 /** Protocol wrong type for socket */;
- enum ENOPROTOOPT = 99 /** Protocol not available */;
- enum EPROTONOSUPPORT = 120 /** Protocol not supported */;
- enum ESOCKTNOSUPPORT = 121 /** Socket type not supported */;
- enum EOPNOTSUPP = 122 /** Operation not supported on socket */;
- enum EPFNOSUPPORT = 123 /** Protocol family not supported */;
- enum EAFNOSUPPORT = 124 /** Address family not supported by the protocol family */;
- enum EADDRINUSE = 125 /** Address already in use */;
- enum EADDRNOTAVAIL = 126 /** Can't assign requested address */;
- enum ENETDOWN = 127 /** Network is down */;
- enum ENETUNREACH = 128 /** Network is unreachable */;
- enum ENETRESET = 129 /** Network dropped connection because of reset */;
- enum ECONNABORTED = 130 /** Software caused connection abort */;
- enum ECONNRESET = 131 /** Connection reset by peer */;
- enum ENOBUFS = 132 /** No buffer space available */;
- enum EISCONN = 133 /** Socket is already connected */;
- enum ENOTCONN = 134 /** Socket is not connected */;
- enum ESHUTDOWN = 143 /** Can't send after socket shutdown */;
- enum ETOOMANYREFS = 144 /** Too many references: can't splice */;
- enum ETIMEDOUT = 145 /** Connection timed out */;
- enum ECONNREFUSED = 146 /** Connection refused */;
- enum EHOSTDOWN = 147 /** Host is down */;
- enum EHOSTUNREACH = 148 /** No route to host */;
- enum EWOULDBLOCK = EAGAIN; /** Resource temporarily unavailable */;
- enum EALREADY = 149 /** operation already in progress */;
- enum EINPROGRESS = 150 /** operation now in progress */;
- enum ESTALE = 151 /** Stale NFS file handle */;
+ enum EPERM = 1; /// Not super-user
+ enum ENOENT = 2; /// No such file or directory
+ enum ESRCH = 3; /// No such process
+ enum EINTR = 4; /// interrupted system call
+ enum EIO = 5; /// I/O error
+ enum ENXIO = 6; /// No such device or address
+ enum E2BIG = 7; /// Arg list too long
+ enum ENOEXEC = 8; /// Exec format error
+ enum EBADF = 9; /// Bad file number
+ enum ECHILD = 10; /// No children
+ enum EAGAIN = 11; /// Resource temporarily unavailable
+ enum ENOMEM = 12; /// Not enough core
+ enum EACCES = 13; /// Permission denied
+ enum EFAULT = 14; /// Bad address
+ enum ENOTBLK = 15; /// Block device required
+ enum EBUSY = 16; /// Mount device busy
+ enum EEXIST = 17; /// File exists
+ enum EXDEV = 18; /// Cross-device link
+ enum ENODEV = 19; /// No such device
+ enum ENOTDIR = 20; /// Not a directory
+ enum EISDIR = 21; /// Is a directory
+ enum EINVAL = 22; /// Invalid argument
+ enum ENFILE = 23; /// File table overflow
+ enum EMFILE = 24; /// Too many open files
+ enum ENOTTY = 25; /// Inappropriate ioctl for device
+ enum ETXTBSY = 26; /// Text file busy
+ enum EFBIG = 27; /// File too large
+ enum ENOSPC = 28; /// No space left on device
+ enum ESPIPE = 29; /// Illegal seek
+ enum EROFS = 30; /// Read only file system
+ enum EMLINK = 31; /// Too many links
+ enum EPIPE = 32; /// Broken pipe
+ enum EDOM = 33; /// Math arg out of domain of func
+ enum ERANGE = 34; /// Math result not representable
+ enum ENOMSG = 35; /// No message of desired type
+ enum EIDRM = 36; /// Identifier removed
+ enum ECHRNG = 37; /// Channel number out of range
+ enum EL2NSYNC = 38; /// Level 2 not synchronized
+ enum EL3HLT = 39; /// Level 3 halted
+ enum EL3RST = 40; /// Level 3 reset
+ enum ELNRNG = 41; /// Link number out of range
+ enum EUNATCH = 42; /// Protocol driver not attached
+ enum ENOCSI = 43; /// No CSI structure available
+ enum EL2HLT = 44; /// Level 2 halted
+ enum EDEADLK = 45; /// Deadlock condition.
+ enum ENOLCK = 46; /// No record locks available.
+ enum ECANCELED = 47; /// Operation canceled
+ enum ENOTSUP = 48; /// Operation not supported
+ enum EDQUOT = 49; /// Disc quota exceeded
+ enum EBADE = 50; /// invalid exchange
+ enum EBADR = 51; /// invalid request descriptor
+ enum EXFULL = 52; /// exchange full
+ enum ENOANO = 53; /// no anode
+ enum EBADRQC = 54; /// invalid request code
+ enum EBADSLT = 55; /// invalid slot
+ enum EDEADLOCK = 56; /// file locking deadlock error
+ enum EBFONT = 57; /// bad font file fmt
+ enum EOWNERDEAD = 58; /// process died with the lock
+ enum ENOTRECOVERABLE = 59; /// lock is not recoverable
+ enum ENOSTR = 60; /// Device not a stream
+ enum ENODATA = 61; /// no data (for no delay io)
+ enum ETIME = 62; /// timer expired
+ enum ENOSR = 63; /// out of streams resources
+ enum ENONET = 64; /// Machine is not on the network
+ enum ENOPKG = 65; /// Package not installed
+ enum EREMOTE = 66; /// The object is remote
+ enum ENOLINK = 67; /// the link has been severed
+ enum EADV = 68; /// advertise error
+ enum ESRMNT = 69; /// srmount error
+ enum ECOMM = 70; /// Communication error on send
+ enum EPROTO = 71; /// Protocol error
+ enum ELOCKUNMAPPED = 72; /// locked lock was unmapped
+ enum ENOTACTIVE = 73; /// Facility is not active
+ enum EMULTIHOP = 74; /// multihop attempted
+ enum EBADMSG = 77; /// trying to read unreadable message
+ enum ENAMETOOLONG = 78; /// path name is too long
+ enum EOVERFLOW = 79; /// value too large to be stored in data type
+ enum ENOTUNIQ = 80; /// given log. name not unique
+ enum EBADFD = 81; /// f.d. invalid for this operation
+ enum EREMCHG = 82; /// Remote address changed
+ enum ELIBACC = 83; /// Can't access a needed shared lib.
+ enum ELIBBAD = 84; /// Accessing a corrupted shared lib.
+ enum ELIBSCN = 85; /// .lib section in a.out corrupted.
+ enum ELIBMAX = 86; /// Attempting to link in too many libs.
+ enum ELIBEXEC = 87; /// Attempting to exec a shared library.
+ enum EILSEQ = 88; /// Illegal byte sequence.
+ enum ENOSYS = 89; /// Unsupported file system operation
+ enum ELOOP = 90; /// Symbolic link loop
+ enum ERESTART = 91; /// Restartable system call
+ enum ESTRPIPE = 92; /// if pipe/FIFO, don't sleep in stream head
+ enum ENOTEMPTY = 93; /// directory not empty
+ enum EUSERS = 94; /// Too many users (for UFS)
+ enum ENOTSOCK = 95; /// Socket operation on non-socket
+ enum EDESTADDRREQ = 96; /// Destination address required
+ enum EMSGSIZE = 97; /// Message too long
+ enum EPROTOTYPE = 98; /// Protocol wrong type for socket
+ enum ENOPROTOOPT = 99; /// Protocol not available
+ enum EPROTONOSUPPORT = 120; /// Protocol not supported
+ enum ESOCKTNOSUPPORT = 121; /// Socket type not supported
+ enum EOPNOTSUPP = 122; /// Operation not supported on socket
+ enum EPFNOSUPPORT = 123; /// Protocol family not supported
+ enum EAFNOSUPPORT = 124; /// Address family not supported by the protocol family
+ enum EADDRINUSE = 125; /// Address already in use
+ enum EADDRNOTAVAIL = 126; /// Can't assign requested address
+ enum ENETDOWN = 127; /// Network is down
+ enum ENETUNREACH = 128; /// Network is unreachable
+ enum ENETRESET = 129; /// Network dropped connection because of reset
+ enum ECONNABORTED = 130; /// Software caused connection abort
+ enum ECONNRESET = 131; /// Connection reset by peer
+ enum ENOBUFS = 132; /// No buffer space available
+ enum EISCONN = 133; /// Socket is already connected
+ enum ENOTCONN = 134; /// Socket is not connected
+ enum ESHUTDOWN = 143; /// Can't send after socket shutdown
+ enum ETOOMANYREFS = 144; /// Too many references: can't splice
+ enum ETIMEDOUT = 145; /// Connection timed out
+ enum ECONNREFUSED = 146; /// Connection refused
+ enum EHOSTDOWN = 147; /// Host is down
+ enum EHOSTUNREACH = 148; /// No route to host
+ enum EWOULDBLOCK = EAGAIN; /// Resource temporarily unavailable
+ enum EALREADY = 149; /// operation already in progress
+ enum EINPROGRESS = 150; /// operation now in progress
+ enum ESTALE = 151; /// Stale NFS file handle
}
else version (Haiku)
{
alias fexcept_t = uint;
}
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/sparc/fpu/bits/fenv.h
- else version (SPARC64)
+ else version (SPARC_Any)
{
- alias fenv_t = ulong;
- alias fexcept_t = ulong;
+ alias fenv_t = c_ulong;
+ alias fexcept_t = c_ulong;
}
// https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/s390/fpu/bits/fenv.h
else version (IBMZ_Any)
uint status; /* Status word register */
uint tag; /* Tag word register */
uint[4] others; /* EIP, Pointer Selector, etc */
- };
+ }
_x87 x87;
uint mxcsr; /* Control and status register */
ushort tag; /* Tag word register */
ushort unused3;
uint[4] others; /* EIP, Pointer Selector, etc */
- };
+ }
_x87 x87;
uint mxcsr; /* Control and status register */
- };
+ }
}
uint status;
uint tag;
uint[4] others;
- };
+ }
_x87 x87;
uint mxcsr;
///
int fegetexceptflag(fexcept_t* flagp, int excepts);
///
-int fesetexceptflag(in fexcept_t* flagp, int excepts);
+int fesetexceptflag(const scope fexcept_t* flagp, int excepts);
///
int fegetround();
///
int fegetenv(fenv_t* envp);
///
-int fesetenv(in fenv_t* envp);
+int fesetenv(const scope fenv_t* envp);
// MS define feraiseexcept() and feupdateenv() inline.
version (CRuntime_Microsoft) // supported since MSVCRT 12 (VS 2013) only
}
///
- int feupdateenv()(in fenv_t* envp)
+ int feupdateenv()(const scope fenv_t* envp)
{
int excepts = fetestexcept(FE_ALL_EXCEPT);
return (fesetenv(envp) != 0 || feraiseexcept(excepts) != 0 ? 1 : 0);
///
int feraiseexcept(int excepts);
///
- int feupdateenv(in fenv_t* envp);
+ int feupdateenv(const scope fenv_t* envp);
}
///
imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom);
///
-intmax_t strtoimax(in char* nptr, char** endptr, int base);
+intmax_t strtoimax(const scope char* nptr, char** endptr, int base);
///
-uintmax_t strtoumax(in char* nptr, char** endptr, int base);
+uintmax_t strtoumax(const scope char* nptr, char** endptr, int base);
///
-intmax_t wcstoimax(in wchar_t* nptr, wchar_t** endptr, int base);
+intmax_t wcstoimax(const scope wchar_t* nptr, wchar_t** endptr, int base);
///
-uintmax_t wcstoumax(in wchar_t* nptr, wchar_t** endptr, int base);
+uintmax_t wcstoumax(const scope wchar_t* nptr, wchar_t** endptr, int base);
else version (WatchOS)
version = Darwin;
-private import core.stdc.config;
+import core.stdc.config;
extern (C):
@trusted: // Constants only.
}
///
-@system char* setlocale(int category, in char* locale);
+@system char* setlocale(int category, const scope char* locale);
///
lconv* localeconv();
module core.stdc.math;
-private import core.stdc.config;
+import core.stdc.config;
version (OSX)
version = Darwin;
// other Darwins
version (OSX)
{
- pure int __fpclassify(real x);
- pure int __isfinite(real x);
- pure int __isinf(real x);
- pure int __isnan(real x);
- alias __fpclassifyl = __fpclassify;
- alias __isfinitel = __isfinite;
- alias __isinfl = __isinf;
- alias __isnanl = __isnan;
+ version (AArch64)
+ {
+ // Available in macOS ARM
+ 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);
+ pure int __isinf(real x);
+ pure int __isnan(real x);
+ alias __fpclassifyl = __fpclassify;
+ alias __isfinitel = __isfinite;
+ alias __isinfl = __isinf;
+ alias __isnanl = __isnan;
+ }
}
else
{
///
extern(D) pure real fmal()(real x, real y, real z) { return fma(cast(double) x, cast(double) y, cast(double) z); }
}
-/* NOTE: freebsd < 8-CURRENT doesn't appear to support *l, but we can
- * approximate.
- * A lot of them were added in 8.0-RELEASE, and so a lot of these workarounds
- * should then be removed.
- */
-// NOTE: FreeBSD 8.0-RELEASE doesn't support log2* nor these *l functions:
-// acoshl, asinhl, atanhl, coshl, sinhl, tanhl, cbrtl, powl, expl,
-// expm1l, logl, log1pl, log10l, erfcl, erfl, lgammal, tgammal;
-// but we can approximate.
else version (FreeBSD)
{
- version (none) // < 8-CURRENT
- {
- extern (D)
- {
- real acosl(real x) { return acos(x); }
- real asinl(real x) { return asin(x); }
- pure real atanl(real x) { return atan(x); }
- real atan2l(real y, real x) { return atan2(y, x); }
- pure real cosl(real x) { return cos(x); }
- pure real sinl(real x) { return sin(x); }
- pure real tanl(real x) { return tan(x); }
- real exp2l(real x) { return exp2(x); }
- pure real frexpl(real value, int* exp) { return frexp(value, exp); }
- int ilogbl(real x) { return ilogb(x); }
- real ldexpl(real x, int exp) { return ldexp(x, exp); }
- real logbl(real x) { return logb(x); }
- //real modfl(real value, real *iptr); // nontrivial conversion
- real scalbnl(real x, int n) { return scalbn(x, n); }
- real scalblnl(real x, c_long n) { return scalbln(x, n); }
- pure real fabsl(real x) { return fabs(x); }
- real hypotl(real x, real y) { return hypot(x, y); }
- real sqrtl(real x) { return sqrt(x); }
- pure real ceill(real x) { return ceil(x); }
- pure real floorl(real x) { return floor(x); }
- pure real nearbyintl(real x) { return nearbyint(x); }
- pure real rintl(real x) { return rint(x); }
- c_long lrintl(real x) { return lrint(x); }
- pure real roundl(real x) { return round(x); }
- c_long lroundl(real x) { return lround(x); }
- long llroundl(real x) { return llround(x); }
- pure real truncl(real x) { return trunc(x); }
- real fmodl(real x, real y) { return fmod(x, y); }
- real remainderl(real x, real y) { return remainder(x, y); }
- real remquol(real x, real y, int* quo) { return remquo(x, y, quo); }
- pure real copysignl(real x, real y) { return copysign(x, y); }
- //pure double nan(char* tagp);
- //pure float nanf(char* tagp);
- //pure real nanl(char* tagp);
- real nextafterl(real x, real y) { return nextafter(x, y); }
- real nexttowardl(real x, real y) { return nexttoward(x, y); }
- real fdiml(real x, real y) { return fdim(x, y); }
- pure real fmaxl(real x, real y) { return fmax(x, y); }
- pure real fminl(real x, real y) { return fmin(x, y); }
- pure real fmal(real x, real y, real z) { return fma(x, y, z); }
- }
- }
- else
- {
- ///
- real acosl(real x);
- ///
- real asinl(real x);
- ///
- pure real atanl(real x);
- ///
- real atan2l(real y, real x);
- ///
- pure real cosl(real x);
- ///
- pure real sinl(real x);
- ///
- pure real tanl(real x);
- ///
- real exp2l(real x);
- ///
- pure real frexpl(real value, int* exp);
- ///
- int ilogbl(real x);
- ///
- real ldexpl(real x, int exp);
- ///
- real logbl(real x);
- ///
- pure real modfl(real value, real *iptr);
- ///
- real scalbnl(real x, int n);
- ///
- real scalblnl(real x, c_long n);
- ///
- pure real fabsl(real x);
- ///
- real hypotl(real x, real y);
- ///
- real sqrtl(real x);
- ///
- pure real ceill(real x);
- ///
- pure real floorl(real x);
- ///
- pure real nearbyintl(real x);
- ///
- pure real rintl(real x);
- ///
- c_long lrintl(real x);
- ///
- pure real roundl(real x);
- ///
- c_long lroundl(real x);
- ///
- long llroundl(real x);
- ///
- pure real truncl(real x);
- ///
- real fmodl(real x, real y);
///
- real remainderl(real x, real y);
- ///
- real remquol(real x, real y, int* quo);
- ///
- pure real copysignl(real x, real y);
- ///
- pure double nan(char* tagp);
- ///
- pure float nanf(char* tagp);
- ///
- pure real nanl(char* tagp);
- ///
- real nextafterl(real x, real y);
- ///
- real nexttowardl(real x, real y);
- ///
- real fdiml(real x, real y);
- ///
- pure real fmaxl(real x, real y);
- ///
- pure real fminl(real x, real y);
- ///
- pure real fmal(real x, real y, real z);
- }
- ///
double acos(double x);
///
float acosf(float x);
+ ///
+ real acosl(real x); // since 8.0
///
double asin(double x);
///
float asinf(float x);
+ ///
+ real asinl(real x); // since 8.0
///
pure double atan(double x);
///
pure float atanf(float x);
+ ///
+ pure real atanl(real x); // since 8.0
///
double atan2(double y, double x);
///
float atan2f(float y, float x);
+ ///
+ real atan2l(real y, real x); // since 8.0
///
pure double cos(double x);
///
pure float cosf(float x);
+ ///
+ pure real cosl(real x); // since 8.0
///
pure double sin(double x);
///
pure float sinf(float x);
+ ///
+ pure real sinl(real x); // since 8.0
///
pure double tan(double x);
///
pure float tanf(float x);
+ ///
+ pure real tanl(real x); // since 8.0
///
double acosh(double x);
///
float acoshf(float x);
///
- extern(D) real acoshl(real x) { return acosh(x); }
+ real acoshl(real x); // since 10.0
///
pure double asinh(double x);
///
pure float asinhf(float x);
///
- extern(D) pure real asinhl(real x) { return asinh(x); }
+ pure real asinhl(real x); // since 10.0
///
double atanh(double x);
///
float atanhf(float x);
///
- extern(D) real atanhl(real x) { return atanh(x); }
+ real atanhl(real x); // since 10.0
///
double cosh(double x);
///
float coshf(float x);
///
- extern(D) real coshl(real x) { return cosh(x); }
+ real coshl(real x); // since 10.1
///
double sinh(double x);
///
float sinhf(float x);
///
- extern(D) real sinhl(real x) { return sinh(x); }
+ real sinhl(real x); // since 10.1
///
pure double tanh(double x);
///
pure float tanhf(float x);
///
- extern(D) pure real tanhl(real x) { return tanh(x); }
+ pure real tanhl(real x); // since 10.1
///
double exp(double x);
///
float expf(float x);
///
- extern(D) real expl(real x) { return exp(x); }
+ real expl(real x); // since 10.0
///
double exp2(double x);
///
float exp2f(float x);
+ ///
+ real exp2l(real x); // since 8.0
///
double expm1(double x);
///
float expm1f(float x);
///
- extern(D) real expm1l(real x) { return expm1(x); }
+ real expm1l(real x); // since 10.0
///
pure double frexp(double value, int* exp);
///
pure float frexpf(float value, int* exp);
+ ///
+ pure real frexpl(real value, int* exp); // since 6.0
///
int ilogb(double x);
///
int ilogbf(float x);
+ ///
+ int ilogbl(real x); // since 5.4
///
double ldexp(double x, int exp);
///
float ldexpf(float x, int exp);
+ ///
+ real ldexpl(real x, int exp); // since 6.0
///
double log(double x);
///
float logf(float x);
///
- extern(D) real logl(real x) { return log(x); }
+ real logl(real x); // since 10.0
///
double log10(double x);
///
float log10f(float x);
///
- extern(D) real log10l(real x) { return log10(x); }
+ real log10l(real x); // since 10.0
///
double log1p(double x);
///
float log1pf(float x);
///
- extern(D) real log1pl(real x) { return log1p(x); }
+ real log1pl(real x); // since 10.0
- private enum real ONE_LN2 = 1 / 0x1.62e42fefa39ef358p-1L;
///
- extern(D) double log2(double x) { return log(x) * ONE_LN2; }
+ double log2(double x); // since 8.3
///
- extern(D) float log2f(float x) { return logf(x) * ONE_LN2; }
+ float log2f(float x); // since 8.3
///
- extern(D) real log2l(real x) { return logl(x) * ONE_LN2; }
+ real log2l(real x); // since 10.0
///
double logb(double x);
///
float logbf(float x);
+ ///
+ real logbl(real x); // since 8.0
///
pure double modf(double value, double* iptr);
///
pure float modff(float value, float* iptr);
+ ///
+ pure real modfl(real value, real *iptr); // since 8.0
///
double scalbn(double x, int n);
///
float scalbnf(float x, int n);
+ ///
+ real scalbnl(real x, int n); // since 6.0
///
double scalbln(double x, c_long n);
///
float scalblnf(float x, c_long n);
+ ///
+ real scalblnl(real x, c_long n); // since 6.0
///
pure double cbrt(double x);
///
pure float cbrtf(float x);
///
- extern(D) pure real cbrtl(real x) { return cbrt(x); }
+ pure real cbrtl(real x); // since 9.0
///
pure double fabs(double x);
///
pure float fabsf(float x);
+ ///
+ pure real fabsl(real x); // since 5.3
///
double hypot(double x, double y);
///
float hypotf(float x, float y);
+ ///
+ real hypotl(real x, real y); // since 8.0
///
double pow(double x, double y);
///
float powf(float x, float y);
///
- extern(D) real powl(real x, real y) { return pow(x, y); }
+ real powl(real x, real y); // since 10.4
///
double sqrt(double x);
///
float sqrtf(float x);
+ ///
+ real sqrtl(real x); // since 8.0
///
pure double erf(double x);
///
pure float erff(float x);
///
- extern(D) pure real erfl(real x) { return erf(x); }
+ pure real erfl(real x); // since 10.1
///
double erfc(double x);
///
float erfcf(float x);
///
- extern(D) real erfcl(real x) { return erfc(x); }
+ real erfcl(real x); // since 10.1
///
double lgamma(double x);
///
float lgammaf(float x);
///
- extern(D) real lgammal(real x) { return lgamma(x); }
+ real lgammal(real x); // since 10.2
///
double tgamma(double x);
///
float tgammaf(float x);
///
- extern(D) real tgammal(real x) { return tgamma(x); }
+ real tgammal(real x); // since 11.2
///
pure double ceil(double x);
///
pure float ceilf(float x);
+ ///
+ pure real ceill(real x); // since 5.4
///
pure double floor(double x);
///
pure float floorf(float x);
+ ///
+ pure real floorl(real x); // since 5.4
///
pure double nearbyint(double x);
///
pure float nearbyintf(float x);
+ ///
+ pure real nearbyintl(real x); // since 8.0
///
pure double rint(double x);
///
pure float rintf(float x);
+ ///
+ pure real rintl(real x); // since 8.0
///
c_long lrint(double x);
///
c_long lrintf(float x);
+ ///
+ c_long lrintl(real x); // since 8.0
///
long llrint(double x);
///
long llrintf(float x);
///
- extern(D) long llrintl(real x) { return llrint(x); }
+ long llrintl(real x); // since 8.0
///
pure double round(double x);
///
pure float roundf(float x);
+ ///
+ pure real roundl(real x); // since 6.0
///
c_long lround(double x);
///
c_long lroundf(float x);
+ ///
+ c_long lroundl(real x); // since 6.0
///
long llround(double x);
///
long llroundf(float x);
+ ///
+ long llroundl(real x); // since 6.0
///
pure double trunc(double x);
///
pure float truncf(float x);
+ ///
+ pure real truncl(real x); // since 6.0
///
double fmod(double x, double y);
///
float fmodf(float x, float y);
+ ///
+ real fmodl(real x, real y); // since 8.0
///
double remainder(double x, double y);
///
float remainderf(float x, float y);
+ ///
+ real remainderl(real x, real y); // since 8.0
///
double remquo(double x, double y, int* quo);
///
float remquof(float x, float y, int* quo);
+ ///
+ real remquol(real x, real y, int* quo); // since 8.0
///
pure double copysign(double x, double y);
///
pure float copysignf(float x, float y);
+ ///
+ pure real copysignl(real x, real y); // since 5.3
+
+ ///
+ pure double nan(const char*); // since 8.0
+ ///
+ pure float nanf(const char*); // since 8.0
+ ///
+ pure real nanl(const char*); // since 8.0
///
double nextafter(double x, double y);
///
float nextafterf(float x, float y);
+ ///
+ real nextafterl(real x, real y); // since 6.0
///
double nexttoward(double x, real y);
///
float nexttowardf(float x, real y);
+ ///
+ real nexttowardl(real x, real y); // since 6.0
///
double fdim(double x, double y);
///
float fdimf(float x, float y);
+ ///
+ real fdiml(real x, real y); // since 5.3
///
pure double fmax(double x, double y);
///
pure float fmaxf(float x, float y);
+ ///
+ pure real fmaxl(real x, real y); // since 5.3
///
pure double fmin(double x, double y);
///
pure float fminf(float x, float y);
+ ///
+ pure real fminl(real x, real y); // since 5.3
///
pure double fma(double x, double y, double z);
///
pure float fmaf(float x, float y, float z);
+ ///
+ pure real fmal(real x, real y, real z); // since 6.0
}
else version (NetBSD)
{
*
* $(C_HEADER_DESCRIPTION pubs.opengroup.org/onlinepubs/009695399/basedefs/_stdarg.h.html, _stdarg.h)
*
- * Copyright: Copyright Digital Mars 2000 - 2009.
+ * Copyright: Copyright Digital Mars 2000 - 2020.
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
* Authors: Walter Bright, Hauke Duden
* Standards: ISO/IEC 9899:1999 (E)
* Source: $(DRUNTIMESRC core/stdc/_stdarg.d)
*/
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
module core.stdc.stdarg;
@system:
-//@nogc: // Not yet, need to make TypeInfo's member functions @nogc first
+@nogc:
nothrow:
+version (X86_64)
+{
+ version (Windows) { /* different ABI */ }
+ else version = SysV_x64;
+}
+
version (GNU)
{
import gcc.builtins;
- alias __builtin_va_list __gnuc_va_list;
-
-
- /*********************
- * The argument pointer type.
- */
- alias __gnuc_va_list va_list;
-
-
- /**********
- * Initialize ap.
- * parmn should be the last named parameter.
- */
- void va_start(T)(out va_list ap, ref T parmn);
-
+}
+else version (SysV_x64)
+{
+ static import core.internal.vararg.sysv_x64;
- /************
- * Retrieve and return the next value that is type T.
- */
- T va_arg(T)(ref va_list ap);
+ version (DigitalMars)
+ {
+ align(16) struct __va_argsave_t
+ {
+ size_t[6] regs; // RDI,RSI,RDX,RCX,R8,R9
+ real[8] fpregs; // XMM0..XMM7
+ __va_list va;
+ }
+ }
+}
+version (ARM) version = ARM_Any;
+version (AArch64) version = ARM_Any;
+version (MIPS32) version = MIPS_Any;
+version (MIPS64) version = MIPS_Any;
+version (PPC) version = PPC_Any;
+version (PPC64) version = PPC_Any;
- /*************
- * Retrieve and store through parmn the next value that is of type T.
- */
- void va_arg(T)(ref va_list ap, ref T parmn);
+version (GNU)
+{
+ // Uses gcc.builtins
+}
+else version (ARM_Any)
+{
+ // Darwin uses a simpler varargs implementation
+ version (OSX) {}
+ else version (iOS) {}
+ else version (TVOS) {}
+ else version (WatchOS) {}
+ else:
+
+ version (ARM)
+ {
+ version = AAPCS32;
+ }
+ else version (AArch64)
+ {
+ version = AAPCS64;
+ static import core.internal.vararg.aarch64;
+ }
+}
- /***********************
- * End use of ap.
- */
- alias __builtin_va_end va_end;
+T alignUp(size_t alignment = size_t.sizeof, T)(T base) pure
+{
+ enum mask = alignment - 1;
+ static assert(alignment > 0 && (alignment & mask) == 0, "alignment must be a power of 2");
+ auto b = cast(size_t) base;
+ b = (b + mask) & ~mask;
+ return cast(T) b;
+}
+unittest
+{
+ assert(1.alignUp == size_t.sizeof);
+ assert(31.alignUp!16 == 32);
+ assert(32.alignUp!16 == 32);
+ assert(33.alignUp!16 == 48);
+ assert((-9).alignUp!8 == -8);
+}
- /***********************
- * Make a copy of ap.
- */
- alias __builtin_va_copy va_copy;
-}
-else version (X86)
+version (BigEndian)
{
- /*********************
- * The argument pointer type.
- */
- alias char* va_list;
-
- /**********
- * Initialize ap.
- * For 32 bit code, parmn should be the last named parameter.
- * For 64 bit code, parmn should be __va_argsave.
- */
- void va_start(T)(out va_list ap, ref T parmn)
+ // Adjusts a size_t-aligned pointer for types smaller than size_t.
+ T* adjustForBigEndian(T)(T* p, size_t size) pure
{
- ap = cast(va_list)( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) );
+ return size >= size_t.sizeof ? p :
+ cast(T*) ((cast(void*) p) + (size_t.sizeof - size));
}
+}
- /************
- * Retrieve and return the next value that is type T.
- * Should use the other va_arg instead, as this won't work for 64 bit code.
- */
- T va_arg(T)(ref va_list ap)
- {
- T arg = *cast(T*) ap;
- ap = cast(va_list)( cast(void*) ap + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) );
- return arg;
- }
- /************
- * Retrieve and return the next value that is type T.
- * This is the preferred version.
- */
- void va_arg(T)(ref va_list ap, ref T parmn)
- {
- parmn = *cast(T*)ap;
- ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1)));
- }
+/**
+ * The argument pointer type.
+ */
+version (GNU)
+{
+ alias va_list = __gnuc_va_list;
+ alias __gnuc_va_list = __builtin_va_list;
+}
+else version (SysV_x64)
+{
+ alias va_list = core.internal.vararg.sysv_x64.va_list;
+ public import core.internal.vararg.sysv_x64 : __va_list, __va_list_tag;
+}
+else version (AAPCS32)
+{
+ alias va_list = __va_list;
- /*************
- * Retrieve and store through parmn the next value that is of TypeInfo ti.
- * Used when the static type is not known.
- */
- void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
+ // need std::__va_list for C++ mangling compatibility (AAPCS32 section 8.1.4)
+ extern (C++, std) struct __va_list
{
- // Wait until everyone updates to get TypeInfo.talign
- //auto talign = ti.talign;
- //auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1);
- auto p = ap;
- auto tsize = ti.tsize;
- ap = cast(va_list)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1)));
- parmn[0..tsize] = p[0..tsize];
+ void* __ap;
}
+}
+else version (AAPCS64)
+{
+ alias va_list = core.internal.vararg.aarch64.va_list;
+}
+else
+{
+ alias va_list = char*; // incl. unknown platforms
+}
- /***********************
- * End use of ap.
- */
- void va_end(va_list ap)
+
+/**
+ * Initialize ap.
+ * parmn should be the last named parameter.
+ */
+version (GNU)
+{
+ void va_start(T)(out va_list ap, ref T parmn);
+}
+else version (LDC)
+{
+ pragma(LDC_va_start)
+ void va_start(T)(out va_list ap, ref T parmn) @nogc;
+}
+else version (DigitalMars)
+{
+ version (X86)
{
+ void va_start(T)(out va_list ap, ref T parmn)
+ {
+ ap = cast(va_list) ((cast(void*) &parmn) + T.sizeof.alignUp);
+ }
}
-
- ///
- void va_copy(out va_list dest, va_list src)
+ else
{
- dest = src;
+ void va_start(T)(out va_list ap, ref T parmn); // intrinsic; parmn should be __va_argsave for non-Windows x86_64 targets
}
}
-else version (Windows) // Win64
-{ /* Win64 is characterized by all arguments fitting into a register size.
- * Smaller ones are padded out to register size, and larger ones are passed by
- * reference.
- */
- /*********************
- * The argument pointer type.
- */
- alias char* va_list;
- /**********
- * Initialize ap.
- * parmn should be the last named parameter.
- */
- void va_start(T)(out va_list ap, ref T parmn); // Compiler intrinsic
-
- /************
- * Retrieve and return the next value that is type T.
- */
- T va_arg(T)(ref va_list ap)
+/**
+ * Retrieve and return the next value that is of type T.
+ */
+version (GNU)
+ T va_arg(T)(ref va_list ap); // intrinsic
+else
+T va_arg(T)(ref va_list ap)
+{
+ version (X86)
{
- static if (T.sizeof > size_t.sizeof)
- T arg = **cast(T**)ap;
- else
- T arg = *cast(T*)ap;
- ap = cast(va_list)(cast(void*)ap + ((size_t.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1)));
- return arg;
+ auto p = cast(T*) ap;
+ ap += T.sizeof.alignUp;
+ return *p;
}
-
- /************
- * Retrieve and return the next value that is type T.
- * This is the preferred version.
- */
- void va_arg(T)(ref va_list ap, ref T parmn)
+ else version (Win64)
{
- static if (T.sizeof > size_t.sizeof)
- parmn = **cast(T**)ap;
+ // LDC passes slices as 2 separate 64-bit values, not as 128-bit struct
+ version (LDC) enum isLDC = true;
+ else enum isLDC = false;
+ static if (isLDC && is(T == E[], E))
+ {
+ auto p = cast(T*) ap;
+ ap += T.sizeof;
+ return *p;
+ }
else
- parmn = *cast(T*)ap;
- ap = cast(va_list)(cast(void*)ap + ((size_t.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1)));
- }
-
- /*************
- * Retrieve and store through parmn the next value that is of TypeInfo ti.
- * Used when the static type is not known.
- */
- void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
- {
- // Wait until everyone updates to get TypeInfo.talign
- //auto talign = ti.talign;
- //auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1);
- auto p = ap;
- auto tsize = ti.tsize;
- ap = cast(va_list)(cast(size_t)p + ((size_t.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1)));
- void* q = (tsize > size_t.sizeof) ? *cast(void**)p : p;
- parmn[0..tsize] = q[0..tsize];
+ {
+ // passed indirectly by value if > 64 bits or of a size that is not a power of 2
+ static if (T.sizeof > size_t.sizeof || (T.sizeof & (T.sizeof - 1)) != 0)
+ auto p = *cast(T**) ap;
+ else
+ auto p = cast(T*) ap;
+ ap += size_t.sizeof;
+ return *p;
+ }
}
-
- /***********************
- * End use of ap.
- */
- void va_end(va_list ap)
+ else version (SysV_x64)
{
+ return core.internal.vararg.sysv_x64.va_arg!T(ap);
}
-
- ///
- void va_copy(out va_list dest, va_list src)
+ else version (AAPCS32)
{
- dest = src;
+ // AAPCS32 section 6.5 B.5: type with alignment >= 8 is 8-byte aligned
+ // instead of normal 4-byte alignment (APCS doesn't do this).
+ if (T.alignof >= 8)
+ ap.__ap = ap.__ap.alignUp!8;
+ auto p = cast(T*) ap.__ap;
+ version (BigEndian)
+ static if (T.sizeof < size_t.sizeof)
+ p = adjustForBigEndian(p, T.sizeof);
+ ap.__ap += T.sizeof.alignUp;
+ return *p;
}
-}
-else version (X86_64)
-{
- // Determine if type is a vector type
- template isVectorType(T)
+ else version (AAPCS64)
{
- enum isVectorType = false;
+ return core.internal.vararg.aarch64.va_arg!T(ap);
}
-
- template isVectorType(T : __vector(T[N]), size_t N)
+ else version (ARM_Any)
{
- enum isVectorType = true;
+ auto p = cast(T*) ap;
+ version (BigEndian)
+ static if (T.sizeof < size_t.sizeof)
+ p = adjustForBigEndian(p, T.sizeof);
+ ap += T.sizeof.alignUp;
+ return *p;
}
-
- // Layout of this struct must match __gnuc_va_list for C ABI compatibility
- struct __va_list_tag
+ else version (PPC_Any)
{
- uint offset_regs = 6 * 8; // no regs
- uint offset_fpregs = 6 * 8 + 8 * 16; // no fp regs
- void* stack_args;
- void* reg_args;
+ /*
+ * The rules are described in the 64bit PowerPC ELF ABI Supplement 1.9,
+ * available here:
+ * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#PARAM-PASS
+ */
+
+ // Chapter 3.1.4 and 3.2.3: alignment may require the va_list pointer to first
+ // be aligned before accessing a value
+ if (T.alignof >= 8)
+ ap = ap.alignUp!8;
+ auto p = cast(T*) ap;
+ version (BigEndian)
+ static if (T.sizeof < size_t.sizeof)
+ p = adjustForBigEndian(p, T.sizeof);
+ ap += T.sizeof.alignUp;
+ return *p;
}
- alias __va_list = __va_list_tag;
-
- align(16) struct __va_argsave_t
+ else version (MIPS_Any)
{
- size_t[6] regs; // RDI,RSI,RDX,RCX,R8,R9
- real[8] fpregs; // XMM0..XMM7
- __va_list va;
+ auto p = cast(T*) ap;
+ version (BigEndian)
+ static if (T.sizeof < size_t.sizeof)
+ p = adjustForBigEndian(p, T.sizeof);
+ ap += T.sizeof.alignUp;
+ return *p;
}
+ else
+ static assert(0, "Unsupported platform");
+}
- /*
- * Making it an array of 1 causes va_list to be passed as a pointer in
- * function argument lists
- */
- alias va_list = __va_list*;
-
- ///
- void va_start(T)(out va_list ap, ref T parmn); // Compiler intrinsic
- ///
- T va_arg(T)(va_list ap)
- { T a;
- va_arg(ap, a);
- return a;
- }
+/**
+ * Retrieve and store in parmn the next value that is of type T.
+ */
+version (GNU)
+ void va_arg(T)(ref va_list ap, ref T parmn); // intrinsic
+else
+void va_arg(T)(ref va_list ap, ref T parmn)
+{
+ parmn = va_arg!T(ap);
+}
- ///
- void va_arg(T)(va_list apx, ref T parmn)
- {
- __va_list* ap = cast(__va_list*)apx;
- static if (is(T U == __argTypes))
- {
- static if (U.length == 0 || T.sizeof > 16 || (U[0].sizeof > 8 && !isVectorType!(U[0])))
- { // Always passed in memory
- // The arg may have more strict alignment than the stack
- auto p = (cast(size_t)ap.stack_args + T.alignof - 1) & ~(T.alignof - 1);
- ap.stack_args = cast(void*)(p + ((T.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1)));
- parmn = *cast(T*)p;
- }
- else static if (U.length == 1)
- { // Arg is passed in one register
- alias U[0] T1;
- static if (is(T1 == double) || is(T1 == float) || isVectorType!(T1))
- { // Passed in XMM register
- if (ap.offset_fpregs < (6 * 8 + 16 * 8))
- {
- parmn = *cast(T*)(ap.reg_args + ap.offset_fpregs);
- ap.offset_fpregs += 16;
- }
- else
- {
- parmn = *cast(T*)ap.stack_args;
- ap.stack_args += (T1.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
- }
- }
- else
- { // Passed in regular register
- if (ap.offset_regs < 6 * 8 && T.sizeof <= 8)
- {
- parmn = *cast(T*)(ap.reg_args + ap.offset_regs);
- ap.offset_regs += 8;
- }
- else
- {
- auto p = (cast(size_t)ap.stack_args + T.alignof - 1) & ~(T.alignof - 1);
- ap.stack_args = cast(void*)(p + ((T.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1)));
- parmn = *cast(T*)p;
- }
- }
- }
- else static if (U.length == 2)
- { // Arg is passed in two registers
- alias U[0] T1;
- alias U[1] T2;
- auto p = cast(void*)&parmn + 8;
- // Both must be in registers, or both on stack, hence 4 cases
+/**
+ * End use of ap.
+ */
+version (GNU)
+{
+ alias va_end = __builtin_va_end;
+}
+else version (LDC)
+{
+ pragma(LDC_va_end)
+ void va_end(va_list ap);
+}
+else version (DigitalMars)
+{
+ void va_end(va_list ap) {}
+}
- static if ((is(T1 == double) || is(T1 == float)) &&
- (is(T2 == double) || is(T2 == float)))
- {
- if (ap.offset_fpregs < (6 * 8 + 16 * 8) - 16)
- {
- *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_fpregs);
- *cast(T2*)p = *cast(T2*)(ap.reg_args + ap.offset_fpregs + 16);
- ap.offset_fpregs += 32;
- }
- else
- {
- *cast(T1*)&parmn = *cast(T1*)ap.stack_args;
- ap.stack_args += (T1.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
- *cast(T2*)p = *cast(T2*)ap.stack_args;
- ap.stack_args += (T2.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
- }
- }
- else static if (is(T1 == double) || is(T1 == float))
- {
- void* a = void;
- if (ap.offset_fpregs < (6 * 8 + 16 * 8) &&
- ap.offset_regs < 6 * 8 && T2.sizeof <= 8)
- {
- *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_fpregs);
- ap.offset_fpregs += 16;
- a = ap.reg_args + ap.offset_regs;
- ap.offset_regs += 8;
- }
- else
- {
- *cast(T1*)&parmn = *cast(T1*)ap.stack_args;
- ap.stack_args += (T1.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
- a = ap.stack_args;
- ap.stack_args += 8;
- }
- // Be careful not to go past the size of the actual argument
- const sz2 = T.sizeof - 8;
- p[0..sz2] = a[0..sz2];
- }
- else static if (is(T2 == double) || is(T2 == float))
- {
- if (ap.offset_regs < 6 * 8 && T1.sizeof <= 8 &&
- ap.offset_fpregs < (6 * 8 + 16 * 8))
- {
- *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_regs);
- ap.offset_regs += 8;
- *cast(T2*)p = *cast(T2*)(ap.reg_args + ap.offset_fpregs);
- ap.offset_fpregs += 16;
- }
- else
- {
- *cast(T1*)&parmn = *cast(T1*)ap.stack_args;
- ap.stack_args += 8;
- *cast(T2*)p = *cast(T2*)ap.stack_args;
- ap.stack_args += (T2.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
- }
- }
- else // both in regular registers
- {
- void* a = void;
- if (ap.offset_regs < 5 * 8 && T1.sizeof <= 8 && T2.sizeof <= 8)
- {
- *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_regs);
- ap.offset_regs += 8;
- a = ap.reg_args + ap.offset_regs;
- ap.offset_regs += 8;
- }
- else
- {
- *cast(T1*)&parmn = *cast(T1*)ap.stack_args;
- ap.stack_args += 8;
- a = ap.stack_args;
- ap.stack_args += 8;
- }
- // Be careful not to go past the size of the actual argument
- const sz2 = T.sizeof - 8;
- p[0..sz2] = a[0..sz2];
- }
- }
- else
- {
- static assert(false);
- }
- }
- else
- {
- static assert(false, "not a valid argument type for va_arg");
- }
- }
- ///
- void va_arg()(va_list apx, TypeInfo ti, void* parmn)
+/**
+ * Make a copy of ap.
+ */
+version (GNU)
+{
+ alias va_copy = __builtin_va_copy;
+}
+else version (LDC)
+{
+ pragma(LDC_va_copy)
+ void va_copy(out va_list dest, va_list src);
+}
+else version (DigitalMars)
+{
+ version (SysV_x64)
{
- __va_list* ap = cast(__va_list*)apx;
- TypeInfo arg1, arg2;
- if (!ti.argTypes(arg1, arg2))
+ void va_copy(out va_list dest, va_list src, void* storage = alloca(__va_list_tag.sizeof))
{
- bool inXMMregister(TypeInfo arg) pure nothrow @safe
- {
- return (arg.flags & 2) != 0;
- }
-
- TypeInfo_Vector v1 = arg1 ? cast(TypeInfo_Vector)arg1 : null;
- if (arg1 && (arg1.tsize <= 8 || v1))
- { // Arg is passed in one register
- auto tsize = arg1.tsize;
- void* p;
- bool stack = false;
- auto offset_fpregs_save = ap.offset_fpregs;
- auto offset_regs_save = ap.offset_regs;
- L1:
- if (inXMMregister(arg1) || v1)
- { // Passed in XMM register
- if (ap.offset_fpregs < (6 * 8 + 16 * 8) && !stack)
- {
- p = ap.reg_args + ap.offset_fpregs;
- ap.offset_fpregs += 16;
- }
- else
- {
- p = ap.stack_args;
- ap.stack_args += (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
- stack = true;
- }
- }
- else
- { // Passed in regular register
- if (ap.offset_regs < 6 * 8 && !stack)
- {
- p = ap.reg_args + ap.offset_regs;
- ap.offset_regs += 8;
- }
- else
- {
- p = ap.stack_args;
- ap.stack_args += 8;
- stack = true;
- }
- }
- parmn[0..tsize] = p[0..tsize];
-
- if (arg2)
- {
- if (inXMMregister(arg2))
- { // Passed in XMM register
- if (ap.offset_fpregs < (6 * 8 + 16 * 8) && !stack)
- {
- p = ap.reg_args + ap.offset_fpregs;
- ap.offset_fpregs += 16;
- }
- else
- {
- if (!stack)
- { // arg1 is really on the stack, so rewind and redo
- ap.offset_fpregs = offset_fpregs_save;
- ap.offset_regs = offset_regs_save;
- stack = true;
- goto L1;
- }
- p = ap.stack_args;
- ap.stack_args += (arg2.tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
- }
- }
- else
- { // Passed in regular register
- if (ap.offset_regs < 6 * 8 && !stack)
- {
- p = ap.reg_args + ap.offset_regs;
- ap.offset_regs += 8;
- }
- else
- {
- if (!stack)
- { // arg1 is really on the stack, so rewind and redo
- ap.offset_fpregs = offset_fpregs_save;
- ap.offset_regs = offset_regs_save;
- stack = true;
- goto L1;
- }
- p = ap.stack_args;
- ap.stack_args += 8;
- }
- }
- auto sz = ti.tsize - 8;
- (parmn + 8)[0..sz] = p[0..sz];
- }
- }
- else
- { // Always passed in memory
- // The arg may have more strict alignment than the stack
- auto talign = ti.talign;
- auto tsize = ti.tsize;
- auto p = cast(void*)((cast(size_t)ap.stack_args + talign - 1) & ~(talign - 1));
- ap.stack_args = cast(void*)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1)));
- parmn[0..tsize] = p[0..tsize];
- }
+ // Instead of copying the pointers, and aliasing the source va_list,
+ // the default argument alloca will allocate storage in the caller's
+ // stack frame. This is still not correct (it should be allocated in
+ // the place where the va_list variable is declared) but most of the
+ // time the caller's stack frame _is_ the place where the va_list is
+ // allocated, so in most cases this will now work.
+ dest = cast(va_list) storage;
+ *dest = *src;
}
- else
- {
- assert(false, "not a valid argument type for va_arg");
- }
- }
- ///
- void va_end(va_list ap)
- {
+ import core.stdc.stdlib : alloca;
}
-
- import core.stdc.stdlib : alloca;
-
- ///
- void va_copy(out va_list dest, va_list src, void* storage = alloca(__va_list_tag.sizeof))
+ else
{
- // Instead of copying the pointers, and aliasing the source va_list,
- // the default argument alloca will allocate storage in the caller's
- // stack frame. This is still not correct (it should be allocated in
- // the place where the va_list variable is declared) but most of the
- // time the caller's stack frame _is_ the place where the va_list is
- // allocated, so in most cases this will now work.
- dest = cast(va_list)storage;
- *dest = *src;
+ void va_copy(out va_list dest, va_list src)
+ {
+ dest = src;
+ }
}
}
-else
-{
- static assert(false, "Unsupported platform");
-}
module core.stdc.stdint;
-private import core.stdc.config;
-private import core.stdc.stddef; // for wchar_t
-private import core.stdc.signal; // for sig_atomic_t
-private import core.stdc.wchar_; // for wint_t
+import core.stdc.config;
+import core.stdc.stddef; // for wchar_t
+import core.stdc.signal; // for sig_atomic_t
+import core.stdc.wchar_; // for wint_t
version (OSX)
version = Darwin;
ssize_t s_len; // current length of string
int s_flags; // flags
ssize_t s_sect_len; // current length of section
- };
+ }
enum {
SBUF_FIXEDLEN = 0x00000000, // fixed length buffer (default)
int function(void*) _close;
int function(void*, char*, int) _read;
fpos_t function(void*, fpos_t, int) _seek;
- int function(void*, in char*, int) _write;
+ int function(void*, const scope char*, int) _write;
__sbuf _ub;
ubyte* _up;
int function(void*) _close;
ssize_t function(void*, char*, size_t) _read;
fpos_t function(void*, fpos_t, int) _seek;
- ssize_t function(void*, in char*, size_t) _write;
+ ssize_t function(void*, const scope char*, size_t) _write;
__sbuf _ub;
ubyte* _up;
// Prefer the MinGW versions over the MSVC ones, as the latter don't handle
// reals at all.
///
- int __mingw_fprintf(FILE* stream, scope const char* format, ...);
+ int __mingw_fprintf(FILE* stream, scope const char* format, scope const ...);
///
alias __mingw_fprintf fprintf;
///
- int __mingw_fscanf(FILE* stream, scope const char* format, ...);
+ int __mingw_fscanf(FILE* stream, scope const char* format, scope ...);
///
alias __mingw_fscanf fscanf;
///
- int __mingw_sprintf(scope char* s, scope const char* format, ...);
+ int __mingw_sprintf(scope char* s, scope const char* format, scope const ...);
///
alias __mingw_sprintf sprintf;
///
- int __mingw_sscanf(scope const char* s, scope const char* format, ...);
+ int __mingw_sscanf(scope const char* s, scope const char* format, scope ...);
///
alias __mingw_sscanf sscanf;
alias __mingw_vscanf vscanf;
///
- int __mingw_printf(scope const char* format, ...);
+ int __mingw_printf(scope const char* format, scope const ...);
///
alias __mingw_printf printf;
///
- int __mingw_scanf(scope const char* format, ...);
+ int __mingw_scanf(scope const char* format, scope ...);
///
alias __mingw_scanf scanf;
}
else
{
///
- int fprintf(FILE* stream, scope const char* format, ...);
+ int fprintf(FILE* stream, scope const char* format, scope const ...);
///
- int fscanf(FILE* stream, scope const char* format, ...);
+ int fscanf(FILE* stream, scope const char* format, scope ...);
///
- int sprintf(scope char* s, scope const char* format, ...);
+ int sprintf(scope char* s, scope const char* format, scope const ...);
///
- int sscanf(scope const char* s, scope const char* format, ...);
+ int sscanf(scope const char* s, scope const char* format, scope ...);
///
int vfprintf(FILE* stream, scope const char* format, va_list arg);
///
///
int vscanf(scope const char* format, va_list arg);
///
- int printf(scope const char* format, ...);
+ int printf(scope const char* format, scope const ...);
///
- int scanf(scope const char* format, ...);
+ int scanf(scope const char* format, scope ...);
}
// No unsafe pointer manipulation.
pure int fileno()(FILE* stream) { return stream._file; }
}
///
- int _snprintf(scope char* s, size_t n, scope const char* fmt, ...);
+ int _snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...);
///
alias _snprintf snprintf;
version (MinGW)
{
- int __mingw_snprintf(scope char* s, size_t n, scope const char* fmt, ...);
+ int __mingw_snprintf(scope char* s, size_t n, scope const char* fmt, scope const ...);
///
alias __mingw_snprintf _snprintf;
///
else
{
///
- int _snprintf(scope char* s, size_t n, scope const char* format, ...);
+ int _snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
int _vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
///
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
}
///
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
}
///
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
}
///
- int snprintf(char* s, size_t n, in char* format, ...);
+ int snprintf(char* s, size_t n, const scope char* format, scope const ...);
///
- int vsnprintf(char* s, size_t n, in char* format, va_list arg);
+ int vsnprintf(char* s, size_t n, const scope char* format, va_list arg);
}
else version (OpenBSD)
{
}
///
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
enum __SALC = 0x4000;
enum __SIGN = 0x8000;
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
- int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
+ int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
else version (Solaris)
{
}
///
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
int fileno(FILE*);
}
- ///
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
+ ///
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
}
///
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
}
///
- int snprintf(scope char* s, size_t n, scope const char* format, ...);
+ int snprintf(scope char* s, size_t n, scope const char* format, scope const ...);
///
int vsnprintf(scope char* s, size_t n, scope const char* format, va_list arg);
}
module core.stdc.stdlib;
-private import core.stdc.config;
+import core.stdc.config;
public import core.stdc.stddef; // for wchar_t
version (OSX)
@nogc:
///
-pure void* memchr(return const void* s, int c, size_t n);
+inout(void)* memchr(return inout void* s, int c, size_t n) pure;
///
-pure int memcmp(scope const void* s1, scope const void* s2, size_t n);
+int memcmp(scope const void* s1, scope const void* s2, size_t n) pure;
///
-pure void* memcpy(return void* s1, scope const void* s2, size_t n);
+void* memcpy(return void* s1, scope const void* s2, size_t n) pure;
version (Windows)
{
///
int memicmp(scope const char* s1, scope const char* s2, size_t n);
}
///
-pure void* memmove(return void* s1, scope const void* s2, size_t n);
+void* memmove(return void* s1, scope const void* s2, size_t n) pure;
///
-pure void* memset(return void* s, int c, size_t n);
+void* memset(return void* s, int c, size_t n) pure;
///
-pure char* strcpy(return char* s1, scope const char* s2);
+char* strcat(return char* s1, scope const char* s2) pure;
///
-pure char* strncpy(return char* s1, scope const char* s2, size_t n);
+inout(char)* strchr(return inout(char)* s, int c) pure;
///
-pure char* strcat(return char* s1, scope const char* s2);
-///
-pure char* strncat(return char* s1, scope const char* s2, size_t n);
-///
-pure int strcmp(scope const char* s1, scope const char* s2);
+int strcmp(scope const char* s1, scope const char* s2) pure;
///
int strcoll(scope const char* s1, scope const char* s2);
///
-pure int strncmp(scope const char* s1, scope const char* s2, size_t n);
-///
-size_t strxfrm(scope char* s1, scope const char* s2, size_t n);
-///
-pure inout(char)* strchr(return inout(char)* s, int c);
-///
-pure size_t strcspn(scope const char* s1, scope const char* s2);
+char* strcpy(return char* s1, scope const char* s2) pure;
///
-pure inout(char)* strpbrk(return inout(char)* s1, scope const char* s2);
+size_t strcspn(scope const char* s1, scope const char* s2) pure;
///
-pure inout(char)* strrchr(return inout(char)* s, int c);
-///
-pure size_t strspn(scope const char* s1, scope const char* s2);
-///
-pure inout(char)* strstr(return inout(char)* s1, scope const char* s2);
-///
-char* strtok(return char* s1, scope const char* s2);
+char* strdup(scope const char *s);
///
char* strerror(int errnum);
// This `strerror_r` definition is not following the POSIX standard
int strerror_r(int errnum, scope char* buf, size_t buflen);
}
///
-pure size_t strlen(scope const char* s);
+size_t strlen(scope const char* s) pure;
///
-char* strdup(scope const char *s);
+char* strncat(return char* s1, scope const char* s2, size_t n) pure;
+///
+int strncmp(scope const char* s1, scope const char* s2, size_t n) pure;
+///
+char* strncpy(return char* s1, scope const char* s2, size_t n) pure;
+///
+inout(char)* strpbrk(return inout(char)* s1, scope const char* s2) pure;
+///
+inout(char)* strrchr(return inout(char)* s, int c) pure;
+///
+size_t strspn(scope const char* s1, scope const char* s2) pure;
+///
+inout(char)* strstr(return inout(char)* s1, scope const char* s2) pure;
+///
+char* strtok(return char* s1, scope const char* s2);
+///
+size_t strxfrm(scope char* s1, scope const char* s2, size_t n);
module core.stdc.tgmath;
-private import core.stdc.config;
+import core.stdc.config;
private static import core.stdc.math;
private static import core.stdc.complex;
nothrow:
@nogc:
-version (FreeBSD)
-{
- ///
- alias core.stdc.math.acos acos;
- ///
- alias core.stdc.math.acosf acos;
- ///
- alias core.stdc.math.acosl acos;
-
- ///
- alias core.stdc.complex.cacos acos;
- ///
- alias core.stdc.complex.cacosf acos;
- ///
- alias core.stdc.complex.cacosl acos;
-
- ///
- alias core.stdc.math.asin asin;
- ///
- alias core.stdc.math.asinf asin;
- ///
- alias core.stdc.math.asinl asin;
-
- ///
- alias core.stdc.complex.casin asin;
- ///
- alias core.stdc.complex.casinf asin;
- ///
- alias core.stdc.complex.casinl asin;
-
- ///
- alias core.stdc.math.atan atan;
- ///
- alias core.stdc.math.atanf atan;
- ///
- alias core.stdc.math.atanl atan;
-
- ///
- alias core.stdc.complex.catan atan;
- ///
- alias core.stdc.complex.catanf atan;
- ///
- alias core.stdc.complex.catanl atan;
-
- ///
- alias core.stdc.math.atan2 atan2;
- ///
- alias core.stdc.math.atan2f atan2;
- ///
- alias core.stdc.math.atan2l atan2;
-
- ///
- alias core.stdc.math.cos cos;
- ///
- alias core.stdc.math.cosf cos;
- ///
- alias core.stdc.math.cosl cos;
-
- ///
- alias core.stdc.complex.ccos cos;
- ///
- alias core.stdc.complex.ccosf cos;
- ///
- alias core.stdc.complex.ccosl cos;
-
- ///
- alias core.stdc.math.sin sin;
- ///
- alias core.stdc.math.sinf sin;
- ///
- alias core.stdc.math.sinl sin;
-
- ///
- alias core.stdc.complex.csin csin;
- ///
- alias core.stdc.complex.csinf csin;
- ///
- alias core.stdc.complex.csinl csin;
-
- ///
- alias core.stdc.math.tan tan;
- ///
- alias core.stdc.math.tanf tan;
- ///
- alias core.stdc.math.tanl tan;
-
- ///
- alias core.stdc.complex.ctan tan;
- ///
- alias core.stdc.complex.ctanf tan;
- ///
- alias core.stdc.complex.ctanl tan;
-
- ///
- alias core.stdc.math.acosh acosh;
- ///
- alias core.stdc.math.acoshf acosh;
- ///
- alias core.stdc.math.acoshl acosh;
-
- ///
- alias core.stdc.complex.cacosh acosh;
- ///
- alias core.stdc.complex.cacoshf acosh;
- ///
- alias core.stdc.complex.cacoshl acosh;
-
- ///
- alias core.stdc.math.asinh asinh;
- ///
- alias core.stdc.math.asinhf asinh;
- ///
- alias core.stdc.math.asinhl asinh;
-
- ///
- alias core.stdc.complex.casinh asinh;
- ///
- alias core.stdc.complex.casinhf asinh;
- ///
- alias core.stdc.complex.casinhl asinh;
-
- ///
- alias core.stdc.math.atanh atanh;
- ///
- alias core.stdc.math.atanhf atanh;
- ///
- alias core.stdc.math.atanhl atanh;
-
- ///
- alias core.stdc.complex.catanh atanh;
- ///
- alias core.stdc.complex.catanhf atanh;
- ///
- alias core.stdc.complex.catanhl atanh;
-
- ///
- alias core.stdc.math.cosh cosh;
- ///
- alias core.stdc.math.coshf cosh;
- ///
- alias core.stdc.math.coshl cosh;
-
- ///
- alias core.stdc.complex.ccosh cosh;
- ///
- alias core.stdc.complex.ccoshf cosh;
- ///
- alias core.stdc.complex.ccoshl cosh;
-
- ///
- alias core.stdc.math.sinh sinh;
- ///
- alias core.stdc.math.sinhf sinh;
- ///
- alias core.stdc.math.sinhl sinh;
-
- ///
- alias core.stdc.complex.csinh sinh;
- ///
- alias core.stdc.complex.csinhf sinh;
- ///
- alias core.stdc.complex.csinhl sinh;
-
- ///
- alias core.stdc.math.tanh tanh;
- ///
- alias core.stdc.math.tanhf tanh;
- ///
- alias core.stdc.math.tanhl tanh;
-
- ///
- alias core.stdc.complex.ctanh tanh;
- ///
- alias core.stdc.complex.ctanhf tanh;
- ///
- alias core.stdc.complex.ctanhl tanh;
-
- ///
- alias core.stdc.math.exp exp;
- ///
- alias core.stdc.math.expf exp;
- ///
- alias core.stdc.math.expl exp;
-
- ///
- alias core.stdc.complex.cexp exp;
- ///
- alias core.stdc.complex.cexpf exp;
- ///
- alias core.stdc.complex.cexpl exp;
-
- ///
- alias core.stdc.math.exp2 exp2;
- ///
- alias core.stdc.math.exp2f exp2;
- ///
- alias core.stdc.math.exp2l exp2;
-
- ///
- alias core.stdc.math.expm1 expm1;
- ///
- alias core.stdc.math.expm1f expm1;
- ///
- alias core.stdc.math.expm1l expm1;
-
- ///
- alias core.stdc.math.frexp frexp;
- ///
- alias core.stdc.math.frexpf frexp;
- ///
- alias core.stdc.math.frexpl frexp;
-
- ///
- alias core.stdc.math.ilogb ilogb;
- ///
- alias core.stdc.math.ilogbf ilogb;
- ///
- alias core.stdc.math.ilogbl ilogb;
-
- ///
- alias core.stdc.math.ldexp ldexp;
- ///
- alias core.stdc.math.ldexpf ldexp;
- ///
- alias core.stdc.math.ldexpl ldexp;
-
- ///
- alias core.stdc.math.log log;
- ///
- alias core.stdc.math.logf log;
- ///
- alias core.stdc.math.logl log;
-
- ///
- alias core.stdc.complex.clog log;
- ///
- alias core.stdc.complex.clogf log;
- ///
- alias core.stdc.complex.clogl log;
-
- ///
- alias core.stdc.math.log10 log10;
- ///
- alias core.stdc.math.log10f log10;
- ///
- alias core.stdc.math.log10l log10;
-
- ///
- alias core.stdc.math.log1p log1p;
- ///
- alias core.stdc.math.log1pf log1p;
- ///
- alias core.stdc.math.log1pl log1p;
-
- ///
- alias core.stdc.math.log2 log2;
- ///
- alias core.stdc.math.log2f log2;
- ///
- alias core.stdc.math.log2l log2;
-
- ///
- alias core.stdc.math.logb logb;
- ///
- alias core.stdc.math.logbf logb;
- ///
- alias core.stdc.math.logbl logb;
-
- ///
- alias core.stdc.math.modf modf;
- ///
- alias core.stdc.math.modff modf;
-// alias core.stdc.math.modfl modf;
-
- ///
- alias core.stdc.math.scalbn scalbn;
- ///
- alias core.stdc.math.scalbnf scalbn;
- ///
- alias core.stdc.math.scalbnl scalbn;
-
- ///
- alias core.stdc.math.scalbln scalbln;
- ///
- alias core.stdc.math.scalblnf scalbln;
- ///
- alias core.stdc.math.scalblnl scalbln;
-
- ///
- alias core.stdc.math.cbrt cbrt;
- ///
- alias core.stdc.math.cbrtf cbrt;
- ///
- alias core.stdc.math.cbrtl cbrt;
-
- ///
- alias core.stdc.math.fabs fabs;
- ///
- alias core.stdc.math.fabsf fabs;
- ///
- alias core.stdc.math.fabsl fabs;
-
- ///
- alias core.stdc.complex.cabs fabs;
- ///
- alias core.stdc.complex.cabsf fabs;
- ///
- alias core.stdc.complex.cabsl fabs;
-
- ///
- alias core.stdc.math.hypot hypot;
- ///
- alias core.stdc.math.hypotf hypot;
- ///
- alias core.stdc.math.hypotl hypot;
-
- ///
- alias core.stdc.math.pow pow;
- ///
- alias core.stdc.math.powf pow;
- ///
- alias core.stdc.math.powl pow;
-
- ///
- alias core.stdc.complex.cpow pow;
- ///
- alias core.stdc.complex.cpowf pow;
- ///
- alias core.stdc.complex.cpowl pow;
-
- ///
- alias core.stdc.math.sqrt sqrt;
- ///
- alias core.stdc.math.sqrtf sqrt;
- ///
- alias core.stdc.math.sqrtl sqrt;
-
- ///
- alias core.stdc.complex.csqrt sqrt;
- ///
- alias core.stdc.complex.csqrtf sqrt;
- ///
- alias core.stdc.complex.csqrtl sqrt;
-
- ///
- alias core.stdc.math.erf erf;
- ///
- alias core.stdc.math.erff erf;
- ///
- alias core.stdc.math.erfl erf;
-
- ///
- alias core.stdc.math.erfc erfc;
- ///
- alias core.stdc.math.erfcf erfc;
- ///
- alias core.stdc.math.erfcl erfc;
-
- ///
- alias core.stdc.math.lgamma lgamma;
- ///
- alias core.stdc.math.lgammaf lgamma;
- ///
- alias core.stdc.math.lgammal lgamma;
-
- ///
- alias core.stdc.math.tgamma tgamma;
- ///
- alias core.stdc.math.tgammaf tgamma;
- ///
- alias core.stdc.math.tgammal tgamma;
-
- ///
- alias core.stdc.math.ceil ceil;
- ///
- alias core.stdc.math.ceilf ceil;
- ///
- alias core.stdc.math.ceill ceil;
-
- ///
- alias core.stdc.math.floor floor;
- ///
- alias core.stdc.math.floorf floor;
- ///
- alias core.stdc.math.floorl floor;
-
- ///
- alias core.stdc.math.nearbyint nearbyint;
- ///
- alias core.stdc.math.nearbyintf nearbyint;
- ///
- alias core.stdc.math.nearbyintl nearbyint;
-
- ///
- alias core.stdc.math.rint rint;
- ///
- alias core.stdc.math.rintf rint;
- ///
- alias core.stdc.math.rintl rint;
-
- ///
- alias core.stdc.math.lrint lrint;
- ///
- alias core.stdc.math.lrintf lrint;
- ///
- alias core.stdc.math.lrintl lrint;
-
- ///
- alias core.stdc.math.llrint llrint;
- ///
- alias core.stdc.math.llrintf llrint;
- ///
- alias core.stdc.math.llrintl llrint;
-
- ///
- alias core.stdc.math.round round;
- ///
- alias core.stdc.math.roundf round;
- ///
- alias core.stdc.math.roundl round;
-
- ///
- alias core.stdc.math.lround lround;
- ///
- alias core.stdc.math.lroundf lround;
- ///
- alias core.stdc.math.lroundl lround;
-
- ///
- alias core.stdc.math.llround llround;
- ///
- alias core.stdc.math.llroundf llround;
- ///
- alias core.stdc.math.llroundl llround;
-
- ///
- alias core.stdc.math.trunc trunc;
- ///
- alias core.stdc.math.truncf trunc;
- ///
- alias core.stdc.math.truncl trunc;
-
- ///
- alias core.stdc.math.fmod fmod;
- ///
- alias core.stdc.math.fmodf fmod;
- ///
- alias core.stdc.math.fmodl fmod;
-
- ///
- alias core.stdc.math.remainder remainder;
- ///
- alias core.stdc.math.remainderf remainder;
- ///
- alias core.stdc.math.remainderl remainder;
-
- ///
- alias core.stdc.math.remquo remquo;
- ///
- alias core.stdc.math.remquof remquo;
- ///
- alias core.stdc.math.remquol remquo;
-
- ///
- alias core.stdc.math.copysign copysign;
- ///
- alias core.stdc.math.copysignf copysign;
- ///
- alias core.stdc.math.copysignl copysign;
-
-// alias core.stdc.math.nan nan;
-// alias core.stdc.math.nanf nan;
-// alias core.stdc.math.nanl nan;
-
- ///
- alias core.stdc.math.nextafter nextafter;
- ///
- alias core.stdc.math.nextafterf nextafter;
- ///
- alias core.stdc.math.nextafterl nextafter;
-
- ///
- alias core.stdc.math.nexttoward nexttoward;
- ///
- alias core.stdc.math.nexttowardf nexttoward;
- ///
- alias core.stdc.math.nexttowardl nexttoward;
-
- ///
- alias core.stdc.math.fdim fdim;
- ///
- alias core.stdc.math.fdimf fdim;
- ///
- alias core.stdc.math.fdiml fdim;
-
- ///
- alias core.stdc.math.fmax fmax;
- ///
- alias core.stdc.math.fmaxf fmax;
- ///
- alias core.stdc.math.fmaxl fmax;
-
- ///
- alias core.stdc.math.fmin fmin;
- ///
- alias core.stdc.math.fmin fmin;
- ///
- alias core.stdc.math.fminl fmin;
-
- ///
- alias core.stdc.math.fma fma;
- ///
- alias core.stdc.math.fmaf fma;
- ///
- alias core.stdc.math.fmal fma;
-
- ///
- alias core.stdc.complex.carg carg;
- ///
- alias core.stdc.complex.cargf carg;
- ///
- alias core.stdc.complex.cargl carg;
-
- ///
- alias core.stdc.complex.cimag cimag;
- ///
- alias core.stdc.complex.cimagf cimag;
- ///
- alias core.stdc.complex.cimagl cimag;
-
- ///
- alias core.stdc.complex.conj conj;
- ///
- alias core.stdc.complex.conjf conj;
- ///
- alias core.stdc.complex.conjl conj;
-
- ///
- alias core.stdc.complex.cproj cproj;
- ///
- alias core.stdc.complex.cprojf cproj;
- ///
- alias core.stdc.complex.cprojl cproj;
-
-// alias core.stdc.complex.creal creal;
-// alias core.stdc.complex.crealf creal;
-// alias core.stdc.complex.creall creal;
-}
version (NetBSD)
{
///
module core.stdc.time;
-private import core.stdc.config;
+version (Posix)
+ public import core.sys.posix.stdc.time;
+else version (Windows)
+ public import core.sys.windows.stdc.time;
+else
+ static assert(0, "unsupported system");
-version (OSX)
- version = Darwin;
-else version (iOS)
- version = Darwin;
-else version (TVOS)
- version = Darwin;
-else version (WatchOS)
- version = Darwin;
+import core.stdc.config;
extern (C):
@trusted: // There are only a few functions here that use unsafe C strings.
nothrow:
@nogc:
-version (Windows)
-{
- ///
- struct tm
- {
- int tm_sec; /// seconds after the minute - [0, 60]
- int tm_min; /// minutes after the hour - [0, 59]
- int tm_hour; /// hours since midnight - [0, 23]
- int tm_mday; /// day of the month - [1, 31]
- int tm_mon; /// months since January - [0, 11]
- int tm_year; /// years since 1900
- int tm_wday; /// days since Sunday - [0, 6]
- int tm_yday; /// days since January 1 - [0, 365]
- int tm_isdst; /// Daylight Saving Time flag
- }
-}
-else version (Posix)
-{
- ///
- struct tm
- {
- int tm_sec; /// seconds after the minute [0-60]
- int tm_min; /// minutes after the hour [0-59]
- int tm_hour; /// hours since midnight [0-23]
- int tm_mday; /// day of the month [1-31]
- int tm_mon; /// months since January [0-11]
- int tm_year; /// years since 1900
- int tm_wday; /// days since Sunday [0-6]
- int tm_yday; /// days since January 1 [0-365]
- int tm_isdst; /// Daylight Savings Time flag
- c_long tm_gmtoff; /// offset from CUT in seconds
- char* tm_zone; /// timezone abbreviation
- }
-}
-
-version (Posix)
-{
- public import core.sys.posix.sys.types : time_t, clock_t;
-}
-else version (Windows)
-{
- ///
- alias c_long time_t;
- ///
- alias c_long clock_t;
-}
-
-///
-version (Windows)
-{
- enum clock_t CLOCKS_PER_SEC = 1000;
- clock_t clock();
-}
-else version (OSX)
-{
- enum clock_t CLOCKS_PER_SEC = 1_000_000; // was 100 until OSX 10.4/10.5
- version (X86)
- extern (C) pragma(mangle, "clock$UNIX2003") clock_t clock();
- else
- clock_t clock();
-}
-else version (Darwin) // other Darwins (iOS, TVOS, WatchOS)
-{
- enum clock_t CLOCKS_PER_SEC = 1_000_000;
- clock_t clock();
-}
-else version (FreeBSD)
-{
- enum clock_t CLOCKS_PER_SEC = 128;
- clock_t clock();
-}
-else version (NetBSD)
-{
- enum clock_t CLOCKS_PER_SEC = 100;
- clock_t clock();
-}
-else version (OpenBSD)
-{
- enum clock_t CLOCKS_PER_SEC = 100;
- clock_t clock();
-}
-else version (DragonFlyBSD)
-{
- enum clock_t CLOCKS_PER_SEC = 128;
- clock_t clock();
-}
-else version (Solaris)
-{
- enum clock_t CLOCKS_PER_SEC = 1_000_000;
- clock_t clock();
-}
-else version (CRuntime_Glibc)
-{
- enum clock_t CLOCKS_PER_SEC = 1_000_000;
- clock_t clock();
-}
-else version (CRuntime_Musl)
-{
- enum clock_t CLOCKS_PER_SEC = 1_000_000;
- clock_t clock();
-}
-else version (CRuntime_Bionic)
-{
- enum clock_t CLOCKS_PER_SEC = 1_000_000;
- clock_t clock();
-}
-else version (CRuntime_UClibc)
-{
- enum clock_t CLOCKS_PER_SEC = 1_000_000;
- clock_t clock();
-}
-else
-{
- static assert(0, "unsupported system");
-}
-
///
pure double difftime(time_t time1, time_t time0); // MT-Safe
///
@system tm* localtime(const scope time_t* timer); // @system: MT-Unsafe race:tmbuf env locale
///
@system size_t strftime(scope char* s, size_t maxsize, const scope char* format, const scope tm* timeptr); // @system: MT-Safe env locale
-
-version (Windows)
-{
- ///
- void tzset(); // non-standard
- ///
- void _tzset(); // non-standard
- ///
- @system char* _strdate(return scope char* s); // non-standard
- ///
- @system char* _strtime(return scope char* s); // non-standard
-
- ///
- extern __gshared const(char)*[2] tzname; // non-standard
-}
-else version (Darwin)
-{
- ///
- void tzset(); // non-standard
- ///
- extern __gshared const(char)*[2] tzname; // non-standard
-}
-else version (CRuntime_Glibc)
-{
- ///
- void tzset(); // non-standard
- ///
- extern __gshared const(char)*[2] tzname; // non-standard
-}
-else version (FreeBSD)
-{
- ///
- void tzset(); // non-standard
- ///
- extern __gshared const(char)*[2] tzname; // non-standard
-}
-else version (NetBSD)
-{
- ///
- void tzset(); // non-standard
- ///
- extern __gshared const(char)*[2] tzname; // non-standard
-}
-else version (OpenBSD)
-{
- ///
- void tzset(); // non-standard
- ///
- extern __gshared const(char)*[2] tzname; // non-standard
-}
-else version (DragonFlyBSD)
-{
- ///
- void tzset(); // non-standard
- ///
- extern __gshared const(char)*[2] tzname; // non-standard
-}
-else version (Solaris)
-{
- ///
- void tzset();
- ///
- extern __gshared const(char)*[2] tzname;
-}
-else version (CRuntime_Bionic)
-{
- ///
- void tzset();
- ///
- extern __gshared const(char)*[2] tzname;
-}
-else version (CRuntime_Musl)
-{
- ///
- void tzset(); // non-standard
- ///
- extern __gshared const(char)*[2] tzname; // non-standard
-}
-else version (CRuntime_UClibc)
-{
- ///
- void tzset();
- ///
- extern __gshared const(char)*[2] tzname;
-}
-else
-{
- static assert(false, "Unsupported platform");
-}
* Standards: ISO/IEC 9899:1999 (E)
*/
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
module core.stdc.wchar_;
-private import core.stdc.config;
-private import core.stdc.stdarg; // for va_list
-private import core.stdc.stdio; // for FILE, not exposed per spec
+import core.stdc.config;
+import core.stdc.stdarg; // for va_list
+import core.stdc.stdio; // for FILE, not exposed per spec
public import core.stdc.stddef; // for wchar_t
public import core.stdc.time; // for tm
public import core.stdc.stdint; // for WCHAR_MIN, WCHAR_MAX
enum wchar_t WEOF = 0xFFFF;
///
-int fwprintf(FILE* stream, in wchar_t* format, ...);
+int fwprintf(FILE* stream, const scope wchar_t* format, scope const ...);
///
-int fwscanf(FILE* stream, in wchar_t* format, ...);
-int swscanf(in wchar_t* s, in wchar_t* format, ...);
+int fwscanf(FILE* stream, const scope wchar_t* format, scope ...);
///
-int vfwprintf(FILE* stream, in wchar_t* format, va_list arg);
+int swprintf(wchar_t* s, size_t n, const scope wchar_t* format, scope const ...);
///
-int vfwscanf(FILE* stream, in wchar_t* format, va_list arg);
-int vswscanf(in wchar_t* s, in wchar_t* format, va_list arg);
+int swscanf(const scope wchar_t* s, const scope wchar_t* format, scope ...);
///
-int vwprintf(in wchar_t* format, va_list arg);
+int vfwprintf(FILE* stream, const scope wchar_t* format, va_list arg);
///
-int vwscanf(in wchar_t* format, va_list arg);
+int vfwscanf(FILE* stream, const scope wchar_t* format, va_list arg);
///
-int wprintf(in wchar_t* format, ...);
+int vswprintf(wchar_t* s, size_t n, const scope wchar_t* format, va_list arg);
///
-int wscanf(in wchar_t* format, ...);
-
-/*
- * Windows has 2 versions of swprintf and vswprintf. MinGW defaults to the
- * Microsoft signature. Alias to match DMD/ANSI signature.
- */
-version (MinGW)
-{
- ///
- int _snwprintf(wchar_t* s, size_t n, in wchar_t* format, ...);
- alias _snwprintf swprintf;
- ///
- int _vsnwprintf(wchar_t* s, size_t n, in wchar_t* format, va_list arg);
- alias _vsnwprintf vswprintf;
-}
-else
-{
- ///
- int swprintf(wchar_t* s, size_t n, in wchar_t* format, ...);
- ///
- int vswprintf(wchar_t* s, size_t n, in wchar_t* format, va_list arg);
-}
+int vswscanf(const scope wchar_t* s, const scope wchar_t* format, va_list arg);
+///
+int vwprintf(const scope wchar_t* format, va_list arg);
+///
+int vwscanf(const scope wchar_t* format, va_list arg);
+///
+int wprintf(const scope wchar_t* format, scope const ...);
+///
+int wscanf(const scope wchar_t* format, scope ...);
// No unsafe pointer manipulation.
@trusted
///
wchar_t* fgetws(wchar_t* s, int n, FILE* stream);
///
-int fputws(in wchar_t* s, FILE* stream);
+int fputws(const scope wchar_t* s, FILE* stream);
// No unsafe pointer manipulation.
extern (D) @trusted
}
///
-double wcstod(in wchar_t* nptr, wchar_t** endptr);
+double wcstod(const scope wchar_t* nptr, wchar_t** endptr);
///
-float wcstof(in wchar_t* nptr, wchar_t** endptr);
+float wcstof(const scope wchar_t* nptr, wchar_t** endptr);
///
-real wcstold(in wchar_t* nptr, wchar_t** endptr);
+real wcstold(const scope wchar_t* nptr, wchar_t** endptr);
///
-c_long wcstol(in wchar_t* nptr, wchar_t** endptr, int base);
+c_long wcstol(const scope wchar_t* nptr, wchar_t** endptr, int base);
///
-long wcstoll(in wchar_t* nptr, wchar_t** endptr, int base);
+long wcstoll(const scope wchar_t* nptr, wchar_t** endptr, int base);
///
-c_ulong wcstoul(in wchar_t* nptr, wchar_t** endptr, int base);
+c_ulong wcstoul(const scope wchar_t* nptr, wchar_t** endptr, int base);
///
-ulong wcstoull(in wchar_t* nptr, wchar_t** endptr, int base);
+ulong wcstoull(const scope wchar_t* nptr, wchar_t** endptr, int base);
///
pure wchar_t* wcscpy(return wchar_t* s1, scope const wchar_t* s2);
pure size_t wcslen(scope const wchar_t* s);
///
-pure wchar_t* wmemchr(return const wchar_t* s, wchar_t c, size_t n);
+pure inout(wchar_t)* wmemchr(return inout wchar_t* s, wchar_t c, size_t n);
///
pure int wmemcmp(scope const wchar_t* s1, scope const wchar_t* s2, size_t n);
///
pure wchar_t* wmemset(return wchar_t* s, wchar_t c, size_t n);
///
-size_t wcsftime(wchar_t* s, size_t maxsize, in wchar_t* format, in tm* timeptr);
+size_t wcsftime(wchar_t* s, size_t maxsize, const scope wchar_t* format, const scope tm* timeptr);
version (Windows)
{
}
///
-int mbsinit(in mbstate_t* ps);
+int mbsinit(const scope mbstate_t* ps);
///
-size_t mbrlen(in char* s, size_t n, mbstate_t* ps);
+size_t mbrlen(const scope char* s, size_t n, mbstate_t* ps);
///
-size_t mbrtowc(wchar_t* pwc, in char* s, size_t n, mbstate_t* ps);
+size_t mbrtowc(wchar_t* pwc, const scope char* s, size_t n, mbstate_t* ps);
///
size_t wcrtomb(char* s, wchar_t wc, mbstate_t* ps);
///
-size_t mbsrtowcs(wchar_t* dst, in char** src, size_t len, mbstate_t* ps);
+size_t mbsrtowcs(wchar_t* dst, const scope char** src, size_t len, mbstate_t* ps);
///
-size_t wcsrtombs(char* dst, in wchar_t** src, size_t len, mbstate_t* ps);
+size_t wcsrtombs(char* dst, const scope wchar_t** src, size_t len, mbstate_t* ps);
///
int iswctype(wint_t wc, wctype_t desc);
///
-@system wctype_t wctype(in char* property);
+@system wctype_t wctype(const scope char* property);
///
pure wint_t towlower(wint_t wc);
///
///
wint_t towctrans(wint_t wc, wctrans_t desc);
///
-@system wctrans_t wctrans(in char* property);
+@system wctrans_t wctrans(const scope char* property);
--- /dev/null
+/**
+ * D header file for Bionic err.h.
+ *
+ * Copyright: Copyright © 2019, The D Language Foundation
+ * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * Authors: Ernesto Castellotti
+ */
+module core.sys.bionic.err;
+import core.stdc.stdarg : va_list;
+
+version (CRuntime_Bionic):
+extern (C):
+nothrow:
+@nogc:
+
+void err(int eval, scope const char* fmt, ...);
+void errx(int eval, scope const char* fmt, ...);
+void warn(scope const char* fmt, ...);
+void warnx(scope const char* fmt, ...);
+void verr(int eval, scope const char* fmt, va_list args);
+void verrx(int eval, scope const char* fmt, va_list args);
+void vwarn(scope const char* fmt, va_list args);
+void vwarnx(scope const char* fmt, va_list args);
void* dli_saddr;
}
-int dladdr(in void* addr, Dl_info* info);
+int dladdr(const scope void* addr, Dl_info* info);
enum RTLD_NOLOAD = 0x10;
enum RTLD_NODELETE = 0x80;
--- /dev/null
+/**
+ * D header file for Darwin err.h.
+ *
+ * Copyright: Copyright © 2019, The D Language Foundation
+ * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * Authors: Ernesto Castellotti
+ */
+module core.sys.darwin.err;
+import core.stdc.stdarg : va_list;
+
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
+
+version (Darwin):
+extern (C):
+nothrow:
+@nogc:
+
+alias ExitFunction = void function(int);
+
+void err(int eval, scope const char* fmt, ...);
+void errc(int eval, int code, scope const char* fmt, ...);
+void errx(int eval, scope const char* fmt, ...);
+void warn(scope const char* fmt, ...);
+void warnc(int code, scope const char* fmt, ...);
+void warnx(scope const char* fmt, ...);
+void verr(int eval, scope const char* fmt, va_list args);
+void verrc(int eval, int code, scope const char* fmt, va_list args);
+void verrx(int eval, scope const char* fmt, va_list args);
+void vwarn(scope const char* fmt, va_list args);
+void vwarnc(int code, scope const char* fmt, va_list args);
+void vwarnx(scope const char* fmt, va_list args);
+void err_set_file(void* vfp);
+void err_set_exit(ExitFunction exitf);
--- /dev/null
+/*******************************************************************************
+
+ Binding for Mac OSX's <ifaddr.h>, expose network interface addresses
+
+ The following functions are present as of Mac OSX 10.15:
+ - getifaddrs(3): get interface addresses
+ - freeifaddrs(3): deallocates the return value of `getifaddrs`
+ - getifmaddrs(3): get multicast group membership
+ - freeifmaddrs(3): deallocates the return value of `getifmaddrs`
+
+ Copyright: Copyright © 2020, The D Language Foundation
+ License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+ Authors: Daniel Graczer
+
+*******************************************************************************/
+
+module core.sys.darwin.ifaddrs;
+
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
+version (Darwin):
+extern (C):
+nothrow:
+@nogc:
+@system:
+
+import core.sys.posix.sys.socket;
+
+///
+struct ifaddrs
+{
+ /// Next item in the list
+ ifaddrs* ifa_next;
+ /// Name of the interface
+ char* ifa_name;
+ /// Flags from SIOCGIFFLAGS
+ uint ifa_flags;
+ /// Address of interface
+ sockaddr* ifa_addr;
+ /// Netmask of interface
+ sockaddr* ifa_netmask;
+ /// Point-to-point destination addresss
+ sockaddr* if_dstaddr;
+ /// Address specific data
+ void* ifa_data;
+}
+
+/// Returns: linked list of ifaddrs structures describing interfaces
+int getifaddrs(ifaddrs**);
+/// Frees the linked list returned by getifaddrs
+void freeifaddrs(ifaddrs*);
+
+///
+struct ifmaddrs
+{
+ /// Pointer to next struct
+ ifmaddrs* ifma_next;
+ /// Interface name (AF_LINK)
+ sockaddr* ifma_name;
+ /// Multicast address
+ sockaddr* ifma_addr;
+ /// Link-layer translation, if any
+ sockaddr* ifma_lladdr;
+}
+
+/// Stores a reference to a linked list of the multicast memberships
+/// on the local machine in the memory referenced by ifmaddrs
+int getifmaddrs(ifmaddrs**);
+/// Frees the list allocated by getifmaddrs
+void freeifmaddrs(ifmaddrs*);
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));
+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));
* Returns the section data of the given section in the given segment in the
* mach executable it is linked into.
*
- * ___
+ * ---
* void main()
* {
* import core.sys.darwin.mach.getsect;
* assert(getsectdata("__TEXT", "__text", &size));
* assert(size > 0);
* }
- * ___
+ * ---
*
* Params:
* segname = the name of the segment
* Returns: a pointer to the section data or `null` if it doesn't exist
*/
char* getsectdata(
- in char* segname,
- in char* sectname,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong *size
);
* Returns the section data of the given section in the given segment in the
* given framework.
*
- * ___
+ * ---
* void main()
* {
* import core.sys.darwin.mach.getsect;
* assert(getsectdatafromFramework("Foundation", "__TEXT", "__text", &size));
* assert(size > 0);
* }
- * ___
+ * ---
*
* Params:
* FrameworkName = the name of the framework to get the section data from
* Returns: a pointer to the section data or `null` if it doesn't exist
*/
char* getsectdatafromFramework(
- in char* FrameworkName,
- in char* segname,
- in char* sectname,
+ const scope char* FrameworkName,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong* size
);
* Returns the section structure of the given section in the given segment
* in the mach executable it is linked into.
*
- * ___
+ * ---
* void main()
* {
* import core.sys.darwin.mach.getsect;
* assert(getsectbyname("__TEXT", "__text"));
* }
- * ___
+ * ---
*
* Params:
* segname = the name of the segment
* Returns: a pointer to the section structure or `null` if it doesn't exist
*/
const(Section)* getsectbyname(
- in char* segname,
- in char* sectname
+ const scope char* segname,
+ const scope char* sectname
);
/**
* Returns the section data of the given section in the given segment in the
* image pointed to by the given mach header.
*
- * ___
+ * ---
* void main()
* {
* import core.sys.darwin.mach.getsect;
* assert(getsectdata(mph, "__TEXT", "__text", &size));
* assert(size > 0);
* }
- * ___
+ * ---
*
* Params:
* mhp = the mach header to get the section data from
* Returns: a pointer to the section data or `null` if it doesn't exist
*/
ubyte* getsectiondata(
- in MachHeader* mhp,
- in char* segname,
- in char* sectname,
+ const scope MachHeader* mhp,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong* size
);
* Returns the segment structure of the given segment in the mach executable
* it is linked into.
*
- * ___
+ * ---
* void main()
* {
* import core.sys.darwin.mach.getsect;
* assert(getsegbyname("__TEXT"));
* }
- * ___
+ * ---
*
* Params:
* segname = the name of the segment
* Returns: a pointer to the section structure or `null` if it doesn't exist
*/
const(SegmentCommand)* getsegbyname(
- in char* segname
+ const scope char* segname
);
/**
* Returns the segment data of the given segment in the image pointed to by
* the given mach header.
*
- * ___
+ * ---
* void main()
* {
* import core.sys.darwin.mach.getsect;
* assert(getsegmentdata(mph, "__TEXT", &size));
* assert(size > 0);
* }
- * ___
+ * ---
*
* Params:
* mhp = the mach header to get the section data from
* Returns: a pointer to the section data or `null` if it doesn't exist
*/
ubyte* getsegmentdata(
- in MachHeader* mhp,
- in char* segname,
+ const scope MachHeader* mhp,
+ const scope char* segname,
c_ulong* size
);
* Returns the section data of the given section in the given segment in the
* image pointed to by the given mach header.
*
- * ___
+ * ---
* void main()
* {
* import core.sys.darwin.mach.getsect;
* assert(getsectdatafromheader(mph, "__TEXT", "__text", &size));
* assert(size > 0);
* }
- * ___
+ * ---
*
* Params:
* mhp = the mach header to get the section data from
* Returns: a pointer to the section data or `null` if it doesn't exist
*/
ubyte* getsectdatafromheader(
- in mach_header* mhp,
- in char* segname,
- in char* sectname,
+ const scope mach_header* mhp,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong* size
);
/// ditto
ubyte* getsectdatafromheader_64(
- in mach_header_64* mhp,
- in char* segname,
- in char* sectname,
+ const scope mach_header_64* mhp,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong* size
);
* Returns the section structure of the given section in the given segment
* in image pointed to by the given mach header.
*
- * ___
+ * ---
* void main()
* {
* import core.sys.darwin.mach.getsect;
* auto mph = _NSGetMachExecuteHeader();
* assert(getsectbynamefromheader(mph, "__TEXT", "__text"));
* }
- * ___
+ * ---
*
* Params:
* mhp = the mach header to get the section from
* Returns: a pointer to the section structure or `null` if it doesn't exist
*/
const(section)* getsectbynamefromheader(
- in mach_header* mhp,
- in char* segname,
- in char* sectname
+ const scope mach_header* mhp,
+ const scope char* segname,
+ const scope char* sectname
);
/// ditto
const(section_64)* getsectbynamefromheader_64(
- in mach_header_64* mhp,
- in char* segname,
- in char* sectname
+ const scope mach_header_64* mhp,
+ const scope char* segname,
+ const scope char* sectname
);
/**
* Returns: a pointer to the section structure or `null` if it doesn't exist
*/
const(section)* getsectbynamefromheaderwithswap(
- in mach_header* mhp,
- in char* segname,
- in char* section,
+ const scope mach_header* mhp,
+ const scope char* segname,
+ const scope char* section,
int fSwap
);
/// ditto
const(section)* getsectbynamefromheaderwithswap_64(
- in mach_header_64* mhp,
- in char* segname,
- in char* section,
+ const scope mach_header_64* mhp,
+ const scope char* segname,
+ const scope char* section,
int fSwap
);
}
import core.stdc.config : c_ulong;
char* getsectdata(
- in char* segname,
- in char* sectname,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong *size
);
char* getsectdatafromFramework(
- in char* FrameworkName,
- in char* segname,
- in char* sectname,
+ const scope char* FrameworkName,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong* size
);
version (D_LP64)
{
const(section_64)* getsectbyname(
- in char* segname,
- in char* sectname
+ const scope char* segname,
+ const scope char* sectname
);
ubyte* getsectiondata(
- in mach_header_64* mhp,
- in char* segname,
- in char* sectname,
+ const scope mach_header_64* mhp,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong* size
);
const(segment_command_64)* getsegbyname(
- in char* segname
+ const scope char* segname
);
ubyte* getsegmentdata(
- in mach_header_64* mhp,
- in char* segname,
+ const scope mach_header_64* mhp,
+ const scope char* segname,
c_ulong* size
);
}
else
{
const(section)* getsectbyname(
- in char* segname,
- in char* sectname
+ const scope char* segname,
+ const scope char* sectname
);
ubyte* getsectiondata(
- in mach_header* mhp,
- in char* segname,
- in char* sectname,
+ const scope mach_header* mhp,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong* size
);
const(segment_command)* getsegbyname(
- in char* segname
+ const scope char* segname
);
ubyte* getsegmentdata(
- in mach_header* mhp,
- in char* segname,
+ const scope mach_header* mhp,
+ const scope char* segname,
c_ulong* size
);
}
// Interfaces for tools working with 32-bit Mach-O files.
ubyte* getsectdatafromheader(
- in mach_header* mhp,
- in char* segname,
- in char* sectname,
+ const scope mach_header* mhp,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong* size
);
const(section)* getsectbynamefromheader(
- in mach_header* mhp,
- in char* segname,
- in char* sectname
+ const scope mach_header* mhp,
+ const scope char* segname,
+ const scope char* sectname
);
const(section)* getsectbynamefromheaderwithswap(
- in mach_header* mhp,
- in char* segname,
- in char* section,
+ const scope mach_header* mhp,
+ const scope char* segname,
+ const scope char* section,
int fSwap
);
// Interfaces for tools working with 64-bit Mach-O files.
ubyte* getsectdatafromheader_64(
- in mach_header_64* mhp,
- in char* segname,
- in char* sectname,
+ const scope mach_header_64* mhp,
+ const scope char* segname,
+ const scope char* sectname,
c_ulong* size
);
const(section_64)* getsectbynamefromheader_64(
- in mach_header_64* mhp,
- in char* segname,
- in char* sectname
+ const scope mach_header_64* mhp,
+ const scope char* segname,
+ const scope char* sectname
);
const(section)* getsectbynamefromheaderwithswap_64(
- in mach_header_64* mhp,
- in char* segname,
- in char* section,
+ const scope mach_header_64* mhp,
+ const scope char* segname,
+ const scope char* section,
int fSwap
);
ulong size;
}
}
-
-else version (OSX)
- version = Darwin;
-else version (iOS)
- version = Darwin;
-else version (TVOS)
- version = Darwin;
-else version (WatchOS)
+else
version = Darwin;
version (Darwin):
}
@property void isym()(uint v) @safe pure nothrow @nogc
- in
- {
- assert(v >= 0U, "Value is smaller than the minimum value of bitfield 'isym'");
- assert(v <= 16777215U, "Value is greater than the maximum value of bitfield 'isym'");
- }
- body
+ in(v >= 0U, "Value is smaller than the minimum value of bitfield 'isym'")
+ in(v <= 16777215U, "Value is greater than the maximum value of bitfield 'isym'")
{
storage = cast(uint) ((storage & (-1 - cast(uint) 16777215U)) |
((cast(uint) v << 0U) & 16777215U));
}
@property void flags()(uint v) pure nothrow @nogc @safe
- in
- {
- assert(v >= 0U, "Value is smaller than the minimum value of bitfield 'flags'");
- assert(v <= 255U, "Value is greater than the maximum value of bitfield 'flags'");
- }
- body
+ in(v >= 0U, "Value is smaller than the minimum value of bitfield 'flags'")
+ in(v <= 255U, "Value is greater than the maximum value of bitfield 'flags'")
{
storage = cast(uint) ((storage & (-1 - cast(uint) 4278190080U)) |
((cast(uint) v << 24U) & 4278190080U));
}
@property void isub_image()(uint v) pure nothrow @nogc @safe
- in
- {
- assert(v >= 0U, "Value is smaller than the minimum value of bitfield 'isub_image'");
- assert(v <= 255U, "Value is greater than the maximum value of bitfield 'isub_image'");
- }
- body
+ in(v >= 0U, "Value is smaller than the minimum value of bitfield 'isub_image'")
+ in(v <= 255U, "Value is greater than the maximum value of bitfield 'isub_image'")
{
storage = cast(uint) ((storage & (-1-cast(uint)255U)) |
((cast(uint) v << 0U) & 255U));
}
@property void itoc()(uint v) pure nothrow @nogc @safe
- in
- {
- assert(v >= 0U, "Value is smaller than the minimum value of bitfield 'itoc'");
- assert(v <= 16777215U, "Value is greater than the maximum value of bitfield 'itoc'");
- }
- body
+ in(v >= 0U, "Value is smaller than the minimum value of bitfield 'itoc'")
+ in(v <= 16777215U, "Value is greater than the maximum value of bitfield 'itoc'")
{
storage = cast(uint) ((storage & (-1-cast(uint)4294967040U)) |
((cast(uint) v << 8U) & 4294967040U));
--- /dev/null
+/**
+ * Bindings for symbols and defines in `mach-o/nlist.h`
+ *
+ * This file was created based on the MacOSX 10.15 SDK.
+ *
+ * Copyright:
+ * D Language Foundation 2020
+ * Some documentation was extracted from the C headers
+ * and is the property of Apple Inc.
+ *
+ * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+ * Authors: Mathias 'Geod24' Lang
+ * Source: $(DRUNTIMESRC core/sys/darwin/mach/_nlist.d)
+ */
+module core.sys.darwin.mach.nlist;
+
+import core.stdc.config;
+
+extern(C):
+nothrow:
+@nogc:
+pure:
+
+/**
+ * An entry in a list of symbols for 64-bits architectures
+ *
+ * Said symbols can be used to describe many different type of data,
+ * including STABS debug infos. Introduced in MacOSX 10.8 SDK.
+ *
+ * See_Also:
+ * https://developer.apple.com/documentation/kernel/nlist_64
+ */
+struct nlist_64
+{
+ /// Compatibility alias, as `n_strx` is in an union in C code
+ alias n_un = n_strx;
+
+ /**
+ * Index of this symbol's name into the string table
+ *
+ * All names are stored as NUL-terminated strings into the string table.
+ * For historical reason, the very first entry into the string table is `0`,
+ * hence all non-NULL names have an index > 0.
+ */
+ uint n_strx;
+
+ /**
+ * A bitfield that describes the type of this symbol
+ *
+ * In reality, this describes 4 fields:
+ * - N_STAB (top 3 bits)
+ * - N_PEXT (next 1 bit)
+ * - N_TYPE (next 3 bits)
+ * - N_EXT (last 1 bit)
+ *
+ * The enum values `N_STAB`, `N_PEXT`, `N_TYPE`, and `N_EXT` should be used
+ * as masks to check which type this `nlist_64` actually is.
+ */
+ ubyte n_type;
+ /// Section number (note that `0` means `NO_SECT`)
+ ubyte n_sect;
+ /* see <mach-o/stab.h> */
+ ushort n_desc;
+ /* value of this symbol (or stab offset) */
+ ulong n_value;
+ // Note: `n_value` *is* `uint64_t`, not `c_ulong` !
+}
+
+/// Mask to use with `nlist_64.n_type` to check what the entry describes
+enum
+{
+ /**
+ * If any of these bits set, a symbolic debugging entry
+ *
+ * Only symbolic debugging entries have some of the N_STAB bits set and if any
+ * of these bits are set then it is a symbolic debugging entry (a stab). In
+ * which case then the values of the n_type field (the entire field) are given
+ * in <mach-o/stab.h>
+ */
+ N_STAB = 0xe0,
+ /// Private external symbol bit
+ N_PEXT = 0x10,
+ /// Mask for the type bits
+ N_TYPE = 0x0e, /* mask for the type bits */
+ /// External symbol bit, set for external symbols
+ N_EXT = 0x01,
+}
+
+/// Values for `NTypeMask.N_TYPE` bits of the `nlist_64.n_type` field.
+enum
+{
+ /// Undefined (`n_sect == NO_SECT`)
+ N_UNDF = 0x0,
+ /// Absolute (`n_sect == NO_SECT`)
+ N_ABS = 0x2,
+ /// Defined in section number `nlist_64.n_sect`
+ N_SECT = 0xe,
+ /// Prebound undefined (defined in a dylib)
+ N_PBUD = 0xc,
+ /**
+ * Indirect symbol
+ *
+ * If the type is `N_INDR` then the symbol is defined to be the same as
+ * another symbol. In this case the `n_value` field is an index into
+ * the string table of the other symbol's name. When the other symbol
+ * is defined then they both take on the defined type and value.
+ */
+ N_INDR = 0xa,
+}
+
+/**
+ * Symbol is not in any section
+ *
+ * If the type is N_SECT then the n_sect field contains an ordinal of the
+ * section the symbol is defined in. The sections are numbered from 1 and
+ * refer to sections in order they appear in the load commands for the file
+ * they are in. This means the same ordinal may very well refer to different
+ * sections in different files.
+ *
+ * The n_value field for all symbol table entries (including N_STAB's) gets
+ * updated by the link editor based on the value of it's n_sect field and where
+ * the section n_sect references gets relocated. If the value of the n_sect
+ * field is NO_SECT then it's n_value field is not changed by the link editor.
+ */
+enum NO_SECT = 0;
+
+/// Maximum number of sections: 1 thru 255 inclusive
+enum MAX_SECT = 255;
+
+/**
+ * Common symbols are represented by undefined (N_UNDF) external (N_EXT) types
+ * who's values (n_value) are non-zero. In which case the value of the n_value
+ * field is the size (in bytes) of the common symbol. The n_sect field is set
+ * to NO_SECT. The alignment of a common symbol may be set as a power of 2
+ * between 2^1 and 2^15 as part of the n_desc field using the macros below. If
+ * the alignment is not set (a value of zero) then natural alignment based on
+ * the size is used.
+ */
+extern(D) ubyte GET_COMM_ALIGN(uint n_desc) @safe
+{
+ return (((n_desc) >> 8) & 0x0f);
+}
+
+/// Ditto
+extern(D) ref ushort SET_COMM_ALIGN(return ref ushort n_desc, size_t wanted_align) @safe
+{
+ return n_desc = (((n_desc) & 0xf0ff) | (((wanted_align) & 0x0f) << 8));
+}
+
+/**
+ * To support the lazy binding of undefined symbols in the dynamic link-editor,
+ * the undefined symbols in the symbol table (the nlist structures) are marked
+ * with the indication if the undefined reference is a lazy reference or
+ * non-lazy reference. If both a non-lazy reference and a lazy reference is
+ * made to the same symbol the non-lazy reference takes precedence. A reference
+ * is lazy only when all references to that symbol are made through a symbol
+ * pointer in a lazy symbol pointer section.
+ *
+ * The implementation of marking nlist structures in the symbol table for
+ * undefined symbols will be to use some of the bits of the n_desc field as a
+ * reference type. The mask REFERENCE_TYPE will be applied to the n_desc field
+ * of an nlist structure for an undefined symbol to determine the type of
+ * undefined reference (lazy or non-lazy).
+ *
+ * The constants for the REFERENCE FLAGS are propagated to the reference table
+ * in a shared library file. In that case the constant for a defined symbol,
+ * REFERENCE_FLAG_DEFINED, is also used.
+ */
+enum
+{
+ /// Reference type bits of the n_desc field of undefined symbols
+ REFERENCE_TYPE = 0x7,
+
+ /// types of references
+ REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0,
+ /// Ditto
+ REFERENCE_FLAG_UNDEFINED_LAZY = 1,
+ /// Ditto
+ REFERENCE_FLAG_DEFINED = 2,
+ /// Ditto
+ REFERENCE_FLAG_PRIVATE_DEFINED = 3,
+ /// Ditto
+ REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4,
+ /// Ditto
+ REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5,
+
+ /**
+ * To simplify stripping of objects that use are used with the dynamic link
+ * editor, the static link editor marks the symbols defined an object that are
+ * referenced by a dynamicly bound object (dynamic shared libraries, bundles).
+ * With this marking strip knows not to strip these symbols.
+ */
+ REFERENCED_DYNAMICALLY = 0x0010,
+}
+
+/**
+ * For images created by the static link editor with the -twolevel_namespace
+ * option in effect the flags field of the mach header is marked with
+ * MH_TWOLEVEL. And the binding of the undefined references of the image are
+ * determined by the static link editor. Which library an undefined symbol is
+ * bound to is recorded by the static linker in the high 8 bits of the n_desc
+ * field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded
+ * references the libraries listed in the Mach-O's LC_LOAD_DYLIB,
+ * LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB, and
+ * LC_LAZY_LOAD_DYLIB, etc. load commands in the order they appear in the
+ * headers. The library ordinals start from 1.
+ * For a dynamic library that is built as a two-level namespace image the
+ * undefined references from module defined in another use the same nlist struct
+ * an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For
+ * defined symbols in all images they also must have the library ordinal set to
+ * SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable
+ * image for references from plugins that refer to the executable that loads
+ * them.
+ *
+ * The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace
+ * image that are looked up by the dynamic linker with flat namespace semantics.
+ * This ordinal was added as a feature in Mac OS X 10.3 by reducing the
+ * value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries
+ * or binaries built with older tools to have 0xfe (254) dynamic libraries. In
+ * this case the ordinal value 0xfe (254) must be treated as a library ordinal
+ * for compatibility.
+ */
+ubyte GET_LIBRARY_ORDINAL(uint n_desc) @safe { return ((n_desc) >> 8) & 0xff; }
+/// Ditto
+ref ushort SET_LIBRARY_ORDINAL(return scope ref ushort n_desc, uint ordinal) @safe
+{
+ return n_desc = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8));
+}
+
+/// Ditto
+enum
+{
+ SELF_LIBRARY_ORDINAL = 0x00,
+ MAX_LIBRARY_ORDINAL = 0xfd,
+ DYNAMIC_LOOKUP_ORDINAL = 0xfe,
+ EXECUTABLE_ORDINAL = 0xff,
+}
+
+/**
+ * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes
+ * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED.
+ */
+enum
+{
+ /**
+ * Symbol is not to be dead stripped
+ *
+ * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a
+ * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the
+ * static link editor it is never to dead strip the symbol.
+ */
+ N_NO_DEAD_STRIP = 0x0020,
+
+ /**
+ * Symbol is discarded
+ *
+ * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image.
+ * But is used in very rare cases by the dynamic link editor to mark an in
+ * memory symbol as discared and longer used for linking.
+ */
+ N_DESC_DISCARDED =0x0020,
+
+ /**
+ * Symbol is weak referenced
+ *
+ * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that
+ * the undefined symbol is allowed to be missing and is to have the address of
+ * zero when missing.
+ */
+ N_WEAK_REF = 0x0040,
+
+ /**
+ * Coalesed symbol is a weak definition
+ *
+ * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic
+ * linkers that the symbol definition is weak, allowing a non-weak symbol to
+ * also be used which causes the weak definition to be discared. Currently this
+ * is only supported for symbols in coalesed sections.
+ */
+ N_WEAK_DEF = 0x0080,
+
+ /**
+ * Reference to a weak symbol
+ *
+ * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker
+ * that the undefined symbol should be resolved using flat namespace searching.
+ */
+ N_REF_TO_WEAK = 0x0080,
+
+ /**
+ * Symbol is a Thumb function (ARM)
+ *
+ * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is
+ * a defintion of a Thumb function.
+ */
+ N_ARM_THUMB_DEF = 0x0008,
+
+ /**
+ * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the
+ * that the function is actually a resolver function and should
+ * be called to get the address of the real function to use.
+ * This bit is only available in .o files (MH_OBJECT filetype)
+ */
+ N_SYMBOL_RESOLVER = 0x0100,
+
+ /**
+ * The N_ALT_ENTRY bit of the n_desc field indicates that the
+ * symbol is pinned to the previous content.
+ */
+ N_ALT_ENTRY = 0x0200,
+
+ /**
+ * The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used
+ * infrequently and the linker should order it towards the end of the section.
+ */
+ N_COLD_FUNC = 0x0400,
+}
--- /dev/null
+/**
+ * Bindings for symbols and defines in `mach-o/stab.h`
+ *
+ * This file gives definitions supplementing <nlist.h> for permanent symbol
+ * table entries of Mach-O files. Modified from the BSD definitions. The
+ * modifications from the original definitions were changing what the values of
+ * what was the n_other field (an unused field) which is now the n_sect field.
+ * These modifications are required to support symbols in an arbitrary number of
+ * sections not just the three sections (text, data and bss) in a BSD file.
+ * The values of the defined constants have NOT been changed.
+ *
+ * These must have one of the N_STAB bits on. The n_value fields are subject
+ * to relocation according to the value of their n_sect field. So for types
+ * that refer to things in sections the n_sect field must be filled in with the
+ * proper section ordinal. For types that are not to have their n_value field
+ * relocatated the n_sect field must be NO_SECT.
+ *
+ * This file was created based on the MacOSX 10.15 SDK.
+ *
+ * Copyright:
+ * D Language Foundation 2020
+ * Some documentation was extracted from the C headers
+ * and is the property of Apple Inc.
+ *
+ * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+ * Authors: Mathias 'Geod24' Lang
+ * Source: $(DRUNTIMESRC core/sys/darwin/mach/_nlist.d)
+ */
+module core.sys.darwin.mach.stab;
+
+extern(C):
+nothrow:
+@nogc:
+pure:
+
+/**
+ * Symbolic debugger symbols.
+ *
+ * The comments give the conventional use for
+ * ```
+ * .stabs "n_name", n_type, n_sect, n_desc, n_value
+ * ```
+ *
+ * where n_type is the defined constant and not listed in the comment. Other
+ * fields not listed are zero. n_sect is the section ordinal the entry is
+ * refering to.
+ */
+enum
+{
+ N_GSYM = 0x20, /// global symbol: name,,NO_SECT,type,0
+ N_FNAME = 0x22, /// procedure name (f77 kludge): name,,NO_SECT,0,0
+ N_FUN = 0x24, /// procedure: name,,n_sect,linenumber,address
+ N_STSYM = 0x26, /// static symbol: name,,n_sect,type,address
+ N_LCSYM = 0x28, /// .lcomm symbol: name,,n_sect,type,address
+ N_BNSYM = 0x2e, /// begin nsect sym: 0,,n_sect,0,address
+ N_AST = 0x32, /// AST file path: name,,NO_SECT,0,0
+ N_OPT = 0x3c, /// emitted with gcc2_compiled and in gcc source
+ N_RSYM = 0x40, /// register sym: name,,NO_SECT,type,register
+ N_SLINE = 0x44, /// src line: 0,,n_sect,linenumber,address
+ N_ENSYM = 0x4e, /// end nsect sym: 0,,n_sect,0,address
+ N_SSYM = 0x60, /// structure elt: name,,NO_SECT,type,struct_offset
+ N_SO = 0x64, /// source file name: name,,n_sect,0,address
+ /**
+ * Object file name: name,,(see below),0,st_mtime
+ *
+ * Historically N_OSO set n_sect to 0.
+ * The N_OSO n_sect may instead hold the low byte of the cpusubtype value
+ * from the Mach-O header.
+ */
+ N_OSO = 0x66,
+ N_LSYM = 0x80, /// local sym: name,,NO_SECT,type,offset
+ N_BINCL = 0x82, /// include file beginning: name,,NO_SECT,0,sum
+ N_SOL = 0x84, /// #included file name: name,,n_sect,0,address
+ N_PARAMS = 0x86, /// compiler parameters: name,,NO_SECT,0,0
+ N_VERSION = 0x88, /// compiler version: name,,NO_SECT,0,0
+ N_OLEVEL = 0x8A, /// compiler -O level: name,,NO_SECT,0,0
+ N_PSYM = 0xa0, /// parameter: name,,NO_SECT,type,offset
+ N_EINCL = 0xa2, /// include file end: name,,NO_SECT,0,0
+ N_ENTRY = 0xa4, /// alternate entry: name,,n_sect,linenumber,address
+ N_LBRAC = 0xc0, /// left bracket: 0,,NO_SECT,nesting level,address
+ N_EXCL = 0xc2, /// deleted include file: name,,NO_SECT,0,sum
+ N_RBRAC = 0xe0, /// right bracket: 0,,NO_SECT,nesting level,address
+ N_BCOMM = 0xe2, /// begin common: name,,NO_SECT,0,0
+ N_ECOMM = 0xe4, /// end common: name,,n_sect,0,0
+ N_ECOML = 0xe8, /// end common (local name): 0,,n_sect,0,address
+ N_LENG = 0xfe, /// second stab entry with length information
+
+ // For the berkeley pascal compiler, pc(1):
+ N_PC = 0x30, /// global pascal symbol: name,,NO_SECT,subtype,line
+}
{
in_addr ip_dst;
char[40] ip_opts = 0;
- };
+ }
enum IP_OPTIONS = 1;
enum IP_HDRINCL = 2;
{
in_addr imr_multiaddr;
in_addr imr_interface;
- };
+ }
struct ip_mreqn
{
in_addr imr_multiaddr;
in_addr imr_address;
int imr_ifindex;
- };
+ }
struct ip_mreq_source
{
in_addr imr_multiaddr;
in_addr imr_sourceaddr;
in_addr imr_interface;
- };
+ }
struct group_req
{
align(4):
uint gr_interface;
sockaddr_storage gr_group;
- };
+ }
struct group_source_req
{
uint gsr_interface;
sockaddr_storage gsr_group;
sockaddr_storage gsr_source;
- };
+ }
int setipv4sourcefilter(int, in_addr, in_addr, uint, uint, in_addr*);
int getipv4sourcefilter(int, in_addr, in_addr, uint*, uint*, in_addr*);
uint ipi_ifindex;
in_addr ipi_spec_dst;
in_addr ipi_addr;
- };
+ }
enum IPPROTO_MAXID = IPPROTO_AH + 1;
{
in6_addr ipi6_addr;
uint ipi6_ifindex;
- };
+ }
struct ip6_mtuinfo
{
sockaddr_in6 ip6m_addr;
uint ip6m_mtu;
- };
+ }
enum IPV6_PORTRANGE_DEFAULT = 0;
enum IPV6_PORTRANGE_HIGH = 1;
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*);
+int pthread_setname_np(const scope char*);
// ^ __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
int pthread_main_np();
mach_port_t pthread_mach_thread_np(pthread_t);
size_t pthread_get_stacksize_np(pthread_t);
void* pthread_get_stackaddr_np(pthread_t);
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_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, in sigset_t*, sigset_t*);
+int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
// ^ __DARWIN_ALIAS(pthread_sigmask)
void pthread_yield_np();
--- /dev/null
+/**
+ * D header file for Darwin
+ *
+ * $(LINK2 https://opensource.apple.com/source/xnu/xnu-2422.115.4/bsd/sys/attr.h.auto.html, Apple sys/attr.h)
+ */
+module core.sys.darwin.sys.attr;
+
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
+version (Darwin):
+extern (C):
+nothrow:
+@nogc:
+
+import core.internal.attributes : betterC;
+import core.sys.darwin.sys.cdefs : c_ulong;
+import core.sys.posix.sys.time : timeval;
+
+// These functions aren't actually declared in attr.h but in unistd.h.
+@system
+{
+ void getattrlist(scope const char* path, scope attrlist* attrList, scope void* attrBuf,
+ size_t attrBufSize, c_ulong options);
+
+ void setattrlist(scope const char* path, scope attrlist* attrList, scope void* attrBuf,
+ size_t attrBufSize, c_ulong options);
+
+ version (TVOS) {}
+ else version (WatchOS) {}
+ else
+ int searchfs(scope const char* path, scope fssearchblock* searchBlock,
+ scope c_ulong* numMatches, uint scriptCode, uint options, scope searchstate* state);
+}
+
+enum
+{
+ FSOPT_NOFOLLOW = 0x00000001,
+ FSOPT_NOINMEMUPDATE = 0x00000002,
+ FSOPT_REPORT_FULLSIZE = 0x00000004,
+ FSOPT_PACK_INVAL_ATTRS = 0x00000008,
+ FSOPT_ATTR_CMN_EXTENDED = 0x00000020, // macOS 10.10
+}
+
+enum SEARCHFS_MAX_SEARCHPARMS = 4096;
+
+alias uint text_encoding_t, fsobj_type_t, fsobj_tag_t, fsfile_type_t, fsvolid_t, attrgroup_t;
+
+struct attrlist
+{
+ ushort bitmapcount, reserved;
+ attrgroup_t commonattr, volattr, dirattr, fileattr, forkattr;
+}
+enum ATTR_BIT_MAP_COUNT = 5;
+
+struct attribute_set_t
+{
+ attrgroup_t commonattr, volattr, dirattr, fileattr, forkattr;
+}
+
+struct attrreference_t
+{
+ int attr_dataoffset;
+ uint attr_length;
+}
+
+struct diskextent
+{
+ uint startblock, blockcount;
+}
+
+alias extentrecord = diskextent[8];
+
+alias vol_capabilities_set_t = uint[4];
+
+enum
+{
+ VOL_CAPABILITIES_FORMAT = 0,
+ VOL_CAPABILITIES_INTERFACES = 1,
+ VOL_CAPABILITIES_RESERVED1 = 2,
+ VOL_CAPABILITIES_RESERVED2 = 3,
+}
+
+struct vol_capabilities_attr_t
+{
+ vol_capabilities_set_t capabilities, valid;
+}
+
+enum ATTR_MAX_BUFFER = 8192;
+
+enum
+{
+ VOL_CAP_FMT_PERSISTENTOBJECTIDS = 0x00000001,
+ VOL_CAP_FMT_SYMBOLICLINKS = 0x00000002,
+ VOL_CAP_FMT_HARDLINKS = 0x00000004,
+ VOL_CAP_FMT_JOURNAL = 0x00000008,
+ VOL_CAP_FMT_JOURNAL_ACTIVE = 0x00000010,
+ VOL_CAP_FMT_NO_ROOT_TIMES = 0x00000020,
+ VOL_CAP_FMT_SPARSE_FILES = 0x00000040,
+ VOL_CAP_FMT_ZERO_RUNS = 0x00000080,
+ VOL_CAP_FMT_CASE_SENSITIVE = 0x00000100,
+ VOL_CAP_FMT_CASE_PRESERVING = 0x00000200,
+ VOL_CAP_FMT_FAST_STATFS = 0x00000400,
+ VOL_CAP_FMT_2TB_FILESIZE = 0x00000800,
+ VOL_CAP_FMT_OPENDENYMODES = 0x00001000,
+ VOL_CAP_FMT_HIDDEN_FILES = 0x00002000,
+ VOL_CAP_FMT_PATH_FROM_ID = 0x00004000,
+ VOL_CAP_FMT_NO_VOLUME_SIZES = 0x00008000,
+ VOL_CAP_FMT_DECMPFS_COMPRESSION = 0x00010000,
+ VOL_CAP_FMT_64BIT_OBJECT_IDS = 0x00020000,
+ VOL_CAP_FMT_DIR_HARDLINKS = 0x00040000, // macOS 10.12
+ VOL_CAP_FMT_DOCUMENT_ID = 0x00080000, // macOS 10.12
+ VOL_CAP_FMT_WRITE_GENERATION_COUNT = 0x00100000, // macOS 10.12
+ VOL_CAP_FMT_NO_IMMUTABLE_FILES = 0x00200000, // macOS 10.12.4
+ VOL_CAP_FMT_NO_PERMISSIONS = 0x00400000, // macOS 10.12.4
+ VOL_CAP_FMT_SHARED_SPACE = 0x00800000, // macOS 10.15
+ VOL_CAP_FMT_VOL_GROUPS = 0x01000000, // macOS 10.15
+}
+
+enum
+{
+ VOL_CAP_INT_SEARCHFS = 0x00000001,
+ VOL_CAP_INT_ATTRLIST = 0x00000002,
+ VOL_CAP_INT_NFSEXPORT = 0x00000004,
+ VOL_CAP_INT_READDIRATTR = 0x00000008,
+ VOL_CAP_INT_EXCHANGEDATA = 0x00000010,
+ VOL_CAP_INT_COPYFILE = 0x00000020,
+ VOL_CAP_INT_ALLOCATE = 0x00000040,
+ VOL_CAP_INT_VOL_RENAME = 0x00000080,
+ VOL_CAP_INT_ADVLOCK = 0x00000100,
+ VOL_CAP_INT_FLOCK = 0x00000200,
+ VOL_CAP_INT_EXTENDED_SECURITY = 0x00000400,
+ VOL_CAP_INT_USERACCESS = 0x00000800,
+ VOL_CAP_INT_MANLOCK = 0x00001000,
+ VOL_CAP_INT_NAMEDSTREAMS = 0x00002000,
+ VOL_CAP_INT_EXTENDED_ATTR = 0x00004000,
+ VOL_CAP_INT_CLONE = 0x00010000, // macOS 10.12
+ VOL_CAP_INT_SNAPSHOT = 0x00020000, // macOS 10.12
+ VOL_CAP_INT_RENAME_SWAP = 0x00040000, // macOS 10.12
+ VOL_CAP_INT_RENAME_EXCL = 0x00080000, // macOS 10.12
+ VOL_CAP_INT_RENAME_OPENFAIL = 0x00100000, // macOS 10.15
+}
+
+struct vol_attributes_attr_t
+{
+ attribute_set_t validattr, nativeattr;
+}
+
+enum
+{
+ ATTR_CMN_NAME = 0x00000001,
+ ATTR_CMN_DEVID = 0x00000002,
+ ATTR_CMN_FSID = 0x00000004,
+ ATTR_CMN_OBJTYPE = 0x00000008,
+ ATTR_CMN_OBJTAG = 0x00000010,
+ ATTR_CMN_OBJID = 0x00000020,
+ ATTR_CMN_OBJPERMANENTID = 0x00000040,
+ ATTR_CMN_PAROBJID = 0x00000080,
+ ATTR_CMN_SCRIPT = 0x00000100,
+ ATTR_CMN_CRTIME = 0x00000200,
+ ATTR_CMN_MODTIME = 0x00000400,
+ ATTR_CMN_CHGTIME = 0x00000800,
+ ATTR_CMN_ACCTIME = 0x00001000,
+ ATTR_CMN_BKUPTIME = 0x00002000,
+ ATTR_CMN_FNDRINFO = 0x00004000,
+ ATTR_CMN_OWNERID = 0x00008000,
+ ATTR_CMN_GRPID = 0x00010000,
+ ATTR_CMN_ACCESSMASK = 0x00020000,
+ ATTR_CMN_FLAGS = 0x00040000,
+
+ ATTR_CMN_GEN_COUNT = 0x00080000,
+ ATTR_CMN_DOCUMENT_ID = 0x00100000,
+
+ ATTR_CMN_USERACCESS = 0x00200000,
+ ATTR_CMN_EXTENDED_SECURITY = 0x00400000,
+ ATTR_CMN_UUID = 0x00800000,
+ ATTR_CMN_GRPUUID = 0x01000000,
+ ATTR_CMN_FILEID = 0x02000000,
+ ATTR_CMN_PARENTID = 0x04000000,
+ ATTR_CMN_FULLPATH = 0x08000000,
+ ATTR_CMN_ADDEDTIME = 0x10000000,
+ ATTR_CMN_ERROR = 0x20000000, // macOS 10.10
+ ATTR_CMN_DATA_PROTECT_FLAGS = 0x40000000, // macOS 10.10
+}
+
+enum ATTR_CMN_RETURNED_ATTRS = 0x80000000;
+enum ATTR_CMN_VALIDMASK = 0xFFFFFFFF;
+enum ATTR_CMN_SETMASK = 0x51C7FF00;
+enum ATTR_CMN_VOLSETMASK = 0x00006700;
+
+enum
+{
+ ATTR_VOL_FSTYPE = 0x00000001,
+ ATTR_VOL_SIGNATURE = 0x00000002,
+ ATTR_VOL_SIZE = 0x00000004,
+ ATTR_VOL_SPACEFREE = 0x00000008,
+ ATTR_VOL_SPACEAVAIL = 0x00000010,
+ ATTR_VOL_MINALLOCATION = 0x00000020,
+ ATTR_VOL_ALLOCATIONCLUMP = 0x00000040,
+ ATTR_VOL_IOBLOCKSIZE = 0x00000080,
+ ATTR_VOL_OBJCOUNT = 0x00000100,
+ ATTR_VOL_FILECOUNT = 0x00000200,
+ ATTR_VOL_DIRCOUNT = 0x00000400,
+ ATTR_VOL_MAXOBJCOUNT = 0x00000800,
+ ATTR_VOL_MOUNTPOINT = 0x00001000,
+ ATTR_VOL_NAME = 0x00002000,
+ ATTR_VOL_MOUNTFLAGS = 0x00004000,
+ ATTR_VOL_MOUNTEDDEVICE = 0x00008000,
+ ATTR_VOL_ENCODINGSUSED = 0x00010000,
+ ATTR_VOL_CAPABILITIES = 0x00020000,
+ ATTR_VOL_UUID = 0x00040000,
+ ATTR_VOL_QUOTA_SIZE = 0x10000000, // macOS 10.12.4
+ ATTR_VOL_RESERVED_SIZE = 0x20000000, // macOS 10.12.4
+ ATTR_VOL_ATTRIBUTES = 0x40000000,
+ ATTR_VOL_INFO = 0x80000000,
+}
+
+enum ATTR_VOL_VALIDMASK = 0xF007FFFF;
+enum ATTR_VOL_SETMASK = 0x80002000;
+
+enum
+{
+ ATTR_DIR_LINKCOUNT = 0x00000001,
+ ATTR_DIR_ENTRYCOUNT = 0x00000002,
+ ATTR_DIR_MOUNTSTATUS = 0x00000004,
+ ATTR_DIR_ALLOCSIZE = 0x00000008, // macOS 10.12.4
+ ATTR_DIR_IOBLOCKSIZE = 0x00000010, // macOS 10.12.4
+ ATTR_DIR_DATALENGTH = 0x00000020, // macOS 10.12.4
+}
+
+enum
+{
+ DIR_MNTSTATUS_MNTPOINT = 0x00000001,
+ DIR_MNTSTATUS_TRIGGER = 0x00000002,
+}
+
+enum ATTR_DIR_VALIDMASK = 0x0000003f;
+enum ATTR_DIR_SETMASK = 0x00000000;
+
+enum
+{
+ ATTR_FILE_LINKCOUNT = 0x00000001,
+ ATTR_FILE_TOTALSIZE = 0x00000002,
+ ATTR_FILE_ALLOCSIZE = 0x00000004,
+ ATTR_FILE_IOBLOCKSIZE = 0x00000008,
+ ATTR_FILE_DEVTYPE = 0x00000020,
+ ATTR_FILE_FORKCOUNT = 0x00000080,
+ ATTR_FILE_FORKLIST = 0x00000100,
+ ATTR_FILE_DATALENGTH = 0x00000200,
+ ATTR_FILE_DATAALLOCSIZE = 0x00000400,
+ ATTR_FILE_RSRCLENGTH = 0x00001000,
+ ATTR_FILE_RSRCALLOCSIZE = 0x00002000,
+}
+
+enum ATTR_FILE_VALIDMASK = 0x000037FF;
+enum ATTR_FILE_SETMASK = 0x00000020;
+
+enum
+{
+ ATTR_CMNEXT_RELPATH = 0x00000004, // macOS 10.12.4
+ ATTR_CMNEXT_PRIVATESIZE = 0x00000008, // macOS 10.12.4
+ ATTR_CMNEXT_NOFIRMLINKPATH = 0x00000020, // macOS 10.15
+ ATTR_CMNEXT_REALDEVID = 0x00000040, // macOS 10.15
+ ATTR_CMNEXT_REALFSID = 0x00000080, // macOS 10.15
+}
+
+enum ATTR_CMNEXT_VALIDMASK = 0x000000fc;
+enum ATTR_CMNEXT_SETMASK = 0x00000000;
+
+enum ATTR_BULK_REQUIRED = ATTR_CMN_NAME | ATTR_CMN_RETURNED_ATTRS;
+
+enum
+{
+ SRCHFS_START = 0x00000001,
+ SRCHFS_MATCHPARTIALNAMES = 0x00000002,
+ SRCHFS_MATCHDIRS = 0x00000004,
+ SRCHFS_MATCHFILES = 0x00000008,
+ SRCHFS_SKIPLINKS = 0x00000010,
+ SRCHFS_SKIPINVISIBLE = 0x00000020,
+ SRCHFS_SKIPPACKAGES = 0x00000040,
+ SRCHFS_SKIPINAPPROPRIATE = 0x00000080,
+
+ SRCHFS_NEGATEPARAMS = 0x80000000,
+ SRCHFS_VALIDOPTIONSMASK = 0x800000FF,
+}
+
+struct fssearchblock
+{
+ attrlist* returnattrs;
+ void* returnbuffer;
+ size_t returnbuffersize;
+ c_ulong maxmatches;
+ timeval timelimit;
+ void* searchparams1;
+ size_t sizeofsearchparams1;
+ void* searchparams2;
+ size_t sizeofsearchparams2;
+ attrlist searchattrs;
+}
+
+struct searchstate
+{
+ uint ss_union_flags;
+ uint ss_union_layer;
+ ubyte[548] ss_fsstate;
+}
+static assert(searchstate.sizeof == uint.sizeof * 2 + searchstate.ss_fsstate.sizeof,
+ "searchstate struct must be packed");
+
+enum FST_EOF = -1;
+
+@betterC @nogc nothrow pure @safe unittest
+{
+ // Use an enum instead of `version (Darwin)` so it works with the betterc test extractor.
+ version (OSX) enum isDarwin = true;
+ else version (iOS) enum isDarwin = true;
+ else version (TVOS) enum isDarwin = true;
+ else version (WatchOS) enum isDarwin = true;
+ else enum isDarwin = false;
+ static if (isDarwin)
+ {
+ // Verify that these types don't need __initZ and so can be used in betterC.
+ attrlist al;
+ attribute_set_t as;
+ attrreference_t ar;
+ diskextent de;
+ vol_capabilities_attr_t vca;
+ vol_attributes_attr_t vaa;
+ fssearchblock fsb;
+ searchstate ss;
+ }
+}
void *dli_fbase; /* Base address of shared object. */
const(char) *dli_sname; /* Name of nearest symbol. */
void *dli_saddr; /* Address of nearest symbol. */
-};
+}
/*
struct Dl_serpath {
char * dls_name; /* single search path entry */
uint dls_flags; /* path information */
-};
+}
struct Dl_serinfo {
size_t dls_size; /* total buffer size */
uint dls_cnt; /* number of path entries */
Dl_serpath[1] dls_serpath; /* there may be more than one */
-};
+}
/*-
* The actual type declared by this typedef is immaterial, provided that
*/
struct __dlfunc_arg {
int __dlfunc_dummy;
-};
+}
alias dlfunc_t = void function(__dlfunc_arg);
--- /dev/null
+/**
+ * D header file for DragonFlyBSD err.h.
+ *
+ * Copyright: Copyright © 2019, The D Language Foundation
+ * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * Authors: Ernesto Castellotti
+ */
+module core.sys.dragonflybsd.err;
+import core.stdc.stdarg : va_list;
+
+version (DragonFlyBSD):
+extern (C):
+nothrow:
+@nogc:
+
+alias ExitFunction = void function(int);
+
+void err(int eval, scope const char* fmt, ...);
+void errc(int eval, int code, scope const char* fmt, ...);
+void errx(int eval, scope const char* fmt, ...);
+void warn(scope const char* fmt, ...);
+void warnc(int code, scope const char* fmt, ...);
+void warnx(scope const char* fmt, ...);
+void verr(int eval, scope const char* fmt, va_list args);
+void verrc(int eval, int code, scope const char* fmt, va_list args);
+void verrx(int eval, scope const char* fmt, va_list args);
+void vwarn(scope const char* fmt, va_list args);
+void vwarnc(int code, scope const char* fmt, va_list args);
+void vwarnx(scope const char* fmt, va_list args);
+void err_set_file(void* vfp);
+void err_set_exit(ExitFunction exitf);
{
in_addr imr_multiaddr;
in_addr imr_interface;
-};
+}
struct ip_mreqn
{
in_addr imr_multiaddr;
in_addr imr_address;
int imr_ifindex;
-};
+}
struct ip_mreq_source
{
in_addr imr_multiaddr;
in_addr imr_sourceaddr;
in_addr imr_interface;
-};
+}
struct group_req
{
uint gr_interface;
sockaddr_storage gr_group;
-};
+}
struct group_source_req
{
uint gsr_interface;
sockaddr_storage gsr_group;
sockaddr_storage gsr_source;
-};
+}
int setipv4sourcefilter(int, in_addr, in_addr, uint, uint, in_addr*);
int getipv4sourcefilter(int, in_addr, in_addr, uint*, uint*, in_addr*);
{
in6_addr ipi6_addr;
uint ipi6_ifindex;
-};
+}
struct ip6_mtuinfo
{
sockaddr_in6 ip6m_addr;
uint ip6m_mtu;
-};
+}
enum IPV6_PORTRANGE_DEFAULT = 0;
enum IPV6_PORTRANGE_HIGH = 1;
int r_version;
link_map* r_map;
void function(r_debug*, link_map*) r_brk;
-};
+}
struct dl_phdr_info
{
uint64_t dlpi_subs;
size_t dlpi_tls_modid;
void* dlpi_tls_data;
-};
+}
private alias int function(dl_phdr_info*, size_t, void *) dl_iterate_phdr_cb;
void *dli_fbase; /* Base address of shared object. */
const(char) *dli_sname; /* Name of nearest symbol. */
void *dli_saddr; /* Address of nearest symbol. */
- };
+ }
/*-
* The actual type declared by this typedef is immaterial, provided that
*/
struct __dlfunc_arg {
int __dlfunc_dummy;
- };
+ }
alias dlfunc_t = void function(__dlfunc_arg);
struct Dl_serpath {
char * dls_name; /* single search path entry */
uint dls_flags; /* path information */
- };
+ }
struct Dl_serinfo {
size_t dls_size; /* total buffer size */
uint dls_cnt; /* number of path entries */
Dl_serpath[1] dls_serpath; /* there may be more than one */
- };
+ }
}
/* XSI functions first. */
--- /dev/null
+/**
+ * D header file for FreeBSD err.h.
+ *
+ * Copyright: Copyright © 2019, The D Language Foundation
+ * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * Authors: Ernesto Castellotti
+ */
+module core.sys.freebsd.err;
+import core.stdc.stdarg : va_list;
+
+version (FreeBSD):
+extern (C):
+nothrow:
+@nogc:
+
+alias ExitFunction = void function(int);
+
+void err(int eval, scope const char* fmt, ...);
+void errc(int eval, int code, scope const char* fmt, ...);
+void errx(int eval, scope const char* fmt, ...);
+void warn(scope const char* fmt, ...);
+void warnc(int code, scope const char* fmt, ...);
+void warnx(scope const char* fmt, ...);
+void verr(int eval, scope const char* fmt, va_list args);
+void verrc(int eval, int code, scope const char* fmt, va_list args);
+void verrx(int eval, scope const char* fmt, va_list args);
+void vwarn(scope const char* fmt, va_list args);
+void vwarnc(int code, scope const char* fmt, va_list args);
+void vwarnx(scope const char* fmt, va_list args);
+void err_set_file(void* vfp);
+void err_set_exit(ExitFunction exitf);
version (GNU)
version = BacktraceExternal;
+version (LDC)
+ version = BacktraceExternal;
version (BacktraceExternal)
{
{
in_addr imr_multiaddr;
in_addr imr_interface;
- };
+ }
struct ip_mreqn
{
in_addr imr_multiaddr;
in_addr imr_address;
int imr_ifindex;
- };
+ }
struct ip_mreq_source
{
in_addr imr_multiaddr;
in_addr imr_sourceaddr;
in_addr imr_interface;
- };
+ }
struct group_req
{
uint gr_interface;
sockaddr_storage gr_group;
- };
+ }
struct group_source_req
{
uint gsr_interface;
sockaddr_storage gsr_group;
sockaddr_storage gsr_source;
- };
+ }
int setipv4sourcefilter(int, in_addr, in_addr, uint, uint, in_addr*);
int getipv4sourcefilter(int, in_addr, in_addr, uint*, uint*, in_addr*);
{
in6_addr ipi6_addr;
uint ipi6_ifindex;
- };
+ }
struct ip6_mtuinfo
{
sockaddr_in6 ip6m_addr;
uint ip6m_mtu;
- };
+ }
enum IPV6_PORTRANGE_DEFAULT = 0;
enum IPV6_PORTRANGE_HIGH = 1;
}
int kqueue();
-int kevent(int kq, const kevent_t *changelist, int nchanges,
- kevent_t *eventlist, int nevents,
- const timespec *timeout);
+
+version (GNU)
+{
+ int kevent(int kq, const kevent_t *changelist, int nchanges,
+ kevent_t *eventlist, int nevents,
+ const timespec *timeout);
+}
+else
+{
+ static if (__FreeBSD_version >= 1200000)
+ pragma(mangle, "kevent@@FBSD_1.5")
+ int kevent(int kq, const kevent_t *changelist, int nchanges,
+ kevent_t *eventlist, int nevents,
+ const timespec *timeout);
+ else
+ pragma(mangle, "kevent@FBSD_1.0")
+ int kevent(int kq, const kevent_t *changelist, int nchanges,
+ kevent_t *eventlist, int nevents,
+ const timespec *timeout);
+}
int r_version;
link_map* r_map;
void function(r_debug*, link_map*) r_brk;
-};
+}
struct dl_phdr_info
{
uint64_t dlpi_subs;
size_t dlpi_tls_modid;
void* dlpi_tls_data;
-};
+}
private alias extern(C) int function(dl_phdr_info*, size_t, void *) dl_iterate_phdr_cb;
enum uint VQ_FLAG4000 = 0x4000;
enum uint VQ_FLAG8000 = 0x8000;
-int fhopen(const fhandle_t*, int);
-int fhstat(const fhandle_t*, stat_t*);
-int fhstatfs(const fhandle_t*, statfs_t*);
-int fstatfs(int, statfs_t*);
-int getfh(const char*, fhandle_t*);
-int getfsstat(statfs_t*, c_long, int);
-int getmntinfo(statfs_t**, int);
-int lgetfh(const char*, fhandle_t*);
-int mount(const char*, const char*, int, void*);
-//int nmount(iovec*, uint, int);
-int statfs(const char*, statfs_t*);
-int unmount(const char*, int);
-
-//int getvfsbyname(const char*, xvfsconf*);
+version (GNU)
+{
+ int fhopen(const fhandle_t*, int);
+ int fhstat(const fhandle_t*, stat_t*);
+ int fhstatfs(const fhandle_t*, statfs_t*);
+ int fstatfs(int, statfs_t*);
+ int getfh(const char*, fhandle_t*);
+ int getfsstat(statfs_t*, c_long, int);
+ int getmntinfo(statfs_t**, int);
+ int lgetfh(const char*, fhandle_t*);
+ int mount(const char*, const char*, int, void*);
+ //int nmount(iovec*, uint, int);
+ int statfs(const char*, statfs_t*);
+ int unmount(const char*, int);
+ //int getvfsbyname(const char*, xvfsconf*);
+}
+else
+{
+ static if (__FreeBSD_version >= 1200000)
+ {
+ pragma(mangle, "fhstat@FBSD_1.5") int fhstat(const fhandle_t*, stat_t*);
+ pragma(mangle, "fhstatfs@FBSD_1.5") int fhstatfs(const fhandle_t*, statfs_t*);
+ pragma(mangle, "fstatfs@FBSD_1.5") int fstatfs(int, statfs_t*);
+ pragma(mangle, "getfsstat@FBSD_1.5") int getfsstat(statfs_t*, c_long, int);
+ pragma(mangle, "getmntinfo@FBSD_1.5") int getmntinfo(statfs_t**, int);
+ pragma(mangle, "statfs@FBSD_1.5") int statfs(const char*, statfs_t*);
+ }
+ else
+ {
+ pragma(mangle, "fhstat@FBSD_1.0") int fhstat(const fhandle_t*, stat_t*);
+ pragma(mangle, "fhstatfs@FBSD_1.0") int fhstatfs(const fhandle_t*, statfs_t*);
+ pragma(mangle, "fstatfs@FBSD_1.0") int fstatfs(int, statfs_t*);
+ pragma(mangle, "getfsstat@FBSD_1.0") int getfsstat(statfs_t*, c_long, int);
+ pragma(mangle, "getmntinfo@FBSD_1.0") int getmntinfo(statfs_t**, int);
+ pragma(mangle, "statfs@FBSD_1.0") int statfs(const char*, statfs_t*);
+ }
+ pragma(mangle, "fhopen@@FBSD_1.0") int fhopen(const fhandle_t*, int);
+ pragma(mangle, "getfh@@FBSD_1.0") int getfh(const char*, fhandle_t*);
+ pragma(mangle, "lgetfh@@FBSD_1.0") int lgetfh(const char*, fhandle_t*);
+ pragma(mangle, "mount@@FBSD_1.0") int mount(const char*, const char*, int, void*);
+ //int nmount(iovec*, uint, int);
+ pragma(mangle, "unmount@@FBSD_1.0") int unmount(const char*, int);
+ //int getvfsbyname(const char*, xvfsconf*);
+}
extern (C):
nothrow:
@nogc:
+@system:
version (ARM) version = ARM_Any;
version (AArch64) version = ARM_Any;
enum LM_ID_NEWLM = -1;
}
-// void* dlopen(in char* __file, int __mode); // POSIX
+// void* dlopen(const scope char* __file, int __mode); // POSIX
// int dlclose(void* __handle); // POSIX
-// void* dlsym(void* __handle, in char* __name); // POSIX
+// void* dlsym(void* __handle, const scope char* __name); // POSIX
static if (__USE_GNU)
{
- void* dlmopen(Lmid_t __nsid, in char* __file, int __mode);
- void* dlvsym(void* __handle, in char* __name, in char* __version);
+ void* dlmopen(Lmid_t __nsid, const scope char* __file, int __mode);
+ void* dlvsym(void* __handle, const scope char* __name, const scope char* __version);
}
// char* dlerror(); // POSIX
void* dli_saddr;
}
- int dladdr(in void* __address, Dl_info* __info);
+ int dladdr(const scope void* __address, Dl_info* __info);
int dladdr1(void* __address, Dl_info* __info, void** __extra_info, int __flags);
enum
extern (C):
pure:
nothrow:
+@system:
import core.stdc.stdint;
enum AT_SYSINFO = 32;
enum AT_SYSINFO_EHDR = 33;
-;
enum AT_L1I_CACHESHAPE = 34;
enum AT_L1D_CACHESHAPE = 35;
enum AT_L2_CACHESHAPE = 36;
@system:
@nogc:
nothrow:
+@system:
version (ARM) version = ARM_Any;
version (AArch64) version = ARM_Any;
--- /dev/null
+/**
+ * D header file for Linux err.h.
+ *
+ * Copyright: Copyright © 2019, The D Language Foundation
+ * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * Authors: Ernesto Castellotti
+ */
+module core.sys.linux.err;
+import core.stdc.stdarg : va_list;
+
+version (linux):
+extern (C):
+nothrow:
+@nogc:
+@system:
+
+void err(int eval, scope const char* fmt, ...);
+void errx(int eval, scope const char* fmt, ...);
+void warn(scope const char* fmt, ...);
+void warnx(scope const char* fmt, ...);
+void verr(int eval, scope const char* fmt, va_list args);
+void verrx(int eval, scope const char* fmt, va_list args);
+void vwarn(scope const char* fmt, va_list args);
+void vwarnx(scope const char* fmt, va_list args);
version (linux):
extern (C):
nothrow:
+@system:
public import core.stdc.errno;
import core.sys.linux.config;
version (linux):
extern (C):
nothrow:
+@system:
+@nogc:
int backtrace(void** buffer, int size);
char** backtrace_symbols(const(void*)* buffer, int size);
version (linux):
extern(C):
nothrow:
+@system:
// From linux/falloc.h
/// fallocate(2) params
extern (C):
nothrow:
@nogc:
+@system:
struct ifaddrs
{
/// Address specific data
void* ifa_data;
-};
+}
/// Returns: linked list of ifaddrs structures describing interfaces
int getifaddrs(ifaddrs** );
version (linux):
extern (C):
nothrow:
+@system:
version (ARM) version = ARM_Any;
version (AArch64) version = ARM_Any;
{
in_addr imr_multiaddr;
in_addr imr_interface;
- };
+ }
struct ip_mreq_source
{
in_addr imr_multiaddr;
in_addr imr_interface;
in_addr imr_sourceaddr;
- };
+ }
struct group_req
{
uint gr_interface;
sockaddr_storage gr_group;
- };
+ }
struct group_source_req
{
uint gsr_interface;
sockaddr_storage gsr_group;
sockaddr_storage gsr_source;
- };
+ }
struct ip_msfilter
{
uint imsf_fmode;
uint imsf_numsrc;
in_addr[1] imsf_slist;
- };
+ }
extern(D) size_t IP_MSFILTER_SIZE(int numsrc)
{
uint gf_fmode;
uint gf_numsrc;
sockaddr_storage[1] gf_slist;
- };
+ }
extern(D) size_t GROUP_FILTER_SIZE(int numsrc) pure @safe
{
{
in6_addr ipi6_addr;
uint ipi6_ifindex;
- };
+ }
struct ip6_mtuinfo
{
sockaddr_in6 ip6m_addr;
uint ip6m_mtu;
- };
+ }
int inet6_opt_init(void* __extbuf, socklen_t __extlen);
int inet6_opt_append(void* __extbuf, socklen_t __extlen, int __offset,
{
in_addr ip_dst;
char[40] ip_opts = 0;
- };
+ }
struct ip_mreqn
{
in_addr imr_multiaddr;
in_addr imr_address;
int imr_ifindex;
- };
+ }
struct in_pktinfo
{
int ipi_ifindex;
in_addr ipi_spec_dst;
in_addr ipi_addr;
- };
+ }
}
enum IPV6_ADDRFORM = 1;
module core.sys.linux.sched;
import core.bitop : popcnt;
+import core.stdc.stdlib : malloc, free;
import core.sys.posix.sched;
import core.sys.posix.config;
import core.sys.posix.sys.types;
extern (C):
@nogc:
nothrow:
+@system:
private // helpers
return 1UL << (cpu % __NCPUBITS);
}
+ cpu_set_t* __CPU_ALLOC(size_t count)
+ {
+ return cast(cpu_set_t*) malloc(__CPU_ALLOC_SIZE(count));
+ }
+
+ size_t __CPU_ALLOC_SIZE(size_t count) pure
+ {
+ return ((count + __NCPUBITS - 1) / __NCPUBITS) * cpu_mask.sizeof;
+ }
+
+ void __CPU_FREE(cpu_set_t* set)
+ {
+ free(cast(void*) set);
+ }
+
cpu_mask __CPU_SET_S(size_t cpu, size_t setsize, cpu_set_t* cpusetp) pure
{
if (cpu < 8 * setsize)
/// Access macros for 'cpu_set' (missing a lot of them)
+cpu_set_t* CPU_ALLOC(size_t count)
+{
+ return __CPU_ALLOC(count);
+}
+
+size_t CPU_ALLOC_SIZE(size_t count) pure
+{
+ return __CPU_ALLOC_SIZE(count);
+}
+
+void CPU_FREE(cpu_set_t* set)
+{
+ __CPU_FREE(set);
+}
+
cpu_mask CPU_SET(size_t cpu, cpu_set_t* cpusetp) pure
{
return __CPU_SET_S(cpu, cpu_set_t.sizeof, cpusetp);
return __CPU_COUNT_S(cpu_set_t.sizeof, cpusetp);
}
+int CPU_COUNT_S(size_t setsize, cpu_set_t* cpusetp) pure
+{
+ return __CPU_COUNT_S(setsize, cpusetp);
+}
+
/* Scheduler control functions */
int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
int clone(int function(void*), void* child_stack, int flags, void* arg, ...);
int unshare(int flags) @trusted;
+version (CRuntime_Glibc)
+{
+ /* Determine CPU on which the calling thread is running */
+ int sched_getcpu();
+}
+
enum CLONE_FILES = 0x400;
enum CLONE_FS = 0x200;
enum CLONE_NEWCGROUP = 0x2000000;
enum CLONE_SIGHAND = 0x800;
enum CLONE_SYSVSEM = 0x40000;
enum CLONE_THREAD = 0x10000;
+enum CLONE_VFORK = 0x4000;
enum CLONE_VM = 0x100;
import core.stdc.stdio : FILE;
import core.stdc.stddef : wchar_t;
+@system:
+
extern(C) nothrow
{
alias ssize_t function(void *cookie, char *buf, size_t size) cookie_read_function_t;
extern (C):
nothrow:
@nogc:
+@system:
static if (__USE_GNU)
{
extern (C):
@system:
nothrow:
+@nogc:
version (ARM) version = ARM_Any;
version (AArch64) version = ARM_Any;
version (linux):
extern (C):
nothrow:
+@system:
+@nogc:
version (ARM) version = ARM_Any;
version (AArch64) version = ARM_Any;
ulong* auxv;
uint auxv_size;
uint exe_fd;
-};
+}
int prctl(int option, size_t arg2, size_t arg3, size_t arg4, size_t arg5);
extern (C):
@system:
nothrow:
+@nogc:
struct signalfd_siginfo
{
module core.sys.linux.sys.sysinfo;
version (linux) extern(C) @nogc nothrow:
+@system:
import core.sys.linux.config;
*/
module core.sys.linux.sys.time;
-private import core.sys.linux.config;
+import core.sys.linux.config;
public import core.sys.posix.sys.time; // timeval
version (linux):
extern (C):
@system:
nothrow:
+@nogc:
enum {
XATTR_CREATE = 1, /* set value, fail if attr already exists. */
enum XATTR_NAME_CAPS = XATTR_SECURITY_PREFIX ~ XATTR_CAPS_SUFFIX;
-int setxattr(in char* path, in char* name, in void* value, size_t size, int flags);
+int setxattr(const scope char* path, const scope char* name, const scope void* value, size_t size, int flags);
-int lsetxattr(in char* path, in char* name, in void* value, size_t size, int flags);
-int fsetxattr(int fd, in char* name, in void* value, size_t size, int flags);
-ssize_t getxattr(in char* path, in char* name, void* value, size_t size);
-ssize_t lgetxattr(in char* path, in char* name, void* value, size_t size);
-ssize_t fgetxattr(int fd, in char* name, void* value, size_t size);
-ssize_t listxattr(in char* path, char* list, size_t size);
-ssize_t llistxattr(in char* path, char* list, size_t size);
+int lsetxattr(const scope char* path, const scope char* name, const scope void* value, size_t size, int flags);
+int fsetxattr(int fd, const scope char* name, const scope void* value, size_t size, int flags);
+ssize_t getxattr(const scope char* path, const scope char* name, void* value, size_t size);
+ssize_t lgetxattr(const scope char* path, const scope char* name, void* value, size_t size);
+ssize_t fgetxattr(int fd, const scope char* name, void* value, size_t size);
+ssize_t listxattr(const scope char* path, char* list, size_t size);
+ssize_t llistxattr(const scope char* path, char* list, size_t size);
ssize_t flistxattr (int __fd, char *list, size_t size);
-int removexattr (in char *path, in char *name);
-int lremovexattr (in char *path, in char *name);
-int fremovexattr (int fd, in char *name);
+int removexattr (const scope char *path, const scope char *name);
+int lremovexattr (const scope char *path, const scope char *name);
+int fremovexattr (int fd, const scope char *name);
version (linux):
extern (C) nothrow @nogc:
+@system:
struct tipc_portid
{
version (linux):
extern(C):
nothrow:
+@system:
// Additional seek constants for sparse file handling
// from Linux's unistd.h, stdio.h, and linux/fs.h
/// Prompt for a password without echoing it.
char* getpass(const(char)* prompt);
+
+// Exit all threads in a process
+void exit_group(int status);
void *dli_fbase; /* Base address of shared object. */
const(char) *dli_sname; /* Name of nearest symbol. */
void *dli_saddr; /* Address of nearest symbol. */
- };
+ }
/*-
* The actual type declared by this typedef is immaterial, provided that
*/
struct __dlfunc_arg {
int __dlfunc_dummy;
- };
+ }
alias dlfunc_t = void function(__dlfunc_arg);
struct Dl_serpath {
char * dls_name; /* single search path entry */
uint dls_flags; /* path information */
- };
+ }
struct Dl_serinfo {
size_t dls_size; /* total buffer size */
uint dls_cnt; /* number of path entries */
Dl_serpath[1] dls_serpath; /* there may be more than one */
- };
+ }
}
private template __externC(RT, P...)
--- /dev/null
+/**
+ * D header file for NetBSD err.h.
+ *
+ * Copyright: Copyright © 2019, The D Language Foundation
+ * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * Authors: Ernesto Castellotti
+ */
+module core.sys.netbsd.err;
+import core.stdc.stdarg : va_list;
+
+version (NetBSD):
+extern (C):
+nothrow:
+@nogc:
+
+void err(int eval, scope const char* fmt, ...);
+void errc(int eval, int code, scope const char* fmt, ...);
+void errx(int eval, scope const char* fmt, ...);
+void warn(scope const char* fmt, ...);
+void warnc(int code, scope const char* fmt, ...);
+void warnx(scope const char* fmt, ...);
+void verr(int eval, scope const char* fmt, va_list args);
+void verrc(int eval, int code, scope const char* fmt, va_list args);
+void verrx(int eval, scope const char* fmt, va_list args);
+void vwarn(scope const char* fmt, va_list args);
+void vwarnc(int code, scope const char* fmt, va_list args);
+void vwarnx(scope const char* fmt, va_list args);
int r_version;
link_map* r_map;
void function(r_debug*, link_map*) r_brk;
-};
+}
struct dl_phdr_info
{
uint64_t dlpi_subs;
size_t dlpi_tls_modid;
void* dlpi_tls_data;
-};
+}
private alias extern(C) int function(dl_phdr_info*, size_t, void *) dl_iterate_phdr_cb;
--- /dev/null
+/**
+ * D header file for OpenBSD err.h.
+ *
+ * Copyright: Copyright © 2019, The D Language Foundation
+ * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * Authors: Ernesto Castellotti
+ */
+module core.sys.openbsd.err;
+import core.stdc.stdarg : va_list;
+
+version (OpenBSD):
+extern (C):
+nothrow:
+@nogc:
+
+void err(int eval, scope const char* fmt, ...);
+void errc(int eval, int code, scope const char* fmt, ...);
+void errx(int eval, scope const char* fmt, ...);
+void warn(scope const char* fmt, ...);
+void warnc(int code, scope const char* fmt, ...);
+void warnx(scope const char* fmt, ...);
+void verr(int eval, scope const char* fmt, va_list args);
+void verrc(int eval, int code, scope const char* fmt, va_list args);
+void verrx(int eval, scope const char* fmt, va_list args);
+void vwarn(scope const char* fmt, va_list args);
+void vwarnc(int code, scope const char* fmt, va_list args);
+void vwarnx(scope const char* fmt, va_list args);
char* dlpi_name;
ElfW!"Phdr"* dlpi_phdr;
ElfW!"Half" dlpi_phnum;
-};
+}
private alias int function(dl_phdr_info*, size_t, void *) dl_iterate_phdr_cb;
*/
module core.sys.posix.aio;
-private import core.sys.posix.signal;
-private import core.sys.posix.sys.types;
+import core.sys.posix.signal;
+import core.sys.posix.sys.types;
version (OSX)
version = Darwin;
*/
module core.sys.posix.arpa.inet;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.stdc.inttypes; // for uint32_t, uint16_t
public import core.sys.posix.sys.socket; // for socklen_t
uint32_t ntohl(uint32_t);
uint16_t ntohs(uint16_t);
-in_addr_t inet_addr(in char*);
+in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
// per spec: const char* inet_ntop(int, const void*, char*, socklen_t);
-char* inet_ntop(int, in void*, char*, socklen_t);
-int inet_pton(int, in char*, void*);
+char* inet_ntop(int, const scope void*, char*, socklen_t);
+int inet_pton(int, const scope char*, void*);
*/
version (CRuntime_Glibc)
uint16_t ntohs(uint16_t);
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, socklen_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, socklen_t);
+ int inet_pton(int, const scope char*, void*);
}
else version (Darwin)
{
uint16_t ntohs(uint16_t);
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, socklen_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, socklen_t);
+ int inet_pton(int, const scope char*, void*);
}
else version (FreeBSD)
{
uint16_t ntohs(uint16_t);
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, socklen_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, socklen_t);
+ int inet_pton(int, const scope char*, void*);
}
else version (NetBSD)
{
uint16_t ntohs(uint16_t);
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, socklen_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, socklen_t);
+ int inet_pton(int, const scope char*, void*);
}
else version (OpenBSD)
{
uint16_t ntohs(uint16_t x) { return __swap16(x); }
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, socklen_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, socklen_t);
+ int inet_pton(int, const scope char*, void*);
}
else version (DragonFlyBSD)
{
uint16_t ntohs(uint16_t);
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, socklen_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, socklen_t);
+ int inet_pton(int, const scope char*, void*);
}
else version (Solaris)
{
uint16_t ntohs(uint16_t);
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, socklen_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, socklen_t);
+ int inet_pton(int, const scope char*, void*);
}
else version (CRuntime_Bionic)
{
uint16_t ntohs(uint16_t x) { return __swap16(x); }
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, size_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, size_t);
+ int inet_pton(int, const scope char*, void*);
}
else version (CRuntime_Musl)
{
uint16_t ntohs(uint16_t);
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, socklen_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, socklen_t);
+ int inet_pton(int, const scope char*, void*);
}
else version (CRuntime_UClibc)
{
uint16_t ntohs(uint16_t);
}
- in_addr_t inet_addr(in char*);
+ in_addr_t inet_addr(const scope char*);
char* inet_ntoa(in_addr);
- const(char)* inet_ntop(int, in void*, char*, socklen_t);
- int inet_pton(int, in char*, void*);
+ const(char)* inet_ntop(int, const scope void*, char*, socklen_t);
+ int inet_pton(int, const scope char*, void*);
}
//
version (Posix):
extern (C) nothrow @nogc:
+@system:
enum _XOPEN_SOURCE = 600;
enum _POSIX_SOURCE = true;
*/
module core.sys.posix.dirent;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for ino_t
version (OSX)
extern (C):
nothrow:
@nogc:
+@system:
//
// Required
}
int closedir(DIR*);
-DIR* opendir(in char*);
+DIR* opendir(const scope char*);
dirent* readdir(DIR*);
void rewinddir(DIR*);
*/
// Other Darwin variants (iOS, TVOS, WatchOS) only support 64-bit inodes,
// no suffix needed
version (OSX)
- pragma(mangle, "readdir$INODE64") dirent* readdir(DIR*);
+ {
+ version (AArch64)
+ dirent* readdir(DIR*);
+ else
+ pragma(mangle, "readdir$INODE64") dirent* readdir(DIR*);
+ }
else
dirent* readdir(DIR*);
}
alias void* DIR;
- dirent* readdir(DIR*);
+ version (GNU)
+ {
+ dirent* readdir(DIR*);
+ }
+ else
+ {
+ static if (__FreeBSD_version >= 1200000)
+ pragma(mangle, "readdir@FBSD_1.5") dirent* readdir(DIR*);
+ else
+ pragma(mangle, "readdir@FBSD_1.0") dirent* readdir(DIR*);
+ }
}
else version (NetBSD)
{
// in else below.
version (OSX)
{
- version (D_LP64)
+ version (AArch64)
+ {
+ int closedir(DIR*);
+ DIR* opendir(const scope char*);
+ void rewinddir(DIR*);
+ }
+ else version (D_LP64)
{
int closedir(DIR*);
- pragma(mangle, "opendir$INODE64") DIR* opendir(in char*);
+ pragma(mangle, "opendir$INODE64") DIR* opendir(const scope char*);
pragma(mangle, "rewinddir$INODE64") void rewinddir(DIR*);
}
else
// 32-bit mangles __DARWIN_UNIX03 specific functions with $UNIX2003 to
// maintain backward compatibility with binaries build pre 10.5
pragma(mangle, "closedir$UNIX2003") int closedir(DIR*);
- pragma(mangle, "opendir$INODE64$UNIX2003") DIR* opendir(in char*);
+ pragma(mangle, "opendir$INODE64$UNIX2003") DIR* opendir(const scope char*);
pragma(mangle, "rewinddir$INODE64$UNIX2003") void rewinddir(DIR*);
}
}
else version (NetBSD)
{
int closedir(DIR*);
- DIR* __opendir30(in char*);
+ DIR* __opendir30(const scope char*);
alias __opendir30 opendir;
void rewinddir(DIR*);
}
else
{
int closedir(DIR*);
- DIR* opendir(in char*);
+ DIR* opendir(const scope char*);
//dirent* readdir(DIR*);
void rewinddir(DIR*);
}
}
else version (FreeBSD)
{
- int readdir_r(DIR*, dirent*, dirent**);
+ version (GNU)
+ {
+ int readdir_r(DIR*, dirent*, dirent**);
+ }
+ else
+ {
+ static if (__FreeBSD_version >= 1200000)
+ pragma(mangle, "readdir_r@FBSD_1.5") int readdir_r(DIR*, dirent*, dirent**);
+ else
+ pragma(mangle, "readdir_r@FBSD_1.0") int readdir_r(DIR*, dirent*, dirent**);
+ }
}
else version (DragonFlyBSD)
{
}
else version (FreeBSD)
{
- void seekdir(DIR*, c_long);
- c_long telldir(DIR*);
+ version (GNU)
+ {
+ void seekdir(DIR*, c_long);
+ c_long telldir(DIR*);
+ }
+ else
+ {
+ pragma(mangle, "seekdir@@FBSD_1.0") void seekdir(DIR*, c_long);
+ pragma(mangle, "telldir@@FBSD_1.0") c_long telldir(DIR*);
+ }
}
else version (NetBSD)
{
*/
module core.sys.posix.dlfcn;
-private import core.sys.posix.config;
+import core.sys.posix.config;
version (OSX)
version = Darwin;
extern (C):
nothrow:
@nogc:
+@system:
//
// XOpen (XSI)
int dlclose(void*);
char* dlerror();
-void* dlopen(in char*, int);
-void* dlsym(void*, in char*);
+void* dlopen(const scope char*, int);
+void* dlsym(void*, const scope char*);
*/
version (CRuntime_Glibc)
int dlclose(void*);
char* dlerror();
- void* dlopen(in char*, int);
- void* dlsym(void*, in char*);
+ void* dlopen(const scope char*, int);
+ void* dlsym(void*, const scope char*);
}
else version (Darwin)
{
int dlclose(void*);
char* dlerror();
- void* dlopen(in char*, int);
- void* dlsym(void*, in char*);
+ void* dlopen(const scope char*, int);
+ void* dlsym(void*, const scope char*);
int dladdr(void* addr, Dl_info* info);
struct Dl_info
int dlclose(void*);
char* dlerror();
- void* dlopen(in char*, int);
- void* dlsym(void*, in char*);
+ void* dlopen(const scope char*, int);
+ void* dlsym(void*, const scope char*);
int dladdr(const(void)* addr, Dl_info* info);
struct Dl_info
int dlclose(void*);
char* dlerror();
- void* dlopen(in char*, int);
- void* dlsym(void*, in char*);
+ void* dlopen(const scope char*, int);
+ void* dlsym(void*, const scope char*);
int dladdr(const(void)* addr, Dl_info* info);
struct Dl_info
int dlclose(void*);
char* dlerror();
- void* dlopen(in char*, int);
- void* dlsym(void*, in char*);
+ void* dlopen(const scope char*, int);
+ void* dlsym(void*, const scope char*);
int dladdr(const(void)* addr, Dl_info* info);
struct Dl_info
int dlclose(void*);
char* dlerror();
- void* dlopen(in char*, int);
- void* dlsym(void*, in char*);
+ void* dlopen(const scope char*, int);
+ void* dlsym(void*, const scope char*);
int dladdr(const(void)* addr, Dl_info* info);
struct Dl_info
RTLD_GLOBAL = 2
}
- int dladdr(in void*, Dl_info*);
+ int dladdr(const scope void*, Dl_info*);
int dlclose(void*);
const(char)* dlerror();
- void* dlopen(in char*, int);
- void* dlsym(void*, in char*);
+ void* dlopen(const scope char*, int);
+ void* dlsym(void*, const scope char*);
struct Dl_info
{
}
int dlclose(void*);
const(char)* dlerror();
- void* dlopen(in char*, int);
- void* dlsym(void*, in char*);
+ void* dlopen(const scope char*, int);
+ void* dlsym(void*, const scope char*);
}
else version (CRuntime_UClibc)
{
int dlclose(void*);
char* dlerror();
- void* dlopen(in char*, int);
- void* dlsym(void*, in char*);
+ void* dlopen(const scope char*, int);
+ void* dlsym(void*, const scope char*);
}
*/
module core.sys.posix.fcntl;
-private import core.sys.posix.config;
-private import core.stdc.stdint;
+import core.sys.posix.config;
+import core.stdc.stdint;
public import core.sys.posix.sys.types; // for off_t, mode_t
public import core.sys.posix.sys.stat; // for S_IFMT, etc.
nothrow:
@nogc:
+@system:
//
// Required
pid_t l_pid;
}
-int creat(in char*, mode_t);
+int creat(const scope char*, mode_t);
int fcntl(int, int, ...);
-int open(in char*, int, ...);
+int open(const scope char*, int, ...);
*/
version (CRuntime_Glibc)
{
static if ( __USE_FILE_OFFSET64 )
{
- int creat64(in char*, mode_t);
+ int creat64(const scope char*, mode_t);
alias creat64 creat;
- int open64(in char*, int, ...);
+ int open64(const scope char*, int, ...);
alias open64 open;
}
else
{
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
}
enum AT_SYMLINK_NOFOLLOW = 0x100;
short l_whence;
}
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
}
else version (FreeBSD)
{
short l_whence;
}
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
enum AT_SYMLINK_NOFOLLOW = 0x200;
enum AT_FDCWD = -100;
short l_whence;
}
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
enum AT_FDCWD = -100;
}
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
}
else version (DragonFlyBSD)
{
alias oflock = flock;
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
//int fcntl(int, int, ...); /*defined below*/
//int flock(int, int);
}
version (D_LP64)
{
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
static if (__USE_LARGEFILE64)
{
{
static if (__USE_LARGEFILE64)
{
- int creat64(in char*, mode_t);
+ int creat64(const scope char*, mode_t);
alias creat64 creat;
- int open64(in char*, int, ...);
+ int open64(const scope char*, int, ...);
alias open64 open;
}
else
{
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
}
}
}
pid_t l_pid;
}
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
enum AT_FDCWD = -100;
}
pid_t l_pid;
}
enum FD_CLOEXEC = 1;
- int open(in char*, int, ...);
+ int open(const scope char*, int, ...);
enum AT_FDCWD = -100;
+ enum AT_SYMLINK_NOFOLLOW = 0x100;
+ enum AT_REMOVEDIR = 0x200;
+ enum AT_SYMLINK_FOLLOW = 0x400;
+ enum AT_EACCESS = 0x200;
}
else version (CRuntime_UClibc)
{
static if ( __USE_FILE_OFFSET64 )
{
- int creat64(in char*, mode_t);
+ int creat64(const scope char*, mode_t);
alias creat64 creat;
- int open64(in char*, int, ...);
+ int open64(const scope char*, int, ...);
alias open64 open;
}
else
{
- int creat(in char*, mode_t);
- int open(in char*, int, ...);
+ int creat(const scope char*, mode_t);
+ int open(const scope char*, int, ...);
}
enum AT_SYMLINK_NOFOLLOW = 0x100;
static assert(false, "Unsupported platform");
}
-//int creat(in char*, mode_t);
+//int creat(const scope char*, mode_t);
int fcntl(int, int, ...);
-//int open(in char*, int, ...);
+//int open(const scope char*, int, ...);
// Generic Posix fallocate
int posix_fallocate(int, off_t, off_t);
*/
module core.sys.posix.grp;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for gid_t, uid_t
version (OSX)
extern (C):
nothrow:
@nogc:
+@system:
//
// Required
char** gr_mem;
}
-group* getgrnam(in char*);
+group* getgrnam(const scope char*);
group* getgrgid(gid_t);
*/
static assert(false, "Unsupported platform");
}
-group* getgrnam(in char*);
+group* getgrnam(const scope char*);
group* getgrgid(gid_t);
//
// Thread-Safe Functions (TSF)
//
/*
-int getgrnam_r(in char*, group*, char*, size_t, group**);
+int getgrnam_r(const scope char*, group*, char*, size_t, group**);
int getgrgid_r(gid_t, group*, char*, size_t, group**);
*/
version (CRuntime_Glibc)
{
- int getgrnam_r(in char*, group*, char*, size_t, group**);
+ int getgrnam_r(const scope char*, group*, char*, size_t, group**);
int getgrgid_r(gid_t, group*, char*, size_t, group**);
}
else version (Darwin)
{
- int getgrnam_r(in char*, group*, char*, size_t, group**);
+ int getgrnam_r(const scope char*, group*, char*, size_t, group**);
int getgrgid_r(gid_t, group*, char*, size_t, group**);
}
else version (FreeBSD)
{
- int getgrnam_r(in char*, group*, char*, size_t, group**);
+ int getgrnam_r(const scope char*, group*, char*, size_t, group**);
int getgrgid_r(gid_t, group*, char*, size_t, group**);
}
else version (NetBSD)
{
- int getgrnam_r(in char*, group*, char*, size_t, group**);
+ int getgrnam_r(const scope char*, group*, char*, size_t, group**);
int getgrgid_r(gid_t, group*, char*, size_t, group**);
}
else version (OpenBSD)
{
- int getgrnam_r(in char*, group*, char*, size_t, group**);
+ int getgrnam_r(const scope char*, group*, char*, size_t, group**);
int getgrgid_r(gid_t, group*, char*, size_t, group**);
}
else version (DragonFlyBSD)
{
- int getgrnam_r(in char*, group*, char*, size_t, group**);
+ int getgrnam_r(const scope char*, group*, char*, size_t, group**);
int getgrgid_r(gid_t, group*, char*, size_t, group**);
}
else version (Solaris)
{
- int getgrnam_r(in char*, group*, char*, int, group**);
+ int getgrnam_r(const scope char*, group*, char*, int, group**);
int getgrgid_r(gid_t, group*, char*, int, group**);
}
else version (CRuntime_Bionic)
}
else version (CRuntime_UClibc)
{
- int getgrnam_r(in char*, group*, char*, size_t, group**);
+ int getgrnam_r(const scope char*, group*, char*, size_t, group**);
int getgrgid_r(gid_t, group*, char*, size_t, group**);
}
else version (CRuntime_Musl)
{
- int getgrnam_r(in char*, group*, char*, size_t, group**);
+ int getgrnam_r(const scope char*, group*, char*, size_t, group**);
int getgrgid_r(gid_t, group*, char*, size_t, group**);
}
else
extern (C):
nothrow:
@nogc:
+@system:
alias void* iconv_t;
/// Allocate descriptor for code conversion from codeset FROMCODE to
/// codeset TOCODE.
-iconv_t iconv_open (in char* tocode, in char* fromcode);
+iconv_t iconv_open (const scope char* tocode, const scope char* fromcode);
/// Convert at most *INBYTESLEFT bytes from *INBUF according to the
/// code conversion algorithm specified by CD and place up to
/// *OUTBYTESLEFT bytes in buffer at *OUTBUF.
-size_t iconv (iconv_t cd, in char** inbuf,
+size_t iconv (iconv_t cd, const scope char** inbuf,
size_t* inbytesleft,
char** outbuf,
size_t* outbytesleft);
*/
module core.sys.posix.inttypes;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.stdc.inttypes;
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// Required
/*
intmax_t imaxabs(intmax_t);
imaxdiv_t imaxdiv(intmax_t, intmax_t);
-intmax_t strtoimax(in char*, char**, int);
-uintmax_t strtoumax(in char*, char**, int);
-intmax_t wcstoimax(in wchar_t*, wchar_t**, int);
-uintmax_t wcstoumax(in wchar_t*, wchar_t**, int);
+intmax_t strtoimax(const scope char*, char**, int);
+uintmax_t strtoumax(const scope char*, char**, int);
+intmax_t wcstoimax(const scope wchar_t*, wchar_t**, int);
+uintmax_t wcstoumax(const scope wchar_t*, wchar_t**, int);
*/
intmax_t imaxabs(intmax_t);
imaxdiv_t imaxdiv(intmax_t, intmax_t);
-intmax_t strtoimax(in char*, char**, int);
-uintmax_t strtoumax(in char*, char**, int);
-intmax_t wcstoimax(in wchar_t*, wchar_t**, int);
-uintmax_t wcstoumax(in wchar_t*, wchar_t**, int);
+intmax_t strtoimax(const scope char*, char**, int);
+uintmax_t strtoumax(const scope char*, char**, int);
+intmax_t wcstoimax(const scope wchar_t*, wchar_t**, int);
+uintmax_t wcstoumax(const scope wchar_t*, wchar_t**, int);
module core.sys.posix.libgen;
@nogc nothrow:
+@system:
extern (C):
version (Posix):
--- /dev/null
+/**
+ * D header file for POSIX's <locale.h>.
+ *
+ * See_Also: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/locale.h.html
+ * Copyright: D Language Foundation, 2019
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Authors: Mathias 'Geod24' Lang
+ * Standards: The Open Group Base Specifications Issue 7, 2018 edition
+ * Source: $(DRUNTIMESRC core/sys/posix/_locale.d)
+ */
+module core.sys.posix.locale;
+
+version (Posix):
+extern(C):
+@system:
+nothrow:
+@nogc:
+
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
+version (Darwin)
+ version = DarwinBSDLocale;
+version (FreeBSD)
+ version = DarwinBSDLocale;
+version (NetBSD)
+ version = DarwinBSDLocale;
+version (DragonflyBSD)
+ version = DarwinBSDLocale;
+
+///
+struct lconv
+{
+ char* currency_symbol;
+ char* decimal_point;
+ char frac_digits;
+ char* grouping;
+ char* int_curr_symbol;
+ char int_frac_digits;
+ char int_n_cs_precedes;
+ char int_n_sep_by_space;
+ char int_n_sign_posn;
+ char int_p_cs_precedes;
+ char int_p_sep_by_space;
+ char int_p_sign_posn;
+ char* mon_decimal_point;
+ char* mon_grouping;
+ char* mon_thousands_sep;
+ char* negative_sign;
+ char n_cs_precedes;
+ char n_sep_by_space;
+ char n_sign_posn;
+ char* positive_sign;
+ char p_cs_precedes;
+ char p_sep_by_space;
+ char p_sign_posn;
+ char* thousands_sep;
+}
+
+/// Duplicate existing locale
+locale_t duplocale(locale_t locale);
+/// Free an allocated locale
+void freelocale(locale_t locale);
+/// Natural language formatting for C
+lconv* localeconv();
+/// Create a new locale
+locale_t newlocale(int mask, const char* locale, locale_t base);
+/// Set the C library's notion of natural language formatting style
+char* setlocale(int category, const char* locale);
+/// Set the per-thread locale
+locale_t uselocale (locale_t locale);
+
+version (DarwinBSDLocale)
+{
+ ///
+ enum
+ {
+ LC_ALL = 0,
+ LC_COLLATE = 1,
+ LC_CTYPE = 2,
+ LC_MESSAGES = 6,
+ LC_MONETARY = 3,
+ LC_NUMERIC = 4,
+ LC_TIME = 5,
+ }
+
+ private struct _xlocale;
+
+ ///
+ alias locale_t = _xlocale*;
+
+ version (NetBSD)
+ enum LC_ALL_MASK = (cast(int)~0);
+ else
+ enum LC_ALL_MASK = (
+ LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK |
+ LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK);
+
+
+ ///
+ enum
+ {
+ LC_COLLATE_MASK = (1 << 0),
+ LC_CTYPE_MASK = (1 << 1),
+ LC_MESSAGES_MASK = (1 << 2),
+ LC_MONETARY_MASK = (1 << 3),
+ LC_NUMERIC_MASK = (1 << 4),
+ LC_TIME_MASK = (1 << 5),
+ }
+
+ ///
+ enum LC_GLOBAL_LOCALE = (cast(locale_t)-1);
+}
+
+version (linux)
+{
+ ///
+ enum
+ {
+ LC_ALL = 6,
+ LC_COLLATE = 3,
+ LC_CTYPE = 0,
+ LC_MESSAGES = 5,
+ LC_MONETARY = 4,
+ LC_NUMERIC = 1,
+ LC_TIME = 2,
+
+ // Linux-specific
+ LC_PAPER = 7,
+ LC_NAME = 8,
+ LC_ADDRESS = 9,
+ LC_TELEPHONE = 10,
+ LC_MEASUREMENT = 11,
+ LC_IDENTIFICATION = 12,
+ }
+
+ ///
+ enum
+ {
+ LC_ALL_MASK = (LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK |
+ LC_COLLATE_MASK | LC_MONETARY_MASK | LC_MESSAGES_MASK |
+ LC_PAPER_MASK | LC_NAME_MASK | LC_ADDRESS_MASK |
+ LC_TELEPHONE_MASK | LC_MEASUREMENT_MASK |
+ LC_IDENTIFICATION_MASK),
+
+ LC_COLLATE_MASK = (1 << LC_COLLATE),
+ LC_CTYPE_MASK = (1 << LC_CTYPE),
+ LC_MESSAGES_MASK = (1 << LC_MESSAGES),
+ LC_MONETARY_MASK = (1 << LC_MONETARY),
+ LC_NUMERIC_MASK = (1 << LC_NUMERIC),
+ LC_TIME_MASK = (1 << LC_TIME),
+
+ // Linux specific
+ LC_PAPER_MASK = (1 << LC_PAPER),
+ LC_NAME_MASK = (1 << LC_NAME),
+ LC_ADDRESS_MASK = (1 << LC_ADDRESS),
+ LC_TELEPHONE_MASK = (1 << LC_TELEPHONE),
+ LC_MEASUREMENT_MASK = (1 << LC_MEASUREMENT),
+ LC_IDENTIFICATION_MASK = (1 << LC_IDENTIFICATION),
+ }
+
+ private struct __locale_struct;
+
+ ///
+ alias locale_t = __locale_struct*;
+
+ ///
+ enum LC_GLOBAL_LOCALE = (cast(locale_t)-1);
+}
version (CRuntime_Glibc):
extern (C):
@nogc nothrow:
+@system:
/// Message queue descriptor.
*/
module core.sys.posix.net.if_;
-private import core.sys.posix.config;
+import core.sys.posix.config;
version (OSX)
version = Darwin;
IF_NAMESIZE
-uint if_nametoindex(in char*);
+uint if_nametoindex(const scope char*);
char* if_indextoname(uint, char*);
if_nameindex_t* if_nameindex();
void if_freenameindex(if_nameindex_t*);
enum IF_NAMESIZE = 16;
- uint if_nametoindex(in char*);
+ uint if_nametoindex(const scope char*);
char* if_indextoname(uint, char*);
if_nameindex_t* if_nameindex();
void if_freenameindex(if_nameindex_t*);
enum IF_NAMESIZE = 16;
- uint if_nametoindex(in char*);
+ uint if_nametoindex(const scope char*);
char* if_indextoname(uint, char*);
if_nameindex_t* if_nameindex();
void if_freenameindex(if_nameindex_t*);
enum IF_NAMESIZE = 16;
- uint if_nametoindex(in char*);
+ uint if_nametoindex(const scope char*);
char* if_indextoname(uint, char*);
if_nameindex_t* if_nameindex();
void if_freenameindex(if_nameindex_t*);
enum IF_NAMESIZE = 16;
- uint if_nametoindex(in char*);
+ uint if_nametoindex(const scope char*);
char* if_indextoname(uint, char*);
if_nameindex_t* if_nameindex();
void if_freenameindex(if_nameindex_t*);
enum IF_NAMESIZE = 16;
- uint if_nametoindex(in char*);
+ uint if_nametoindex(const scope char*);
char* if_indextoname(uint, char*);
if_nameindex_t* if_nameindex();
void if_freenameindex(if_nameindex_t*);
enum IF_NAMESIZE = 16;
- uint if_nametoindex(in char*);
+ uint if_nametoindex(const scope char*);
char* if_indextoname(uint, char*);
if_nameindex_t* if_nameindex();
void if_freenameindex(if_nameindex_t*);
{
enum IF_NAMESIZE = 16;
- uint if_nametoindex(in char*);
+ uint if_nametoindex(const scope char*);
char* if_indextoname(uint, char*);
}
else version (CRuntime_UClibc)
enum IF_NAMESIZE = 16;
- uint if_nametoindex(in char*);
+ uint if_nametoindex(const scope char*);
char* if_indextoname(uint, char*);
if_nameindex_t* if_nameindex();
void if_freenameindex(if_nameindex_t*);
*/
module core.sys.posix.netdb;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.stdc.inttypes; // for uint32_t
public import core.sys.posix.netinet.in_; // for in_port_t, in_addr_t
public import core.sys.posix.sys.types; // for ino_t
extern (C):
nothrow:
@nogc:
+@system:
//
// Required
*/
module core.sys.posix.netinet.in_;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.stdc.inttypes; // for uint32_t, uint16_t, uint8_t
public import core.sys.posix.arpa.inet;
public import core.sys.posix.sys.socket; // for sa_family_t
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xff;
}
- extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( in in6_addr* a ) pure
+ extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure
{
return a.s6_addr[1] & 0x0f;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL;
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xff;
}
- extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( in in6_addr* a ) pure
+ extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure
{
return a.s6_addr[1] & 0x0f;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL;
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xff;
}
- extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( in in6_addr* a ) pure
+ extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure
{
return a.s6_addr[1] & 0x0f;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL;
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
{
return a.s6_addr[0] == 0xff;
}
- extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( in in6_addr* a ) pure
+ extern (D) uint8_t __IPV6_ADDR_MC_SCOPE( const scope in6_addr* a ) pure
{
return a.s6_addr[1] & 0x0f;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
{
return IN6_IS_ADDR_MULTICAST(a) &&
__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL;
}
// macros
- extern (D) int IN6_IS_ADDR_UNSPECIFIED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a ) pure
{
return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) &&
(a.s6_addr32[2] == 0) && (a.s6_addr32[3] == 0);
}
- extern (D) int IN6_IS_ADDR_LOOPBACK( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a ) pure
{
return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) &&
(a.s6_addr32[2] == 0) && (a.s6_addr32[3] == ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4COMPAT( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a ) pure
{
return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) &&
(a.s6_addr32[2] == 0) && (a.s6_addr32[3] != 0) &&
(a.s6_addr32[3] != ntohl(1));
}
- extern (D) int IN6_IS_ADDR_V4MAPPED( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a ) pure
{
return (a.s6_addr32[0] == 0) && (a.s6_addr32[1] == 0) &&
(a.s6_addr32[2] == ntohl(0x0000ffff));
}
- extern (D) int IN6_IS_ADDR_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr8[0] == 0xfe && (a.s6_addr8[1] & 0xc0) == 0x80;
}
- extern (D) int IN6_IS_ADDR_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr8[0] == 0xfe && (a.s6_addr8[1] & 0xc0) == 0xc0;
}
- extern (D) int IN6_IS_ADDR_MULTICAST( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MULTICAST( const scope in6_addr* a ) pure
{
return a.s6_addr8[0] == 0xff;
}
- extern (D) int IN6_IS_ADDR_MC_NODELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x01;
}
- extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x02;
}
- extern (D) int IN6_IS_ADDR_MC_SITELOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x05;
}
- extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a ) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x08;
}
- extern (D) int IN6_IS_ADDR_MC_GLOBAL( in in6_addr* a ) pure
+ extern (D) int IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a ) pure
{
return a.s6_addr8[0] == 0xff && (a.s6_addr8[1] & 0x0f) == 0x0e;
}
extern (D) pure
{
- bool IN6_IS_ADDR_UNSPECIFIED( in in6_addr* a )
+ bool IN6_IS_ADDR_UNSPECIFIED( const scope in6_addr* a )
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == 0);
}
- bool IN6_IS_ADDR_LOOPBACK( in in6_addr* a )
+ bool IN6_IS_ADDR_LOOPBACK( const scope in6_addr* a )
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) == ntohl(1));
}
- bool IN6_IS_ADDR_V4COMPAT( in in6_addr* a )
+ bool IN6_IS_ADDR_V4COMPAT( const scope in6_addr* a )
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[12]) != ntohl(1));
}
- bool IN6_IS_ADDR_V4MAPPED( in in6_addr* a )
+ bool IN6_IS_ADDR_V4MAPPED( const scope in6_addr* a )
{
return (*cast(const uint32_t*) cast(const void*) (&a.s6_addr[0]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[4]) == 0) &&
(*cast(const uint32_t*) cast(const void*) (&a.s6_addr[8]) == ntohl(0x0000ffff));
}
- bool IN6_IS_ADDR_LINKLOCAL( in in6_addr* a )
+ bool IN6_IS_ADDR_LINKLOCAL( const scope in6_addr* a )
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0x80;
}
- bool IN6_IS_ADDR_SITELOCAL( in in6_addr* a )
+ bool IN6_IS_ADDR_SITELOCAL( const scope in6_addr* a )
{
return a.s6_addr[0] == 0xfe && (a.s6_addr[1] & 0xc0) == 0xc0;
}
- bool IN6_IS_ADDR_ULA( in in6_addr* a )
+ bool IN6_IS_ADDR_ULA( const scope in6_addr* a )
{
return (a.s6_addr[0] & 0xfe) == 0xfc;
}
- bool IN6_IS_ADDR_MULTICAST( in in6_addr* a )
+ bool IN6_IS_ADDR_MULTICAST( const scope in6_addr* a )
{
return a.s6_addr[0] == 0xff;
}
- uint8_t IPV6_ADDR_MC_SCOPE( in in6_addr* a )
+ uint8_t IPV6_ADDR_MC_SCOPE( const scope in6_addr* a )
{
return a.s6_addr[1] & 0x0f;
}
- bool IN6_IS_ADDR_MC_NODELOCAL( in in6_addr* a )
+ bool IN6_IS_ADDR_MC_NODELOCAL( const scope in6_addr* a )
{
return IN6_IS_ADDR_MULTICAST(a) &&
IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_NODELOCAL;
}
- bool IN6_IS_ADDR_MC_LINKLOCAL( in in6_addr* a )
+ bool IN6_IS_ADDR_MC_LINKLOCAL( const scope in6_addr* a )
{
return IN6_IS_ADDR_MULTICAST(a) &&
IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_LINKLOCAL;
}
- bool IN6_IS_ADDR_MC_SITELOCAL( in in6_addr* a )
+ bool IN6_IS_ADDR_MC_SITELOCAL( const scope in6_addr* a )
{
return IN6_IS_ADDR_MULTICAST(a) &&
IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_SITELOCAL;
}
- bool IN6_IS_ADDR_MC_ORGLOCAL( in in6_addr* a )
+ bool IN6_IS_ADDR_MC_ORGLOCAL( const scope in6_addr* a )
{
return IN6_IS_ADDR_MULTICAST(a) &&
IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_ORGLOCAL;
}
- bool IN6_IS_ADDR_MC_GLOBAL( in in6_addr* a )
+ bool IN6_IS_ADDR_MC_GLOBAL( const scope in6_addr* a )
{
return IN6_IS_ADDR_MULTICAST(a) &&
IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_GLOBAL;
*/
module core.sys.posix.netinet.tcp;
-private import core.sys.posix.config;
+import core.sys.posix.config;
version (OSX)
version = Darwin;
*/
module core.sys.posix.poll;
-private import core.sys.posix.config;
+import core.sys.posix.config;
version (OSX)
version = Darwin;
extern (C):
nothrow:
@nogc:
+@system:
//
// XOpen (XSI)
int fd;
short events;
short revents;
- };
+ }
alias uint nfds_t;
int fd;
short events;
short revents;
- };
+ }
enum
{
int fd;
short events;
short revents;
- };
+ }
enum
{
int fd;
short events;
short revents;
- };
+ }
enum
{
int fd;
short events;
short revents;
- };
+ }
enum
{
*/
module core.sys.posix.pthread;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types;
public import core.sys.posix.sched;
public import core.sys.posix.time;
version (Posix):
extern (C)
nothrow:
+@system:
//
// Required
int pthread_atfork(void function(), void function(), void function());
int pthread_attr_destroy(pthread_attr_t*);
-int pthread_attr_getdetachstate(in pthread_attr_t*, int*);
-int pthread_attr_getschedparam(in pthread_attr_t*, sched_param*);
+int pthread_attr_getdetachstate(const scope pthread_attr_t*, int*);
+int pthread_attr_getschedparam(const scope pthread_attr_t*, sched_param*);
int pthread_attr_init(pthread_attr_t*);
int pthread_attr_setdetachstate(pthread_attr_t*, int);
-int pthread_attr_setschedparam(in pthread_attr_t*, sched_param*);
+int pthread_attr_setschedparam(const scope pthread_attr_t*, sched_param*);
int pthread_cancel(pthread_t);
void pthread_cleanup_push(void function(void*), void*);
void pthread_cleanup_pop(int);
int pthread_cond_broadcast(pthread_cond_t*);
int pthread_cond_destroy(pthread_cond_t*);
-int pthread_cond_init(in pthread_cond_t*, pthread_condattr_t*);
+int pthread_cond_init(const scope pthread_cond_t*, pthread_condattr_t*);
int pthread_cond_signal(pthread_cond_t*);
-int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, in timespec*);
+int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, const scope timespec*);
int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*);
int pthread_condattr_destroy(pthread_condattr_t*);
int pthread_condattr_init(pthread_condattr_t*);
-int pthread_create(pthread_t*, in pthread_attr_t*, void* function(void*), void*);
+int pthread_create(pthread_t*, const scope pthread_attr_t*, void* function(void*), void*);
int pthread_detach(pthread_t);
int pthread_equal(pthread_t, pthread_t);
void pthread_exit(void*);
int pthread_mutexattr_init(pthread_mutexattr_t*);
int pthread_once(pthread_once_t*, void function());
int pthread_rwlock_destroy(pthread_rwlock_t*);
-int pthread_rwlock_init(pthread_rwlock_t*, in pthread_rwlockattr_t*);
+int pthread_rwlock_init(pthread_rwlock_t*, const scope pthread_rwlockattr_t*);
int pthread_rwlock_rdlock(pthread_rwlock_t*);
int pthread_rwlock_tryrdlock(pthread_rwlock_t*);
int pthread_rwlock_trywrlock(pthread_rwlock_t*);
pthread_t pthread_self();
int pthread_setcancelstate(int, int*);
int pthread_setcanceltype(int, int*);
-int pthread_setspecific(pthread_key_t, in void*);
+int pthread_setspecific(pthread_key_t, const scope void*);
void pthread_testcancel();
*/
version (CRuntime_Glibc)
enum PTHREAD_MUTEX_INITIALIZER = null;
//enum PTHREAD_ONCE_INIT = { PTHREAD_NEEDS_INIT, NULL };
- enum PTHREAD_ONCE_INIT = pthread_once_t.init;;
+ enum PTHREAD_ONCE_INIT = pthread_once_t.init;
enum PTHREAD_COND_INITIALIZER = null;
enum PTHREAD_RWLOCK_INITIALIZER = null;
}
@nogc {
int pthread_atfork(void function() @nogc, void function() @nogc, void function() @nogc);
int pthread_attr_destroy(pthread_attr_t*);
- int pthread_attr_getdetachstate(in pthread_attr_t*, int*);
- int pthread_attr_getschedparam(in pthread_attr_t*, sched_param*);
+ int pthread_attr_getdetachstate(const scope pthread_attr_t*, int*);
+ int pthread_attr_getschedparam(const scope pthread_attr_t*, sched_param*);
int pthread_attr_init(pthread_attr_t*);
int pthread_attr_setdetachstate(pthread_attr_t*, int);
- int pthread_attr_setschedparam(in pthread_attr_t*, sched_param*);
+ int pthread_attr_setschedparam(const scope pthread_attr_t*, sched_param*);
int pthread_cancel(pthread_t);
}
int pthread_cond_broadcast(pthread_cond_t*);
int pthread_cond_destroy(pthread_cond_t*);
-int pthread_cond_init(in pthread_cond_t*, pthread_condattr_t*) @trusted;
+int pthread_cond_init(const scope pthread_cond_t*, pthread_condattr_t*) @trusted;
int pthread_cond_signal(pthread_cond_t*);
-int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, in timespec*);
+int pthread_cond_timedwait(pthread_cond_t*, pthread_mutex_t*, const scope timespec*);
int pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*);
int pthread_condattr_destroy(pthread_condattr_t*);
int pthread_condattr_init(pthread_condattr_t*);
-int pthread_create(pthread_t*, in pthread_attr_t*, void* function(void*), void*);
+int pthread_create(pthread_t*, const scope pthread_attr_t*, void* function(void*), void*);
int pthread_detach(pthread_t);
int pthread_equal(pthread_t, pthread_t);
void pthread_exit(void*);
int pthread_mutexattr_init(pthread_mutexattr_t*) @trusted;
int pthread_once(pthread_once_t*, void function());
int pthread_rwlock_destroy(pthread_rwlock_t*);
-int pthread_rwlock_init(pthread_rwlock_t*, in pthread_rwlockattr_t*);
+int pthread_rwlock_init(pthread_rwlock_t*, const scope pthread_rwlockattr_t*);
int pthread_rwlock_rdlock(pthread_rwlock_t*);
int pthread_rwlock_tryrdlock(pthread_rwlock_t*);
int pthread_rwlock_trywrlock(pthread_rwlock_t*);
pthread_t pthread_self();
int pthread_setcancelstate(int, int*);
int pthread_setcanceltype(int, int*);
-int pthread_setspecific(pthread_key_t, in void*);
+int pthread_setspecific(pthread_key_t, const scope void*);
void pthread_testcancel();
//
PTHREAD_BARRIER_SERIAL_THREAD
int pthread_barrier_destroy(pthread_barrier_t*);
-int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+int pthread_barrier_init(pthread_barrier_t*, const scope pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
-int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*); (BAR|TSH)
+int pthread_barrierattr_getpshared(const scope pthread_barrierattr_t*, int*); (BAR|TSH)
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int); (BAR|TSH)
*/
enum PTHREAD_BARRIER_SERIAL_THREAD = -1;
int pthread_barrier_destroy(pthread_barrier_t*);
- int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+ int pthread_barrier_init(pthread_barrier_t*, const scope pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
- int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
+ int pthread_barrierattr_getpshared(const scope pthread_barrierattr_t*, int*);
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
}
enum PTHREAD_BARRIER_SERIAL_THREAD = -1;
int pthread_barrier_destroy(pthread_barrier_t*);
- int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+ int pthread_barrier_init(pthread_barrier_t*, const scope pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
- int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
+ int pthread_barrierattr_getpshared(const scope pthread_barrierattr_t*, int*);
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
}
enum PTHREAD_THREADS_MAX = c_ulong.max;
int pthread_barrier_destroy(pthread_barrier_t*);
- int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+ int pthread_barrier_init(pthread_barrier_t*, const scope pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
- int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
+ int pthread_barrierattr_getpshared(const scope pthread_barrierattr_t*, int*);
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
}
enum PTHREAD_BARRIER_SERIAL_THREAD = 1234567;
int pthread_barrier_destroy(pthread_barrier_t*);
- int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+ int pthread_barrier_init(pthread_barrier_t*, const scope pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
- int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
+ int pthread_barrierattr_getpshared(const scope pthread_barrierattr_t*, int*);
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
}
enum PTHREAD_BARRIER_SERIAL_THREAD = -1;
int pthread_barrier_destroy(pthread_barrier_t*);
- int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+ int pthread_barrier_init(pthread_barrier_t*, const scope pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
- int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
+ int pthread_barrierattr_getpshared(const scope pthread_barrierattr_t*, int*);
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
}
enum PTHREAD_BARRIER_SERIAL_THREAD = -2;
int pthread_barrier_destroy(pthread_barrier_t*);
- int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+ int pthread_barrier_init(pthread_barrier_t*, const scope pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
- int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
+ int pthread_barrierattr_getpshared(const scope pthread_barrierattr_t*, int*);
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
}
enum PTHREAD_BARRIER_SERIAL_THREAD = -1;
int pthread_barrier_destroy(pthread_barrier_t*);
- int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+ int pthread_barrier_init(pthread_barrier_t*, const scope pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
- int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
+ int pthread_barrierattr_getpshared(const scope pthread_barrierattr_t*, int*);
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
}
enum PTHREAD_BARRIER_SERIAL_THREAD = -1;
int pthread_barrier_destroy(pthread_barrier_t*);
- int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint);
+ int pthread_barrier_init(pthread_barrier_t*, const scope pthread_barrierattr_t*, uint);
int pthread_barrier_wait(pthread_barrier_t*);
int pthread_barrierattr_destroy(pthread_barrierattr_t*);
- int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
+ int pthread_barrierattr_getpshared(const scope pthread_barrierattr_t*, int*);
int pthread_barrierattr_init(pthread_barrierattr_t*);
int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
}
// Clock (CS)
//
/*
-int pthread_condattr_getclock(in pthread_condattr_t*, clockid_t*);
+int pthread_condattr_getclock(const scope pthread_condattr_t*, clockid_t*);
int pthread_condattr_setclock(pthread_condattr_t*, clockid_t);
*/
version (CRuntime_Glibc)
{
- int pthread_condattr_getclock(in pthread_condattr_t*, clockid_t*);
+ int pthread_condattr_getclock(const scope pthread_condattr_t*, clockid_t*);
int pthread_condattr_setclock(pthread_condattr_t*, clockid_t);
}
else version (FreeBSD)
{
- int pthread_condattr_getclock(in pthread_condattr_t*, clockid_t*);
+ int pthread_condattr_getclock(const scope pthread_condattr_t*, clockid_t*);
int pthread_condattr_setclock(pthread_condattr_t*, clockid_t);
}
else version (DragonFlyBSD)
{
- int pthread_condattr_getclock(in pthread_condattr_t*, clockid_t*);
+ int pthread_condattr_getclock(const scope pthread_condattr_t*, clockid_t*);
int pthread_condattr_setclock(pthread_condattr_t*, clockid_t);
}
else version (NetBSD)
}
else version (OpenBSD)
{
- int pthread_condattr_getclock(in pthread_condattr_t*, clockid_t*);
+ int pthread_condattr_getclock(const scope pthread_condattr_t*, clockid_t*);
int pthread_condattr_setclock(pthread_condattr_t*, clockid_t);
}
else version (Darwin)
}
else version (Solaris)
{
- int pthread_condattr_getclock(in pthread_condattr_t*, clockid_t*);
+ int pthread_condattr_getclock(const scope pthread_condattr_t*, clockid_t*);
int pthread_condattr_setclock(pthread_condattr_t*, clockid_t);
}
else version (CRuntime_Bionic)
}
else version (CRuntime_Musl)
{
- int pthread_condattr_getclock(in pthread_condattr_t*, clockid_t*);
+ int pthread_condattr_getclock(const scope pthread_condattr_t*, clockid_t*);
int pthread_condattr_setclock(pthread_condattr_t*, clockid_t);
}
else version (CRuntime_UClibc)
{
- int pthread_condattr_getclock(in pthread_condattr_t*, clockid_t*);
+ int pthread_condattr_getclock(const scope pthread_condattr_t*, clockid_t*);
int pthread_condattr_setclock(pthread_condattr_t*, clockid_t);
}
else
PTHREAD_MUTEX_NORMAL
PTHREAD_MUTEX_RECURSIVE
-int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
int pthread_getconcurrency();
-int pthread_mutexattr_gettype(in pthread_mutexattr_t*, int*);
+int pthread_mutexattr_gettype(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_settype(pthread_mutexattr_t*, int);
int pthread_setconcurrency(int);
*/
enum PTHREAD_MUTEX_ERRORCHECK = 2;
enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL;
- int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
int pthread_getconcurrency();
- int pthread_mutexattr_gettype(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_gettype(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_settype(pthread_mutexattr_t*, int) @trusted;
int pthread_setconcurrency(int);
}
enum PTHREAD_MUTEX_RECURSIVE = 2;
enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL;
- int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
int pthread_getconcurrency();
- int pthread_mutexattr_gettype(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_gettype(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_settype(pthread_mutexattr_t*, int) @trusted;
int pthread_setconcurrency(int);
}
}
enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_ERRORCHECK;
- int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
int pthread_getconcurrency();
int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*);
}
enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_ERRORCHECK;
- int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
int pthread_getconcurrency();
int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*);
}
enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_ERRORCHECK;
- int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
int pthread_getconcurrency();
int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*);
}
enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_ERRORCHECK;
- int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
int pthread_getconcurrency();
int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*);
enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL;
- int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
int pthread_getconcurrency();
int pthread_mutexattr_gettype(pthread_mutexattr_t*, int*);
enum PTHREAD_MUTEX_ERRORCHECK = 2;
enum PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL;
- int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
- int pthread_mutexattr_gettype(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_gettype(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_settype(pthread_mutexattr_t*, int) @trusted;
}
else version (CRuntime_Musl)
PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
}
- int pthread_attr_getguardsize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getguardsize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setguardsize(pthread_attr_t*, size_t);
int pthread_getconcurrency();
- int pthread_mutexattr_gettype(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_gettype(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_settype(pthread_mutexattr_t*, int) @trusted;
int pthread_setconcurrency(int);
}
// Timeouts (TMO)
//
/*
-int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
-int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
-int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
*/
version (CRuntime_Glibc)
{
- int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else version (Darwin)
{
- int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else version (FreeBSD)
{
- int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else version (NetBSD)
{
- int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else version (OpenBSD)
{
- int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else version (DragonFlyBSD)
{
- int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else version (Solaris)
{
- int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else version (CRuntime_Bionic)
{
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else version (CRuntime_Musl)
{
- int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else version (CRuntime_UClibc)
{
- int pthread_mutex_timedlock(pthread_mutex_t*, in timespec*);
- int pthread_rwlock_timedrdlock(pthread_rwlock_t*, in timespec*);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t*, in timespec*);
+ int pthread_mutex_timedlock(pthread_mutex_t*, const scope timespec*);
+ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const scope timespec*);
+ int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const scope timespec*);
}
else
{
PTHREAD_PRIO_NONE (TPP|TPI)
PTHREAD_PRIO_PROTECT (TPI)
-int pthread_mutex_getprioceiling(in pthread_mutex_t*, int*); (TPP)
+int pthread_mutex_getprioceiling(const scope pthread_mutex_t*, int*); (TPP)
int pthread_mutex_setprioceiling(pthread_mutex_t*, int, int*); (TPP)
int pthread_mutexattr_getprioceiling(pthread_mutexattr_t*, int*); (TPP)
-int pthread_mutexattr_getprotocol(in pthread_mutexattr_t*, int*); (TPI|TPP)
+int pthread_mutexattr_getprotocol(const scope pthread_mutexattr_t*, int*); (TPI|TPP)
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t*, int); (TPP)
int pthread_mutexattr_setprotocol(pthread_mutexattr_t*, int); (TPI|TPP)
*/
PTHREAD_PRIO_PROTECT
}
- int pthread_mutex_getprioceiling(in pthread_mutex_t*, int*);
+ int pthread_mutex_getprioceiling(const scope pthread_mutex_t*, int*);
int pthread_mutex_setprioceiling(pthread_mutex_t*, int, int*);
- int pthread_mutexattr_getprioceiling(in pthread_mutexattr_t*, int*);
- int pthread_mutexattr_getprotocol(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getprioceiling(const scope pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getprotocol(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t*, int);
int pthread_mutexattr_setprotocol(pthread_mutexattr_t*, int);
}
PTHREAD_PRIO_PROTECT = 0x20,
}
- int pthread_mutex_getprioceiling(in pthread_mutex_t*, int*);
+ int pthread_mutex_getprioceiling(const scope pthread_mutex_t*, int*);
int pthread_mutex_setprioceiling(pthread_mutex_t*, int, int*);
- int pthread_mutexattr_getprioceiling(in pthread_mutexattr_t*, int*);
- int pthread_mutexattr_getprotocol(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getprioceiling(const scope pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getprotocol(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t*, int);
int pthread_mutexattr_setprotocol(pthread_mutexattr_t*, int);
}
PTHREAD_SCOPE_PROCESS
PTHREAD_SCOPE_SYSTEM
-int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
-int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
-int pthread_attr_getscope(in pthread_attr_t*, int*);
+int pthread_attr_getinheritsched(const scope pthread_attr_t*, int*);
+int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+int pthread_attr_getscope(const scope pthread_attr_t*, int*);
int pthread_attr_setinheritsched(pthread_attr_t*, int);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
int pthread_attr_setscope(pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
-int pthread_setschedparam(pthread_t, int, in sched_param*);
+int pthread_setschedparam(pthread_t, int, const scope sched_param*);
int pthread_setschedprio(pthread_t, int);
*/
PTHREAD_SCOPE_PROCESS
}
- int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
- int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
- int pthread_attr_getscope(in pthread_attr_t*, int*);
+ int pthread_attr_getinheritsched(const scope pthread_attr_t*, int*);
+ int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+ int pthread_attr_getscope(const scope pthread_attr_t*, int*);
int pthread_attr_setinheritsched(pthread_attr_t*, int);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
int pthread_attr_setscope(pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
- int pthread_setschedparam(pthread_t, int, in sched_param*);
+ int pthread_setschedparam(pthread_t, int, const scope sched_param*);
int pthread_setschedprio(pthread_t, int);
}
else version (Darwin)
PTHREAD_SCOPE_PROCESS = 2
}
- int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
- int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
- int pthread_attr_getscope(in pthread_attr_t*, int*);
+ int pthread_attr_getinheritsched(const scope pthread_attr_t*, int*);
+ int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+ int pthread_attr_getscope(const scope pthread_attr_t*, int*);
int pthread_attr_setinheritsched(pthread_attr_t*, int);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
int pthread_attr_setscope(pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
- int pthread_setschedparam(pthread_t, int, in sched_param*);
+ int pthread_setschedparam(pthread_t, int, const scope sched_param*);
// int pthread_setschedprio(pthread_t, int); // not implemented
}
else version (FreeBSD)
PTHREAD_SCOPE_SYSTEM = 0x2
}
- int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
- int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
- int pthread_attr_getscope(in pthread_attr_t*, int*);
+ int pthread_attr_getinheritsched(const scope pthread_attr_t*, int*);
+ int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+ int pthread_attr_getscope(const scope pthread_attr_t*, int*);
int pthread_attr_setinheritsched(pthread_attr_t*, int);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
- int pthread_attr_setscope(in pthread_attr_t*, int);
+ int pthread_attr_setscope(const scope pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
int pthread_setschedparam(pthread_t, int, sched_param*);
// int pthread_setschedprio(pthread_t, int); // not implemented
PTHREAD_SCOPE_SYSTEM = 0x1
}
- int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
- int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
- int pthread_attr_getscope(in pthread_attr_t*, int*);
+ int pthread_attr_getinheritsched(const scope pthread_attr_t*, int*);
+ int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+ int pthread_attr_getscope(const scope pthread_attr_t*, int*);
int pthread_attr_setinheritsched(pthread_attr_t*, int);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
- int pthread_attr_setscope(in pthread_attr_t*, int);
+ int pthread_attr_setscope(const scope pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
int pthread_setschedparam(pthread_t, int, sched_param*);
//int pthread_setschedprio(pthread_t, int);
PTHREAD_SCOPE_SYSTEM = 0x2
}
- int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
- int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
- int pthread_attr_getscope(in pthread_attr_t*, int*);
+ int pthread_attr_getinheritsched(const scope pthread_attr_t*, int*);
+ int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+ int pthread_attr_getscope(const scope pthread_attr_t*, int*);
int pthread_attr_setinheritsched(pthread_attr_t*, int);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
- int pthread_attr_setscope(in pthread_attr_t*, int);
+ int pthread_attr_setscope(const scope pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
int pthread_setschedparam(pthread_t, int, sched_param*);
// int pthread_setschedprio(pthread_t, int); // not implemented
PTHREAD_SCOPE_SYSTEM = 0x2
}
- int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
- int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
- int pthread_attr_getscope(in pthread_attr_t*, int*);
+ int pthread_attr_getinheritsched(const scope pthread_attr_t*, int*);
+ int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+ int pthread_attr_getscope(const scope pthread_attr_t*, int*);
int pthread_attr_setinheritsched(pthread_attr_t*, int);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
- int pthread_attr_setscope(in pthread_attr_t*, int);
+ int pthread_attr_setscope(const scope pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
int pthread_setschedparam(pthread_t, int, sched_param*);
}
PTHREAD_SCOPE_SYSTEM = 1,
}
- int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
- int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
- int pthread_attr_getscope(in pthread_attr_t*, int*);
+ int pthread_attr_getinheritsched(const scope pthread_attr_t*, int*);
+ int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+ int pthread_attr_getscope(const scope pthread_attr_t*, int*);
int pthread_attr_setinheritsched(pthread_attr_t*, int);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
- int pthread_attr_setscope(in pthread_attr_t*, int);
+ int pthread_attr_setscope(const scope pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
int pthread_setschedparam(pthread_t, int, sched_param*);
int pthread_setschedprio(pthread_t, int);
PTHREAD_SCOPE_PROCESS
}
- int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
- int pthread_attr_getscope(in pthread_attr_t*);
+ int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+ int pthread_attr_getscope(const scope pthread_attr_t*);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
int pthread_attr_setscope(pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
- int pthread_setschedparam(pthread_t, int, in sched_param*);
+ int pthread_setschedparam(pthread_t, int, const scope sched_param*);
}
else version (CRuntime_Musl)
{
}
int pthread_getschedparam(pthread_t, int*, sched_param*);
- int pthread_setschedparam(pthread_t, int, in sched_param*);
+ int pthread_setschedparam(pthread_t, int, const scope sched_param*);
int pthread_setschedprio(pthread_t, int);
}
else version (CRuntime_UClibc)
PTHREAD_SCOPE_PROCESS
}
- int pthread_attr_getinheritsched(in pthread_attr_t*, int*);
- int pthread_attr_getschedpolicy(in pthread_attr_t*, int*);
- int pthread_attr_getscope(in pthread_attr_t*, int*);
+ int pthread_attr_getinheritsched(const scope pthread_attr_t*, int*);
+ int pthread_attr_getschedpolicy(const scope pthread_attr_t*, int*);
+ int pthread_attr_getscope(const scope pthread_attr_t*, int*);
int pthread_attr_setinheritsched(pthread_attr_t*, int);
int pthread_attr_setschedpolicy(pthread_attr_t*, int);
int pthread_attr_setscope(pthread_attr_t*, int);
int pthread_getschedparam(pthread_t, int*, sched_param*);
- int pthread_setschedparam(pthread_t, int, in sched_param*);
+ int pthread_setschedparam(pthread_t, int, const scope sched_param*);
int pthread_setschedprio(pthread_t, int);
}
else
// Stack (TSA|TSS)
//
/*
-int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*); (TSA|TSS)
-int pthread_attr_getstackaddr(in pthread_attr_t*, void**); (TSA)
-int pthread_attr_getstacksize(in pthread_attr_t*, size_t*); (TSS)
+int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*); (TSA|TSS)
+int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**); (TSA)
+int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*); (TSS)
int pthread_attr_setstack(pthread_attr_t*, void*, size_t); (TSA|TSS)
int pthread_attr_setstackaddr(pthread_attr_t*, void*); (TSA)
int pthread_attr_setstacksize(pthread_attr_t*, size_t); (TSS)
version (CRuntime_Glibc)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
- int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
- int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**);
+ int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
}
else version (Darwin)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
- int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
- int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**);
+ int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
}
else version (FreeBSD)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
- int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
- int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**);
+ int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
}
else version (NetBSD)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
- int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
- int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**);
+ int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
}
else version (OpenBSD)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
- int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
- int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**);
+ int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
}
else version (DragonFlyBSD)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
- int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
- int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**);
+ int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
}
else version (Solaris)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
- int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
- int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**);
+ int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
}
else version (CRuntime_Bionic)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
- int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
- int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**);
+ int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
}
else version (CRuntime_Musl)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
}
else version (CRuntime_UClibc)
{
- int pthread_attr_getstack(in pthread_attr_t*, void**, size_t*);
- int pthread_attr_getstackaddr(in pthread_attr_t*, void**);
- int pthread_attr_getstacksize(in pthread_attr_t*, size_t*);
+ int pthread_attr_getstack(const scope pthread_attr_t*, void**, size_t*);
+ int pthread_attr_getstackaddr(const scope pthread_attr_t*, void**);
+ int pthread_attr_getstacksize(const scope pthread_attr_t*, size_t*);
int pthread_attr_setstack(pthread_attr_t*, void*, size_t);
int pthread_attr_setstackaddr(pthread_attr_t*, void*);
int pthread_attr_setstacksize(pthread_attr_t*, size_t);
// Shared Synchronization (TSH)
//
/*
-int pthread_condattr_getpshared(in pthread_condattr_t*, int*);
+int pthread_condattr_getpshared(const scope pthread_condattr_t*, int*);
int pthread_condattr_setpshared(pthread_condattr_t*, int);
-int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*);
+int pthread_mutexattr_getpshared(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
-int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*);
+int pthread_rwlockattr_getpshared(const scope pthread_rwlockattr_t*, int*);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
*/
version (CRuntime_Glibc)
{
- int pthread_condattr_getpshared(in pthread_condattr_t*, int*);
+ int pthread_condattr_getpshared(const scope pthread_condattr_t*, int*);
int pthread_condattr_setpshared(pthread_condattr_t*, int);
- int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getpshared(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
- int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*);
+ int pthread_rwlockattr_getpshared(const scope pthread_rwlockattr_t*, int*);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
}
else version (FreeBSD)
{
- int pthread_condattr_getpshared(in pthread_condattr_t*, int*);
+ int pthread_condattr_getpshared(const scope pthread_condattr_t*, int*);
int pthread_condattr_setpshared(pthread_condattr_t*, int);
- int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getpshared(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
- int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*);
+ int pthread_rwlockattr_getpshared(const scope pthread_rwlockattr_t*, int*);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
}
else version (NetBSD)
{
- int pthread_condattr_getpshared(in pthread_condattr_t*, int*);
+ int pthread_condattr_getpshared(const scope pthread_condattr_t*, int*);
int pthread_condattr_setpshared(pthread_condattr_t*, int);
- int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getpshared(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
- int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*);
+ int pthread_rwlockattr_getpshared(const scope pthread_rwlockattr_t*, int*);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
}
else version (OpenBSD)
}
else version (DragonFlyBSD)
{
- int pthread_condattr_getpshared(in pthread_condattr_t*, int*);
+ int pthread_condattr_getpshared(const scope pthread_condattr_t*, int*);
int pthread_condattr_setpshared(pthread_condattr_t*, int);
- int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getpshared(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
- int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*);
+ int pthread_rwlockattr_getpshared(const scope pthread_rwlockattr_t*, int*);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
}
else version (Darwin)
{
- int pthread_condattr_getpshared(in pthread_condattr_t*, int*);
+ int pthread_condattr_getpshared(const scope pthread_condattr_t*, int*);
int pthread_condattr_setpshared(pthread_condattr_t*, int);
- int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getpshared(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
- int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*);
+ int pthread_rwlockattr_getpshared(const scope pthread_rwlockattr_t*, int*);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
}
else version (Solaris)
{
- int pthread_condattr_getpshared(in pthread_condattr_t*, int*);
+ int pthread_condattr_getpshared(const scope pthread_condattr_t*, int*);
int pthread_condattr_setpshared(pthread_condattr_t*, int);
- int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getpshared(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
- int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*);
+ int pthread_rwlockattr_getpshared(const scope pthread_rwlockattr_t*, int*);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
}
else version (CRuntime_Bionic)
}
else version (CRuntime_UClibc)
{
- int pthread_condattr_getpshared(in pthread_condattr_t*, int*);
+ int pthread_condattr_getpshared(const scope pthread_condattr_t*, int*);
int pthread_condattr_setpshared(pthread_condattr_t*, int);
- int pthread_mutexattr_getpshared(in pthread_mutexattr_t*, int*);
+ int pthread_mutexattr_getpshared(const scope pthread_mutexattr_t*, int*);
int pthread_mutexattr_setpshared(pthread_mutexattr_t*, int);
- int pthread_rwlockattr_getpshared(in pthread_rwlockattr_t*, int*);
+ int pthread_rwlockattr_getpshared(const scope pthread_rwlockattr_t*, int*);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t*, int);
}
else
*/
module core.sys.posix.pwd;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for gid_t, uid_t
version (OSX)
extern (C):
nothrow:
@nogc:
+@system:
//
// Required
char* pw_shell;
}
-passwd* getpwnam(in char*);
+passwd* getpwnam(const scope char*);
passwd* getpwuid(uid_t);
*/
static assert(false, "Unsupported platform");
}
-passwd* getpwnam(in char*);
+passwd* getpwnam(const scope char*);
passwd* getpwuid(uid_t);
//
// Thread-Safe Functions (TSF)
//
/*
-int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+int getpwnam_r(const scope char*, passwd*, char*, size_t, passwd**);
int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
*/
version (CRuntime_Glibc)
{
- int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+ int getpwnam_r(const scope char*, passwd*, char*, size_t, passwd**);
int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
}
else version (Darwin)
{
- int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+ int getpwnam_r(const scope char*, passwd*, char*, size_t, passwd**);
int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
}
else version (FreeBSD)
{
- int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+ int getpwnam_r(const scope char*, passwd*, char*, size_t, passwd**);
int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
}
else version (NetBSD)
{
- int __getpwnam_r50(in char*, passwd*, char*, size_t, passwd**);
+ int __getpwnam_r50(const scope char*, passwd*, char*, size_t, passwd**);
alias __getpwnam_r50 getpwnam_r;
int __getpwuid_r50(uid_t, passwd*, char*, size_t, passwd**);
alias __getpwuid_r50 getpwuid_r;
}
else version (OpenBSD)
{
- int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+ int getpwnam_r(const scope char*, passwd*, char*, size_t, passwd**);
int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
}
else version (DragonFlyBSD)
{
- int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+ int getpwnam_r(const scope char*, passwd*, char*, size_t, passwd**);
int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
}
else version (Solaris)
alias getpwuid_r = __posix_getpwuid_r;
// POSIX.1c standard version of the functions
- int __posix_getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+ int __posix_getpwnam_r(const scope char*, passwd*, char*, size_t, passwd**);
int __posix_getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
}
else version (CRuntime_Bionic)
}
else version (CRuntime_Musl)
{
- int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+ int getpwnam_r(const scope char*, passwd*, char*, size_t, passwd**);
int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
}
else version (CRuntime_UClibc)
{
- int getpwnam_r(in char*, passwd*, char*, size_t, passwd**);
+ int getpwnam_r(const scope char*, passwd*, char*, size_t, passwd**);
int getpwuid_r(uid_t, passwd*, char*, size_t, passwd**);
}
else
*/
module core.sys.posix.sched;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.time;
public import core.sys.posix.sys.types;
extern (C):
nothrow:
@nogc:
+@system:
//
// Required
int sched_getparam(pid_t, sched_param*);
int sched_getscheduler(pid_t);
-int sched_setparam(pid_t, in sched_param*);
-int sched_setscheduler(pid_t, int, in sched_param*);
+int sched_setparam(pid_t, const scope sched_param*);
+int sched_setscheduler(pid_t, int, const scope sched_param*);
*/
version (CRuntime_Glibc)
int sched_getparam(pid_t, sched_param*);
int sched_getscheduler(pid_t);
-int sched_setparam(pid_t, in sched_param*);
-int sched_setscheduler(pid_t, int, in sched_param*);
+int sched_setparam(pid_t, const scope sched_param*);
+int sched_setscheduler(pid_t, int, const scope sched_param*);
//
// Thread (THR)
*/
module core.sys.posix.semaphore;
-private import core.sys.posix.config;
-private import core.sys.posix.time;
+import core.sys.posix.config;
+import core.sys.posix.time;
version (OSX)
version = Darwin;
extern (C):
nothrow:
@nogc:
+@system:
//
// Required
int sem_destroy(sem_t*);
int sem_getvalue(sem_t*, int*);
int sem_init(sem_t*, int, uint);
-sem_t* sem_open(in char*, int, ...);
+sem_t* sem_open(const scope char*, int, ...);
int sem_post(sem_t*);
int sem_trywait(sem_t*);
-int sem_unlink(in char*);
+int sem_unlink(const scope char*);
int sem_wait(sem_t*);
*/
int sem_destroy(sem_t*);
int sem_getvalue(sem_t*, int*);
int sem_init(sem_t*, int, uint);
-sem_t* sem_open(in char*, int, ...);
+sem_t* sem_open(const scope char*, int, ...);
int sem_post(sem_t*);
int sem_trywait(sem_t*);
-int sem_unlink(in char*);
+int sem_unlink(const scope char*);
int sem_wait(sem_t*);
//
// Timeouts (TMO)
//
/*
-int sem_timedwait(sem_t*, in timespec*);
+int sem_timedwait(sem_t*, const scope timespec*);
*/
version (CRuntime_Glibc)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else version (Darwin)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else version (FreeBSD)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else version (NetBSD)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else version (OpenBSD)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else version (DragonFlyBSD)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else version (Solaris)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else version (CRuntime_Bionic)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else version (CRuntime_Musl)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else version (CRuntime_UClibc)
{
- int sem_timedwait(sem_t*, in timespec*);
+ int sem_timedwait(sem_t*, const scope timespec*);
}
else
{
*/
module core.sys.posix.setjmp;
-private import core.sys.posix.config;
-private import core.sys.posix.signal; // for sigset_t
+import core.sys.posix.config;
+import core.sys.posix.signal; // for sigset_t
version (Posix):
extern (C) nothrow @nogc:
+@system:
version (RISCV32) version = RISCV_Any;
version (RISCV64) version = RISCV_Any;
c_long __pc;
c_long[12] __regs;
c_long __sp;
- double[12] __fpregs;
+ static if (__traits(getTargetInfo, "floatAbi") == "double")
+ double[12] __fpregs;
}
alias __jmp_buf = __riscv_jmp_buf[1];
}
{
enum _JBLEN = 31;
// __int128_t
- struct _jmp_buf { long[2][_JBLEN + 1] _jb; };
+ struct _jmp_buf { long[2][_JBLEN + 1] _jb; }
}
else version (PPC_Any)
{
double[8] __fpregs;
else
double[6] __fpregs;
- };
+ }
}
else
static assert(0, "unimplemented");
else version (AArch64)
{
// __int128_t
- struct _sigjmp_buf { long[2][_JBLEN + 1] _jb; };
+ struct _sigjmp_buf { long[2][_JBLEN + 1] _jb; }
}
else version (PPC_Any)
{
module core.sys.posix.signal;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.stdc.signal;
public import core.sys.posix.sys.types; // for pid_t
//public import core.sys.posix.time; // for timespec, now defined here
version (Posix):
extern (C):
-//nothrow: // this causes Issue 12738
+//nothrow: // this causes http://issues.dlang.org/show_bug.cgi?id=12738 (which has been fixed)
+//@system:
//
// Required
return sig;
}
}
-else version (CRuntime_Glibc)
-{
- private extern (C) nothrow @nogc
- {
- int __libc_current_sigrtmin();
- int __libc_current_sigrtmax();
- }
-
- @property int SIGRTMIN() nothrow @nogc {
- __gshared static int sig = -1;
- if (sig == -1) {
- sig = __libc_current_sigrtmin();
- }
- return sig;
- }
-
- @property int SIGRTMAX() nothrow @nogc {
- __gshared static int sig = -1;
- if (sig == -1) {
- sig = __libc_current_sigrtmax();
- }
- return sig;
- }
-}
else version (FreeBSD) {
// Note: it appears that FreeBSD (prior to 7) and OSX do not support realtime signals
// https://github.com/freebsd/freebsd/blob/e79c62ff68fc74d88cb6f479859f6fae9baa5101/sys/sys/signal.h#L117
enum SIGRTMIN = 33;
enum SIGRTMAX = 63;
}
-else version (CRuntime_Bionic)
+else version (linux)
{
- // Switched to calling these functions since Lollipop
+ // Note: CRuntime_Bionic switched to calling these functions
+ // since Lollipop, and Glibc, UClib and Musl all implement them
+ // the same way since it's part of LSB.
private extern (C) nothrow @nogc
{
int __libc_current_sigrtmin();
return sig;
}
}
-else version (CRuntime_UClibc)
-{
- private extern (C) nothrow @nogc
- {
- int __libc_current_sigrtmin();
- int __libc_current_sigrtmax();
- }
-
- @property int SIGRTMIN() nothrow @nogc
- {
- return __libc_current_sigrtmin();
- }
-
- @property int SIGRTMAX() nothrow @nogc
- {
- return __libc_current_sigrtmax();
- }
-}
version (linux)
{
SI_MESGQ
int kill(pid_t, int);
-int sigaction(int, in sigaction_t*, sigaction_t*);
+int sigaction(int, const scope sigaction_t*, sigaction_t*);
int sigaddset(sigset_t*, int);
int sigdelset(sigset_t*, int);
int sigemptyset(sigset_t*);
int sigfillset(sigset_t*);
-int sigismember(in sigset_t*, int);
+int sigismember(const scope sigset_t*, int);
int sigpending(sigset_t*);
-int sigprocmask(int, in sigset_t*, sigset_t*);
-int sigsuspend(in sigset_t*);
-int sigwait(in sigset_t*, int*);
+int sigprocmask(int, const scope sigset_t*, sigset_t*);
+int sigsuspend(const scope sigset_t*);
+int sigwait(const scope sigset_t*, int*);
*/
nothrow @nogc
}
int kill(pid_t, int);
- int sigaction(int, in sigaction_t*, sigaction_t*);
+ int sigaction(int, const scope sigaction_t*, sigaction_t*);
int sigaddset(sigset_t*, int);
int sigdelset(sigset_t*, int);
int sigemptyset(sigset_t*);
int sigfillset(sigset_t*);
- int sigismember(in sigset_t*, int);
+ int sigismember(const scope sigset_t*, int);
int sigpending(sigset_t*);
- int sigprocmask(int, in sigset_t*, sigset_t*);
- int sigsuspend(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int sigprocmask(int, const scope sigset_t*, sigset_t*);
+ int sigsuspend(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
}
else version (Darwin)
{
enum SI_MESGQ = 0x10005;
int kill(pid_t, int);
- int sigaction(int, in sigaction_t*, sigaction_t*);
+ int sigaction(int, const scope sigaction_t*, sigaction_t*);
int sigaddset(sigset_t*, int);
int sigdelset(sigset_t*, int);
int sigemptyset(sigset_t*);
int sigfillset(sigset_t*);
- int sigismember(in sigset_t*, int);
+ int sigismember(const scope sigset_t*, int);
int sigpending(sigset_t*);
- int sigprocmask(int, in sigset_t*, sigset_t*);
- int sigsuspend(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int sigprocmask(int, const scope sigset_t*, sigset_t*);
+ int sigsuspend(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
}
else version (FreeBSD)
{
enum SI_MESGQ = 0x10005;
int kill(pid_t, int);
- int sigaction(int, in sigaction_t*, sigaction_t*);
+ int sigaction(int, const scope sigaction_t*, sigaction_t*);
int sigaddset(sigset_t*, int);
int sigdelset(sigset_t*, int);
int sigemptyset(sigset_t *);
int sigfillset(sigset_t *);
- int sigismember(in sigset_t*, int);
+ int sigismember(const scope sigset_t*, int);
int sigpending(sigset_t *);
- int sigprocmask(int, in sigset_t*, sigset_t*);
- int sigsuspend(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int sigprocmask(int, const scope sigset_t*, sigset_t*);
+ int sigsuspend(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
}
else version (NetBSD)
{
enum SI_MESGQ = -4;
int kill(pid_t, int);
- int __sigaction14(int, in sigaction_t*, sigaction_t*);
+ int __sigaction14(int, const scope sigaction_t*, sigaction_t*);
int __sigaddset14(sigset_t*, int);
int __sigdelset14(sigset_t*, int);
int __sigemptyset14(sigset_t *);
int __sigfillset14(sigset_t *);
- int __sigismember14(in sigset_t*, int);
+ int __sigismember14(const scope sigset_t*, int);
int __sigpending14(sigset_t *);
- int __sigprocmask14(int, in sigset_t*, sigset_t*);
- int __sigsuspend14(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int __sigprocmask14(int, const scope sigset_t*, sigset_t*);
+ int __sigsuspend14(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
alias __sigaction14 sigaction;
alias __sigaddset14 sigaddset;
enum SI_TIMER = -3;
int kill(pid_t, int);
- int sigaction(int, in sigaction_t*, sigaction_t*);
+ int sigaction(int, const scope sigaction_t*, sigaction_t*);
int sigaddset(sigset_t*, int);
int sigdelset(sigset_t*, int);
int sigemptyset(sigset_t *);
int sigfillset(sigset_t *);
- int sigismember(in sigset_t*, int);
+ int sigismember(const scope sigset_t*, int);
int sigpending(sigset_t *);
- int sigprocmask(int, in sigset_t*, sigset_t*);
- int sigsuspend(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int sigprocmask(int, const scope sigset_t*, sigset_t*);
+ int sigsuspend(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
}
else version (DragonFlyBSD)
{
enum SI_MESGQ = -4;
int kill(pid_t, int);
- int sigaction(int, in sigaction_t*, sigaction_t*);
+ int sigaction(int, const scope sigaction_t*, sigaction_t*);
int sigaddset(sigset_t*, int);
int sigdelset(sigset_t*, int);
int sigemptyset(sigset_t *);
int sigfillset(sigset_t *);
- int sigismember(in sigset_t*, int);
+ int sigismember(const scope sigset_t*, int);
int sigpending(sigset_t *);
- int sigprocmask(int, in sigset_t*, sigset_t*);
- int sigsuspend(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int sigprocmask(int, const scope sigset_t*, sigset_t*);
+ int sigsuspend(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
}
else version (Solaris)
{
}
int kill(pid_t, int);
- int sigaction(int, in sigaction_t*, sigaction_t*);
+ int sigaction(int, const scope sigaction_t*, sigaction_t*);
int sigaddset(sigset_t*, int);
int sigdelset(sigset_t*, int);
int sigemptyset(sigset_t*);
int sigfillset(sigset_t*);
- int sigismember(in sigset_t*, int);
+ int sigismember(const scope sigset_t*, int);
int sigpending(sigset_t*);
- int sigprocmask(int, in sigset_t*, sigset_t*);
- int sigsuspend(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int sigprocmask(int, const scope sigset_t*, sigset_t*);
+ int sigsuspend(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
}
else version (CRuntime_Bionic)
{
public import core.sys.posix.time: timer_t;
- private import core.stdc.string : memset;
+ import core.stdc.string : memset;
version (X86)
{
}
int kill(pid_t, int);
- int sigaction(int, in sigaction_t*, sigaction_t*);
+ int sigaction(int, const scope sigaction_t*, sigaction_t*);
// These functions are defined inline in bionic.
int sigaddset(sigset_t* set, int signum)
}
int sigpending(sigset_t*);
- int sigprocmask(int, in sigset_t*, sigset_t*);
- int sigsuspend(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int sigprocmask(int, const scope sigset_t*, sigset_t*);
+ int sigsuspend(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
}
else version (CRuntime_Musl)
{
}
int kill(pid_t, int);
- int sigaction(int, in sigaction_t*, sigaction_t*);
+ int sigaction(int, const scope sigaction_t*, sigaction_t*);
int sigaddset(sigset_t*, int);
int sigdelset(sigset_t*, int);
int sigemptyset(sigset_t*);
int sigfillset(sigset_t*);
- int sigismember(in sigset_t*, int);
+ int sigismember(const scope sigset_t*, int);
int sigpending(sigset_t*);
- int sigprocmask(int, in sigset_t*, sigset_t*);
- int sigsuspend(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int sigprocmask(int, const scope sigset_t*, sigset_t*);
+ int sigsuspend(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
}
else version (CRuntime_UClibc)
{
}
int kill(pid_t, int);
- int sigaction(int, in sigaction_t*, sigaction_t*);
+ int sigaction(int, const scope sigaction_t*, sigaction_t*);
int sigaddset(sigset_t*, int);
int sigdelset(sigset_t*, int);
int sigemptyset(sigset_t*);
int sigfillset(sigset_t*);
- int sigismember(in sigset_t*, int);
+ int sigismember(const scope sigset_t*, int);
int sigpending(sigset_t*);
- int sigprocmask(int, in sigset_t*, sigset_t*);
- int sigsuspend(in sigset_t*);
- int sigwait(in sigset_t*, int*);
+ int sigprocmask(int, const scope sigset_t*, sigset_t*);
+ int sigsuspend(const scope sigset_t*);
+ int sigwait(const scope sigset_t*, int*);
}
else
{
sigfn_t sigset(int sig, sigfn_t func);
int killpg(pid_t, int);
-int sigaltstack(in stack_t*, stack_t*);
+int sigaltstack(const scope stack_t*, stack_t*);
int sighold(int);
int sigignore(int);
int siginterrupt(int, int);
sigfn_t2 sigset(int sig, sigfn_t2 func);
int killpg(pid_t, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int sighold(int);
int sigignore(int);
int siginterrupt(int, int);
sigfn_t2 sigset(int sig, sigfn_t2 func);
int killpg(pid_t, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int sighold(int);
int sigignore(int);
int siginterrupt(int, int);
enum MINSIGSTKSZ = 512 * 4;
enum SIGSTKSZ = (MINSIGSTKSZ + 32768);
-;
+
//ucontext_t (defined in core.sys.posix.ucontext)
//mcontext_t (defined in core.sys.posix.ucontext)
sigfn_t2 sigset(int sig, sigfn_t2 func);
int killpg(pid_t, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int sighold(int);
int sigignore(int);
int siginterrupt(int, int);
enum MINSIGSTKSZ = 8192;
enum SIGSTKSZ = (MINSIGSTKSZ + 32768);
-;
+
//ucontext_t (defined in core.sys.posix.ucontext)
//mcontext_t (defined in core.sys.posix.ucontext)
sigfn_t2 sigset(int sig, sigfn_t2 func);
int killpg(pid_t, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int sighold(int);
int sigignore(int);
int siginterrupt(int, int);
nothrow:
@nogc:
int killpg(pid_t, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int siginterrupt(int, int);
int sigpause(int);
}
enum MINSIGSTKSZ = 8192;
enum SIGSTKSZ = (MINSIGSTKSZ + 32768);
-;
+
//ucontext_t (defined in core.sys.posix.ucontext)
//mcontext_t (defined in core.sys.posix.ucontext)
sigfn_t2 sigset(int sig, sigfn_t2 func);
int killpg(pid_t, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int sighold(int);
int sigignore(int);
int siginterrupt(int, int);
sigfn_t2 sigset(int sig, sigfn_t2 func);
int killpg(pid_t, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int sighold(int);
int sigignore(int);
int siginterrupt(int, int);
sigfn_t2 bsd_signal(int, sigfn_t2);
int killpg(int, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int siginterrupt(int, int);
}
else version (CRuntime_Musl)
sigfn_t2 sigset(int sig, sigfn_t2 func);
int killpg(pid_t, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int sighold(int);
int sigignore(int);
int siginterrupt(int, int);
sigfn_t2 sigset(int sig, sigfn_t2 func);
int killpg(pid_t, int);
- int sigaltstack(in stack_t*, stack_t*);
+ int sigaltstack(const scope stack_t*, stack_t*);
int sighold(int);
int sigignore(int);
int siginterrupt(int, int);
}
int sigqueue(pid_t, int, in sigval);
-int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
-int sigwaitinfo(in sigset_t*, siginfo_t*);
+int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+int sigwaitinfo(const scope sigset_t*, siginfo_t*);
*/
nothrow:
}
int sigqueue(pid_t, int, in sigval);
- int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
- int sigwaitinfo(in sigset_t*, siginfo_t*);
+ int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+ int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
else version (FreeBSD)
{
}
int sigqueue(pid_t, int, in sigval);
- int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
- int sigwaitinfo(in sigset_t*, siginfo_t*);
+ int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+ int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
else version (NetBSD)
{
}
int sigqueue(pid_t, int, in sigval);
- int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
- int sigwaitinfo(in sigset_t*, siginfo_t*);
+ int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+ int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
else version (OpenBSD)
{
int sigev_signo;
int sigev_notify_kqueue;
void /*pthread_attr_t*/ * sigev_notify_attributes;
- };
+ }
union _sigval_t
{
int sival_int;
void * sival_ptr;
int sigval_int;
void * sigval_ptr;
- };
+ }
struct sigevent
{
int sigev_notify;
}
int sigqueue(pid_t, int, in sigval);
- int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
- int sigwaitinfo(in sigset_t*, siginfo_t*);
+ int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+ int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
else version (Darwin)
{
}
int sigqueue(pid_t, int, in sigval);
- int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
- int sigwaitinfo(in sigset_t*, siginfo_t*);
+ int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+ int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
else version (CRuntime_Bionic)
{
@property void* sigev_notify_attributes(ref sigevent _sigevent) { return _sigevent._sigev_un._sigev_thread._attribute; }
int sigqueue(pid_t, int, in sigval);
- int sigtimedwait(in sigset_t*, siginfo_t*, in timespec*);
- int sigwaitinfo(in sigset_t*, siginfo_t*);
+ int sigtimedwait(const scope sigset_t*, siginfo_t*, const scope timespec*);
+ int sigwaitinfo(const scope sigset_t*, siginfo_t*);
}
else
{
//
/*
int pthread_kill(pthread_t, int);
-int pthread_sigmask(int, in sigset_t*, sigset_t*);
+int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
*/
version (CRuntime_Glibc)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
}
else version (Darwin)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
}
else version (FreeBSD)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
}
else version (NetBSD)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
}
else version (OpenBSD)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
}
else version (DragonFlyBSD)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
}
else version (Solaris)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
}
else version (CRuntime_Bionic)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
}
else version (CRuntime_Musl)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
}
else version (CRuntime_UClibc)
{
int pthread_kill(pthread_t, int);
- int pthread_sigmask(int, in sigset_t*, sigset_t*);
+ int pthread_sigmask(int, const scope sigset_t*, sigset_t*);
int pthread_sigqueue(pthread_t, int, sigval);
}
else
extern(C):
@nogc:
nothrow:
+@system:
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t*, int);
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t*, int, int);
--- /dev/null
+/**
+ * D header file for C99.
+ *
+ * $(C_HEADER_DESCRIPTION pubs.opengroup.org/onlinepubs/009695399/basedefs/_time.h.html, _time.h)
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly,
+ * Alex Rønne Petersen
+ * Source: $(DRUNTIMESRC core/stdc/_time.d)
+ * Standards: ISO/IEC 9899:1999 (E)
+ */
+
+module core.sys.posix.stdc.time;
+
+version (Posix):
+
+import core.stdc.config;
+
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
+extern (C):
+@trusted: // There are only a few functions here that use unsafe C strings.
+nothrow:
+@nogc:
+
+///
+struct tm
+{
+ int tm_sec; /// seconds after the minute [0-60]
+ int tm_min; /// minutes after the hour [0-59]
+ int tm_hour; /// hours since midnight [0-23]
+ int tm_mday; /// day of the month [1-31]
+ int tm_mon; /// months since January [0-11]
+ int tm_year; /// years since 1900
+ int tm_wday; /// days since Sunday [0-6]
+ int tm_yday; /// days since January 1 [0-365]
+ int tm_isdst; /// Daylight Savings Time flag
+ c_long tm_gmtoff; /// offset from CUT in seconds
+ char* tm_zone; /// timezone abbreviation
+}
+
+public import core.sys.posix.sys.types : time_t, clock_t;
+
+///
+version (OSX)
+{
+ enum clock_t CLOCKS_PER_SEC = 1_000_000; // was 100 until OSX 10.4/10.5
+ version (X86)
+ extern (C) pragma(mangle, "clock$UNIX2003") clock_t clock();
+ else
+ clock_t clock();
+}
+else version (Darwin) // other Darwins (iOS, TVOS, WatchOS)
+{
+ enum clock_t CLOCKS_PER_SEC = 1_000_000;
+ clock_t clock();
+}
+else version (FreeBSD)
+{
+ enum clock_t CLOCKS_PER_SEC = 128;
+ clock_t clock();
+}
+else version (NetBSD)
+{
+ enum clock_t CLOCKS_PER_SEC = 100;
+ clock_t clock();
+}
+else version (OpenBSD)
+{
+ enum clock_t CLOCKS_PER_SEC = 100;
+ clock_t clock();
+}
+else version (DragonFlyBSD)
+{
+ enum clock_t CLOCKS_PER_SEC = 128;
+ clock_t clock();
+}
+else version (Solaris)
+{
+ enum clock_t CLOCKS_PER_SEC = 1_000_000;
+ clock_t clock();
+}
+else version (CRuntime_Glibc)
+{
+ enum clock_t CLOCKS_PER_SEC = 1_000_000;
+ clock_t clock();
+}
+else version (CRuntime_Musl)
+{
+ enum clock_t CLOCKS_PER_SEC = 1_000_000;
+ clock_t clock();
+}
+else version (CRuntime_Bionic)
+{
+ enum clock_t CLOCKS_PER_SEC = 1_000_000;
+ clock_t clock();
+}
+else version (CRuntime_UClibc)
+{
+ enum clock_t CLOCKS_PER_SEC = 1_000_000;
+ clock_t clock();
+}
+else
+{
+ static assert(0, "unsupported system");
+}
+
+version (Darwin)
+{
+ ///
+ void tzset(); // non-standard
+ ///
+ extern __gshared const(char)*[2] tzname; // non-standard
+}
+else version (CRuntime_Glibc)
+{
+ ///
+ void tzset(); // non-standard
+ ///
+ extern __gshared const(char)*[2] tzname; // non-standard
+}
+else version (FreeBSD)
+{
+ ///
+ void tzset(); // non-standard
+ ///
+ extern __gshared const(char)*[2] tzname; // non-standard
+}
+else version (NetBSD)
+{
+ ///
+ void tzset(); // non-standard
+ ///
+ extern __gshared const(char)*[2] tzname; // non-standard
+}
+else version (OpenBSD)
+{
+ ///
+ void tzset(); // non-standard
+ ///
+ extern __gshared const(char)*[2] tzname; // non-standard
+}
+else version (DragonFlyBSD)
+{
+ ///
+ void tzset(); // non-standard
+ ///
+ extern __gshared const(char)*[2] tzname; // non-standard
+}
+else version (Solaris)
+{
+ ///
+ void tzset();
+ ///
+ extern __gshared const(char)*[2] tzname;
+}
+else version (CRuntime_Bionic)
+{
+ ///
+ void tzset();
+ ///
+ extern __gshared const(char)*[2] tzname;
+}
+else version (CRuntime_Musl)
+{
+ ///
+ void tzset(); // non-standard
+ ///
+ extern __gshared const(char)*[2] tzname; // non-standard
+}
+else version (CRuntime_UClibc)
+{
+ ///
+ void tzset();
+ ///
+ extern __gshared const(char)*[2] tzname;
+}
+else
+{
+ static assert(false, "Unsupported platform");
+}
*/
module core.sys.posix.stdio;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.stdc.stdio;
public import core.sys.posix.sys.types; // for off_t
nothrow:
@nogc:
+@system:
//
// Required (defined in core.stdc.stdio)
int fgetc(FILE*);
int fgetpos(FILE*, fpos_t *);
char* fgets(char*, int, FILE*);
-FILE* fopen(in char*, in char*);
-int fprintf(FILE*, in char*, ...);
+FILE* fopen(const scope char*, const scope char*);
+int fprintf(FILE*, const scope char*, ...);
int fputc(int, FILE*);
-int fputs(in char*, FILE*);
+int fputs(const scope char*, FILE*);
size_t fread(void *, size_t, size_t, FILE*);
-FILE* freopen(in char*, in char*, FILE*);
-int fscanf(FILE*, in char*, ...);
+FILE* freopen(const scope char*, const scope char*, FILE*);
+int fscanf(FILE*, const scope char*, ...);
int fseek(FILE*, c_long, int);
-int fsetpos(FILE*, in fpos_t*);
+int fsetpos(FILE*, const scope fpos_t*);
c_long ftell(FILE*);
size_t fwrite(in void *, size_t, size_t, FILE*);
int getc(FILE*);
int getchar();
char* gets(char*);
-void perror(in char*);
-int printf(in char*, ...);
+void perror(const scope char*);
+int printf(const scope char*, ...);
int putc(int, FILE*);
int putchar(int);
-int puts(in char*);
-int remove(in char*);
-int rename(in char*, in char*);
+int puts(const scope char*);
+int remove(const scope char*);
+int rename(const scope char*, const scope char*);
void rewind(FILE*);
-int scanf(in char*, ...);
+int scanf(const scope char*, ...);
void setbuf(FILE*, char*);
int setvbuf(FILE*, char*, int, size_t);
-int snprintf(char*, size_t, in char*, ...);
-int sprintf(char*, in char*, ...);
-int sscanf(in char*, in char*, int ...);
+int snprintf(char*, size_t, const scope char*, ...);
+int sprintf(char*, const scope char*, ...);
+int sscanf(const scope char*, const scope char*, int ...);
FILE* tmpfile();
char* tmpnam(char*);
int ungetc(int, FILE*);
-int vfprintf(FILE*, in char*, va_list);
-int vfscanf(FILE*, in char*, va_list);
-int vprintf(in char*, va_list);
-int vscanf(in char*, va_list);
-int vsnprintf(char*, size_t, in char*, va_list);
-int vsprintf(char*, in char*, va_list);
-int vsscanf(in char*, in char*, va_list arg);
+int vfprintf(FILE*, const scope char*, va_list);
+int vfscanf(FILE*, const scope char*, va_list);
+int vprintf(const scope char*, va_list);
+int vscanf(const scope char*, va_list);
+int vsnprintf(char*, size_t, const scope char*, va_list);
+int vsprintf(char*, const scope char*, va_list);
+int vsscanf(const scope char*, const scope char*, va_list arg);
*/
version (CRuntime_Glibc)
int fgetpos64(FILE*, fpos_t *);
alias fgetpos64 fgetpos;
- FILE* fopen64(in char*, in char*);
+ FILE* fopen64(const scope char*, const scope char*);
alias fopen64 fopen;
- FILE* freopen64(in char*, in char*, FILE*);
+ FILE* freopen64(const scope char*, const scope char*, FILE*);
alias freopen64 freopen;
int fseek(FILE*, c_long, int);
- int fsetpos64(FILE*, in fpos_t*);
+ int fsetpos64(FILE*, const scope fpos_t*);
alias fsetpos64 fsetpos;
FILE* tmpfile64();
else
{
int fgetpos(FILE*, fpos_t *);
- FILE* fopen(in char*, in char*);
- FILE* freopen(in char*, in char*, FILE*);
+ FILE* fopen(const scope char*, const scope char*);
+ FILE* freopen(const scope char*, const scope char*, FILE*);
int fseek(FILE*, c_long, int);
- int fsetpos(FILE*, in fpos_t*);
+ int fsetpos(FILE*, const scope fpos_t*);
FILE* tmpfile();
}
}
else version (CRuntime_Bionic)
{
int fgetpos(FILE*, fpos_t *);
- FILE* fopen(in char*, in char*);
- FILE* freopen(in char*, in char*, FILE*);
+ FILE* fopen(const scope char*, const scope char*);
+ FILE* freopen(const scope char*, const scope char*, FILE*);
int fseek(FILE*, c_long, int);
- int fsetpos(FILE*, in fpos_t*);
+ int fsetpos(FILE*, const scope fpos_t*);
}
else version (CRuntime_UClibc)
{
int fgetpos64(FILE*, fpos_t *);
alias fgetpos64 fgetpos;
- FILE* fopen64(in char*, in char*);
+ FILE* fopen64(const scope char*, const scope char*);
alias fopen64 fopen;
- FILE* freopen64(in char*, in char*, FILE*);
+ FILE* freopen64(const scope char*, const scope char*, FILE*);
alias freopen64 freopen;
int fseek(FILE*, c_long, int);
- int fsetpos64(FILE*, in fpos_t*);
+ int fsetpos64(FILE*, const scope fpos_t*);
alias fsetpos64 fsetpos;
FILE* tmpfile64();
else
{
int fgetpos(FILE*, fpos_t *);
- FILE* fopen(in char*, in char*);
- FILE* freopen(in char*, in char*, FILE*);
+ FILE* fopen(const scope char*, const scope char*);
+ FILE* freopen(const scope char*, const scope char*, FILE*);
int fseek(FILE*, c_long, int);
- int fsetpos(FILE*, in fpos_t*);
+ int fsetpos(FILE*, const scope fpos_t*);
FILE* tmpfile();
}
}
int fgetpos64(FILE*, fpos_t *);
alias fgetpos64 fgetpos;
- FILE* fopen64(in char*, in char*);
+ FILE* fopen64(const scope char*, const scope char*);
alias fopen64 fopen;
- FILE* freopen64(in char*, in char*, FILE*);
+ FILE* freopen64(const scope char*, const scope char*, FILE*);
alias freopen64 freopen;
int fseek(FILE*, c_long, int);
- int fsetpos64(FILE*, in fpos_t*);
+ int fsetpos64(FILE*, const scope fpos_t*);
alias fsetpos64 fsetpos;
FILE* tmpfile64();
else
{
int fgetpos(FILE*, fpos_t *);
- FILE* fopen(in char*, in char*);
- FILE* freopen(in char*, in char*, FILE*);
+ FILE* fopen(const scope char*, const scope char*);
+ FILE* freopen(const scope char*, const scope char*, FILE*);
int fseek(FILE*, c_long, int);
- int fsetpos(FILE*, in fpos_t*);
+ int fsetpos(FILE*, const scope fpos_t*);
FILE* tmpfile();
}
}
int fgetpos64(FILE*, fpos_t *);
alias fgetpos = fgetpos64;
- FILE* fopen64(in char*, in char*);
+ FILE* fopen64(const scope char*, const scope char*);
alias fopen = fopen64;
- FILE* freopen64(in char*, in char*, FILE*);
+ FILE* freopen64(const scope char*, const scope char*, FILE*);
alias freopen = freopen64;
int fseek(FILE*, c_long, int);
- int fsetpos64(FILE*, in fpos_t*);
+ int fsetpos64(FILE*, const scope fpos_t*);
alias fsetpos = fsetpos64;
FILE* tmpfile64();
else
{
int fgetpos(FILE*, fpos_t *);
- FILE* fopen(in char*, in char*);
- FILE* freopen(in char*, in char*, FILE*);
+ FILE* fopen(const scope char*, const scope char*);
+ FILE* freopen(const scope char*, const scope char*, FILE*);
int fseek(FILE*, c_long, int);
- int fsetpos(FILE*, in fpos_t*);
+ int fsetpos(FILE*, const scope fpos_t*);
FILE* tmpfile();
}
}
/*
L_ctermid
-char* ctermid(char*);
-FILE* fdopen(int, in char*);
-int fileno(FILE*);
-int fseeko(FILE*, off_t, int);
-off_t ftello(FILE*);
-char* gets(char*);
-int pclose(FILE*);
-FILE* popen(in char*, in char*);
+char* ctermid(char*);
+FILE* fdopen(int, const scope char*);
+int fileno(FILE*);
+int fseeko(FILE*, off_t, int);
+off_t ftello(FILE*);
+ssize_t getdelim(char**, size_t*, int, FILE*);
+ssize_t getline(char**, size_t*, FILE*);
+char* gets(char*);
+int pclose(FILE*);
+FILE* popen(const scope char*, const scope char*);
*/
version (CRuntime_Glibc)
{
enum L_ctermid = 9;
- static if ( __USE_FILE_OFFSET64 )
- {
- int fseeko64(FILE*, off_t, int);
- alias fseeko64 fseeko;
- }
- else
- {
- int fseeko(FILE*, off_t, int);
- }
-
- static if ( __USE_FILE_OFFSET64 )
- {
- off_t ftello64(FILE*);
- alias ftello64 ftello;
- }
- else
- {
- off_t ftello(FILE*);
- }
+ static if ( __USE_FILE_OFFSET64 )
+ {
+ int fseeko64(FILE*, off_t, int);
+ alias fseeko64 fseeko;
+ }
+ else
+ {
+ int fseeko(FILE*, off_t, int);
+ }
+
+ static if ( __USE_FILE_OFFSET64 )
+ {
+ off_t ftello64(FILE*);
+ alias ftello64 ftello;
+ }
+ else
+ {
+ off_t ftello(FILE*);
+ }
+
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
}
else version (CRuntime_UClibc)
{
enum L_ctermid = 9;
enum L_cuserid = 9;
- static if ( __USE_FILE_OFFSET64 )
- {
- int fseeko64(FILE*, off_t, int);
- alias fseeko64 fseeko;
- }
- else
- {
- int fseeko(FILE*, off_t, int);
- }
-
- static if ( __USE_FILE_OFFSET64 )
- {
- off_t ftello64(FILE*);
- alias ftello64 ftello;
- }
- else
- {
- off_t ftello(FILE*);
- }
+ static if ( __USE_FILE_OFFSET64 )
+ {
+ int fseeko64(FILE*, off_t, int);
+ alias fseeko64 fseeko;
+ }
+ else
+ {
+ int fseeko(FILE*, off_t, int);
+ }
+
+ static if ( __USE_FILE_OFFSET64 )
+ {
+ off_t ftello64(FILE*);
+ alias ftello64 ftello;
+ }
+ else
+ {
+ off_t ftello(FILE*);
+ }
+
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
}
else version (CRuntime_Musl)
{
{
off_t ftello(FILE*);
}
+
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
+}
+else version (CRuntime_Bionic)
+{
+ enum L_ctermid = 1024;
+
+ static if ( __USE_FILE_OFFSET64 )
+ {
+ int fseeko64(FILE*, off_t, int);
+ alias fseeko64 fseeko;
+ }
+ else
+ {
+ int fseeko(FILE*, off_t, int);
+ }
+
+ static if ( __USE_FILE_OFFSET64 )
+ {
+ off_t ftello64(FILE*);
+ alias ftello64 ftello;
+ }
+ else
+ {
+ off_t ftello(FILE*);
+ }
+
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
+}
+else version (Darwin)
+{
+ enum L_ctermid = 1024;
+
+ int fseeko(FILE*, off_t, int);
+ off_t ftello(FILE*);
+
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
+}
+else version (FreeBSD)
+{
+ import core.sys.freebsd.config;
+
+ enum L_ctermid = 1024;
+
+ int fseeko(FILE*, off_t, int);
+ off_t ftello(FILE*);
+
+ static if (__FreeBSD_version >= 800000)
+ {
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
+ }
+}
+else version (NetBSD)
+{
+ enum L_ctermid = 1024;
+
+ int fseeko(FILE*, off_t, int);
+ off_t ftello(FILE*);
+
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
+}
+else version (OpenBSD)
+{
+ enum L_ctermid = 1024;
+
+ int fseeko(FILE*, off_t, int);
+ off_t ftello(FILE*);
+
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
+}
+else version (DragonFlyBSD)
+{
+ enum L_ctermid = 1024;
+
+ int fseeko(FILE*, off_t, int);
+ off_t ftello(FILE*);
+
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
}
else version (Solaris)
{
{
off_t ftello(FILE*);
}
+
+ ssize_t getdelim(char**, size_t*, int, FILE*);
+ ssize_t getline(char**, size_t*, FILE*);
}
else version (Posix)
{
}
char* ctermid(char*);
-FILE* fdopen(int, in char*);
+FILE* fdopen(int, const scope char*);
int fileno(FILE*);
-//int fseeko(FILE*, off_t, int);
-//off_t ftello(FILE*);
char* gets(char*);
int pclose(FILE*);
-FILE* popen(in char*, in char*);
+FILE* popen(const scope char*, const scope char*);
// memstream functions are conforming to POSIX.1-2008. These functions are
version (HaveMemstream)
{
- FILE* fmemopen(in void* buf, in size_t size, in char* mode);
+ FILE* fmemopen(const scope void* buf, in size_t size, const scope char* mode);
FILE* open_memstream(char** ptr, size_t* sizeloc);
version (CRuntime_UClibc) {} else
FILE* open_wmemstream(wchar_t** ptr, size_t* sizeloc);
P_tmpdir
va_list (defined in core.stdc.stdarg)
-char* tempnam(in char*, in char*);
+char* tempnam(const scope char*, const scope char*);
*/
-char* tempnam(in char*, in char*);
+char* tempnam(const scope char*, const scope char*);
version (CRuntime_Glibc)
{
assert(memcmp(ptr, testdata.ptr, testdata.length*wchar_t.sizeof) == 0);
assert(fclose(f) == 0);
}
-
-
-ssize_t getdelim (char** lineptr, size_t* n, int delimiter, FILE* stream);
-ssize_t getline (char** lineptr, size_t* n, FILE* stream);
*/
module core.sys.posix.stdlib;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.stdc.stdlib;
public import core.sys.posix.sys.wait;
extern (C):
nothrow:
@nogc:
+@system:
//
// Required (defined in core.stdc.stdlib)
void abort();
int abs(int);
int atexit(void function());
-double atof(in char*);
-int atoi(in char*);
-c_long atol(in char*);
-long atoll(in char*);
-void* bsearch(in void*, in void*, size_t, size_t, int function(in void*, in void*));
+double atof(const scope char*);
+int atoi(const scope char*);
+c_long atol(const scope char*);
+long atoll(const scope char*);
+void* bsearch(const scope void*, const scope void*, size_t, size_t, int function(const scope void*, const scope void*));
void* calloc(size_t, size_t);
div_t div(int, int);
void exit(int);
void free(void*);
-char* getenv(in char*);
+char* getenv(const scope char*);
c_long labs(c_long);
ldiv_t ldiv(c_long, c_long);
long llabs(long);
lldiv_t lldiv(long, long);
void* malloc(size_t);
-int mblen(in char*, size_t);
-size_t mbstowcs(wchar_t*, in char*, size_t);
-int mbtowc(wchar_t*, in char*, size_t);
-void qsort(void*, size_t, size_t, int function(in void*, in void*));
+int mblen(const scope char*, size_t);
+size_t mbstowcs(wchar_t*, const scope char*, size_t);
+int mbtowc(wchar_t*, const scope char*, size_t);
+void qsort(void*, size_t, size_t, int function(const scope void*, const scope void*));
int rand();
void* realloc(void*, size_t);
void srand(uint);
-double strtod(in char*, char**);
-float strtof(in char*, char**);
-c_long strtol(in char*, char**, int);
-real strtold(in char*, char**);
-long strtoll(in char*, char**, int);
-c_ulong strtoul(in char*, char**, int);
-ulong strtoull(in char*, char**, int);
-int system(in char*);
-size_t wcstombs(char*, in wchar_t*, size_t);
+double strtod(const scope char*, char**);
+float strtof(const scope char*, char**);
+c_long strtol(const scope char*, char**, int);
+real strtold(const scope char*, char**);
+long strtoll(const scope char*, char**, int);
+c_ulong strtoul(const scope char*, char**, int);
+ulong strtoull(const scope char*, char**, int);
+int system(const scope char*);
+size_t wcstombs(char*, const scope wchar_t*, size_t);
int wctomb(char*, wchar_t);
*/
// C Extension (CX)
//
/*
-int setenv(in char*, in char*, int);
-int unsetenv(in char*);
+int setenv(const scope char*, const scope char*, int);
+int unsetenv(const scope char*);
*/
version (CRuntime_Glibc)
{
- int setenv(in char*, in char*, int);
- int unsetenv(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int unsetenv(const scope char*);
void* valloc(size_t); // LEGACY non-standard
}
else version (Darwin)
{
- int setenv(in char*, in char*, int);
- int unsetenv(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int unsetenv(const scope char*);
void* valloc(size_t); // LEGACY non-standard
}
else version (FreeBSD)
{
- int setenv(in char*, in char*, int);
- int unsetenv(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int unsetenv(const scope char*);
void* valloc(size_t); // LEGACY non-standard
}
else version (NetBSD)
{
- int setenv(in char*, in char*, int);
- int __unsetenv13(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int __unsetenv13(const scope char*);
alias __unsetenv13 unsetenv;
void* valloc(size_t); // LEGACY non-standard
}
else version (OpenBSD)
{
- int setenv(in char*, in char*, int);
- int unsetenv(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int unsetenv(const scope char*);
void* valloc(size_t); // LEGACY non-standard
}
else version (DragonFlyBSD)
{
- int setenv(in char*, in char*, int);
- int unsetenv(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int unsetenv(const scope char*);
void* valloc(size_t); // LEGACY non-standard
}
else version (CRuntime_Bionic)
{
- int setenv(in char*, in char*, int);
- int unsetenv(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int unsetenv(const scope char*);
void* valloc(size_t);
}
else version (Solaris)
{
- int setenv(in char*, in char*, int);
- int unsetenv(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int unsetenv(const scope char*);
void* valloc(size_t); // LEGACY non-standard
}
else version (CRuntime_Musl)
{
- int setenv(in char*, in char*, int);
- int unsetenv(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int unsetenv(const scope char*);
}
else version (CRuntime_UClibc)
{
- int setenv(in char*, in char*, int);
- int unsetenv(in char*);
+ int setenv(const scope char*, const scope char*, int);
+ int unsetenv(const scope char*);
void* valloc(size_t);
}
WSTOPSIG (defined in core.sys.posix.sys.wait)
WTERMSIG (defined in core.sys.posix.sys.wait)
-c_long a64l(in char*);
+c_long a64l(const scope char*);
double drand48();
char* ecvt(double, int, int *, int *); // LEGACY
double erand48(ref ushort[3]);
char* fcvt(double, int, int *, int *); // LEGACY
char* gcvt(double, int, char*); // LEGACY
// per spec: int getsubopt(char** char* const*, char**);
-int getsubopt(char**, in char**, char**);
+int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
-char* realpath(in char*, char*);
+char* realpath(const scope char*, char*);
ushort *seed48(ref ushort[3]);
-void setkey(in char*);
-char* setstate(in char*);
+void setkey(const scope char*);
+char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
//WSTOPSIG (defined in core.sys.posix.sys.wait)
//WTERMSIG (defined in core.sys.posix.sys.wait)
- c_long a64l(in char*);
+ c_long a64l(const scope char*);
double drand48();
char* ecvt(double, int, int *, int *); // LEGACY
double erand48(ref ushort[3]);
char* fcvt(double, int, int *, int *); // LEGACY
char* gcvt(double, int, char*); // LEGACY
- int getsubopt(char**, in char**, char**);
+ int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort *seed48(ref ushort[3]);
- void setkey(in char*);
- char* setstate(in char*);
+ void setkey(const scope char*);
+ char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
//WSTOPSIG (defined in core.sys.posix.sys.wait)
//WTERMSIG (defined in core.sys.posix.sys.wait)
- c_long a64l(in char*);
+ c_long a64l(const scope char*);
double drand48();
char* ecvt(double, int, int *, int *); // LEGACY
double erand48(ref ushort[3]);
char* fcvt(double, int, int *, int *); // LEGACY
char* gcvt(double, int, char*); // LEGACY
- int getsubopt(char**, in char**, char**);
+ int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort *seed48(ref ushort[3]);
- void setkey(in char*);
- char* setstate(in char*);
+ void setkey(const scope char*);
+ char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
//WSTOPSIG (defined in core.sys.posix.sys.wait)
//WTERMSIG (defined in core.sys.posix.sys.wait)
- c_long a64l(in char*);
+ c_long a64l(const scope char*);
double drand48();
//char* ecvt(double, int, int *, int *); // LEGACY
double erand48(ref ushort[3]);
//char* fcvt(double, int, int *, int *); // LEGACY
//char* gcvt(double, int, char*); // LEGACY
- int getsubopt(char**, in char**, char**);
+ int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort *seed48(ref ushort[3]);
- void setkey(in char*);
- char* setstate(in char*);
+ void setkey(const scope char*);
+ char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
//WSTOPSIG (defined in core.sys.posix.sys.wait)
//WTERMSIG (defined in core.sys.posix.sys.wait)
- c_long a64l(in char*);
+ c_long a64l(const scope char*);
double drand48();
//char* ecvt(double, int, int *, int *); // LEGACY
double erand48(ref ushort[3]);
//char* fcvt(double, int, int *, int *); // LEGACY
//char* gcvt(double, int, char*); // LEGACY
- int getsubopt(char**, in char**, char**);
+ int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort *seed48(ref ushort[3]);
- void setkey(in char*);
- char* setstate(in char*);
+ void setkey(const scope char*);
+ char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
//WSTOPSIG (defined in core.sys.posix.sys.wait)
//WTERMSIG (defined in core.sys.posix.sys.wait)
- c_long a64l(in char*);
+ c_long a64l(const scope char*);
double drand48();
//char* ecvt(double, int, int *, int *); // LEGACY
double erand48(ref ushort[3]);
//char* fcvt(double, int, int *, int *); // LEGACY
//char* gcvt(double, int, char*); // LEGACY
- int getsubopt(char**, in char**, char**);
+ int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort *seed48(ref ushort[3]);
- // void setkey(in char*); // not implemented
- char* setstate(in char*);
+ // void setkey(const scope char*); // not implemented
+ char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
//WSTOPSIG (defined in core.sys.posix.sys.wait)
//WTERMSIG (defined in core.sys.posix.sys.wait)
- c_long a64l(in char*);
+ c_long a64l(const scope char*);
double drand48();
//char* ecvt(double, int, int *, int *); // LEGACY
double erand48(ref ushort[3]);
//char* fcvt(double, int, int *, int *); // LEGACY
//char* gcvt(double, int, char*); // LEGACY
- int getsubopt(char**, in char**, char**);
+ int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort *seed48(ref ushort[3]);
- void setkey(in char*);
- char* setstate(in char*);
+ void setkey(const scope char*);
+ char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
c_long mrand48();
c_long nrand48(ref ushort[3]);
char* ptsname(int);
- int putenv(in char*);
+ int putenv(const scope char*);
c_long random() { return lrand48(); }
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort* seed48(ref ushort[3]);
void srand48(c_long);
void srandom(uint s) { srand48(s); }
}
else version (CRuntime_Musl)
{
- c_long a64l(in char*);
+ c_long a64l(const scope char*);
double drand48();
char* ecvt(double, int, int *, int *); // LEGACY
double erand48(ref ushort[3]);
char* fcvt(double, int, int *, int *); // LEGACY
char* gcvt(double, int, char*); // LEGACY
- int getsubopt(char**, in char**, char**);
+ int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort *seed48(ref ushort[3]);
- void setkey(in char*);
- char* setstate(in char*);
+ void setkey(const scope char*);
+ char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
//WSTOPSIG (defined in core.sys.posix.sys.wait)
//WTERMSIG (defined in core.sys.posix.sys.wait)
- c_long a64l(in char*);
+ c_long a64l(const scope char*);
double drand48();
char* ecvt(double, int, int *, int *); // LEGACY
double erand48(ref ushort[3]);
char* fcvt(double, int, int *, int *); // LEGACY
char* gcvt(double, int, char*); // LEGACY
- int getsubopt(char**, in char**, char**);
+ int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort *seed48(ref ushort[3]);
- void setkey(in char*);
- char* setstate(in char*);
+ void setkey(const scope char*);
+ char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
}
else version (CRuntime_UClibc)
{
- c_long a64l(in char*);
+ c_long a64l(const scope char*);
double drand48();
char* ecvt(double, int, int *, int *);
double erand48(ref ushort[3]);
char* fcvt(double, int, int *, int *);
char* gcvt(double, int, char*);
- int getsubopt(char**, in char**, char**);
+ int getsubopt(char**, const scope char**, char**);
int grantpt(int);
char* initstate(uint, char*, size_t);
c_long jrand48(ref ushort[3]);
char* ptsname(int);
int putenv(char*);
c_long random();
- char* realpath(in char*, char*);
+ char* realpath(const scope char*, char*);
ushort* seed48(ref ushort[3]);
- void setkey(in char*);
- char* setstate(in char*);
+ void setkey(const scope char*);
+ char* setstate(const scope char*);
void srand48(c_long);
void srandom(uint);
int unlockpt(int);
--- /dev/null
+/**
+ * D header file for POSIX's <string.h>.
+ *
+ * Note:
+ * - The <string.h> header shall define NULL and size_t as described in <stddef.h>.
+ * However, D has builtin `null` and `size_t` is defined in `object`.
+ *
+ * See_Also: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/string.h.html
+ * Copyright: D Language Foundation, 2019
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Authors: Mathias 'Geod24' Lang
+ * Standards: The Open Group Base Specifications Issue 7, 2018 edition
+ * Source: $(DRUNTIMESRC core/sys/posix/_string.d)
+ */
+module core.sys.posix.string;
+
+version (Posix):
+extern(C):
+@system:
+nothrow:
+@nogc:
+
+/// Exposes `locale_t` as defined in `core.sys.posix.locale` (`<locale.h>`)
+public import core.sys.posix.locale : locale_t;
+
+/**
+ * Exposes the C99 functions
+ *
+ * C extensions and XSI extensions are missing
+ */
+public import core.stdc.string;
+
+/// Copy string until character found
+void* memccpy(return void* dst, scope const void* src, int c, size_t n);
+/// Copy string (including terminating '\0')
+char* stpcpy(return char* dst, scope const char* src);
+/// Ditto
+char* stpncpy(return char* dst, const char* src, size_t len);
+/// Compare strings according to current collation
+int strcoll_l(scope const char* s1, scope const char* s2, locale_t locale);
+///
+char* strerror_l(int, locale_t);
+/// Save a copy of a string
+char* strndup(scope const char* str, size_t len);
+/// Find length of string up to `maxlen`
+size_t strnlen(scope const char* str, size_t maxlen);
+/// System signal messages
+const(char)* strsignal(int);
+/// Isolate sequential tokens in a null-terminated string
+char* strtok_r(return char* str, scope const char* sep, char** context) pure;
+/// Transform a string under locale
+size_t strxfrm_l(char* s1, scope const char* s2, size_t n, locale_t locale);
--- /dev/null
+/**
+ * D header file for POSIX's <strings.h>.
+ *
+ * Note: Do not mistake this module for <string.h> (singular),
+ * available at `core.sys.posix.string`.
+ *
+ * See_Also: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/strings.h.html
+ * Copyright: D Language Foundation, 2019
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Authors: Mathias 'Geod24' Lang
+ * Standards: The Open Group Base Specifications Issue 7, 2018 edition
+ * Source: $(DRUNTIMESRC core/sys/posix/_strings.d)
+ */
+module core.sys.posix.strings;
+
+version (Posix):
+extern(C):
+@system:
+nothrow:
+@nogc:
+
+///
+public import core.sys.posix.locale : locale_t;
+
+/// Find first bit set in a word
+int ffs(int i) @safe pure;
+/// Compare two strings ignoring case
+int strcasecmp(scope const char* s1, scope const char* s2);
+/// Compare two strings ignoring case, with the specified locale
+int strcasecmp_l(scope const char* s1, scope const char* s2, scope locale_t locale);
+/// Compare two strings ignoring case, up to n characters
+int strncasecmp(scope const char* s1, scope const char* s2, size_t n);
+/// Compare two strings ignoring case, with the specified locale, up to n characters
+int strncasecmp_l(scope const char* s1, const char* s2, size_t n, locale_t locale);
version (Posix):
nothrow @nogc:
+@system:
version (Darwin)
{
version (Posix):
nothrow @nogc:
+@system:
version (Darwin)
{
version (Posix):
extern (C) nothrow @nogc:
+@system:
version (CRuntime_Glibc)
{
enum TIOCGSID = 0x5429;
enum TCGETS2 = _IOR!termios2('T', 0x2A);
- enum TCSETS2 = _IOR!termios2('T', 0x2B);
+ enum TCSETS2 = _IOW!termios2('T', 0x2B);
enum TCSETSW2 = _IOW!termios2('T', 0x2C);
enum TCSETSF2 = _IOW!termios2('T', 0x2D);
enum TIOCGSID = 0x5429;
enum TCGETS2 = _IOR!termios2('T', 0x2A);
- enum TCSETS2 = _IOR!termios2('T', 0x2B);
+ enum TCSETS2 = _IOW!termios2('T', 0x2B);
enum TCSETSW2 = _IOW!termios2('T', 0x2C);
enum TCSETSF2 = _IOW!termios2('T', 0x2D);
*/
module core.sys.posix.sys.ipc;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for uid_t, gid_t, mode_t, key_t
version (OSX)
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// XOpen (XSI)
IPC_SET
IPC_STAT
-key_t ftok(in char*, int);
+key_t ftok(const scope char*, int);
*/
version (CRuntime_Glibc)
enum IPC_SET = 1;
enum IPC_STAT = 2;
- key_t ftok(in char*, int);
+ key_t ftok(const scope char*, int);
}
else version (Darwin)
{
enum IPC_SET = 1;
enum IPC_STAT = 2;
- key_t ftok(in char*, int);
+ key_t ftok(const scope char*, int);
}
else version (NetBSD)
{
enum IPC_SET = 1;
enum IPC_STAT = 2;
- key_t ftok(in char*, int);
+ key_t ftok(const scope char*, int);
}
else version (OpenBSD)
{
enum IPC_SET = 1;
enum IPC_STAT = 2;
- key_t ftok(in char*, int);
+ key_t ftok(const scope char*, int);
}
else version (DragonFlyBSD)
{
enum IPC_SET = 1;
enum IPC_STAT = 2;
- key_t ftok(in char*, int);
+ key_t ftok(const scope char*, int);
}
else version (CRuntime_Bionic)
{
enum IPC_SET = 1;
enum IPC_STAT = 2;
- key_t ftok(in char*, int);
+ key_t ftok(const scope char*, int);
}
else version (CRuntime_UClibc)
{
enum IPC_STAT = 2;
enum IPC_INFO = 3;
- key_t ftok(in char*, int);
+ key_t ftok(const scope char*, int);
}
*/
module core.sys.posix.sys.mman;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for off_t, mode_t
version (OSX)
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// Advisory Information (ADV)
enum MS_ASYNC = 1;
enum MS_INVALIDATE = 2;
- int msync(in void*, size_t, int);
+ int msync(const scope void*, size_t, int);
}
else version (CRuntime_Musl)
{
// Range Memory Locking (MLR)
//
/*
-int mlock(in void*, size_t);
-int munlock(in void*, size_t);
+int mlock(const scope void*, size_t);
+int munlock(const scope void*, size_t);
*/
version (CRuntime_Glibc)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else version (Darwin)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else version (FreeBSD)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else version (NetBSD)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else version (OpenBSD)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else version (DragonFlyBSD)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else version (Solaris)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else version (CRuntime_Bionic)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else version (CRuntime_Musl)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else version (CRuntime_UClibc)
{
- int mlock(in void*, size_t);
- int munlock(in void*, size_t);
+ int mlock(const scope void*, size_t);
+ int munlock(const scope void*, size_t);
}
else
{
}
else version (CRuntime_Bionic)
{
- int mprotect(in void*, size_t, int);
+ int mprotect(const scope void*, size_t, int);
}
else version (CRuntime_Musl)
{
// Shared Memory Objects (SHM)
//
/*
-int shm_open(in char*, int, mode_t);
-int shm_unlink(in char*);
+int shm_open(const scope char*, int, mode_t);
+int shm_unlink(const scope char*);
*/
version (CRuntime_Glibc)
{
- int shm_open(in char*, int, mode_t);
- int shm_unlink(in char*);
+ int shm_open(const scope char*, int, mode_t);
+ int shm_unlink(const scope char*);
}
else version (Darwin)
{
- int shm_open(in char*, int, mode_t);
- int shm_unlink(in char*);
+ int shm_open(const scope char*, int, mode_t);
+ int shm_unlink(const scope char*);
}
else version (FreeBSD)
{
- int shm_open(in char*, int, mode_t);
- int shm_unlink(in char*);
+ int shm_open(const scope char*, int, mode_t);
+ int shm_unlink(const scope char*);
}
else version (NetBSD)
{
- int shm_open(in char*, int, mode_t);
- int shm_unlink(in char*);
+ int shm_open(const scope char*, int, mode_t);
+ int shm_unlink(const scope char*);
}
else version (OpenBSD)
{
- int shm_open(in char*, int, mode_t);
- int shm_unlink(in char*);
+ int shm_open(const scope char*, int, mode_t);
+ int shm_unlink(const scope char*);
}
else version (DragonFlyBSD)
{
- int shm_open(in char*, int, mode_t);
- int shm_unlink(in char*);
+ int shm_open(const scope char*, int, mode_t);
+ int shm_unlink(const scope char*);
}
else version (Solaris)
{
- int shm_open(in char*, int, mode_t);
- int shm_unlink(in char*);
+ int shm_open(const scope char*, int, mode_t);
+ int shm_unlink(const scope char*);
}
else version (CRuntime_Bionic)
{
}
else version (CRuntime_Musl)
{
- int shm_open(in char*, int, mode_t);
- int shm_unlink(in char*);
+ int shm_open(const scope char*, int, mode_t);
+ int shm_unlink(const scope char*);
}
else version (CRuntime_UClibc)
{
- int shm_open(in char*, int, mode_t);
- int shm_unlink(in char*);
+ int shm_open(const scope char*, int, mode_t);
+ int shm_unlink(const scope char*);
}
else
{
size_t posix_tmi_length;
}
-int posix_mem_offset(in void*, size_t, off_t *, size_t *, int *);
+int posix_mem_offset(const scope void*, size_t, off_t *, size_t *, int *);
int posix_typed_mem_get_info(int, struct posix_typed_mem_info *);
-int posix_typed_mem_open(in char*, int, int);
+int posix_typed_mem_open(const scope char*, int, int);
*/
version (CRuntime_Glibc):
// Some of these may be from linux kernel headers.
extern (C):
+@system:
version (ARM) version = ARM_Any;
version (AArch64) version = ARM_Any;
version = Darwin;
nothrow @nogc extern(C):
+@system:
//
// XOpen (XSI)
enum RLIM_INFINITY = cast(c_ulong)(~0UL);
int getrlimit(int, rlimit*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
alias getrlimit getrlimit64;
alias setrlimit setrlimit64;
enum
static if (__USE_FILE_OFFSET64)
{
int getrlimit64(int, rlimit*);
- int setrlimit64(int, in rlimit*);
+ int setrlimit64(int, const scope rlimit*);
alias getrlimit = getrlimit64;
alias setrlimit = setrlimit64;
}
else
{
int getrlimit(int, rlimit*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
}
int getrusage(int, rusage*);
}
{
int getrlimit(int, rlimit*);
int getrusage(int, rusage*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
}
else version (Darwin)
{
int getrlimit(int, rlimit*);
int getrusage(int, rusage*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
}
else version (FreeBSD)
{
int getrlimit(int, rlimit*);
int getrusage(int, rusage*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
}
else version (NetBSD)
{
int getrlimit(int, rlimit*);
int getrusage(int, rusage*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
}
else version (OpenBSD)
{
int getrlimit(int, rlimit*);
int getrusage(int, rusage*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
}
else version (DragonFlyBSD)
{
int getrlimit(int, rlimit*);
int getrusage(int, rusage*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
}
else version (Solaris)
{
int getrlimit(int, rlimit*);
int getrusage(int, rusage*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
}
else version (CRuntime_UClibc)
{
static if (__USE_FILE_OFFSET64)
{
int getrlimit64(int, rlimit*);
- int setrlimit64(int, in rlimit*);
+ int setrlimit64(int, const scope rlimit*);
alias getrlimit = getrlimit64;
alias setrlimit = setrlimit64;
}
else
{
int getrlimit(int, rlimit*);
- int setrlimit(int, in rlimit*);
+ int setrlimit(int, const scope rlimit*);
}
int getrusage(int, rusage*);
}
*/
module core.sys.posix.sys.select;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.stdc.time; // for timespec
public import core.sys.posix.sys.time; // for timeval
public import core.sys.posix.sys.types; // for time_t
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// Required
FD_SETSIZE
-int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
*/
__result; }))
+/
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
}
else version (Darwin)
fdset.fds_bits[0 .. $] = 0;
}
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
}
else version (FreeBSD)
_p.__fds_bits[--_n] = 0;
}
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
}
else version (NetBSD)
_p.__fds_bits[--_n] = 0;
}
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
}
else version (OpenBSD)
_p.__fds_bits[--_n] = 0;
}
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
}
else version (DragonFlyBSD)
_p.__fds_bits[--_n] = 0;
}
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
}
else version (Solaris)
}
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
}
else version (CRuntime_Bionic)
{
fdset.fds_bits[0 .. $] = 0;
}
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
}
else version (CRuntime_Musl)
{
fdset.fds_bits[0 .. $] = 0;
}
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
}
else version (CRuntime_UClibc)
fdset.fds_bits[0 .. $] = 0;
}
- int pselect(int, fd_set*, fd_set*, fd_set*, in timespec*, in sigset_t*);
+ int pselect(int, fd_set*, fd_set*, fd_set*, const scope timespec*, const scope sigset_t*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*);
}
else
*/
module core.sys.posix.sys.shm;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for pid_t, time_t, key_t
public import core.sys.posix.sys.ipc;
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// XOpen (XSI)
time_t shm_ctime;
}
-void* shmat(int, in void*, int);
+void* shmat(int, const scope void*, int);
int shmctl(int, int, shmid_ds*);
-int shmdt(in void*);
+int shmdt(const scope void*);
int shmget(key_t, size_t, int);
*/
c_ulong __unused5;
}
- void* shmat(int, in void*, int);
+ void* shmat(int, const scope void*, int);
int shmctl(int, int, shmid_ds*);
- int shmdt(in void*);
+ int shmdt(const scope void*);
int shmget(key_t, size_t, int);
}
else version (FreeBSD)
time_t shm_ctime;
}
- void* shmat(int, in void*, int);
+ void* shmat(int, const scope void*, int);
int shmctl(int, int, shmid_ds*);
- int shmdt(in void*);
+ int shmdt(const scope void*);
int shmget(key_t, size_t, int);
}
else version (NetBSD)
void* shm_internal;
}
- void* shmat(int, in void*, int);
+ void* shmat(int, const scope void*, int);
int shmctl(int, int, shmid_ds*);
- int shmdt(in void*);
+ int shmdt(const scope void*);
int shmget(key_t, size_t, int);
}
else version (OpenBSD)
void* shm_internal;
}
- void* shmat(int, in void*, int);
+ void* shmat(int, const scope void*, int);
int shmctl(int, int, shmid_ds*);
- int shmdt(in void*);
+ int shmdt(const scope void*);
int shmget(key_t, size_t, int);
}
else version (DragonFlyBSD)
private void* shm_internal;
}
- void* shmat(int, in void*, int);
+ void* shmat(int, const scope void*, int);
int shmctl(int, int, shmid_ds*);
- int shmdt(in void*);
+ int shmdt(const scope void*);
int shmget(key_t, size_t, int);
}
else version (Darwin)
c_ulong swap_successes;
}
- void* shmat(int, in void*, int);
+ void* shmat(int, const scope void*, int);
int shmctl(int, int, shmid_ds*);
- int shmdt(in void*);
+ int shmdt(const scope void*);
int shmget(key_t, size_t, int);
}
*/
module core.sys.posix.sys.socket;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for ssize_t
public import core.sys.posix.sys.uio; // for iovec
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// Required
SHUT_WR
int accept(int, sockaddr*, socklen_t*);
-int bind(int, in sockaddr*, socklen_t);
-int connect(int, in sockaddr*, socklen_t);
+int bind(int, const scope sockaddr*, socklen_t);
+int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, sockaddr*, socklen_t*);
int getsockname(int, sockaddr*, socklen_t*);
int getsockopt(int, int, int, void*, socklen_t*);
ssize_t recv(int, void*, size_t, int);
ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
ssize_t recvmsg(int, msghdr*, int);
-ssize_t send(int, in void*, size_t, int);
-ssize_t sendmsg(int, in msghdr*, int);
-ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
-int setsockopt(int, int, int, in void*, socklen_t);
+ssize_t send(int, const scope void*, size_t, int);
+ssize_t sendmsg(int, const scope msghdr*, int);
+ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int);
int socket(int, int, int);
int sockatmark(int);
}
else
{
- extern (D) inout(ubyte)* CMSG_DATA( inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); }
+ extern (D) inout(ubyte)* CMSG_DATA( return inout(cmsghdr)* cmsg ) pure nothrow @nogc { return cast(ubyte*)( cmsg + 1 ); }
}
private inout(cmsghdr)* __cmsg_nxthdr(inout(msghdr)*, inout(cmsghdr)*) pure nothrow @nogc;
}
int accept(int, scope sockaddr*, scope socklen_t*);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, scope sockaddr*, scope socklen_t*);
int getsockname(int, scope sockaddr*, scope socklen_t*);
int getsockopt(int, int, int, scope void*, scope socklen_t*);
ssize_t recv(int, scope void*, size_t, int);
ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
ssize_t recvmsg(int, scope msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- ssize_t sendmsg(int, in msghdr*, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- int setsockopt(int, int, int, in void*, socklen_t);
+ ssize_t send(int, const scope void*, size_t, int);
+ ssize_t sendmsg(int, const scope msghdr*, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int) @safe;
int socket(int, int, int) @safe;
int sockatmark(int) @safe;
}
int accept(int, scope sockaddr*, scope socklen_t*);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, scope sockaddr*, scope socklen_t*);
int getsockname(int, scope sockaddr*, scope socklen_t*);
int getsockopt(int, int, int, scope void*, scope socklen_t*);
ssize_t recv(int, scope void*, size_t, int);
ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
ssize_t recvmsg(int, scope msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- ssize_t sendmsg(int, in msghdr*, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- int setsockopt(int, int, int, in void*, socklen_t);
+ ssize_t send(int, const scope void*, size_t, int);
+ ssize_t sendmsg(int, const scope msghdr*, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int) @safe;
int socket(int, int, int) @safe;
int sockatmark(int) @safe;
}
int accept(int, scope sockaddr*, scope socklen_t*);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, scope sockaddr*, scope socklen_t*);
int getsockname(int, scope sockaddr*, scope socklen_t*);
int getsockopt(int, int, int, scope void*, scope socklen_t*);
ssize_t recv(int, scope void*, size_t, int);
ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
ssize_t recvmsg(int, scope msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- ssize_t sendmsg(int, in msghdr*, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- int setsockopt(int, int, int, in void*, socklen_t);
+ ssize_t send(int, const scope void*, size_t, int);
+ ssize_t sendmsg(int, const scope msghdr*, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int) @safe;
int socket(int, int, int) @safe;
int sockatmark(int) @safe;
}
int accept(int, scope sockaddr*, scope socklen_t*);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, scope sockaddr*, scope socklen_t*);
int getsockname(int, scope sockaddr*, scope socklen_t*);
int getsockopt(int, int, int, scope void*, scope socklen_t*);
ssize_t recv(int, scope void*, size_t, int);
ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
ssize_t recvmsg(int, scope msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- ssize_t sendmsg(int, in msghdr*, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- int setsockopt(int, int, int, in void*, socklen_t);
+ ssize_t send(int, const scope void*, size_t, int);
+ ssize_t sendmsg(int, const scope msghdr*, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int) @safe;
int socket(int, int, int) @safe;
int sockatmark(int) @safe;
}
int accept(int, scope sockaddr*, scope socklen_t*);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, scope sockaddr*, scope socklen_t*);
int getsockname(int, scope sockaddr*, scope socklen_t*);
int getsockopt(int, int, int, scope void*, scope socklen_t*);
ssize_t recv(int, scope void*, size_t, int);
ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
ssize_t recvmsg(int, scope msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- ssize_t sendmsg(int, in msghdr*, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- int setsockopt(int, int, int, in void*, socklen_t);
+ ssize_t send(int, const scope void*, size_t, int);
+ ssize_t sendmsg(int, const scope msghdr*, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int) @safe;
int socket(int, int, int) @safe;
int sockatmark(int) @safe;
gid_t cmcred_gid;
short cmcred_ngroups;
gid_t[CMGROUP_MAX] cmcred_groups;
- };
+ }
enum : uint
{
int hdr_cnt;
iovec * trailers;
int trl_cnt;
- };
+ }
*/
int accept(int, sockaddr*, socklen_t*);
// int accept4(int, sockaddr*, socklen_t*, int);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
// int extconnect(int, int, sockaddr*, socklen_t);
int getpeername(int, sockaddr*, socklen_t*);
int getsockname(int, sockaddr*, socklen_t*);
ssize_t recv(int, void*, size_t, int);
ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
ssize_t recvmsg(int, msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- ssize_t sendmsg(int, in msghdr*, int);
+ ssize_t send(int, const scope void*, size_t, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ ssize_t sendmsg(int, const scope msghdr*, int);
// int sendfile(int, int, off_t, size_t, sf_hdtr *, off_t *, int);
- int setsockopt(int, int, int, in void*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int);
int sockatmark(int);
int socket(int, int, int);
}
int accept(int, scope sockaddr*, scope socklen_t*);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, scope sockaddr*, scope socklen_t*);
int getsockname(int, scope sockaddr*, scope socklen_t*);
int getsockopt(int, int, int, scope void*, scope socklen_t*);
ssize_t recv(int, scope void*, size_t, int);
ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
ssize_t recvmsg(int, scope msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- ssize_t sendmsg(int, in msghdr*, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- int setsockopt(int, int, int, in void*, socklen_t);
+ ssize_t send(int, const scope void*, size_t, int);
+ ssize_t sendmsg(int, const scope msghdr*, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int) @safe;
int socket(int, int, int) @safe;
int sockatmark(int) @safe;
enum SOCK_RDM = 4;
int accept(int, scope sockaddr*, scope socklen_t*);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, scope sockaddr*, scope socklen_t*);
int getsockname(int, scope sockaddr*, scope socklen_t*);
int getsockopt(int, int, int, scope void*, scope socklen_t*);
ssize_t recv(int, scope void*, size_t, int);
ssize_t recvfrom(int, scope void*, size_t, int, scope sockaddr*, scope socklen_t*);
int recvmsg(int, scope msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- int sendmsg(int, in msghdr*, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- int setsockopt(int, int, int, in void*, socklen_t);
+ ssize_t send(int, const scope void*, size_t, int);
+ int sendmsg(int, const scope msghdr*, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int) @safe;
int socket(int, int, int) @safe;
int sockatmark(int) @safe;
int msg_flags;
}
int accept(int, sockaddr*, socklen_t*);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, sockaddr*, socklen_t*);
int getsockname(int, sockaddr*, socklen_t*);
int getsockopt(int, int, int, void*, socklen_t*);
ssize_t recv(int, void*, size_t, int);
ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
ssize_t recvmsg(int, msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- ssize_t sendmsg(int, in msghdr*, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- int setsockopt(int, int, int, in void*, socklen_t);
+ ssize_t send(int, const scope void*, size_t, int);
+ ssize_t sendmsg(int, const scope msghdr*, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int);
int socket(int, int, int);
int sockatmark(int);
}
int accept(int, sockaddr*, socklen_t*);
- int bind(int, in sockaddr*, socklen_t);
- int connect(int, in sockaddr*, socklen_t);
+ int bind(int, const scope sockaddr*, socklen_t);
+ int connect(int, const scope sockaddr*, socklen_t);
int getpeername(int, sockaddr*, socklen_t*);
int getsockname(int, sockaddr*, socklen_t*);
int getsockopt(int, int, int, void*, socklen_t*);
ssize_t recv(int, void*, size_t, int);
ssize_t recvfrom(int, void*, size_t, int, sockaddr*, socklen_t*);
ssize_t recvmsg(int, msghdr*, int);
- ssize_t send(int, in void*, size_t, int);
- ssize_t sendmsg(int, in msghdr*, int);
- ssize_t sendto(int, in void*, size_t, int, in sockaddr*, socklen_t);
- int setsockopt(int, int, int, in void*, socklen_t);
+ ssize_t send(int, const scope void*, size_t, int);
+ ssize_t sendmsg(int, const scope msghdr*, int);
+ ssize_t sendto(int, const scope void*, size_t, int, const scope sockaddr*, socklen_t);
+ int setsockopt(int, int, int, const scope void*, socklen_t);
int shutdown(int, int);
int socket(int, int, int);
int sockatmark(int);
*/
module core.sys.posix.sys.stat;
-private import core.sys.posix.config;
-private import core.stdc.stdint;
-private import core.sys.posix.time; // for timespec
+import core.sys.posix.config;
+import core.stdc.stdint;
+import core.sys.posix.time; // for timespec
public import core.sys.posix.sys.types; // for off_t, mode_t
version (OSX)
version (RISCV32) version = RISCV_Any;
version (RISCV64) version = RISCV_Any;
+version (SPARC) version = SPARC_Any;
+version (SPARC64) version = SPARC_Any;
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// Required
S_TYPEISSEM(buf)
S_TYPEISSHM(buf)
-int chmod(in char*, mode_t);
+int chmod(const scope char*, mode_t);
int fchmod(int, mode_t);
int fstat(int, stat*);
-int lstat(in char*, stat*);
-int mkdir(in char*, mode_t);
-int mkfifo(in char*, mode_t);
-int stat(in char*, stat*);
+int lstat(const scope char*, stat*);
+int mkdir(const scope char*, mode_t);
+int mkfifo(const scope char*, mode_t);
+int stat(const scope char*, stat*);
mode_t umask(mode_t);
*/
timespec st_atim;
timespec st_mtim;
timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
timespec st_atim;
timespec st_mtim;
timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
__timespec st_atim;
__timespec st_mtim;
__timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
timespec st_atim;
timespec st_mtim;
timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
timespec st_atim;
timespec st_mtim;
timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
__timespec st_atim;
__timespec st_mtim;
__timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
__timespec st_atim;
__timespec st_mtim;
__timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
__timespec st_atim;
__timespec st_mtim;
__timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
else
static assert(stat_t.sizeof == 104);
}
- else version (SPARC64)
+ else version (SPARC_Any)
{
private
{
struct stat_t
{
__dev_t st_dev;
- ushort __pad1;
- __ino_t st_ino;
+ static if (__WORDSIZE == 64 || !__USE_FILE_OFFSET64)
+ {
+ ushort __pad1;
+ __ino_t st_ino;
+ }
+ else
+ {
+ __ino64_t st_ino;
+ }
__mode_t st_mode;
__nlink_t st_nlink;
__uid_t st_uid;
__timespec st_atim;
__timespec st_mtim;
__timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
c_ulong __unused4;
c_ulong __unused5;
}
- static assert(stat_t.sizeof == 144);
+ static if (__USE_LARGEFILE64) alias stat_t stat64_t;
+
+ static if (__WORDSIZE == 64)
+ static assert(stat_t.sizeof == 144);
+ else static if (__USE_FILE_OFFSET64)
+ static assert(stat_t.sizeof == 104);
+ else
+ static assert(stat_t.sizeof == 88);
+
}
else version (S390)
{
__timespec st_atim;
__timespec st_mtim;
__timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
__timespec st_atim;
__timespec st_mtim;
__timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
timespec st_atim;
timespec st_mtim;
timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
int32_t st_lspare;
int64_t st_qspare1; /* was recursive change detect */
int64_t st_qspare2;
- };
+ }
enum S_IRUSR = 0x100; // octal 0000400
enum S_IWUSR = 0x080; // octal 0000200
timespec st_atim;
timespec st_mtim;
timespec st_ctim;
- extern(D)
+ extern(D) @safe @property inout pure nothrow
{
- @property ref time_t st_atime() { return st_atim.tv_sec; }
- @property ref time_t st_mtime() { return st_mtim.tv_sec; }
- @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+ ref inout(time_t) st_atime() return { return st_atim.tv_sec; }
+ ref inout(time_t) st_mtime() return { return st_mtim.tv_sec; }
+ ref inout(time_t) st_ctime() return { return st_ctim.tv_sec; }
}
}
else
static assert(false, "Unsupported platform");
}
-int chmod(in char*, mode_t);
+int chmod(const scope char*, mode_t);
int fchmod(int, mode_t);
//int fstat(int, stat_t*);
-//int lstat(in char*, stat_t*);
-int mkdir(in char*, mode_t);
-int mkfifo(in char*, mode_t);
-//int stat(in char*, stat_t*);
+//int lstat(const scope char*, stat_t*);
+int mkdir(const scope char*, mode_t);
+int mkfifo(const scope char*, mode_t);
+//int stat(const scope char*, stat_t*);
mode_t umask(mode_t);
version (CRuntime_Glibc)
int fstat64(int, stat_t*) @trusted;
alias fstat64 fstat;
- int lstat64(in char*, stat_t*);
+ int lstat64(const scope char*, stat_t*);
alias lstat64 lstat;
- int stat64(in char*, stat_t*);
+ int stat64(const scope char*, stat_t*);
alias stat64 stat;
}
else
{
int fstat(int, stat_t*) @trusted;
- int lstat(in char*, stat_t*);
- int stat(in char*, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
}
}
else version (Solaris)
version (D_LP64)
{
int fstat(int, stat_t*) @trusted;
- int lstat(in char*, stat_t*);
- int stat(in char*, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
static if (__USE_LARGEFILE64)
{
int fstat64(int, stat_t*) @trusted;
alias fstat64 fstat;
- int lstat64(in char*, stat_t*);
+ int lstat64(const scope char*, stat_t*);
alias lstat64 lstat;
- int stat64(in char*, stat_t*);
+ int stat64(const scope char*, stat_t*);
alias stat64 stat;
}
else
{
int fstat(int, stat_t*) @trusted;
- int lstat(in char*, stat_t*);
- int stat(in char*, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
}
}
}
// inode functions by appending $INODE64 to newer 64-bit inode functions.
version (OSX)
{
- pragma(mangle, "fstat$INODE64") int fstat(int, stat_t*);
- pragma(mangle, "lstat$INODE64") int lstat(in char*, stat_t*);
- pragma(mangle, "stat$INODE64") int stat(in char*, stat_t*);
+ version (AArch64)
+ {
+ int fstat(int, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
+ }
+ else
+ {
+ pragma(mangle, "fstat$INODE64") int fstat(int, stat_t*);
+ pragma(mangle, "lstat$INODE64") int lstat(const scope char*, stat_t*);
+ pragma(mangle, "stat$INODE64") int stat(const scope char*, stat_t*);
+ }
}
else
{
int fstat(int, stat_t*);
- int lstat(in char*, stat_t*);
- int stat(in char*, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
}
}
else version (FreeBSD)
{
- int fstat(int, stat_t*);
- int lstat(in char*, stat_t*);
- int stat(in char*, stat_t*);
+ version (GNU)
+ {
+ int fstat(int, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
+ }
+ else
+ {
+ static if (__FreeBSD_version >= INO64_FIRST)
+ {
+ pragma(mangle, "fstat@FBSD_1.5") int fstat(int, stat_t*);
+ pragma(mangle, "lstat@FBSD_1.5") int lstat(const scope char*, stat_t*);
+ pragma(mangle, "stat@FBSD_1.5") int stat(const scope char*, stat_t*);
+ }
+ else
+ {
+ pragma(mangle, "fstat@FBSD_1.0") int fstat(int, stat_t*);
+ pragma(mangle, "lstat@FBSD_1.0") int lstat(const scope char*, stat_t*);
+ pragma(mangle, "stat@FBSD_1.0") int stat(const scope char*, stat_t*);
+ }
+ }
}
else version (NetBSD)
{
int __fstat50(int, stat_t*);
- int __lstat50(in char*, stat_t*);
- int __stat50(in char*, stat_t*);
+ int __lstat50(const scope char*, stat_t*);
+ int __stat50(const scope char*, stat_t*);
alias __fstat50 fstat;
alias __lstat50 lstat;
alias __stat50 stat;
else version (OpenBSD)
{
int fstat(int, stat_t*);
- int lstat(in char*, stat_t*);
- int stat(in char*, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
}
else version (DragonFlyBSD)
{
int fstat(int, stat_t*);
- int lstat(in char*, stat_t*);
- int stat(in char*, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
}
else version (CRuntime_Bionic)
{
int fstat(int, stat_t*) @trusted;
- int lstat(in char*, stat_t*);
- int stat(in char*, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
}
else version (CRuntime_Musl)
{
- int stat(in char*, stat_t*);
+ int stat(const scope char*, stat_t*);
int fstat(int, stat_t*);
- int lstat(in char*, stat_t*);
+ int lstat(const scope char*, stat_t*);
alias fstat fstat64;
alias lstat lstat64;
int fstat64(int, stat_t*) @trusted;
alias fstat64 fstat;
- int lstat64(in char*, stat_t*);
+ int lstat64(const scope char*, stat_t*);
alias lstat64 lstat;
- int stat64(in char*, stat_t*);
+ int stat64(const scope char*, stat_t*);
alias stat64 stat;
}
else
{
int fstat(int, stat_t*) @trusted;
- int lstat(in char*, stat_t*);
- int stat(in char*, stat_t*);
+ int lstat(const scope char*, stat_t*);
+ int stat(const scope char*, stat_t*);
}
}
enum S_IFLNK = 0xA000; // octal 0120000
enum S_IFSOCK = 0xC000; // octal 0140000
- int mknod(in char*, mode_t, dev_t);
+ int mknod(const scope char*, mode_t, dev_t);
}
else version (Darwin)
{
enum S_IFLNK = 0xA000; // octal 0120000
enum S_IFSOCK = 0xC000; // octal 0140000
- int mknod(in char*, mode_t, dev_t);
+ int mknod(const scope char*, mode_t, dev_t);
}
else version (FreeBSD)
{
enum S_IFLNK = 0xA000; // octal 0120000
enum S_IFSOCK = 0xC000; // octal 0140000
- int mknod(in char*, mode_t, dev_t);
+ version (GNU)
+ {
+ int mknod(const scope char*, mode_t, dev_t);
+ }
+ else
+ {
+ static if (__FreeBSD_version >= INO64_FIRST)
+ pragma(mangle, "mknod@FBSD_1.5") int mknod(const scope char*, mode_t, dev_t);
+ else
+ pragma(mangle, "mknod@FBSD_1.0") int mknod(const scope char*, mode_t, dev_t);
+ }
}
else version (NetBSD)
{
enum S_IFLNK = 0xA000; // octal 0120000
enum S_IFSOCK = 0xC000; // octal 0140000
- int mknod(in char*, mode_t, dev_t);
+ int mknod(const scope char*, mode_t, dev_t);
}
else version (OpenBSD)
{
enum S_IFLNK = 0xA000; // octal 0120000
enum S_IFSOCK = 0xC000; // octal 0140000
- int mknod(in char*, mode_t, dev_t);
+ int mknod(const scope char*, mode_t, dev_t);
}
else version (DragonFlyBSD)
{
enum S_IFLNK = 0xA000; // octal 0120000
enum S_IFSOCK = 0xC000; // octal 0140000
- int mknod(in char*, mode_t, dev_t);
+ int mknod(const scope char*, mode_t, dev_t);
}
else version (Solaris)
{
enum S_IFDOOR = 0xD000;
enum S_IFPORT = 0xE000;
- int mknod(in char*, mode_t, dev_t);
+ int mknod(const scope char*, mode_t, dev_t);
}
else version (CRuntime_Bionic)
{
enum S_IFLNK = 0xA000; // octal 0120000
enum S_IFSOCK = 0xC000; // octal 0140000
- int mknod(in char*, mode_t, dev_t);
+ int mknod(const scope char*, mode_t, dev_t);
}
else version (CRuntime_Musl)
{
S_IFSOCK = 0xC000, // octal 0140000
}
- int mknod(in char*, mode_t, dev_t);
+ int mknod(const scope char*, mode_t, dev_t);
}
else version (CRuntime_UClibc)
{
enum S_IFLNK = 0xA000; // octal 0120000
enum S_IFSOCK = 0xC000; // octal 0140000
- int mknod(in char*, mode_t, dev_t);
+ int mknod(const scope char*, mode_t, dev_t);
}
else
{
The Open Group Base Specifications Issue 7 IEEE Std 1003.1, 2018 Edition)
+/
module core.sys.posix.sys.statvfs;
-private import core.stdc.config;
-private import core.sys.posix.config;
+import core.stdc.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types;
version (Posix):
extern (C) :
nothrow:
@nogc:
+@system:
version (CRuntime_Glibc) {
static if (__WORDSIZE == 32)
enum FFlag
{
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_RDONLY = 1, /* read only filesystem */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_SYNCHRONOUS = 2, /* fs written synchronously */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_NOEXEC = 4, /* can't exec from filesystem */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_NOSUID = 8, /* don't honor setuid fs bits */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_NFS4ACLS = 16, /* enable NFS version 4 ACLs */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_UNION = 32, /* union with underlying fs */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_ASYNC = 64, /* fs written asynchronously */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_SUIDDIR = 128, /* special SUID dir handling */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_SOFTDEP = 256, /* using soft updates */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_NOSYMFOLLOW = 512, /* do not follow symlinks */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_GJOURNAL = 1024, /* GEOM journal support enabled */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_MULTILABEL = 2048, /* MAC support for objects */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_ACLS = 4096, /* ACL support enabled */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_NOATIME = 8192, /* dont update file access time */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_NOCLUSTERR = 16384, /* disable cluster read */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_NOCLUSTERW = 32768, /* disable cluster write */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_SUJ = 65536, /* using journaled soft updates */
// @@@DEPRECATED_2.091@@@
+ deprecated("Moved to core.sys.freebsd.sys.mount to correspond to C header file sys/mount.h")
MNT_AUTOMOUNTED = 131072 /* mounted by automountd(8) */
}
enum uint ST_RDONLY = 0x1;
enum uint ST_NOSUID = 0x2;
- int fstatvfs(int, statvfs_t*);
- int statvfs(const char*, statvfs_t*);
+ version (GNU)
+ {
+ int fstatvfs(int, statvfs_t*);
+ int statvfs(const char*, statvfs_t*);
+ }
+ else
+ {
+ pragma(mangle, "fstatvfs@FBSD_1.0") int fstatvfs(int, statvfs_t*);
+ pragma(mangle, "statvfs@FBSD_1.0") int statvfs(const char*, statvfs_t*);
+ }
}
else
{
*/
module core.sys.posix.sys.time;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for time_t, suseconds_t
public import core.sys.posix.sys.select; // for fd_set, FD_CLR() FD_ISSET() FD_SET() FD_ZERO() FD_SETSIZE, select()
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// XOpen (XSI)
int getitimer(int, itimerval*);
int gettimeofday(timeval*, void*);
int select(int, fd_set*, fd_set*, fd_set*, timeval*); (defined in core.sys.posix.sys.signal)
-int setitimer(int, in itimerval*, itimerval*);
-int utimes(in char*, ref const(timeval)[2]); // LEGACY
+int setitimer(int, const scope itimerval*, itimerval*);
+int utimes(const scope char*, ref const(timeval)[2]); // LEGACY
*/
version (CRuntime_Glibc)
int getitimer(int, itimerval*);
int gettimeofday(timeval*, void*);
- int setitimer(int, in itimerval*, itimerval*);
- int utimes(in char*, ref const(timeval)[2]); // LEGACY
+ int setitimer(int, const scope itimerval*, itimerval*);
+ int utimes(const scope char*, ref const(timeval)[2]); // LEGACY
}
else version (CRuntime_Musl)
{
suseconds_t tv_usec;
}
int gettimeofday(timeval*, void*);
- int utimes(in char*, ref const(timeval)[2]);
+ int utimes(const scope char*, ref const(timeval)[2]);
}
else version (Darwin)
{
int getitimer(int, itimerval*);
int gettimeofday(timeval*, timezone_t*); // timezone_t* is normally void*
- int setitimer(int, in itimerval*, itimerval*);
- int utimes(in char*, ref const(timeval)[2]);
+ int setitimer(int, const scope itimerval*, itimerval*);
+ int utimes(const scope char*, ref const(timeval)[2]);
}
else version (FreeBSD)
{
int getitimer(int, itimerval*);
int gettimeofday(timeval*, timezone_t*); // timezone_t* is normally void*
- int setitimer(int, in itimerval*, itimerval*);
- int utimes(in char*, ref const(timeval)[2]);
+ int setitimer(int, const scope itimerval*, itimerval*);
+ int utimes(const scope char*, ref const(timeval)[2]);
}
else version (NetBSD)
{
int getitimer(int, itimerval*);
int gettimeofday(timeval*, void*); // timezone_t* is normally void*
- int setitimer(int, in itimerval*, itimerval*);
- int utimes(in char*, ref const(timeval)[2]);
+ int setitimer(int, const scope itimerval*, itimerval*);
+ int utimes(const scope char*, ref const(timeval)[2]);
}
else version (OpenBSD)
{
int getitimer(int, itimerval*);
int gettimeofday(timeval*, timezone_t*);
- int setitimer(int, in itimerval*, itimerval*);
- int utimes(in char*, ref const(timeval)[2]);
+ int setitimer(int, const scope itimerval*, itimerval*);
+ int utimes(const scope char*, ref const(timeval)[2]);
}
else version (DragonFlyBSD)
{
int getitimer(int, itimerval*);
int gettimeofday(timeval*, timezone_t*); // timezone_t* is normally void*
- int setitimer(int, in itimerval*, itimerval*);
- int utimes(in char*, ref const(timeval)[2]);
+ int setitimer(int, const scope itimerval*, itimerval*);
+ int utimes(const scope char*, ref const(timeval)[2]);
}
else version (Solaris)
{
int getitimer(int, itimerval*);
int gettimeofday(timeval*, void*);
- int setitimer(int, in itimerval*, itimerval*);
- int utimes(in char*, ref const(timeval)[2]);
+ int setitimer(int, const scope itimerval*, itimerval*);
+ int utimes(const scope char*, ref const(timeval)[2]);
}
else version (CRuntime_Bionic)
{
int getitimer(int, itimerval*);
int gettimeofday(timeval*, timezone_t*);
- int setitimer(int, in itimerval*, itimerval*);
- int utimes(in char*, ref const(timeval)[2]);
+ int setitimer(int, const scope itimerval*, itimerval*);
+ int utimes(const scope char*, ref const(timeval)[2]);
}
else version (CRuntime_UClibc)
{
int getitimer(int, itimerval*);
int gettimeofday(timeval*, void*);
- int setitimer(int, in itimerval*, itimerval*);
- int utimes(in char*, ref const(timeval)[2]);
+ int setitimer(int, const scope itimerval*, itimerval*);
+ int utimes(const scope char*, ref const(timeval)[2]);
}
else
{
version (Posix):
nothrow @nogc:
+@system:
version (Darwin)
{
*/
module core.sys.posix.sys.types;
-private import core.sys.posix.config;
-private import core.stdc.stdint;
+import core.sys.posix.config;
+import core.stdc.stdint;
public import core.stdc.stddef;
version (OSX)
version (Posix):
extern (C):
+@system:
//
// bits/typesizes.h -- underlying types for *_t.
alias int pid_t;
alias uint uid_t;
alias uint gid_t;
+
+ /**
+ * Musl versions before v1.2.0 (up to v1.1.24) had different
+ * definitions for `time_t` for 32 bits.
+ * This was changed to always be 64 bits in v1.2.0:
+ * https://musl.libc.org/time64.html
+ * This change was only for 32 bits system and
+ * didn't affect 64 bits systems
+ *
+ * To check previous definitions, `grep` for `time_t` in `arch/`,
+ * and the result should be (in v1.1.24):
+ * ---
+ * // arch/riscv64/bits/alltypes.h.in:20:TYPEDEF long time_t;
+ * // arch/s390x/bits/alltypes.h.in:17:TYPEDEF long time_t;
+ * // arch/sh/bits/alltypes.h.in:21:TYPEDEF long time_t;
+ * ---
+ *
+ * In order to be compatible with old versions of Musl,
+ * one can recompile druntime with `CRuntime_Musl_Pre_Time64`.
+ */
version (D_X32)
alias long time_t;
- else
+ else version (CRuntime_Musl_Pre_Time64)
alias c_long time_t;
+ else
+ alias long time_t;
+
alias c_long clock_t;
alias c_ulong pthread_t;
version (D_LP64)
enum __SIZEOF_PTHREAD_BARRIER_T = 32;
enum __SIZEOF_PTHREAD_BARRIERATTR_T = 4;
}
+ else version (SPARC)
+ {
+ enum __SIZEOF_PTHREAD_ATTR_T = 36;
+ enum __SIZEOF_PTHREAD_MUTEX_T = 24;
+ enum __SIZEOF_PTHREAD_MUTEXATTR_T = 4;
+ enum __SIZEOF_PTHREAD_COND_T = 48;
+ enum __SIZEOF_PTHREAD_CONDATTR_T = 4;
+ enum __SIZEOF_PTHREAD_RWLOCK_T = 32;
+ enum __SIZEOF_PTHREAD_RWLOCKATTR_T = 8;
+ enum __SIZEOF_PTHREAD_BARRIER_T = 20;
+ enum __SIZEOF_PTHREAD_BARRIERATTR_T = 4;
+ }
else version (SPARC64)
{
enum __SIZEOF_PTHREAD_ATTR_T = 56;
*/
module core.sys.posix.sys.uio;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for ssize_t
version (OSX)
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// Required
ssize_t // from core.sys.posix.sys.types
size_t // from core.sys.posix.sys.types
-ssize_t readv(int, in iovec*, int);
-ssize_t writev(int, in iovec*, int);
+ssize_t readv(int, const scope iovec*, int);
+ssize_t writev(int, const scope iovec*, int);
*/
version (CRuntime_Glibc)
size_t iov_len;
}
- ssize_t readv(int, in iovec*, int);
- ssize_t writev(int, in iovec*, int);
+ ssize_t readv(int, const scope iovec*, int);
+ ssize_t writev(int, const scope iovec*, int);
}
else version (Darwin)
{
size_t iov_len;
}
- ssize_t readv(int, in iovec*, int);
- ssize_t writev(int, in iovec*, int);
+ ssize_t readv(int, const scope iovec*, int);
+ ssize_t writev(int, const scope iovec*, int);
}
else version (FreeBSD)
{
size_t iov_len;
}
- ssize_t readv(int, in iovec*, int);
- ssize_t writev(int, in iovec*, int);
+ ssize_t readv(int, const scope iovec*, int);
+ ssize_t writev(int, const scope iovec*, int);
}
else version (NetBSD)
{
size_t iov_len;
}
- ssize_t readv(int, in iovec*, int);
- ssize_t writev(int, in iovec*, int);
+ ssize_t readv(int, const scope iovec*, int);
+ ssize_t writev(int, const scope iovec*, int);
}
else version (OpenBSD)
{
size_t iov_len;
}
- ssize_t readv(int, in iovec*, int);
- ssize_t writev(int, in iovec*, int);
+ ssize_t readv(int, const scope iovec*, int);
+ ssize_t writev(int, const scope iovec*, int);
}
else version (DragonFlyBSD)
{
size_t iov_len;
}
- ssize_t readv(int, in iovec*, int);
- ssize_t writev(int, in iovec*, int);
+ ssize_t readv(int, const scope iovec*, int);
+ ssize_t writev(int, const scope iovec*, int);
}
else version (Solaris)
{
size_t iov_len;
}
- ssize_t readv(int, in iovec*, int);
- ssize_t writev(int, in iovec*, int);
+ ssize_t readv(int, const scope iovec*, int);
+ ssize_t writev(int, const scope iovec*, int);
}
else version (CRuntime_Bionic)
{
size_t iov_len;
}
- int readv(int, in iovec*, int);
- int writev(int, in iovec*, int);
+ int readv(int, const scope iovec*, int);
+ int writev(int, const scope iovec*, int);
}
else version (CRuntime_Musl)
{
size_t iov_len;
}
- ssize_t readv(int, in iovec*, int);
- ssize_t writev(int, in iovec*, int);
+ ssize_t readv(int, const scope iovec*, int);
+ ssize_t writev(int, const scope iovec*, int);
}
else version (CRuntime_UClibc)
{
size_t iov_len;
}
- ssize_t readv(int, in iovec*, int);
- ssize_t writev(int, in iovec*, int);
+ ssize_t readv(int, const scope iovec*, int);
+ ssize_t writev(int, const scope iovec*, int);
}
else
{
version (Posix):
extern(C):
+@system:
public import core.sys.posix.sys.socket: sa_family_t;
extern(C):
nothrow:
@nogc:
+@system:
version (CRuntime_Glibc)
{
*/
module core.sys.posix.sys.wait;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for id_t, pid_t
public import core.sys.posix.signal; // for siginfo_t (XSI)
//public import core.sys.posix.resource; // for rusage (XSI)
version (Posix):
extern (C) nothrow @nogc:
+@system:
//
// Required
version (CRuntime_Glibc)
{
+ @safe pure:
+
enum WNOHANG = 1;
enum WUNTRACED = 2;
}
else version (Darwin)
{
+ @safe pure:
+
enum WNOHANG = 1;
enum WUNTRACED = 2;
}
else version (FreeBSD)
{
+ @safe pure:
+
enum WNOHANG = 1;
enum WUNTRACED = 2;
}
else version (NetBSD)
{
+ @safe pure:
+
enum WNOHANG = 1;
enum WUNTRACED = 2;
}
else version (OpenBSD)
{
+ @safe pure:
+
enum WNOHANG = 1;
enum WUNTRACED = 2;
}
else version (DragonFlyBSD)
{
+ @safe pure:
+
enum WNOHANG = 1;
enum WUNTRACED = 2;
}
else version (Solaris)
{
+ @safe pure:
+
enum WNOHANG = 64;
enum WUNTRACED = 4;
}
else version (CRuntime_Bionic)
{
+ @safe pure:
+
enum WNOHANG = 1;
enum WUNTRACED = 2;
}
else version (CRuntime_Musl)
{
+ @safe pure:
+
enum WNOHANG = 1;
enum WUNTRACED = 2;
}
else version (CRuntime_UClibc)
{
+ @safe pure:
+
enum WNOHANG = 1;
enum WUNTRACED = 2;
enum WSTOPPED = WUNTRACED;
enum WCONTINUED = 4;
enum WNOWAIT = 8;
+ enum WEXITED = 16;
+ enum WTRAPPED = 32;
+
+ enum idtype_t
+ {
+ P_UID,
+ P_GID,
+ P_SID,
+ P_JAILID,
+ P_PID,
+ P_PPID,
+ P_PGID,
+ P_CID,
+ P_ALL,
+ P_LWPID,
+ P_TASKID,
+ P_PROJID,
+ P_POOLID,
+ P_CTID,
+ P_CPUID,
+ P_PSETID
+ }
- // http://www.freebsd.org/projects/c99/
+ int waitid(idtype_t, id_t, siginfo_t*, int);
}
else version (NetBSD)
{
version (Posix):
extern (C) nothrow @nogc:
+@system:
version (CRuntime_Glibc)
{
LOG_NOTICE = 5, /* normal but significant condition */
LOG_INFO = 6, /* informational */
LOG_DEBUG = 7, /* debug-level messages */
- };
+ }
//OPTIONS
enum {
LOG_NDELAY = 0x08, /* don't delay open */
LOG_NOWAIT = 0x10, /* don't wait for console forks: DEPRECATED */
LOG_PERROR = 0x20, /* log to stderr as well */
- };
+ }
//FACILITY
enum {
LOG_LOCAL7 = (23<<3), /* reserved for local use */
LOG_NFACILITIES = 24, /* current number of facilities */
- };
+ }
int LOG_MASK(int pri) { return 1 << pri; } /* mask for one priority */
int LOG_UPTO(int pri) { return (1 << (pri+1)) - 1; } /* all priorities through pri */
LOG_NOTICE = 5, /* normal but significant condition */
LOG_INFO = 6, /* informational */
LOG_DEBUG = 7, /* debug-level messages */
- };
+ }
//OPTIONS
enum {
LOG_ODELAY = 0x04, /* delay open until first syslog() (default) */
LOG_NDELAY = 0x08, /* don't delay open */
LOG_NOWAIT = 0x10, /* don't wait for console forks: DEPRECATED */
- };
+ }
//FACILITY
enum {
LOG_LOCAL7 = (23<<3), /* reserved for local use */
LOG_NFACILITIES = 24, /* current number of facilities */
- };
+ }
int LOG_MASK(int pri) { return 1 << pri; } /* mask for one priority */
int LOG_UPTO(int pri) { return (1 << (pri+1)) - 1; } /* all priorities through pri */
LOG_NOTICE = 5, /* normal but significant condition */
LOG_INFO = 6, /* informational */
LOG_DEBUG = 7, /* debug-level messages */
- };
+ }
//OPTIONS
enum {
LOG_NDELAY = 0x08, /* don't delay open */
LOG_NOWAIT = 0x10, /* don't wait for console forks: DEPRECATED */
LOG_PERROR = 0x20, /* log to stderr as well */
- };
+ }
//FACILITY
enum {
LOG_LOCAL7 = (23<<3), /* reserved for local use */
LOG_NFACILITIES = 24, /* current number of facilities */
- };
+ }
int LOG_MASK(int pri) { return 1 << pri; } /* mask for one priority */
int LOG_UPTO(int pri) { return (1 << (pri+1)) - 1; } /* all priorities through pri */
LOG_NOTICE = 5, /* normal but significant condition */
LOG_INFO = 6, /* informational */
LOG_DEBUG = 7, /* debug-level messages */
- };
+ }
//OPTIONS
enum {
LOG_NDELAY = 0x08, /* don't delay open */
LOG_NOWAIT = 0x10, /* don't wait for console forks: DEPRECATED */
LOG_PERROR = 0x20, /* log to stderr as well */
- };
+ }
//FACILITY
enum {
LOG_LOCAL7 = (23<<3), /* reserved for local use */
LOG_NFACILITIES = 24, /* current number of facilities */
- };
+ }
int LOG_MASK(int pri) { return 1 << pri; } /* mask for one priority */
int LOG_UPTO(int pri) { return (1 << (pri+1)) - 1; } /* all priorities through pri */
LOG_NOTICE = 5, /* normal but significant condition */
LOG_INFO = 6, /* informational */
LOG_DEBUG = 7, /* debug-level messages */
- };
+ }
//OPTIONS
enum {
LOG_NDELAY = 0x08, /* don't delay open */
LOG_NOWAIT = 0x10, /* don't wait for console forks: DEPRECATED */
LOG_PERROR = 0x20, /* log to stderr as well */
- };
+ }
//FACILITY
enum {
LOG_LOCAL7 = (23<<3), /* reserved for local use */
LOG_NFACILITIES = 24, /* current number of facilities */
- };
+ }
int LOG_MASK(int pri) { return 1 << pri; } /* mask for one priority */
int LOG_UPTO(int pri) { return (1 << (pri+1)) - 1; } /* all priorities through pri */
LOG_NOTICE = 5, /* normal but significant condition */
LOG_INFO = 6, /* informational */
LOG_DEBUG = 7, /* debug-level messages */
- };
+ }
//OPTIONS
enum {
LOG_CONS = 0x02, /* log on the console if errors in sending */
LOG_NDELAY = 0x08, /* don't delay open */
LOG_NOWAIT = 0x10, /* don't wait for console forks: DEPRECATED */
- };
+ }
//FACILITY
enum {
LOG_LOCAL7 = (23<<3), /* reserved for local use */
LOG_NFACILITIES = 24, /* current number of facilities */
- };
+ }
int LOG_MASK(int pri) { return 1 << pri; } /* mask for one priority */
int LOG_UPTO(int pri) { return (1 << (pri+1)) - 1; } /* all priorities through pri */
LOG_NOTICE = 5, /* normal but significant condition */
LOG_INFO = 6, /* informational */
LOG_DEBUG = 7, /* debug-level messages */
- };
+ }
//OPTIONS
enum {
LOG_NDELAY = 0x08, /* don't delay open */
LOG_NOWAIT = 0x10, /* don't wait for console forks: DEPRECATED */
LOG_PERROR = 0x20, /* log to stderr as well */
- };
+ }
//FACILITY
enum {
LOG_LOCAL7 = (23<<3), /* reserved for local use */
LOG_NFACILITIES = 24, /* current number of facilities */
- };
+ }
int LOG_MASK(int pri) { return 1 << pri; } /* mask for one priority */
int LOG_UPTO(int pri) { return (1 << (pri+1)) - 1; } /* all priorities through pri */
LOG_NOTICE = 5, /* normal but significant condition */
LOG_INFO = 6, /* informational */
LOG_DEBUG = 7, /* debug-level messages */
- };
+ }
//OPTIONS
enum {
LOG_NDELAY = 0x08, /* don't delay open */
LOG_NOWAIT = 0x10, /* don't wait for console forks: DEPRECATED */
LOG_PERROR = 0x20, /* log to stderr as well */
- };
+ }
//FACILITY
enum {
LOG_LOCAL7 = (23<<3), /* reserved for local use */
LOG_NFACILITIES = 24, /* current number of facilities */
- };
+ }
int LOG_MASK(int pri) { return 1 << pri; } /* mask for one priority */
int LOG_UPTO(int pri) { return (1 << (pri+1)) - 1; } /* all priorities through pri */
*/
module core.sys.posix.termios;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for pid_t
version (OSX)
nothrow:
@nogc:
+@system:
//
// Required
TCOOFF
TCOON
-speed_t cfgetispeed(in termios*);
-speed_t cfgetospeed(in termios*);
+speed_t cfgetispeed(const scope termios*);
+speed_t cfgetospeed(const scope termios*);
int cfsetispeed(termios*, speed_t);
int cfsetospeed(termios*, speed_t);
int tcdrain(int);
int tcflush(int, int);
int tcgetattr(int, termios*);
int tcsendbreak(int, int);
-int tcsetattr(int, int, in termios*);
+int tcsetattr(int, int, const scope termios*);
*/
version (CRuntime_Glibc)
enum TCOOFF = 0;
enum TCOON = 1;
- speed_t cfgetispeed(in termios*);
- speed_t cfgetospeed(in termios*);
+ speed_t cfgetispeed(const scope termios*);
+ speed_t cfgetospeed(const scope termios*);
int cfsetispeed(termios*, speed_t);
int cfsetospeed(termios*, speed_t);
int tcdrain(int);
int tcflush(int, int);
int tcgetattr(int, termios*);
int tcsendbreak(int, int);
- int tcsetattr(int, int, in termios*);
+ int tcsetattr(int, int, const scope termios*);
}
else version (Darwin)
{
enum TCOOFF = 1;
enum TCOON = 2;
- speed_t cfgetispeed(in termios*);
- speed_t cfgetospeed(in termios*);
+ speed_t cfgetispeed(const scope termios*);
+ speed_t cfgetospeed(const scope termios*);
int cfsetispeed(termios*, speed_t);
int cfsetospeed(termios*, speed_t);
int tcdrain(int);
int tcflush(int, int);
int tcgetattr(int, termios*);
int tcsendbreak(int, int);
- int tcsetattr(int, int, in termios*);
+ int tcsetattr(int, int, const scope termios*);
}
else version (FreeBSD)
enum TCOOFF = 1;
enum TCOON = 2;
- speed_t cfgetispeed(in termios*);
- speed_t cfgetospeed(in termios*);
+ speed_t cfgetispeed(const scope termios*);
+ speed_t cfgetospeed(const scope termios*);
int cfsetispeed(termios*, speed_t);
int cfsetospeed(termios*, speed_t);
int tcdrain(int);
int tcflush(int, int);
int tcgetattr(int, termios*);
int tcsendbreak(int, int);
- int tcsetattr(int, int, in termios*);
+ int tcsetattr(int, int, const scope termios*);
}
else version (DragonFlyBSD)
{
enum TCOOFF = 1;
enum TCOON = 2;
- speed_t cfgetispeed(in termios*);
- speed_t cfgetospeed(in termios*);
+ speed_t cfgetispeed(const scope termios*);
+ speed_t cfgetospeed(const scope termios*);
int cfsetispeed(termios*, speed_t);
int cfsetospeed(termios*, speed_t);
int tcdrain(int);
int tcflush(int, int);
int tcgetattr(int, termios*);
int tcsendbreak(int, int);
- int tcsetattr(int, int, in termios*);
+ int tcsetattr(int, int, const scope termios*);
}
else version (NetBSD)
{
enum TCOOFF = 1;
enum TCOON = 2;
- speed_t cfgetispeed(in termios*);
- speed_t cfgetospeed(in termios*);
+ speed_t cfgetispeed(const scope termios*);
+ speed_t cfgetospeed(const scope termios*);
int cfsetispeed(termios*, speed_t);
int cfsetospeed(termios*, speed_t);
int tcdrain(int);
int tcflush(int, int);
int tcgetattr(int, termios*);
int tcsendbreak(int, int);
- int tcsetattr(int, int, in termios*);
+ int tcsetattr(int, int, const scope termios*);
}
else version (OpenBSD)
{
enum TCOOFF = 1;
enum TCOON = 2;
- speed_t cfgetispeed(in termios*);
- speed_t cfgetospeed(in termios*);
+ speed_t cfgetispeed(const scope termios*);
+ speed_t cfgetospeed(const scope termios*);
int cfsetispeed(termios*, speed_t);
int cfsetospeed(termios*, speed_t);
int tcdrain(int);
int tcflush(int, int);
int tcgetattr(int, termios*);
int tcsendbreak(int, int);
- int tcsetattr(int, int, in termios*);
+ int tcsetattr(int, int, const scope termios*);
}
else version (Solaris)
{
* POSIX termios functions
* These functions get mapped into ioctls.
*/
- speed_t cfgetospeed(in termios*);
+ speed_t cfgetospeed(const scope termios*);
int cfsetospeed(termios*, speed_t);
- speed_t cfgetispeed(in termios*);
+ speed_t cfgetispeed(const scope termios*);
int cfsetispeed(termios*, speed_t);
int tcgetattr(int, termios*);
- int tcsetattr(int, int, in termios*);
+ int tcsetattr(int, int, const scope termios*);
int tcsendbreak(int, int);
int tcdrain(int);
int tcflush(int, int);
enum TCOOFF = 0;
enum TCOON = 1;
- speed_t cfgetispeed(in termios*);
- speed_t cfgetospeed(in termios*);
+ speed_t cfgetispeed(const scope termios*);
+ speed_t cfgetospeed(const scope termios*);
int cfsetispeed(termios*, speed_t);
int cfsetospeed(termios*, speed_t);
int tcdrain(int);
int tcflush(int, int);
int tcgetattr(int, termios*);
int tcsendbreak(int, int);
- int tcsetattr(int, int, in termios*);
+ int tcsetattr(int, int, const scope termios*);
}
//
*/
module core.sys.posix.time;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.stdc.time;
public import core.sys.posix.sys.types;
public import core.sys.posix.signal; // for sigevent
extern (C):
nothrow:
@nogc:
+@system:
//
// Required (defined in core.stdc.time)
//
/*
-char* asctime(in tm*);
+char* asctime(const scope tm*);
clock_t clock();
-char* ctime(in time_t*);
+char* ctime(const scope time_t*);
double difftime(time_t, time_t);
-tm* gmtime(in time_t*);
-tm* localtime(in time_t*);
+tm* gmtime(const scope time_t*);
+tm* localtime(const scope time_t*);
time_t mktime(tm*);
-size_t strftime(char*, size_t, in char*, in tm*);
+size_t strftime(char*, size_t, const scope char*, const scope tm*);
time_t time(time_t*);
*/
// Clock Selection (CS)
//
/*
-int clock_nanosleep(clockid_t, int, in timespec*, timespec*);
+int clock_nanosleep(clockid_t, int, const scope timespec*, timespec*);
*/
//
int clock_getres(clockid_t, timespec*);
int clock_gettime(clockid_t, timespec*);
-int clock_settime(clockid_t, in timespec*);
-int nanosleep(in timespec*, timespec*);
+int clock_settime(clockid_t, const scope timespec*);
+int nanosleep(const scope timespec*, timespec*);
int timer_create(clockid_t, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_gettime(timer_t, itimerspec*);
int timer_getoverrun(timer_t);
-int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
*/
version (CRuntime_Glibc)
int clock_getres(clockid_t, timespec*);
int clock_gettime(clockid_t, timespec*);
- int clock_settime(clockid_t, in timespec*);
- int nanosleep(in timespec*, timespec*);
+ int clock_settime(clockid_t, const scope timespec*);
+ int nanosleep(const scope timespec*, timespec*);
int timer_create(clockid_t, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_gettime(timer_t, itimerspec*);
int timer_getoverrun(timer_t);
- int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+ int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
}
else version (Darwin)
{
- int nanosleep(in timespec*, timespec*);
+ int nanosleep(const scope timespec*, timespec*);
}
else version (FreeBSD)
{
int clock_getres(clockid_t, timespec*);
int clock_gettime(clockid_t, timespec*);
- int clock_settime(clockid_t, in timespec*);
- int nanosleep(in timespec*, timespec*);
+ int clock_settime(clockid_t, const scope timespec*);
+ int nanosleep(const scope timespec*, timespec*);
int timer_create(clockid_t, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_gettime(timer_t, itimerspec*);
int timer_getoverrun(timer_t);
- int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+ int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
}
else version (DragonFlyBSD)
{
int clock_getres(clockid_t, timespec*);
int clock_gettime(clockid_t, timespec*);
- int clock_settime(clockid_t, in timespec*);
- int nanosleep(in timespec*, timespec*);
+ int clock_settime(clockid_t, const scope timespec*);
+ int nanosleep(const scope timespec*, timespec*);
int timer_create(clockid_t, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_gettime(timer_t, itimerspec*);
int timer_getoverrun(timer_t);
- int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+ int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
}
else version (NetBSD)
{
int clock_getres(clockid_t, timespec*);
int clock_gettime(clockid_t, timespec*);
- int clock_settime(clockid_t, in timespec*);
- int nanosleep(in timespec*, timespec*);
+ int clock_settime(clockid_t, const scope timespec*);
+ int nanosleep(const scope timespec*, timespec*);
int timer_create(clockid_t, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_gettime(timer_t, itimerspec*);
int timer_getoverrun(timer_t);
- int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+ int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
}
else version (OpenBSD)
{
int clock_getres(clockid_t, timespec*);
int clock_gettime(clockid_t, timespec*);
- int clock_settime(clockid_t, in timespec*);
- int nanosleep(in timespec*, timespec*);
+ int clock_settime(clockid_t, const scope timespec*);
+ int nanosleep(const scope timespec*, timespec*);
int timer_create(clockid_t, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_gettime(timer_t, itimerspec*);
int timer_getoverrun(timer_t);
- int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+ int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
}
else version (Solaris)
{
int clock_getres(clockid_t, timespec*);
int clock_gettime(clockid_t, timespec*);
- int clock_settime(clockid_t, in timespec*);
- int clock_nanosleep(clockid_t, int, in timespec*, timespec*);
+ int clock_settime(clockid_t, const scope timespec*);
+ int clock_nanosleep(clockid_t, int, const scope timespec*, timespec*);
- int nanosleep(in timespec*, timespec*);
+ int nanosleep(const scope timespec*, timespec*);
int timer_create(clockid_t, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_getoverrun(timer_t);
int timer_gettime(timer_t, itimerspec*);
- int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+ int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
}
else version (CRuntime_Bionic)
{
int clock_getres(int, timespec*);
int clock_gettime(int, timespec*);
- int nanosleep(in timespec*, timespec*);
+ int nanosleep(const scope timespec*, timespec*);
int timer_create(int, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_gettime(timer_t, itimerspec*);
int timer_getoverrun(timer_t);
- int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+ int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
}
else version (CRuntime_Musl)
{
enum CLOCK_SGI_CYCLE = 10;
enum CLOCK_TAI = 11;
- int nanosleep(in timespec*, timespec*);
+ int nanosleep(const scope timespec*, timespec*);
int clock_getres(clockid_t, timespec*);
int clock_gettime(clockid_t, timespec*);
- int clock_settime(clockid_t, in timespec*);
- int clock_nanosleep(clockid_t, int, in timespec*, timespec*);
+ int clock_settime(clockid_t, const scope timespec*);
+ int clock_nanosleep(clockid_t, int, const scope timespec*, timespec*);
int clock_getcpuclockid(pid_t, clockid_t *);
int timer_create(clockid_t, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_gettime(timer_t, itimerspec*);
- int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+ int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
int timer_getoverrun(timer_t);
}
else version (CRuntime_UClibc)
int clock_getres(clockid_t, timespec*);
int clock_gettime(clockid_t, timespec*);
- int clock_settime(clockid_t, in timespec*);
- int nanosleep(in timespec*, timespec*);
+ int clock_settime(clockid_t, const scope timespec*);
+ int nanosleep(const scope timespec*, timespec*);
int timer_create(clockid_t, sigevent*, timer_t*);
int timer_delete(timer_t);
int timer_gettime(timer_t, itimerspec*);
int timer_getoverrun(timer_t);
- int timer_settime(timer_t, int, in itimerspec*, itimerspec*);
+ int timer_settime(timer_t, int, const scope itimerspec*, itimerspec*);
}
else
{
// Thread-Safe Functions (TSF)
//
/*
-char* asctime_r(in tm*, char*);
-char* ctime_r(in time_t*, char*);
-tm* gmtime_r(in time_t*, tm*);
-tm* localtime_r(in time_t*, tm*);
+char* asctime_r(const scope tm*, char*);
+char* ctime_r(const scope time_t*, char*);
+tm* gmtime_r(const scope time_t*, tm*);
+tm* localtime_r(const scope time_t*, tm*);
*/
version (CRuntime_Glibc)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else version (Darwin)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else version (FreeBSD)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else version (NetBSD)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else version (OpenBSD)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else version (DragonFlyBSD)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else version (Solaris)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else version (CRuntime_Bionic)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else version (CRuntime_Musl)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else version (CRuntime_UClibc)
{
- char* asctime_r(in tm*, char*);
- char* ctime_r(in time_t*, char*);
- tm* gmtime_r(in time_t*, tm*);
- tm* localtime_r(in time_t*, tm*);
+ char* asctime_r(const scope tm*, char*);
+ char* ctime_r(const scope time_t*, char*);
+ tm* gmtime_r(const scope time_t*, tm*);
+ tm* localtime_r(const scope time_t*, tm*);
}
else
{
int daylight;
int timezone;
-tm* getdate(in char*);
-char* strptime(in char*, in char*, tm*);
+tm* getdate(const scope char*);
+char* strptime(const scope char*, const scope char*, tm*);
*/
version (CRuntime_Glibc)
extern __gshared int daylight;
extern __gshared c_long timezone;
- tm* getdate(in char*);
- char* strptime(in char*, in char*, tm*);
+ tm* getdate(const scope char*);
+ char* strptime(const scope char*, const scope char*, tm*);
}
else version (Darwin)
{
extern __gshared c_long timezone;
extern __gshared int daylight;
- tm* getdate(in char*);
- char* strptime(in char*, in char*, tm*);
+ tm* getdate(const scope char*);
+ char* strptime(const scope char*, const scope char*, tm*);
}
else version (FreeBSD)
{
- //tm* getdate(in char*);
- char* strptime(in char*, in char*, tm*);
+ //tm* getdate(const scope char*);
+ char* strptime(const scope char*, const scope char*, tm*);
}
else version (NetBSD)
{
- tm* getdate(in char*);
- char* strptime(in char*, in char*, tm*);
+ tm* getdate(const scope char*);
+ char* strptime(const scope char*, const scope char*, tm*);
}
else version (OpenBSD)
{
- //tm* getdate(in char*);
- char* strptime(in char*, in char*, tm*);
+ //tm* getdate(const scope char*);
+ char* strptime(const scope char*, const scope char*, tm*);
}
else version (DragonFlyBSD)
{
- //tm* getdate(in char*);
- char* strptime(in char*, in char*, tm*);
+ //tm* getdate(const scope char*);
+ char* strptime(const scope char*, const scope char*, tm*);
}
else version (Solaris)
{
extern __gshared c_long timezone, altzone;
extern __gshared int daylight;
- tm* getdate(in char*);
- char* __strptime_dontzero(in char*, in char*, tm*);
+ tm* getdate(const scope char*);
+ char* __strptime_dontzero(const scope char*, const scope char*, tm*);
alias __strptime_dontzero strptime;
}
else version (CRuntime_Bionic)
extern __gshared int daylight;
extern __gshared c_long timezone;
- char* strptime(in char*, in char*, tm*);
+ char* strptime(const scope char*, const scope char*, tm*);
}
else version (CRuntime_Musl)
{
extern __gshared int daylight;
extern __gshared c_long timezone;
- tm* getdate(in char*);
- char* strptime(in char*, in char*, tm*);
+ tm* getdate(const scope char*);
+ char* strptime(const scope char*, const scope char*, tm*);
}
else version (CRuntime_UClibc)
{
extern __gshared int daylight;
extern __gshared c_long timezone;
- tm* getdate(in char*);
- char* strptime(in char*, in char*, tm*);
+ tm* getdate(const scope char*);
+ char* strptime(const scope char*, const scope char*, tm*);
}
else
{
*/
module core.sys.posix.ucontext;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.signal; // for sigset_t, stack_t
-private import core.stdc.stdint : uintptr_t;
+import core.stdc.stdint : uintptr_t;
version (Posix):
extern (C):
nothrow:
@nogc:
-
+@system:
+
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
+version (ARM) version = ARM_Any;
+version (AArch64) version = ARM_Any;
version (MIPS32) version = MIPS_Any;
version (MIPS64) version = MIPS_Any;
version (PPC) version = PPC_Any;
mcontext_t uc_mcontext;
}
}
- else version (SPARC64)
+ else version (SPARC_Any)
{
enum MC_NGREG = 19;
alias mc_greg_t = c_ulong;
else
static assert(0, "unimplemented");
}
+else version (Darwin)
+{
+ private
+ {
+ version (X86_64)
+ {
+ struct __darwin_mcontext
+ {
+ ulong[89] __opaque;
+ }
+ static assert(__darwin_mcontext.sizeof == 712);
+ }
+ else version (X86)
+ {
+ struct __darwin_mcontext
+ {
+ uint[150] __opaque;
+ }
+ static assert(__darwin_mcontext.sizeof == 600);
+ }
+ else version (AArch64)
+ {
+ struct __darwin_mcontext
+ {
+ align(16) ulong[102] __opaque;
+ }
+ static assert(__darwin_mcontext.sizeof == 816);
+ }
+ else version (ARM)
+ {
+ struct __darwin_mcontext
+ {
+ uint[85] __opaque;
+ }
+ static assert(__darwin_mcontext.sizeof == 340);
+ }
+ else version (PPC_Any)
+ {
+ struct __darwin_mcontext
+ {
+ version (PPC64)
+ ulong[129] __opaque;
+ else
+ uint[258] __opaque;
+ }
+ static assert(__darwin_mcontext.sizeof == 1032);
+ }
+ else
+ static assert(false, "mcontext_t unimplemented for this platform.");
+ }
+
+ alias mcontext_t = __darwin_mcontext*;
+
+ struct ucontext
+ {
+ int uc_onstack;
+ sigset_t uc_sigmask;
+ stack_t uc_stack;
+ ucontext* uc_link;
+ size_t uc_mcsize;
+ __darwin_mcontext* uc_mcontext;
+ __darwin_mcontext __mcontext_data;
+ }
+
+ alias ucontext_t = ucontext;
+}
else version (FreeBSD)
{
// <machine/ucontext.h>
int sc_trapno;
int sc_err;
void* sc_fpstate; // union savefpu*
- };
+ }
}
else version (PPC)
{
uint mc_reserved;
uint[8] mc_unused;
int[256] mc_fpregs;
- }; // __attribute__((aligned(64)));
+ } // __attribute__((aligned(64)));
}
else
{
}
else version (Solaris)
{
- private import core.stdc.stdint;
+ import core.stdc.stdint;
alias uint[4] upad128_t;
{
uint[32] fpu_regs;
double[16] fpu_dregs;
- };
+ }
fq *fpu_q;
uint fpu_fsr;
ubyte fpu_qcnt;
/*
int getcontext(ucontext_t*);
void makecontext(ucontext_t*, void function(), int, ...);
-int setcontext(in ucontext_t*);
-int swapcontext(ucontext_t*, in ucontext_t*);
+int setcontext(const scope ucontext_t*);
+int swapcontext(ucontext_t*, const scope ucontext_t*);
*/
static if ( is( ucontext_t ) )
else
void makecontext(ucontext_t*, void function(), int, ...);
- int setcontext(in ucontext_t*);
- int swapcontext(ucontext_t*, in ucontext_t*);
+ int setcontext(const scope ucontext_t*);
+ int swapcontext(ucontext_t*, const scope ucontext_t*);
}
version (Solaris)
{
- int walkcontext(in ucontext_t*, int function(uintptr_t, int, void*), void*);
+ int walkcontext(const scope ucontext_t*, int function(uintptr_t, int, void*), void*);
int addrtosymstr(uintptr_t, char*, int);
int printstack(int);
}
*/
module core.sys.posix.unistd;
-private import core.sys.posix.config;
-private import core.stdc.stddef;
+import core.sys.posix.config;
+import core.stdc.stddef;
public import core.sys.posix.inttypes; // for intptr_t
public import core.sys.posix.sys.types; // for ssize_t, uid_t, gid_t, off_t, pid_t, useconds_t
extern (C):
nothrow:
@nogc:
+@system:
enum STDIN_FILENO = 0;
enum STDOUT_FILENO = 1;
extern __gshared int opterr;
extern __gshared int optopt;
-int access(in char*, int);
+int access(const scope char*, int);
uint alarm(uint) @trusted;
-int chdir(in char*);
-int chown(in char*, uid_t, gid_t);
+int chdir(const scope char*);
+int chown(const scope char*, uid_t, gid_t);
int close(int) @trusted;
size_t confstr(int, char*, size_t);
int dup(int) @trusted;
int dup2(int, int) @trusted;
-int execl(in char*, in char*, ...);
-int execle(in char*, in char*, ...);
-int execlp(in char*, in char*, ...);
-int execv(in char*, in char**);
-int execve(in char*, in char**, in char**);
-int execvp(in char*, in char**);
+int execl(const scope char*, const scope char*, ...);
+int execle(const scope char*, const scope char*, ...);
+int execlp(const scope char*, const scope char*, ...);
+int execv(const scope char*, const scope char**);
+int execve(const scope char*, const scope char**, const scope char**);
+int execvp(const scope char*, const scope char**);
void _exit(int) @trusted;
int fchown(int, uid_t, gid_t) @trusted;
pid_t fork() @trusted;
int gethostname(char*, size_t);
char* getlogin() @trusted;
int getlogin_r(char*, size_t);
-int getopt(int, in char**, in char*);
+int getopt(int, const scope char**, const scope char*);
pid_t getpgrp() @trusted;
pid_t getpid() @trusted;
pid_t getppid() @trusted;
uid_t getuid() @trusted;
int isatty(int) @trusted;
-int link(in char*, in char*);
+int link(const scope char*, const scope char*);
//off_t lseek(int, off_t, int);
-c_long pathconf(in char*, int);
+c_long pathconf(const scope char*, int);
int pause() @trusted;
int pipe(ref int[2]) @trusted;
ssize_t read(int, void*, size_t);
-ssize_t readlink(in char*, char*, size_t);
-int rmdir(in char*);
+ssize_t readlink(const scope char*, char*, size_t);
+int rmdir(const scope char*);
int setegid(gid_t) @trusted;
int seteuid(uid_t) @trusted;
int setgid(gid_t) @trusted;
-int setgroups(size_t, in gid_t*) @trusted;
+int setgroups(size_t, const scope gid_t*) @trusted;
int setpgid(pid_t, pid_t) @trusted;
pid_t setsid() @trusted;
int setuid(uid_t) @trusted;
uint sleep(uint) @trusted;
-int symlink(in char*, in char*);
+int symlink(const scope char*, const scope char*);
c_long sysconf(int) @trusted;
pid_t tcgetpgrp(int) @trusted;
int tcsetpgrp(int, pid_t) @trusted;
char* ttyname(int) @trusted;
int ttyname_r(int, char*, size_t);
-int unlink(in char*);
-ssize_t write(int, in void*, size_t);
+int unlink(const scope char*);
+ssize_t write(int, const scope void*, size_t);
version (CRuntime_Glibc)
{
// XOpen (XSI)
//
/*
-char* crypt(in char*, in char*);
+char* crypt(const scope char*, const scope char*);
char* ctermid(char*);
void encrypt(ref char[64], int);
int fchdir(int);
pid_t getpgid(pid_t);
pid_t getsid(pid_t);
char* getwd(char*); // LEGACY
-int lchown(in char*, uid_t, gid_t);
+int lchown(const scope char*, uid_t, gid_t);
int lockf(int, int, off_t);
int nice(int);
ssize_t pread(int, void*, size_t, off_t);
-ssize_t pwrite(int, in void*, size_t, off_t);
+ssize_t pwrite(int, const scope void*, size_t, off_t);
pid_t setpgrp();
int setregid(gid_t, gid_t);
int setreuid(uid_t, uid_t);
-void swab(in void*, void*, ssize_t);
+void swab(const scope void*, void*, ssize_t);
void sync();
-int truncate(in char*, off_t);
+int truncate(const scope char*, off_t);
useconds_t ualarm(useconds_t, useconds_t);
int usleep(useconds_t);
pid_t vfork();
version (CRuntime_Glibc)
{
- char* crypt(in char*, in char*);
+ char* crypt(const scope char*, const scope char*);
char* ctermid(char*);
void encrypt(ref char[64], int) @trusted;
int fchdir(int) @trusted;
pid_t getpgid(pid_t) @trusted;
pid_t getsid(pid_t) @trusted;
char* getwd(char*); // LEGACY
- int lchown(in char*, uid_t, gid_t);
+ int lchown(const scope char*, uid_t, gid_t);
//int lockf(int, int, off_t);
int nice(int) @trusted;
//ssize_t pread(int, void*, size_t, off_t);
- //ssize_t pwrite(int, in void*, size_t, off_t);
+ //ssize_t pwrite(int, const scope void*, size_t, off_t);
pid_t setpgrp() @trusted;
int setregid(gid_t, gid_t) @trusted;
int setreuid(uid_t, uid_t) @trusted;
- void swab(in void*, void*, ssize_t);
+ void swab(const scope void*, void*, ssize_t);
void sync() @trusted;
- //int truncate(in char*, off_t);
+ //int truncate(const scope char*, off_t);
useconds_t ualarm(useconds_t, useconds_t) @trusted;
int usleep(useconds_t) @trusted;
pid_t vfork();
ssize_t pread64(int, void*, size_t, off_t);
alias pread64 pread;
- ssize_t pwrite64(int, in void*, size_t, off_t);
+ ssize_t pwrite64(int, const scope void*, size_t, off_t);
alias pwrite64 pwrite;
- int truncate64(in char*, off_t);
+ int truncate64(const scope char*, off_t);
alias truncate64 truncate;
}
else
{
int lockf(int, int, off_t) @trusted;
ssize_t pread(int, void*, size_t, off_t);
- ssize_t pwrite(int, in void*, size_t, off_t);
- int truncate(in char*, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
+ int truncate(const scope char*, off_t);
}
}
else version (CRuntime_Musl)
}
else version (Darwin)
{
- char* crypt(in char*, in char*);
+ char* crypt(const scope char*, const scope char*);
char* ctermid(char*);
void encrypt(ref char[64], int) @trusted;
int fchdir(int) @trusted;
pid_t getpgid(pid_t) @trusted;
pid_t getsid(pid_t) @trusted;
char* getwd(char*); // LEGACY
- int lchown(in char*, uid_t, gid_t);
+ int lchown(const scope char*, uid_t, gid_t);
int lockf(int, int, off_t) @trusted;
int nice(int) @trusted;
ssize_t pread(int, void*, size_t, off_t);
- ssize_t pwrite(int, in void*, size_t, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
pid_t setpgrp() @trusted;
int setregid(gid_t, gid_t) @trusted;
int setreuid(uid_t, uid_t) @trusted;
- void swab(in void*, void*, ssize_t);
+ void swab(const scope void*, void*, ssize_t);
void sync() @trusted;
- int truncate(in char*, off_t);
+ int truncate(const scope char*, off_t);
useconds_t ualarm(useconds_t, useconds_t) @trusted;
int usleep(useconds_t) @trusted;
pid_t vfork();
}
else version (FreeBSD)
{
- char* crypt(in char*, in char*);
+ char* crypt(const scope char*, const scope char*);
//char* ctermid(char*);
void encrypt(ref char[64], int) @trusted;
int fchdir(int) @trusted;
int getpgid(pid_t) @trusted;
int getsid(pid_t) @trusted;
char* getwd(char*); // LEGACY
- int lchown(in char*, uid_t, gid_t);
+ int lchown(const scope char*, uid_t, gid_t);
int lockf(int, int, off_t) @trusted;
int nice(int) @trusted;
ssize_t pread(int, void*, size_t, off_t);
- ssize_t pwrite(int, in void*, size_t, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
int setpgrp(pid_t, pid_t) @trusted;
int setregid(gid_t, gid_t) @trusted;
int setreuid(uid_t, uid_t) @trusted;
- void swab(in void*, void*, ssize_t);
+ void swab(const scope void*, void*, ssize_t);
void sync() @trusted;
- int truncate(in char*, off_t);
+ int truncate(const scope char*, off_t);
useconds_t ualarm(useconds_t, useconds_t) @trusted;
int usleep(useconds_t) @trusted;
pid_t vfork();
}
else version (NetBSD)
{
- char* crypt(in char*, in char*);
+ char* crypt(const scope char*, const scope char*);
//char* ctermid(char*);
void encrypt(ref char[64], int) @trusted;
int fchdir(int) @trusted;
int getpgid(pid_t) @trusted;
int getsid(pid_t) @trusted;
char* getwd(char*); // LEGACY
- int lchown(in char*, uid_t, gid_t);
+ int lchown(const scope char*, uid_t, gid_t);
int lockf(int, int, off_t) @trusted;
int nice(int) @trusted;
ssize_t pread(int, void*, size_t, off_t);
- ssize_t pwrite(int, in void*, size_t, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
int setpgrp(pid_t, pid_t) @trusted;
int setregid(gid_t, gid_t) @trusted;
int setreuid(uid_t, uid_t) @trusted;
- void swab(in void*, void*, ssize_t);
+ void swab(const scope void*, void*, ssize_t);
void sync() @trusted;
- int truncate(in char*, off_t);
+ int truncate(const scope char*, off_t);
useconds_t ualarm(useconds_t, useconds_t) @trusted;
int usleep(useconds_t) @trusted;
pid_t vfork();
}
else version (OpenBSD)
{
- char* crypt(in char*, in char*);
+ char* crypt(const scope char*, const scope char*);
//char* ctermid(char*);
//void encrypt(ref char[64], int) @trusted;
int fchdir(int) @trusted;
pid_t getpgid(pid_t) @trusted;
pid_t getsid(pid_t) @trusted;
char* getwd(char*);
- int lchown(in char*, uid_t, gid_t);
+ int lchown(const scope char*, uid_t, gid_t);
int lockf(int, int, off_t) @trusted;
int nice(int) @trusted;
ssize_t pread(int, void*, size_t, off_t);
- ssize_t pwrite(int, in void*, size_t, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
int setpgrp(pid_t, pid_t) @trusted;
int setregid(gid_t, gid_t) @trusted;
int setreuid(uid_t, uid_t) @trusted;
- void swab(in void*, void*, ssize_t);
+ void swab(const scope void*, void*, ssize_t);
void sync() @trusted;
- int truncate(in char*, off_t);
+ int truncate(const scope char*, off_t);
useconds_t ualarm(useconds_t, useconds_t) @trusted;
int usleep(useconds_t) @trusted;
pid_t vfork();
}
else version (DragonFlyBSD)
{
- char* crypt(in char*, in char*);
+ char* crypt(const scope char*, const scope char*);
//char* ctermid(char*);
void encrypt(ref char[64], int) @trusted;
int fchdir(int) @trusted;
int getpgid(pid_t) @trusted;
int getsid(pid_t) @trusted;
char* getwd(char*); // LEGACY
- int lchown(in char*, uid_t, gid_t);
+ int lchown(const scope char*, uid_t, gid_t);
int lockf(int, int, off_t) @trusted;
int nice(int) @trusted;
ssize_t pread(int, void*, size_t, off_t);
- ssize_t pwrite(int, in void*, size_t, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
int setpgrp(pid_t, pid_t) @trusted;
int setregid(gid_t, gid_t) @trusted;
int setreuid(uid_t, uid_t) @trusted;
- void swab(in void*, void*, ssize_t);
+ void swab(const scope void*, void*, ssize_t);
void sync() @trusted;
- int truncate(in char*, off_t);
+ int truncate(const scope char*, off_t);
useconds_t ualarm(useconds_t, useconds_t) @trusted;
int usleep(useconds_t) @trusted;
pid_t vfork();
{
int fchdir(int) @trusted;
pid_t getpgid(pid_t) @trusted;
- int lchown(in char*, uid_t, gid_t);
+ int lchown(const scope char*, uid_t, gid_t);
int nice(int) @trusted;
ssize_t pread(int, void*, size_t, off_t);
- ssize_t pwrite(int, in void*, size_t, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
int setpgrp() @trusted;
int setregid(gid_t, gid_t) @trusted;
int setreuid(uid_t, uid_t) @trusted;
int sync() @trusted;
- int truncate(in char*, off_t);
+ int truncate(const scope char*, off_t);
int usleep(c_ulong) @trusted;
pid_t vfork();
}
else version (Solaris)
{
- char* crypt(in char*, in char*);
+ char* crypt(const scope char*, const scope char*);
char* ctermid(char*);
void encrypt(ref char[64], int);
int fchdir(int);
pid_t getpgid(pid_t);
pid_t getsid(pid_t);
char* getwd(char*); // LEGACY
- int lchown(in char*, uid_t, gid_t);
+ int lchown(const scope char*, uid_t, gid_t);
int nice(int);
pid_t setpgrp();
int setregid(gid_t, gid_t);
int setreuid(uid_t, uid_t);
- void swab(in void*, void*, ssize_t);
+ void swab(const scope void*, void*, ssize_t);
void sync();
useconds_t ualarm(useconds_t, useconds_t);
int usleep(useconds_t);
ssize_t pread(int, void*, size_t, off_t);
alias pread pread64;
- ssize_t pwrite(int, in void*, size_t, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
alias pwrite pwrite64;
- int truncate(in char*, off_t);
+ int truncate(const scope char*, off_t);
alias truncate truncate64;
}
else
ssize_t pread64(int, void*, size_t, off64_t);
alias pread64 pread;
- ssize_t pwrite64(int, in void*, size_t, off_t);
+ ssize_t pwrite64(int, const scope void*, size_t, off_t);
alias pwrite64 pwrite;
- int truncate64(in char*, off_t);
+ int truncate64(const scope char*, off_t);
alias truncate64 truncate;
}
else
{
int lockf(int, int, off_t);
ssize_t pread(int, void*, size_t, off_t);
- ssize_t pwrite(int, in void*, size_t, off_t);
- int truncate(in char*, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
+ int truncate(const scope char*, off_t);
}
}
}
else version (CRuntime_UClibc)
{
- char* crypt(in char*, in char*);
+ char* crypt(const scope char*, const scope char*);
char* ctermid(char*);
void encrypt(ref char[64], int) @trusted;
int fchdir(int) @trusted;
pid_t getpgid(pid_t) @trusted;
pid_t getsid(pid_t) @trusted;
char* getwd(char*); // LEGACY
- int lchown(in char*, uid_t, gid_t);
+ int lchown(const scope char*, uid_t, gid_t);
int nice(int) @trusted;
pid_t setpgrp() @trusted;
int setregid(gid_t, gid_t) @trusted;
int setreuid(uid_t, uid_t) @trusted;
- void swab(in void*, void*, ssize_t);
+ void swab(const scope void*, void*, ssize_t);
void sync() @trusted;
useconds_t ualarm(useconds_t, useconds_t) @trusted;
int usleep(useconds_t) @trusted;
ssize_t pread64(int, void*, size_t, off_t);
alias pread64 pread;
- ssize_t pwrite64(int, in void*, size_t, off_t);
+ ssize_t pwrite64(int, const scope void*, size_t, off_t);
alias pwrite64 pwrite;
- int truncate64(in char*, off_t);
+ int truncate64(const scope char*, off_t);
alias truncate64 truncate;
}
else
{
int lockf(int, int, off_t) @trusted;
ssize_t pread(int, void*, size_t, off_t);
- ssize_t pwrite(int, in void*, size_t, off_t);
- int truncate(in char*, off_t);
+ ssize_t pwrite(int, const scope void*, size_t, off_t);
+ int truncate(const scope char*, off_t);
}
}
*/
module core.sys.posix.utime;
-private import core.sys.posix.config;
+import core.sys.posix.config;
public import core.sys.posix.sys.types; // for time_t
version (OSX)
extern (C):
nothrow:
@nogc:
+@system:
//
// Required
time_t modtime;
}
-int utime(in char*, in utimbuf*);
+int utime(const scope char*, const scope utimbuf*);
*/
version (CRuntime_Glibc)
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
else version (CRuntime_Musl)
{
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
else version (Darwin)
{
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
else version (FreeBSD)
{
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
else version (NetBSD)
{
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
else version (OpenBSD)
{
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
else version (DragonFlyBSD)
{
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
else version (Solaris)
{
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
else version (CRuntime_Bionic)
{
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
else version (CRuntime_UClibc)
{
time_t modtime;
}
- int utime(in char*, in utimbuf*);
+ int utime(const scope char*, const scope utimbuf*);
}
alias c_ulong Lmid_t;
-void* dlmopen(Lmid_t, in char*, int);
+void* dlmopen(Lmid_t, const scope char*, int);
enum
{
RTLD_CONFSET = 0x10000,
}
-int dldump(in char*, in char*, int);
+int dldump(const scope char*, const scope char*, int);
struct Dl_info
{
--- /dev/null
+/**
+ * D header file for Solaris err.h.
+ *
+ * Copyright: Copyright © 2019, The D Language Foundation
+ * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
+ * Authors: Ernesto Castellotti
+ */
+module core.sys.solaris.err;
+import core.stdc.stdarg : va_list;
+
+version (Solaris):
+extern (C):
+nothrow:
+@nogc:
+
+void err(int eval, scope const char* fmt, ...);
+void errx(int eval, scope const char* fmt, ...);
+void warn(scope const char* fmt, ...);
+void warnx(scope const char* fmt, ...);
+void verr(int eval, scope const char* fmt, va_list args);
+void verrx(int eval, scope const char* fmt, va_list args);
+void vwarn(scope const char* fmt, va_list args);
+void vwarnx(scope const char* fmt, va_list args);
int elf_getshdrnum(Elf*, size_t*);
int elf_getshstrndx(Elf*, size_t*);
int elf_getshdrstrndx(Elf*, size_t*);
-c_ulong elf_hash(in char*);
+c_ulong elf_hash(const scope char*);
uint elf_sys_encoding();
long elf32_checksum(Elf*);
Elf_Kind elf_kind(Elf*);
char* elf_strptr(Elf*, size_t, size_t);
off_t elf_update(Elf*, Elf_Cmd);
uint elf_version(uint);
-Elf_Data* elf32_xlatetof(Elf_Data*, in Elf_Data*, uint);
-Elf_Data* elf32_xlatetom(Elf_Data*, in Elf_Data*, uint);
+Elf_Data* elf32_xlatetof(Elf_Data*, const scope Elf_Data*, uint);
+Elf_Data* elf32_xlatetom(Elf_Data*, const scope Elf_Data*, uint);
version (D_LP64)
{
long elf64_checksum(Elf*);
Elf64_Ehdr* elf64_newehdr(Elf*);
Elf64_Phdr* elf64_newphdr(Elf*, size_t);
-Elf_Data* elf64_xlatetof(Elf_Data*, in Elf_Data*, uint);
-Elf_Data* elf64_xlatetom(Elf_Data*, in Elf_Data*, uint);
-}
\ No newline at end of file
+Elf_Data* elf64_xlatetof(Elf_Data*, const scope Elf_Data*, uint);
+Elf_Data* elf64_xlatetom(Elf_Data*, const scope Elf_Data*, uint);
+}
uint ld_version(uint);
void ld_input_done(uint*);
-void ld_start(in char*, in Elf32_Half, in char*);
+void ld_start(const scope char*, const Elf32_Half, const scope char*);
void ld_atexit(int);
-void ld_open(in char**, in char**, int*, int, Elf**, Elf*, size_t, in Elf_Kind);
-void ld_file(in char*, in Elf_Kind, int, Elf*);
-void ld_input_section(in char*, Elf32_Shdr**, Elf32_Word, Elf_Data*, Elf*, uint*);
-void ld_section(in char*, Elf32_Shdr*, Elf32_Word, Elf_Data*, Elf*);
+void ld_open(const scope char**, const scope char**, int*, int, Elf**, Elf*, size_t, const Elf_Kind);
+void ld_file(const scope char*, const Elf_Kind, int, Elf*);
+void ld_input_section(const scope char*, Elf32_Shdr**, Elf32_Word, Elf_Data*, Elf*, uint*);
+void ld_section(const scope char*, Elf32_Shdr*, Elf32_Word, Elf_Data*, Elf*);
version (D_LP64)
{
- void ld_start64(in char*, in Elf64_Half, in char*);
+ void ld_start64(const scope char*, const Elf64_Half, const scope char*);
void ld_atexit64(int);
- void ld_open64(in char**, in char**, int*, int, Elf**, Elf*, size_t, in Elf_Kind);
- void ld_file64(in char*, in Elf_Kind, int, Elf*);
- void ld_input_section64(in char*, Elf64_Shdr**, Elf64_Word, Elf_Data*, Elf*, uint*);
- void ld_section64(in char*, Elf64_Shdr*, Elf64_Word, Elf_Data*, Elf*);
+ void ld_open64(const scope char**, const scope char**, int*, int, Elf**, Elf*, size_t, const Elf_Kind);
+ void ld_file64(const scope char*, const Elf_Kind, int, Elf*);
+ void ld_input_section64(const scope char*, Elf64_Shdr**, Elf64_Word, Elf_Data*, Elf*, uint*);
+ void ld_section64(const scope char*, Elf64_Shdr*, Elf64_Word, Elf_Data*, Elf*);
}
enum LD_SUP_VNONE = 0;
uint la_version(uint);
void la_activity(uintptr_t*, uint);
void la_preinit(uintptr_t*);
-char* la_objsearch(in char*, uintptr_t*, uint);
+char* la_objsearch(const scope char*, uintptr_t*, uint);
uint la_objopen(Link_map*, Lmid_t, uintptr_t*);
uint la_objclose(uintptr_t*);
-int la_objfilter(uintptr_t*, in char*, uintptr_t*, uint);
+int la_objfilter(uintptr_t*, const scope char*, uintptr_t*, uint);
version (D_LP64)
{
uintptr_t la_amd64_pltenter(Elf64_Sym*, uint, uintptr_t*, uintptr_t*,
- La_amd64_regs*, uint*, in char*);
- uintptr_t la_symbind64(Elf64_Sym*, uint, uintptr_t*, uintptr_t*, uint*, in char*);
+ La_amd64_regs*, uint*, const scope char*);
+ uintptr_t la_symbind64(Elf64_Sym*, uint, uintptr_t*, uintptr_t*, uint*, const scope char*);
uintptr_t la_sparcv9_pltenter(Elf64_Sym*, uint, uintptr_t*, uintptr_t*,
- La_sparcv9_regs*, uint*, in char*);
- uintptr_t la_pltexit64(Elf64_Sym*, uint, uintptr_t*, uintptr_t*, uintptr_t, in char*);
+ La_sparcv9_regs*, uint*, const scope char*);
+ uintptr_t la_pltexit64(Elf64_Sym*, uint, uintptr_t*, uintptr_t*, uintptr_t, const scope char*);
}
else
{
uint64_t dlpi_subs;
size_t dlpi_tls_modid; // since Solaris 11.5
void* dlpi_tls_data; // since Solaris 11.5
-};
+}
private alias extern(C) int function(dl_phdr_info*, size_t, void *) dl_iterate_phdr_cb;
private alias extern(C) int function(dl_phdr_info*, size_t, void *) @nogc dl_iterate_phdr_cb_ngc;
enum M_PLT_RESERVSZ = M32_PLT_RESERVSZ;
enum M_GOT_ENTSIZE = M32_GOT_ENTSIZE;
enum M_GOT_MAXSMALL = M32_GOT_MAXSMALL;
-}
\ No newline at end of file
+}
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.basetyps, core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.windef;
+import core.sys.windows.basetyps, core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.windef;
// FIXME: check types and grouping of constants
// FIXME: check Windows version support
*/
module core.sys.windows.aclapi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "advapi32");
*/
module core.sys.windows.aclui;
version (Windows):
+@system:
pragma(lib, "aclui");
-private import core.sys.windows.w32api;
+import core.sys.windows.w32api;
/*
static assert (_WIN32_WINNT >= 0x500,
"core.sys.windows.aclui is available only if version Windows2000, WindowsXP, Windows2003 "
"or WindowsVista is set");
*/
import core.sys.windows.accctrl, core.sys.windows.commctrl, core.sys.windows.objbase;
-private import core.sys.windows.basetyps, core.sys.windows.prsht, core.sys.windows.unknwn, core.sys.windows.windef,
+import core.sys.windows.basetyps, core.sys.windows.prsht, core.sys.windows.unknwn, core.sys.windows.windef,
core.sys.windows.winuser;
*/
module core.sys.windows.basetsd;
version (Windows):
+@system:
/* This template is used in these modules to declare constant pointer types,
* in order to support both D 1.x and 2.x.
*/
module core.sys.windows.basetyps;
version (Windows):
+@system:
-private import core.sys.windows.windef, core.sys.windows.basetsd;
+import core.sys.windows.windef, core.sys.windows.basetsd;
align(1) struct GUID { // size is 16
align(1):
module core.sys.windows.cguid;
version (Windows):
-private import core.sys.windows.basetyps;
+import core.sys.windows.basetyps;
module core.sys.windows.com;
version (Windows):
+@system:
pragma(lib,"uuid");
*/
module core.sys.windows.comcat;
version (Windows):
+@system:
import core.sys.windows.ole2;
-private import core.sys.windows.basetyps, core.sys.windows.cguid, core.sys.windows.objbase, core.sys.windows.unknwn,
+import core.sys.windows.basetyps, core.sys.windows.cguid, core.sys.windows.objbase, core.sys.windows.unknwn,
core.sys.windows.windef, core.sys.windows.wtypes;
alias IEnumGUID LPENUMGUID;
*/
module core.sys.windows.commctrl;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "comctl32");
-private import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.winuser;
-private import core.sys.windows.winbase; // for SYSTEMTIME
-private import core.sys.windows.objfwd; // for LPSTREAM
+import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.winuser;
+import core.sys.windows.winbase; // for SYSTEMTIME
+import core.sys.windows.objfwd; // for LPSTREAM
import core.sys.windows.prsht;
{
int iItem;
int iGroup;
- };
+ }
alias LVITEMINDEX* PLVITEMINDEX;
struct LVFOOTERINFO
*/
module core.sys.windows.commdlg;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "comdlg32");
-private import core.sys.windows.w32api;
+import core.sys.windows.w32api;
import core.sys.windows.windef, core.sys.windows.winuser;
import core.sys.windows.wingdi; // for LPLOGFONTA
*/
module core.sys.windows.cpl;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.windef, core.sys.windows.winuser;
+import core.sys.windows.windef, core.sys.windows.winuser;
enum : uint {
WM_CPL_LAUNCH = WM_USER + 1000,
*/
module core.sys.windows.cplext;
version (Windows):
+@system:
enum : uint {
CPLPAGE_MOUSE_BUTTONS = 1,
*/
module core.sys.windows.custcntl;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
// FIXME: check type
enum CCF_NOTEXT = 1;
module core.sys.windows.dbghelp;
version (Windows):
+@system:
import core.sys.windows.winbase /+: FreeLibrary, GetProcAddress, LoadLibraryA+/;
import core.sys.windows.windef;
alias DWORD64 function(HANDLE hProcess, DWORD64 dwAddr) SymGetModuleBase64Func;
alias BOOL function(HANDLE hProcess, DWORD64 dwAddr, IMAGEHLP_MODULEA64 *ModuleInfo) SymGetModuleInfo64Func;
alias BOOL function(HANDLE hProcess, DWORD64 Address, DWORD64 *Displacement, IMAGEHLP_SYMBOLA64 *Symbol) SymGetSymFromAddr64Func;
- alias DWORD function(PCTSTR DecoratedName, PTSTR UnDecoratedName, DWORD UndecoratedLength, DWORD Flags) UnDecorateSymbolNameFunc;
+ alias DWORD function(PCSTR DecoratedName, PSTR UnDecoratedName, DWORD UndecoratedLength, DWORD Flags) UnDecorateSymbolNameFunc;
alias DWORD64 function(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll) SymLoadModule64Func;
alias BOOL function(HANDLE HProcess, PTSTR SearchPath, DWORD SearchPathLength) SymGetSearchPathFunc;
alias BOOL function(HANDLE hProcess, DWORD64 Address) SymUnloadModule64Func;
sm_inst.SymGetModuleBase64 = cast(SymGetModuleBase64Func) GetProcAddress(sm_hndl,"SymGetModuleBase64");
sm_inst.SymGetModuleInfo64 = cast(SymGetModuleInfo64Func) GetProcAddress(sm_hndl,"SymGetModuleInfo64");
sm_inst.SymGetSymFromAddr64 = cast(SymGetSymFromAddr64Func) GetProcAddress(sm_hndl,"SymGetSymFromAddr64");
+ sm_inst.UnDecorateSymbolName = cast(UnDecorateSymbolNameFunc) GetProcAddress(sm_hndl,"UnDecorateSymbolName");
sm_inst.SymLoadModule64 = cast(SymLoadModule64Func) GetProcAddress(sm_hndl,"SymLoadModule64");
sm_inst.SymGetSearchPath = cast(SymGetSearchPathFunc) GetProcAddress(sm_hndl,"SymGetSearchPath");
sm_inst.SymUnloadModule64 = cast(SymUnloadModule64Func) GetProcAddress(sm_hndl,"SymUnloadModule64");
assert( sm_inst.SymInitialize && sm_inst.SymCleanup && sm_inst.StackWalk64 && sm_inst.SymGetOptions &&
sm_inst.SymSetOptions && sm_inst.SymFunctionTableAccess64 && sm_inst.SymGetLineFromAddr64 &&
sm_inst.SymGetModuleBase64 && sm_inst.SymGetModuleInfo64 && sm_inst.SymGetSymFromAddr64 &&
- sm_inst.SymLoadModule64 && sm_inst.SymGetSearchPath && sm_inst.SymUnloadModule64 &&
- sm_inst.SymRegisterCallback64 && sm_inst.ImagehlpApiVersion);
+ sm_inst.UnDecorateSymbolName && sm_inst.SymLoadModule64 && sm_inst.SymGetSearchPath &&
+ sm_inst.SymUnloadModule64 && sm_inst.SymRegisterCallback64 && sm_inst.ImagehlpApiVersion);
return &sm_inst;
}
module core.sys.windows.dbghelp_types;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
*/
module core.sys.windows.dbt;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
*/
module core.sys.windows.dde;
version (Windows):
+@system:
pragma(lib, "user32");
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum : uint {
WM_DDE_FIRST = 0x03E0,
*/
module core.sys.windows.ddeml;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "user32");
-private import core.sys.windows.basetsd, core.sys.windows.windef, core.sys.windows.winnt;
+import core.sys.windows.basetsd, core.sys.windows.windef, core.sys.windows.winnt;
enum : int {
CP_WINANSI = 1004,
*/
module core.sys.windows.dhcpcsdk;
version (Windows):
+@system:
-private import core.sys.windows.w32api, core.sys.windows.windef;
+import core.sys.windows.w32api, core.sys.windows.windef;
/*static assert (_WIN32_WINNT >= 0x500,
"core.sys.windows.dhcpcsdk is available only if version Windows2000, WindowsXP, Windows2003
*/
module core.sys.windows.dlgs;
version (Windows):
+@system:
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum : ushort {
FILEOPENORD = 1536,
*/
module core.sys.windows.dll;
version (Windows):
+@system:
import core.sys.windows.winbase;
import core.sys.windows.winnt;
}
private:
-version (Win32)
-{
struct dll_aux
{
// don't let symbols leak into other modules
+version (Win32)
+{
struct LdrpTlsListEntry
{
LdrpTlsListEntry* next;
// let the old array leak, in case a oncurrent thread is still relying on it
return true;
}
+} // Win32
alias bool BOOLEAN;
LIST_ENTRY* prev;
}
- // the following structures can be found here: http://undocumented.ntinternals.net/
+ // the following structures can be found here:
+ // https://www.geoffchappell.com/studies/windows/win32/ntdll/structs/ldr_data_table_entry.htm
// perhaps this should be same as LDR_DATA_TABLE_ENTRY, which is introduced with PEB_LDR_DATA
struct LDR_MODULE
{
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
- SHORT LoadCount;
+ SHORT LoadCount; // obsolete after Version 6.1
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
+ PVOID EntryPointActivationContext;
+ PVOID PatchInformation;
+ LDR_DDAG_NODE *DdagNode; // starting with Version 6.2
+ }
+
+ struct LDR_DDAG_NODE
+ {
+ LIST_ENTRY Modules;
+ void* ServiceTagList; // LDR_SERVICE_TAG_RECORD
+ ULONG LoadCount;
+ ULONG ReferenceCount; // Version 10: ULONG LoadWhileUnloadingCount;
+ ULONG DependencyCount; // Version 10: ULONG LowestLink;
}
struct PEB_LDR_DATA
LIST_ENTRY InInitializationOrderModuleList;
}
- static LDR_MODULE* findLdrModule( HINSTANCE hInstance, void** peb ) nothrow
+ static LDR_MODULE* findLdrModule( HINSTANCE hInstance, void** peb ) nothrow @nogc
{
PEB_LDR_DATA* ldrData = cast(PEB_LDR_DATA*) peb[3];
LIST_ENTRY* root = &ldrData.InLoadOrderModuleList;
return true;
}
}
-}
public:
/* *****************************************************
}
}
+private extern (Windows) ULONGLONG VerSetConditionMask(ULONGLONG, DWORD, BYTE) nothrow @nogc;
+
+private bool isWindows8OrLater() nothrow @nogc
+{
+ OSVERSIONINFOEXW osvi;
+ osvi.dwOSVersionInfoSize = osvi.sizeof;
+ DWORDLONG dwlConditionMask = VerSetConditionMask(
+ VerSetConditionMask(
+ VerSetConditionMask(
+ 0, VER_MAJORVERSION, VER_GREATER_EQUAL),
+ VER_MINORVERSION, VER_GREATER_EQUAL),
+ VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+
+ osvi.dwMajorVersion = 6;
+ osvi.dwMinorVersion = 2;
+ osvi.wServicePackMajor = 0;
+
+ return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
+}
+
+/* *****************************************************
+ * Get the process reference count for the given DLL handle
+ * Params:
+ * hInstance = DLL instance handle
+ * Returns:
+ * the reference count for the DLL in the current process,
+ * -1 if the DLL is implicitely loaded with the process
+ * or -2 if the DLL handle is invalid
+ */
+int dll_getRefCount( HINSTANCE hInstance ) nothrow @nogc
+{
+ void** peb;
+ version (Win64)
+ {
+ version (GNU_InlineAsm)
+ {
+ asm pure nothrow @nogc { "movq %%gs:0x60, %0;" : "=r" peb; }
+ }
+ else
+ {
+ asm pure nothrow @nogc
+ {
+ mov RAX, 0x60;
+ mov RAX,GS:[RAX];
+ mov peb, RAX;
+ }
+ }
+
+ }
+ else version (Win32)
+ {
+ version (GNU_InlineAsm)
+ {
+ asm pure nothrow @nogc { "movl %%fs:0x30, %0;" : "=r" peb; }
+ }
+ else
+ {
+ asm pure nothrow @nogc
+ {
+ mov EAX,FS:[0x30];
+ mov peb, EAX;
+ }
+ }
+ }
+ dll_aux.LDR_MODULE *ldrMod = dll_aux.findLdrModule( hInstance, peb );
+ if ( !ldrMod )
+ return -2; // not in module list, bail out
+ if (isWindows8OrLater())
+ return ldrMod.DdagNode.LoadCount;
+ return ldrMod.LoadCount;
+}
+
// fixup TLS storage, initialize runtime and attach to threads
// to be called from DllMain with reason DLL_PROCESS_ATTACH
bool dll_process_attach( HINSTANCE hInstance, bool attach_threads,
// attach to all other threads
return enumProcessThreads(
function (uint id, void* context) {
- if ( !thread_findByAddr( id ) )
+ if ( !thread_findByAddr( id ) && !findLowLevelThread( id ) )
{
// if the OS has not prepared TLS for us, don't attach to the thread
if ( GetTlsDataAddress( id ) )
// to be called from DllMain with reason DLL_PROCESS_DETACH
void dll_process_detach( HINSTANCE hInstance, bool detach_threads = true )
{
+ // notify core.thread.joinLowLevelThread that the DLL is about to be unloaded
+ thread_DLLProcessDetaching = true;
+
// detach from all other threads
if ( detach_threads )
enumProcessThreads(
- function (uint id, void* context) {
- if ( id != GetCurrentThreadId() && thread_findByAddr( id ) )
+ function (uint id, void* context)
+ {
+ if ( id != GetCurrentThreadId() )
{
- thread_moduleTlsDtor( id );
- thread_detachByAddr( id );
+ if ( auto t = thread_findByAddr( id ) )
+ {
+ thread_moduleTlsDtor( id );
+ if ( !t.isMainThread() )
+ thread_detachByAddr( id );
+ }
}
return true;
}, null );
{
// if the OS has not prepared TLS for us, don't attach to the thread
// (happened when running under x64 OS)
- if ( !GetTlsDataAddress( GetCurrentThreadId() ) )
+ auto tid = GetCurrentThreadId();
+ if ( !GetTlsDataAddress( tid ) )
return false;
- if ( !thread_findByAddr( GetCurrentThreadId() ) )
+ if ( !thread_findByAddr( tid ) && !findLowLevelThread( tid ) )
{
// only attach to thread and initalize it if it is not in the thread list (so it's not created by "new Thread")
if ( attach_thread )
*/
module core.sys.windows.docobj;
version (Windows):
+@system:
-private import core.sys.windows.basetyps, core.sys.windows.oaidl, core.sys.windows.objidl, core.sys.windows.oleidl,
+import core.sys.windows.basetyps, core.sys.windows.oaidl, core.sys.windows.objidl, core.sys.windows.oleidl,
core.sys.windows.unknwn, core.sys.windows.windef, core.sys.windows.wtypes;
// FIXME: remove inherited methods from interface definitions
*/
module core.sys.windows.errorrep;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.w32api, core.sys.windows.windef;
+import core.sys.windows.w32api, core.sys.windows.windef;
static assert (_WIN32_WINNT >= 0x501,
"core.sys.windows.errorrep is available only if version WindowsXP, Windows2003 "
*/
module core.sys.windows.exdisp;
version (Windows):
+@system:
import core.sys.windows.docobj, core.sys.windows.oaidl, core.sys.windows.ocidl;
-private import core.sys.windows.basetyps, core.sys.windows.windef, core.sys.windows.wtypes;
+import core.sys.windows.basetyps, core.sys.windows.windef, core.sys.windows.wtypes;
enum BrowserNavConstants {
*/
module core.sys.windows.httpext;
version (Windows):
+@system:
/* Comment from MinGW
httpext.h - Header for ISAPI extensions.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
-private import core.sys.windows.basetsd /+: DECLARE_HANDLE, HANDLE+/;
-private import core.sys.windows.windef /+: BOOL, CHAR, DWORD, LPBYTE, LPDWORD+/;
-private import core.sys.windows.winnt /+: LPCSTR, LPSTR, LPVOID, PVOID, VOID+/;
+import core.sys.windows.basetsd /+: DECLARE_HANDLE, HANDLE+/;
+import core.sys.windows.windef /+: BOOL, CHAR, DWORD, LPBYTE, LPDWORD+/;
+import core.sys.windows.winnt /+: LPCSTR, LPSTR, LPVOID, PVOID, VOID+/;
enum {
HSE_VERSION_MAJOR = 2,
*/
module core.sys.windows.imagehlp;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
as well provide it here.
*/
-private import core.sys.windows.winbase, core.sys.windows.windef;
+import core.sys.windows.winbase, core.sys.windows.windef;
// FIXME: check types of constants
*/
module core.sys.windows.imm;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "imm32");
import core.sys.windows.windef, core.sys.windows.wingdi;
import core.sys.windows.winuser; // for the MFS_xxx enums.
-private import core.sys.windows.w32api;
+import core.sys.windows.w32api;
enum WM_CONVERTREQUESTEX = 0x108;
enum WM_IME_STARTCOMPOSITION = 0x10D;
*/
module core.sys.windows.intshcut;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.unknwn, core.sys.windows.windef;
+import core.sys.windows.unknwn, core.sys.windows.windef;
enum : SCODE {
E_FLAGS = 0x80041000,
*/
module core.sys.windows.ipexport;
version (Windows):
+@system:
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum size_t MAX_ADAPTER_NAME = 128;
*/
module core.sys.windows.iphlpapi;
version (Windows):
+@system:
import core.sys.windows.ipexport, core.sys.windows.iprtrmib, core.sys.windows.iptypes;
-private import core.sys.windows.winbase, core.sys.windows.windef;
+import core.sys.windows.winbase, core.sys.windows.windef;
extern (Windows) {
DWORD AddIPAddress(IPAddr, IPMask, DWORD, PULONG, PULONG);
*/
module core.sys.windows.iprtrmib;
version (Windows):
+@system:
import core.sys.windows.ipifcons;
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
// FIXME: check types of constants
*/
module core.sys.windows.iptypes;
version (Windows):
+@system:
import core.sys.windows.windef;
import core.stdc.time;
module core.sys.windows.isguids;
version (Windows):
-private import core.sys.windows.basetyps;
+import core.sys.windows.basetyps;
extern (C) extern const GUID
CLSID_InternetShortcut,
*/
module core.sys.windows.lm;
version (Windows):
+@system:
+
/* removed - now supporting only Win2k up
version (WindowsVista) {
version = WIN32_WINNT_ONLY;
*/
module core.sys.windows.lmaccess;
version (Windows):
+@system:
pragma(lib, "netapi32");
/**
the Platform SDK docs, so they have been dropped from this file.
*/
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
const wchar[]
GROUP_SPECIALGRP_USERS = "USERS",
*/
module core.sys.windows.lmalert;
version (Windows):
+@system:
pragma(lib, "netapi32");
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
const TCHAR[]
ALERTER_MAILSLOT = `\\.\MAILSLOT\Alerter`,
version (Windows):
pragma(lib, "netapi32");
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
extern (Windows) {
NET_API_STATUS NetApiBufferAllocate(DWORD, PVOID*);
*/
module core.sys.windows.lmat;
version (Windows):
+@system:
pragma(lib, "netapi32");
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
enum JOB_RUN_PERIODICALLY = 1;
enum JOB_EXEC_ERROR = 2;
// COMMENT: This file may be deprecated.
module core.sys.windows.lmaudit;
version (Windows):
+@system:
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
enum LOGFLAGS_FORWARD = 0;
enum LOGFLAGS_BACKWARD = 1;
*/
module core.sys.windows.lmbrowsr;
version (Windows):
+@system:
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
enum BROWSER_ROLE_PDC = 1;
enum BROWSER_ROLE_BDC = 2;
*/
module core.sys.windows.lmchdev;
version (Windows):
+@system:
// COMMENT: This file might be deprecated.
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
enum CHARDEVQ_NO_REQUESTS = -1;
enum CHARDEV_CLOSE = 0;
*/
module core.sys.windows.lmconfig;
version (Windows):
+@system:
// All functions in this file are deprecated!
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
deprecated {
struct CONFIG_INFO_0 {
*/
module core.sys.windows.lmcons;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.windef;
-private import core.sys.windows.lmerr; // for NERR_BASE
+import core.sys.windows.windef;
+import core.sys.windows.lmerr; // for NERR_BASE
const TCHAR[]
MESSAGE_FILENAME = "NETMSG",
*/
module core.sys.windows.lmerr;
version (Windows):
+@system:
import core.sys.windows.winerror;
*/
module core.sys.windows.lmerrlog;
version (Windows):
+@system:
// COMMENT: This appears to be only for Win16. All functions are deprecated.
-private import core.sys.windows.lmcons, core.sys.windows.windef;
-private import core.sys.windows.lmaudit; // for LPHLOG
+import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmaudit; // for LPHLOG
enum ERRLOG_BASE=3100;
enum ERRLOG2_BASE=5700;
*/
module core.sys.windows.lmmsg;
version (Windows):
+@system:
pragma(lib, "netapi32");
-private import core.sys.windows.lmcons, core.sys.windows.windef, core.sys.windows.w32api;
+import core.sys.windows.lmcons, core.sys.windows.windef, core.sys.windows.w32api;
static assert (_WIN32_WINNT >= 0x501,
"core.sys.windows.lmmsg is available only if version WindowsXP, Windows2003 "
*/
module core.sys.windows.lmremutl;
version (Windows):
+@system:
pragma(lib, "netapi32");
// D Conversion Note: DESC_CHAR is defined as TCHAR.
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
enum SUPPORTS_REMOTE_ADMIN_PROTOCOL = 2;
enum SUPPORTS_RPC = 4;
*/
module core.sys.windows.lmrepl;
version (Windows):
+@system:
pragma(lib, "netapi32");
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
enum REPL_ROLE_EXPORT=1;
enum REPL_ROLE_IMPORT=2;
*/
module core.sys.windows.lmserver;
version (Windows):
+@system:
import core.sys.windows.winsvc;
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
struct SERVER_INFO_100 {
DWORD sv100_platform_id;
*/
module core.sys.windows.lmshare;
version (Windows):
+@system:
pragma(lib, "netapi32");
import core.sys.windows.lmcons;
-private import core.sys.windows.w32api, core.sys.windows.windef;
+import core.sys.windows.w32api, core.sys.windows.windef;
enum SHARE_NETNAME_PARMNUM = 1;
*/
module core.sys.windows.lmsname;
version (Windows):
+@system:
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
const TCHAR[]
SERVICE_WORKSTATION = "LanmanWorkstation",
*/
module core.sys.windows.lmstats;
version (Windows):
+@system:
pragma(lib, "netapi32");
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
enum ULONG
STATSOPT_CLR = 1,
*/
module core.sys.windows.lmsvc;
version (Windows):
+@system:
// FIXME: Is this file deprecated? All of the functions are only for Win16.
/**
*/
// TODO: 5 macros
-private import core.sys.windows.lmcons, core.sys.windows.lmsname, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.lmsname, core.sys.windows.windef;
const TCHAR[] SERVICE_DOS_ENCRYPTION = "ENCRYPT";
*/
module core.sys.windows.lmuse;
version (Windows):
+@system:
pragma(lib, "netapi32");
import core.sys.windows.lmuseflg;
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
enum {
USE_LOCAL_PARMNUM = 1,
*/
module core.sys.windows.lmwksta;
version (Windows):
+@system:
pragma(lib, "netapi32");
import core.sys.windows.lmuseflg;
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
pragma(lib, "Netapi32");
*/
module core.sys.windows.lzexpand;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "lz32");
-private import core.sys.windows.winbase, core.sys.windows.windef;
+import core.sys.windows.winbase, core.sys.windows.windef;
enum : LONG {
LZERROR_BADINHANDLE = -1,
*/
module core.sys.windows.mapi;
version (Windows):
+@system:
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
// FIXME: check types and grouping of constants
*/
module core.sys.windows.mciavi;
version (Windows):
+@system:
-private import core.sys.windows.mmsystem;
+import core.sys.windows.mmsystem;
// FIXME: check types and grouping of constants
*/
module core.sys.windows.mcx;
version (Windows):
+@system:
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum DWORD
DIALOPTION_BILLING = 64,
*/
module core.sys.windows.mgmtapi;
version (Windows):
+@system:
import core.sys.windows.snmp;
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum {
SNMP_MGMTAPI_TIMEOUT = 40,
*/
module core.sys.windows.mmsystem;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "winmm");
* compile-time constants, so they are implemented as templates.
*/
-private import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.winver;
+import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.winver;
align(1):
BYTE fps;
BYTE dummy;
BYTE[2] pad;
- };
+ }
_smpte smpte;
struct _midi {
DWORD songptrpos;
*/
module core.sys.windows.msacm;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.basetsd, core.sys.windows.mmsystem, core.sys.windows.windef;
+import core.sys.windows.basetsd, core.sys.windows.mmsystem, core.sys.windows.windef;
mixin DECLARE_HANDLE!("HACMDRIVERID");
mixin DECLARE_HANDLE!("HACMDRIVER");
*/
module core.sys.windows.mshtml;
version (Windows):
+@system:
-private import core.sys.windows.basetyps, core.sys.windows.oaidl, core.sys.windows.unknwn,
+import core.sys.windows.basetyps, core.sys.windows.oaidl, core.sys.windows.unknwn,
core.sys.windows.windef, core.sys.windows.wtypes;
// These are used in this file, but not defined in MinGW.
-interface IHTMLStyleSheet {};
+interface IHTMLStyleSheet {}
alias IHTMLStyle LPHTMLSTYLE;
alias IHTMLStyleSheet LPHTMLSTYLESHEET;
-interface IHTMLLocation {};
+interface IHTMLLocation {}
alias IHTMLLocation LPHTMLLOCATION;
-interface IHTMLFramesCollection {};
+interface IHTMLFramesCollection {}
alias IHTMLFramesCollection LPHTMLFRAMESCOLLECTION;
-interface IHTMLStyleSheetsCollection {};
+interface IHTMLStyleSheetsCollection {}
alias IHTMLStyleSheetsCollection LPHTMLSTYLESHEETSCOLLECTION;
-interface IHTMLStyle {};
-interface IHTMLFiltersCollection {};
+interface IHTMLStyle {}
+interface IHTMLFiltersCollection {}
alias IHTMLFiltersCollection LPHTMLFILTERSCOLLECTION;
interface IOmHistory : IDispatch {
HRESULT get_length(short* p);
HRESULT back(VARIANT*);
HRESULT forward(VARIANT*);
HRESULT go(VARIANT*);
-};
+}
alias IOmHistory LPOMHISTORY;
-interface IOmNavigator {};
+interface IOmNavigator {}
alias IOmNavigator LPOMNAVIGATOR;
-interface IHTMLImageElementFactory {};
+interface IHTMLImageElementFactory {}
alias IHTMLImageElementFactory LPHTMLIMAGEELEMENTFACTORY;
-interface IHTMLEventObj {};
+interface IHTMLEventObj {}
alias IHTMLEventObj LPHTMLEVENTOBJ;
-interface IHTMLScreen {};
+interface IHTMLScreen {}
alias IHTMLScreen LPHTMLSCREEN;
-interface IHTMLOptionElementFactory {};
+interface IHTMLOptionElementFactory {}
alias IHTMLOptionElementFactory LPHTMLOPTIONELEMENTFACTORY;
interface IHTMLLinkElement : IDispatch {
*/
module core.sys.windows.mswsock;
version (Windows):
+@system:
import core.sys.windows.winbase, core.sys.windows.windef;
-private import core.sys.windows.basetyps, core.sys.windows.w32api;
+import core.sys.windows.basetyps, core.sys.windows.w32api;
import core.sys.windows.winsock2;
*/
module core.sys.windows.nb30;
version (Windows):
+@system:
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum size_t
NCBNAMSZ = 16,
*/
module core.sys.windows.nddeapi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
// FIXME: check types and grouping of constants
*/
module core.sys.windows.nspapi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.basetyps, core.sys.windows.windef;
+import core.sys.windows.basetyps, core.sys.windows.windef;
// FIXME: check types of constants
*/
module core.sys.windows.ntdef;
version (Windows):
+@system:
-private import core.sys.windows.basetsd, core.sys.windows.subauth, core.sys.windows.windef, core.sys.windows.winnt;
+import core.sys.windows.basetsd, core.sys.windows.subauth, core.sys.windows.windef, core.sys.windows.winnt;
enum uint
OBJ_INHERIT = 0x0002,
*/
module core.sys.windows.ntdll;
version (Windows):
+@system:
-private import core.sys.windows.w32api;
+import core.sys.windows.w32api;
enum SHUTDOWN_ACTION {
*/
module core.sys.windows.ntldap;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
*/
module core.sys.windows.ntsecapi;
version (Windows):
+@system:
pragma(lib, "advapi32");
version (ANSI) {} else version = Unicode;
*/
module core.sys.windows.ntsecpkg;
version (Windows):
+@system:
import core.sys.windows.windef, core.sys.windows.ntsecapi, core.sys.windows.security, core.sys.windows.ntdef, core.sys.windows.sspi;
import core.sys.windows.basetyps : GUID;
*/
module core.sys.windows.oaidl;
version (Windows):
+@system:
-private import core.sys.windows.basetyps, core.sys.windows.unknwn, core.sys.windows.windef, core.sys.windows.wtypes;
+import core.sys.windows.basetyps, core.sys.windows.unknwn, core.sys.windows.windef, core.sys.windows.wtypes;
enum DISPID_UNKNOWN = -1;
enum DISPID_VALUE = 0;
*/
module core.sys.windows.objbase;
version (Windows):
+@system:
pragma(lib, "ole32");
import core.sys.windows.cguid, core.sys.windows.objidl, core.sys.windows.unknwn, core.sys.windows.wtypes;
-private import core.sys.windows.basetyps, core.sys.windows.objfwd, core.sys.windows.rpcdce, core.sys.windows.winbase,
+import core.sys.windows.basetyps, core.sys.windows.objfwd, core.sys.windows.rpcdce, core.sys.windows.winbase,
core.sys.windows.windef;
// DAC: Not needed for D?
*/
module core.sys.windows.objfwd;
version (Windows):
+@system:
-private import core.sys.windows.objidl;
+import core.sys.windows.objidl;
/+
// Forward declararions are not necessary in D.
// # do we need the proxies that are defined in this file?
module core.sys.windows.objidl;
version (Windows):
+@system:
import core.sys.windows.unknwn;
import core.sys.windows.objfwd;
-private import core.sys.windows.windef;
-private import core.sys.windows.basetyps;
-private import core.sys.windows.oleidl;
-private import core.sys.windows.wtypes;
-private import core.sys.windows.winbase; // for FILETIME
-private import core.sys.windows.rpcdce;
+import core.sys.windows.windef;
+import core.sys.windows.basetyps;
+import core.sys.windows.oleidl;
+import core.sys.windows.wtypes;
+import core.sys.windows.winbase; // for FILETIME
+import core.sys.windows.rpcdce;
struct STATSTG {
LPOLESTR pwcsName;
*/
module core.sys.windows.objsafe;
version (Windows):
+@system:
-private import core.sys.windows.basetyps, core.sys.windows.unknwn, core.sys.windows.windef;
+import core.sys.windows.basetyps, core.sys.windows.unknwn, core.sys.windows.windef;
enum {
INTERFACESAFE_FOR_UNTRUSTED_CALLER = 1,
*/
module core.sys.windows.ocidl;
version (Windows):
+@system:
-private import core.sys.windows.ole2, core.sys.windows.oleidl, core.sys.windows.oaidl, core.sys.windows.objfwd,
+import core.sys.windows.ole2, core.sys.windows.oleidl, core.sys.windows.oaidl, core.sys.windows.objfwd,
core.sys.windows.windef, core.sys.windows.wtypes;
-private import core.sys.windows.objidl; // for CLIPFORMAT
-private import core.sys.windows.wingdi; // for TEXTMETRICW
-private import core.sys.windows.winuser; // for LPMSG
+import core.sys.windows.objidl; // for CLIPFORMAT
+import core.sys.windows.wingdi; // for TEXTMETRICW
+import core.sys.windows.winuser; // for LPMSG
interface IBindHost : IUnknown {}
/*
// TODO:
-//private import core.sys.windows.servprov; // for IServiceProvider
-// private import core.sys.windows.urlmon; // for IBindHost. This is not included in MinGW.
+//import core.sys.windows.servprov; // for IServiceProvider
+// import core.sys.windows.urlmon; // for IBindHost. This is not included in MinGW.
// core.sys.windows.urlmon should contain:
interface IBindHost : IUnknown
*/
module core.sys.windows.odbcinst;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
import core.sys.windows.sql;
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
/* FIXME: The Unicode/Ansi functions situation is a mess. How do the xxxA
* versions of these functions fit into the scheme?
*/
module core.sys.windows.ole;
version (Windows):
+@system:
pragma(lib, "ole32");
-private import core.sys.windows.windef, core.sys.windows.wingdi, core.sys.windows.uuid;
+import core.sys.windows.windef, core.sys.windows.wingdi, core.sys.windows.uuid;
alias LPCSTR OLE_LPCSTR;
*/
module core.sys.windows.ole2;
version (Windows):
+@system:
pragma(lib, "ole32");
public import core.sys.windows.basetyps, core.sys.windows.objbase, core.sys.windows.oleauto, core.sys.windows.olectlid,
core.sys.windows.oleidl, core.sys.windows.unknwn, core.sys.windows.winerror, core.sys.windows.uuid;
-private import core.sys.windows.objfwd, core.sys.windows.objidl, core.sys.windows.windef, core.sys.windows.wtypes;
-private import core.sys.windows.winuser; // for LPMSG
+import core.sys.windows.objfwd, core.sys.windows.objidl, core.sys.windows.windef, core.sys.windows.wtypes;
+import core.sys.windows.winuser; // for LPMSG
enum E_DRAW = VIEW_E_DRAW;
*/
module core.sys.windows.oleacc;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "oleacc");
-private import core.sys.windows.basetyps, core.sys.windows.oaidl, core.sys.windows.unknwn, core.sys.windows.wtypes,
+import core.sys.windows.basetyps, core.sys.windows.oaidl, core.sys.windows.unknwn, core.sys.windows.wtypes,
core.sys.windows.windef;
enum {
*/
module core.sys.windows.oleauto;
version (Windows):
+@system:
pragma(lib, "oleaut32");
import core.sys.windows.oaidl;
-private import core.sys.windows.basetyps, core.sys.windows.unknwn, core.sys.windows.windef, core.sys.windows.wtypes;
-private import core.sys.windows.winbase; // for SYSTEMTIME
+import core.sys.windows.basetyps, core.sys.windows.unknwn, core.sys.windows.windef, core.sys.windows.wtypes;
+import core.sys.windows.winbase; // for SYSTEMTIME
align(8):
enum STDOLE_MAJORVERNUM = 1;
deprecated { // not actually deprecated, but they aren't converted yet.
// (will need to reinstate CreateTypeLib as well)
- interface ICreateTypeInfo {};
- interface ICreateTypeInfo2 {};
- interface ICreateTypeLib {};
- interface ICreateTypeLib2 {};
+ interface ICreateTypeInfo {}
+ interface ICreateTypeInfo2 {}
+ interface ICreateTypeLib {}
+ interface ICreateTypeLib2 {}
alias ICreateTypeInfo LPCREATETYPEINFO;
alias ICreateTypeInfo2 LPCREATETYPEINFO2;
*/
module core.sys.windows.olectl;
version (Windows):
+@system:
// In conversion from MinGW, the following was deleted:
//#define FONTSIZE(n) {n##0000, 0}
import core.sys.windows.ocidl, core.sys.windows.olectlid;
-private import core.sys.windows.basetyps, core.sys.windows.oaidl, core.sys.windows.oleauto, core.sys.windows.unknwn,
+import core.sys.windows.basetyps, core.sys.windows.oaidl, core.sys.windows.oleauto, core.sys.windows.unknwn,
core.sys.windows.windef, core.sys.windows.wingdi, core.sys.windows.winuser, core.sys.windows.wtypes;
-private import core.sys.windows.ntdef; // for NTSTATUS
-private import core.sys.windows.objfwd; // for LPSTREAM
-private import core.sys.windows.winerror; // for SCODE
+import core.sys.windows.ntdef; // for NTSTATUS
+import core.sys.windows.objfwd; // for LPSTREAM
+import core.sys.windows.winerror; // for SCODE
private {
module core.sys.windows.olectlid;
version (Windows):
-private import core.sys.windows.basetyps;
+import core.sys.windows.basetyps;
* Source: $(DRUNTIMESRC src/core/sys/windows/_oledlg.d)
*/
module core.sys.windows.oledlg;
+@system:
version (Windows):
version (ANSI) {} else version = Unicode;
import core.sys.windows.commdlg, core.sys.windows.dlgs, core.sys.windows.ole2, core.sys.windows.prsht, core.sys.windows.shellapi;
-private import core.sys.windows.winbase, core.sys.windows.objidl, core.sys.windows.objfwd, core.sys.windows.winnt;
+import core.sys.windows.winbase, core.sys.windows.objidl, core.sys.windows.objfwd, core.sys.windows.winnt;
// FIXME: remove inherited methods from interface definitions
*/
module core.sys.windows.oleidl;
version (Windows):
+@system:
// DAC: This is defined in ocidl !!
// what is it doing in here?
//alias IEnumOleUndoUnits LPENUMOLEUNDOUNITS;
-private import core.sys.windows.basetyps, core.sys.windows.objidl, core.sys.windows.unknwn, core.sys.windows.windef,
+import core.sys.windows.basetyps, core.sys.windows.objidl, core.sys.windows.unknwn, core.sys.windows.windef,
core.sys.windows.winuser, core.sys.windows.wtypes;
-private import core.sys.windows.objfwd; // for LPMONIKER
-private import core.sys.windows.wingdi; // for LPLOGPALETTE
+import core.sys.windows.objfwd; // for LPMONIKER
+import core.sys.windows.wingdi; // for LPLOGPALETTE
enum MK_ALT = 32;
*/
module core.sys.windows.pbt;
version (Windows):
+@system:
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum : WPARAM {
PBT_APMQUERYSUSPEND,
*/
module core.sys.windows.powrprof;
version (Windows):
+@system:
pragma(lib, "powrprof");
-private import core.sys.windows.windef;
-private import core.sys.windows.ntdef;
+import core.sys.windows.windef;
+import core.sys.windows.ntdef;
// FIXME: look up Windows version support
*/
module core.sys.windows.prsht;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "comctl32");
-private import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.winuser;
+import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.winuser;
enum MAXPROPPAGES = 100;
module core.sys.windows.psapi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.w32api;
-private import core.sys.windows.winbase;
-private import core.sys.windows.windef;
+import core.sys.windows.w32api;
+import core.sys.windows.winbase;
+import core.sys.windows.windef;
struct MODULEINFO {
LPVOID lpBaseOfDll;
/* application-defined callback function used with the EnumPageFiles()
* http://windowssdk.msdn.microsoft.com/library/ms682627.aspx */
-version (Unicode) {
- alias BOOL function(LPVOID, PENUM_PAGE_FILE_INFORMATION, LPCWSTR)
- PENUM_PAGE_FILE_CALLBACK;
-} else {
- alias BOOL function(LPVOID, PENUM_PAGE_FILE_INFORMATION, LPCSTR)
- PENUM_PAGE_FILE_CALLBACK;
-}
+alias BOOL function(LPVOID, PENUM_PAGE_FILE_INFORMATION, LPCWSTR)
+ PENUM_PAGE_FILE_CALLBACKW;
+alias BOOL function(LPVOID, PENUM_PAGE_FILE_INFORMATION, LPCSTR)
+ PENUM_PAGE_FILE_CALLBACKA;
+
// Grouped by application, not in alphabetical order.
extern (Windows) {
/* Resources Information */
BOOL GetPerformanceInfo(PPERFORMANCE_INFORMATION, DWORD); /* XP/Server2003/Vista/Longhorn */
- BOOL EnumPageFilesW(PENUM_PAGE_FILE_CALLBACK, LPVOID); /* 2000/XP/Server2003/Vista/Longhorn */
- BOOL EnumPageFilesA(PENUM_PAGE_FILE_CALLBACK, LPVOID); /* 2000/XP/Server2003/Vista/Longhorn */
+ BOOL EnumPageFilesW(PENUM_PAGE_FILE_CALLBACKW, LPVOID); /* 2000/XP/Server2003/Vista/Longhorn */
+ BOOL EnumPageFilesA(PENUM_PAGE_FILE_CALLBACKA, LPVOID); /* 2000/XP/Server2003/Vista/Longhorn */
}
version (Unicode) {
+ alias PENUM_PAGE_FILE_CALLBACKW PENUM_PAGE_FILE_CALLBACK;
alias GetModuleBaseNameW GetModuleBaseName;
alias GetModuleFileNameExW GetModuleFileNameEx;
alias GetMappedFileNameW GetMappedFileName;
alias EnumPageFilesW EnumPageFiles;
alias GetProcessImageFileNameW GetProcessImageFileName;
} else {
+ alias PENUM_PAGE_FILE_CALLBACKA PENUM_PAGE_FILE_CALLBACK;
alias GetModuleBaseNameA GetModuleBaseName;
alias GetModuleFileNameExA GetModuleFileNameEx;
alias GetMappedFileNameA GetMappedFileName;
*/
module core.sys.windows.rapi;
version (Windows):
+@system:
/* Comment from MinGW
NOTE: This strictly does not belong in the Win32 API since it's
really part of Platform SDK.
*/
-private import core.sys.windows.winbase, core.sys.windows.windef;
+import core.sys.windows.winbase, core.sys.windows.windef;
extern (Windows):
*/
module core.sys.windows.ras;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "rasapi32");
-private import core.sys.windows.basetyps, core.sys.windows.lmcons, core.sys.windows.w32api, core.sys.windows.windef;
+import core.sys.windows.basetyps, core.sys.windows.lmcons, core.sys.windows.w32api, core.sys.windows.windef;
align(4):
*/
module core.sys.windows.rasdlg;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
import core.sys.windows.ras;
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
enum {
RASPBDEVENT_AddEntry = 1,
*/
module core.sys.windows.raserror;
version (Windows):
+@system:
enum {
SUCCESS = 0,
*/
module core.sys.windows.rassapi;
version (Windows):
+@system:
-private import core.sys.windows.lmcons, core.sys.windows.windef;
+import core.sys.windows.lmcons, core.sys.windows.windef;
// FIXME: check types of constants
*/
module core.sys.windows.reason;
version (Windows):
+@system:
-private import core.sys.windows.w32api, core.sys.windows.windef;
+import core.sys.windows.w32api, core.sys.windows.windef;
static assert (_WIN32_WINNT >= 0x501,
"core.sys.windows.reason is only available on WindowsXP and later");
*/
module core.sys.windows.regstr;
version (Windows):
+@system:
// TODO: fix possible conflict with shloj. Sort out NEC_98 issue.
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum REGSTR_MAX_VALUE_LENGTH = 256;
*/
module core.sys.windows.richedit;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.windef, core.sys.windows.winuser;
-private import core.sys.windows.wingdi; // for LF_FACESIZE
+import core.sys.windows.windef, core.sys.windows.winuser;
+import core.sys.windows.wingdi; // for LF_FACESIZE
align(4):
*/
module core.sys.windows.richole;
version (Windows):
+@system:
-private import core.sys.windows.objfwd, core.sys.windows.objidl, core.sys.windows.ole2, core.sys.windows.unknwn,
+import core.sys.windows.objfwd, core.sys.windows.objidl, core.sys.windows.ole2, core.sys.windows.unknwn,
core.sys.windows.windef;
-private import core.sys.windows.richedit; // for CHARRANGE
+import core.sys.windows.richedit; // for CHARRANGE
//align(4):
HRESULT ContextSensitiveHelp(BOOL);
HRESULT GetClipboardData(CHARRANGE*, DWORD, LPDATAOBJECT*);
HRESULT ImportDataObject(LPDATAOBJECT, CLIPFORMAT, HGLOBAL);
-};
+}
alias IRichEditOle LPRICHEDITOLE;
interface IRichEditOleCallback : IUnknown {
HRESULT GetClipboardData(CHARRANGE*, DWORD, LPDATAOBJECT*);
HRESULT GetDragDropEffect(BOOL, DWORD, PDWORD);
HRESULT GetContextMenu(WORD, LPOLEOBJECT, CHARRANGE*, HMENU*);
-};
+}
alias IRichEditOleCallback LPRICHEDITOLECALLBACK;
*/
module core.sys.windows.rpc;
version (Windows):
+@system:
/* Moved to rpcdecp (duplicate definition).
typedef void *I_RPC_HANDLE;
*/
module core.sys.windows.rpcdce;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "Rpcrt4");
// replaced aliases for version (Unicode)
public import core.sys.windows.rpcdcep;
-private import core.sys.windows.basetyps, core.sys.windows.w32api, core.sys.windows.windef;
+import core.sys.windows.basetyps, core.sys.windows.w32api, core.sys.windows.windef;
// FIXME: clean up Windows version support
*/
module core.sys.windows.rpcdce2;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
import core.sys.windows.rpcdce;
-private import core.sys.windows.basetyps;
+import core.sys.windows.basetyps;
// FIXME: deal with RPC_UNICODE_SUPPORTED
// FIXME: check types of constants
*/
module core.sys.windows.rpcdcep;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.basetyps;
-private import core.sys.windows.w32api;
-private import core.sys.windows.windef;
+import core.sys.windows.basetyps;
+import core.sys.windows.w32api;
+import core.sys.windows.windef;
mixin DECLARE_HANDLE!("I_RPC_HANDLE");
alias long RPC_STATUS;
*/
module core.sys.windows.rpcndr;
version (Windows):
+@system:
pragma(lib, "rpcrt4");
/* Translation notes:
enum __RPCNDR_H_VERSION__= 450;
import core.sys.windows.rpcnsip;
-private import core.sys.windows.rpc, core.sys.windows.rpcdce, core.sys.windows.unknwn, core.sys.windows.windef;
-private import core.sys.windows.objidl; // for IRpcChannelBuffer, IRpcStubBuffer
-private import core.sys.windows.basetyps;
+import core.sys.windows.rpc, core.sys.windows.rpcdce, core.sys.windows.unknwn, core.sys.windows.windef;
+import core.sys.windows.objidl; // for IRpcChannelBuffer, IRpcStubBuffer
+import core.sys.windows.basetyps;
extern (Windows):
*/
module core.sys.windows.rpcnsi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "rpcns4");
-private import core.sys.windows.basetyps, core.sys.windows.rpcdcep, core.sys.windows.rpcnsi, core.sys.windows.rpcdce,
+import core.sys.windows.basetyps, core.sys.windows.rpcdcep, core.sys.windows.rpcnsi, core.sys.windows.rpcdce,
core.sys.windows.w32api;
-private import core.sys.windows.windef; // for HANDLE
+import core.sys.windows.windef; // for HANDLE
mixin DECLARE_HANDLE!("RPC_NS_HANDLE");
*/
module core.sys.windows.rpcnsip;
version (Windows):
+@system:
-private import core.sys.windows.rpcdce, core.sys.windows.rpcdcep, core.sys.windows.rpcnsi;
+import core.sys.windows.rpcdce, core.sys.windows.rpcdcep, core.sys.windows.rpcnsi;
struct RPC_IMPORT_CONTEXT_P {
RPC_NS_HANDLE LookupContext;
*/
module core.sys.windows.rpcnterr;
version (Windows):
+@system:
import core.sys.windows.winerror;
*/
module core.sys.windows.schannel;
version (Windows):
+@system:
import core.sys.windows.wincrypt;
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum DWORD SCHANNEL_CRED_VERSION = 4;
enum SCHANNEL_SHUTDOWN = 1;
--- /dev/null
+/**
+ * Windows API header module
+ *
+ * Translated from Windows SDK API
+ *
+ * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source: $(DRUNTIMESRC src/core/sys/windows/sdkddkver.d)
+ */
+module core.sys.windows.sdkddkver;
+
+version (Windows):
+@system:
+
+enum _WIN32_WINNT_NT4 = 0x0400;
+enum _WIN32_WINNT_WIN2K = 0x0500;
+enum _WIN32_WINNT_WINXP = 0x0501;
+enum _WIN32_WINNT_WS03 = 0x0502;
+enum _WIN32_WINNT_WIN6 = 0x0600;
+enum _WIN32_WINNT_VISTA = 0x0600;
+enum _WIN32_WINNT_WS08 = 0x0600;
+enum _WIN32_WINNT_LONGHORN = 0x0600;
+enum _WIN32_WINNT_WIN7 = 0x0601;
+enum _WIN32_WINNT_WIN8 = 0x0602;
+enum _WIN32_WINNT_WINBLUE = 0x0603;
+enum _WIN32_WINNT_WIN10 = 0x0A00;
+
+enum _WIN32_IE_IE20 = 0x0200;
+enum _WIN32_IE_IE30 = 0x0300;
+enum _WIN32_IE_IE302 = 0x0302;
+enum _WIN32_IE_IE40 = 0x0400;
+enum _WIN32_IE_IE401 = 0x0401;
+enum _WIN32_IE_IE50 = 0x0500;
+enum _WIN32_IE_IE501 = 0x0501;
+enum _WIN32_IE_IE55 = 0x0550;
+enum _WIN32_IE_IE60 = 0x0600;
+enum _WIN32_IE_IE60SP1 = 0x0601;
+enum _WIN32_IE_IE60SP2 = 0x0603;
+enum _WIN32_IE_IE70 = 0x0700;
+enum _WIN32_IE_IE80 = 0x0800;
+enum _WIN32_IE_IE90 = 0x0900;
+enum _WIN32_IE_IE100 = 0x0A00;
+
+enum _WIN32_IE_NT4 = _WIN32_IE_IE20;
+enum _WIN32_IE_NT4SP1 = _WIN32_IE_IE20;
+enum _WIN32_IE_NT4SP2 = _WIN32_IE_IE20;
+enum _WIN32_IE_NT4SP3 = _WIN32_IE_IE302;
+enum _WIN32_IE_NT4SP4 = _WIN32_IE_IE401;
+enum _WIN32_IE_NT4SP5 = _WIN32_IE_IE401;
+enum _WIN32_IE_NT4SP6 = _WIN32_IE_IE50;
+enum _WIN32_IE_WIN98 = _WIN32_IE_IE401;
+enum _WIN32_IE_WIN98SE = _WIN32_IE_IE50;
+enum _WIN32_IE_WINME = _WIN32_IE_IE55;
+enum _WIN32_IE_WIN2K = _WIN32_IE_IE501;
+enum _WIN32_IE_WIN2KSP1 = _WIN32_IE_IE501;
+enum _WIN32_IE_WIN2KSP2 = _WIN32_IE_IE501;
+enum _WIN32_IE_WIN2KSP3 = _WIN32_IE_IE501;
+enum _WIN32_IE_WIN2KSP4 = _WIN32_IE_IE501;
+enum _WIN32_IE_XP = _WIN32_IE_IE60;
+enum _WIN32_IE_XPSP1 = _WIN32_IE_IE60SP1;
+enum _WIN32_IE_XPSP2 = _WIN32_IE_IE60SP2;
+enum _WIN32_IE_WS03 = 0x0602;
+enum _WIN32_IE_WS03SP1 = _WIN32_IE_IE60SP2;
+enum _WIN32_IE_WIN6 = _WIN32_IE_IE70;
+enum _WIN32_IE_LONGHORN = _WIN32_IE_IE70;
+enum _WIN32_IE_WIN7 = _WIN32_IE_IE80;
+enum _WIN32_IE_WIN8 = _WIN32_IE_IE100;
+enum _WIN32_IE_WINBLUE = _WIN32_IE_IE100;
+
+
+enum NTDDI_WIN2K = 0x05000000;
+enum NTDDI_WIN2KSP1 = 0x05000100;
+enum NTDDI_WIN2KSP2 = 0x05000200;
+enum NTDDI_WIN2KSP3 = 0x05000300;
+enum NTDDI_WIN2KSP4 = 0x05000400;
+
+enum NTDDI_WINXP = 0x05010000;
+enum NTDDI_WINXPSP1 = 0x05010100;
+enum NTDDI_WINXPSP2 = 0x05010200;
+enum NTDDI_WINXPSP3 = 0x05010300;
+enum NTDDI_WINXPSP4 = 0x05010400;
+
+enum NTDDI_WS03 = 0x05020000;
+enum NTDDI_WS03SP1 = 0x05020100;
+enum NTDDI_WS03SP2 = 0x05020200;
+enum NTDDI_WS03SP3 = 0x05020300;
+enum NTDDI_WS03SP4 = 0x05020400;
+
+enum NTDDI_WIN6 = 0x06000000;
+enum NTDDI_WIN6SP1 = 0x06000100;
+enum NTDDI_WIN6SP2 = 0x06000200;
+enum NTDDI_WIN6SP3 = 0x06000300;
+enum NTDDI_WIN6SP4 = 0x06000400;
+
+enum NTDDI_VISTA = NTDDI_WIN6;
+enum NTDDI_VISTASP1 = NTDDI_WIN6SP1;
+enum NTDDI_VISTASP2 = NTDDI_WIN6SP2;
+enum NTDDI_VISTASP3 = NTDDI_WIN6SP3;
+enum NTDDI_VISTASP4 = NTDDI_WIN6SP4;
+
+enum NTDDI_LONGHORN = NTDDI_VISTA;
+
+enum NTDDI_WS08 = NTDDI_WIN6SP1;
+enum NTDDI_WS08SP2 = NTDDI_WIN6SP2;
+enum NTDDI_WS08SP3 = NTDDI_WIN6SP3;
+enum NTDDI_WS08SP4 = NTDDI_WIN6SP4;
+
+enum NTDDI_WIN7 = 0x06010000;
+enum NTDDI_WIN8 = 0x06020000;
+enum NTDDI_WINBLUE = 0x06030000;
+
+enum OSVERSION_MASK = 0xFFFF0000;
+enum SPVERSION_MASK = 0x0000FF00;
+enum SUBVERSION_MASK = 0x000000FF;
+
+enum _WIN32_WINNT = 0x0603;
+
+enum NTDDI_VERSION = 0x06030000;
+enum WINVER = _WIN32_WINNT;
// Don't include this file directly, use core.sys.windows.security instead.
module core.sys.windows.secext;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "secur32");
-private import core.sys.windows.w32api, core.sys.windows.windef;
+import core.sys.windows.w32api, core.sys.windows.windef;
static assert (_WIN32_WINNT >= 0x501,
"SecExt is only available on WindowsXP and later");
*
* Translated from MinGW Windows headers
*
- * Authors: Ellery Newcomer
+ * Authors: Ellery Newcomer, John Colvin
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(DRUNTIMESRC src/core/sys/windows/_security.d)
*/
module core.sys.windows.security;
version (Windows):
+@system:
-enum :SECURITY_STATUS{
- SEC_E_OK = 0,
- SEC_E_CERT_EXPIRED = (-2146893016),
- SEC_E_INCOMPLETE_MESSAGE = (-2146893032),
- SEC_E_INSUFFICIENT_MEMORY = (-2146893056),
- SEC_E_INTERNAL_ERROR = (-2146893052),
- SEC_E_INVALID_HANDLE = (-2146893055),
- SEC_E_INVALID_TOKEN = (-2146893048),
- SEC_E_LOGON_DENIED = (-2146893044),
- SEC_E_NO_AUTHENTICATING_AUTHORITY = (-2146893039),
- SEC_E_NO_CREDENTIALS = (-2146893042),
- SEC_E_TARGET_UNKNOWN = (-2146893053),
- SEC_E_UNSUPPORTED_FUNCTION = (-2146893054),
- SEC_E_UNTRUSTED_ROOT = (-2146893019),
- SEC_E_WRONG_PRINCIPAL = (-2146893022),
- SEC_E_SECPKG_NOT_FOUND = (-2146893051),
- SEC_E_QOP_NOT_SUPPORTED = (-2146893046),
- SEC_E_UNKNOWN_CREDENTIALS = (-2146893043),
- SEC_E_NOT_OWNER = (-2146893050),
+enum : SECURITY_STATUS
+{
+ SEC_E_OK = 0x00000000,
+ SEC_E_INSUFFICIENT_MEMORY = 0x80090300,
+ SEC_E_INVALID_HANDLE = 0x80090301,
+ SEC_E_UNSUPPORTED_FUNCTION = 0x80090302,
+ SEC_E_TARGET_UNKNOWN = 0x80090303,
+ SEC_E_INTERNAL_ERROR = 0x80090304,
+ SEC_E_SECPKG_NOT_FOUND = 0x80090305,
+ SEC_E_NOT_OWNER = 0x80090306,
+ SEC_E_CANNOT_INSTALL = 0x80090307,
+ SEC_E_INVALID_TOKEN = 0x80090308,
+ SEC_E_CANNOT_PACK = 0x80090309,
+ SEC_E_QOP_NOT_SUPPORTED = 0x8009030A,
+ SEC_E_NO_IMPERSONATION = 0x8009030B,
+ SEC_E_LOGON_DENIED = 0x8009030C,
+ SEC_E_UNKNOWN_CREDENTIALS = 0x8009030D,
+ SEC_E_NO_CREDENTIALS = 0x8009030E,
+ SEC_E_MESSAGE_ALTERED = 0x8009030F,
+ SEC_E_OUT_OF_SEQUENCE = 0x80090310,
+ SEC_E_NO_AUTHENTICATING_AUTHORITY = 0x80090311,
+ SEC_E_BAD_PKGID = 0x80090316,
+ SEC_E_CONTEXT_EXPIRED = 0x80090317,
+ SEC_E_INCOMPLETE_MESSAGE = 0x80090318,
+ SEC_E_INCOMPLETE_CREDENTIALS = 0x80090320,
+ SEC_E_BUFFER_TOO_SMALL = 0x80090321,
+ SEC_E_WRONG_PRINCIPAL = 0x80090322,
+ SEC_E_TIME_SKEW = 0x80090324,
+ SEC_E_UNTRUSTED_ROOT = 0x80090325,
+ SEC_E_ILLEGAL_MESSAGE = 0x80090326,
+ SEC_E_CERT_UNKNOWN = 0x80090327,
+ SEC_E_CERT_EXPIRED = 0x80090328,
+ SEC_E_ENCRYPT_FAILURE = 0x80090329,
+ SEC_E_DECRYPT_FAILURE = 0x80090330,
+ SEC_E_ALGORITHM_MISMATCH = 0x80090331,
+ SEC_E_SECURITY_QOS_FAILED = 0x80090332,
+ SEC_E_UNFINISHED_CONTEXT_DELETED = 0x80090333,
+ SEC_E_NO_TGT_REPLY = 0x80090334,
+ SEC_E_NO_IP_ADDRESSES = 0x80090335,
+ SEC_E_WRONG_CREDENTIAL_HANDLE = 0x80090336,
+ SEC_E_CRYPTO_SYSTEM_INVALID = 0x80090337,
+ SEC_E_MAX_REFERRALS_EXCEEDED = 0x80090338,
+ SEC_E_MUST_BE_KDC = 0x80090339,
+ SEC_E_STRONG_CRYPTO_NOT_SUPPORTED = 0x8009033A,
+ SEC_E_TOO_MANY_PRINCIPALS = 0x8009033B,
+ SEC_E_NO_PA_DATA = 0x8009033C,
+ SEC_E_PKINIT_NAME_MISMATCH = 0x8009033D,
+ SEC_E_SMARTCARD_LOGON_REQUIRED = 0x8009033E,
+ SEC_E_SHUTDOWN_IN_PROGRESS = 0x8009033F,
+ SEC_E_KDC_INVALID_REQUEST = 0x80090340,
+ SEC_E_KDC_UNABLE_TO_REFER = 0x80090341,
+ SEC_E_KDC_UNKNOWN_ETYPE = 0x80090342,
+ SEC_E_UNSUPPORTED_PREAUTH = 0x80090343,
+ SEC_E_DELEGATION_REQUIRED = 0x80090345,
+ SEC_E_BAD_BINDINGS = 0x80090346,
+ SEC_E_MULTIPLE_ACCOUNTS = 0x80090347,
+ SEC_E_NO_KERB_KEY = 0x80090348,
+ SEC_E_CERT_WRONG_USAGE = 0x80090349,
+ SEC_E_DOWNGRADE_DETECTED = 0x80090350,
+ SEC_E_SMARTCARD_CERT_REVOKED = 0x80090351,
+ SEC_E_ISSUING_CA_UNTRUSTED = 0x80090352,
+ SEC_E_REVOCATION_OFFLINE_C = 0x80090353,
+ SEC_E_PKINIT_CLIENT_FAILURE = 0x80090354,
+ SEC_E_SMARTCARD_CERT_EXPIRED = 0x80090355,
+ SEC_E_NO_S4U_PROT_SUPPORT = 0x80090356,
+ SEC_E_CROSSREALM_DELEGATION_FAILURE = 0x80090357,
+ SEC_E_REVOCATION_OFFLINE_KDC = 0x80090358,
+ SEC_E_ISSUING_CA_UNTRUSTED_KDC = 0x80090359,
+ SEC_E_KDC_CERT_EXPIRED = 0x8009035A,
+ SEC_E_KDC_CERT_REVOKED = 0x8009035B,
+ SEC_E_INVALID_PARAMETER = 0x8009035D,
+ SEC_E_DELEGATION_POLICY = 0x8009035E,
+ SEC_E_POLICY_NLTM_ONLY = 0x8009035F,
+ SEC_E_NO_CONTEXT = 0x80090361,
+ SEC_E_PKU2U_CERT_FAILURE = 0x80090362,
+ SEC_E_MUTUAL_AUTH_FAILED = 0x80090363,
+ SEC_E_ONLY_HTTPS_ALLOWED = 0x80090365,
+ SEC_E_APPLICATION_PROTOCOL_MISMATCH = 0x80090367,
+ SEC_E_INVALID_UPN_NAME = 0x80090369,
+ SEC_E_EXT_BUFFER_TOO_SMALL = 0x8009036A,
+ SEC_E_INSUFFICIENT_BUFFERS = 0x8009036B,
+ SEC_E_NO_SPM = SEC_E_INTERNAL_ERROR,
+ SEC_E_NOT_SUPPORTED = SEC_E_UNSUPPORTED_FUNCTION
}
-enum :SECURITY_STATUS {
- SEC_I_RENEGOTIATE = 590625,
- SEC_I_COMPLETE_AND_CONTINUE = 590612,
- SEC_I_COMPLETE_NEEDED = 590611,
- SEC_I_CONTINUE_NEEDED = 590610,
- SEC_I_INCOMPLETE_CREDENTIALS = 590624,
+enum : SECURITY_STATUS
+{
+ SEC_I_CONTINUE_NEEDED = 0x00090312,
+ SEC_I_COMPLETE_NEEDED = 0x00090313,
+ SEC_I_COMPLETE_AND_CONTINUE = 0x00090314,
+ SEC_I_LOCAL_LOGON = 0x00090315,
+ SEC_I_GENERIC_EXTENSION_RECEIVED = 0x00090316,
+ SEC_I_CONTEXT_EXPIRED = 0x00090317,
+ SEC_I_INCOMPLETE_CREDENTIALS = 0x00090320,
+ SEC_I_RENEGOTIATE = 0x00090321,
+ SEC_I_NO_LSA_CONTEXT = 0x00090323,
+ SEC_I_SIGNATURE_NEEDED = 0x0009035C,
+ SEC_I_NO_RENEGOTIATION = 0x00090360,
+ SEC_I_MESSAGE_FRAGMENT = 0x00090364,
+ SEC_I_CONTINUE_NEEDED_MESSAGE_OK = 0x00090366,
+ SEC_I_ASYNC_CALL_PENDING = 0x00090368,
}
/* always a char */
-alias char SEC_CHAR;
-alias wchar SEC_WCHAR;
-
-alias int SECURITY_STATUS;
+alias SEC_CHAR = char;
+alias SEC_WCHAR = wchar;
+alias SECURITY_STATUS = int;
*/
module core.sys.windows.servprov;
version (Windows):
+@system:
-private import core.sys.windows.basetyps, core.sys.windows.unknwn, core.sys.windows.windef, core.sys.windows.wtypes;
+import core.sys.windows.basetyps, core.sys.windows.unknwn, core.sys.windows.windef, core.sys.windows.wtypes;
interface IServiceProvider : IUnknown {
HRESULT QueryService(REFGUID, REFIID, void**);
*/
module core.sys.windows.setupapi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "setupapi");
-private import core.sys.windows.basetyps, core.sys.windows.commctrl, core.sys.windows.prsht, core.sys.windows.w32api,
+import core.sys.windows.basetyps, core.sys.windows.commctrl, core.sys.windows.prsht, core.sys.windows.w32api,
core.sys.windows.winreg, core.sys.windows.windef;
-private import core.sys.windows.winbase; // for SYSTEMTIME
+import core.sys.windows.winbase; // for SYSTEMTIME
/*static if (_WIN32_WINNT < _WIN32_WINDOWS) {
enum UINT _SETUPAPI_VER = _WIN32_WINNT; // SetupAPI version follows Windows NT version
*/
module core.sys.windows.shellapi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "shell32");
-private import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.basetyps;
+import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.basetyps;
enum : UINT {
ABE_LEFT,
*/
module core.sys.windows.shldisp;
version (Windows):
+@system:
-private import core.sys.windows.unknwn, core.sys.windows.windef, core.sys.windows.wtypes;
+import core.sys.windows.unknwn, core.sys.windows.windef, core.sys.windows.wtypes;
// options for IAutoComplete2
enum DWORD ACO_AUTOSUGGEST = 0x01;
*/
module core.sys.windows.shlguid;
version (Windows):
+@system:
-private import core.sys.windows.basetyps, core.sys.windows.w32api;
+import core.sys.windows.basetyps, core.sys.windows.w32api;
// FIXME: clean up Windows version support
*/
module core.sys.windows.shlobj;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "shell32");
// SHGetFolderPath in shfolder.dll on W9x, NT4, also in shell32.dll on W2K
import core.sys.windows.commctrl, core.sys.windows.ole2, core.sys.windows.shlguid, core.sys.windows.shellapi;
-private import core.sys.windows.prsht, core.sys.windows.unknwn, core.sys.windows.w32api, core.sys.windows.winbase,
+import core.sys.windows.prsht, core.sys.windows.unknwn, core.sys.windows.w32api, core.sys.windows.winbase,
core.sys.windows.winnt, core.sys.windows.winuser, core.sys.windows.wtypes, core.sys.windows.objfwd, core.sys.windows.objidl;
-private import core.sys.windows.winnetwk; // for NETRESOURCE
-private import core.sys.windows.oaidl : VARIANT;
+import core.sys.windows.winnetwk; // for NETRESOURCE
+import core.sys.windows.oaidl : VARIANT;
// FIXME: clean up Windows version support
interface IContextMenu2 : IContextMenu {
HRESULT HandleMenuMsg(UINT, WPARAM, LPARAM);
-};
+}
alias IContextMenu2 LPCONTEXTMENU2;
static if (_WIN32_IE >= 0x500) {
interface IExtractIconA : IUnknown {
HRESULT GetIconLocation(UINT, LPSTR, UINT, int*, PUINT);
HRESULT Extract(LPCSTR, UINT, HICON*, HICON*, UINT);
-};
+}
alias IExtractIconA LPEXTRACTICONA;
interface IExtractIconW : IUnknown {
alias IEnumExtraSearch LPENUMEXTRASEARCH;
interface IShellFolder2 : IShellFolder {
- HRESULT ParseDisplayName(HWND, LPBC, LPOLESTR, PULONG, LPITEMIDLIST*, PULONG);
- HRESULT EnumObjects(HWND, DWORD, LPENUMIDLIST*);
- HRESULT BindToObject(LPCITEMIDLIST, LPBC, REFIID, PVOID*);
- HRESULT BindToStorage(LPCITEMIDLIST, LPBC, REFIID, PVOID*);
- HRESULT CompareIDs(LPARAM, LPCITEMIDLIST, LPCITEMIDLIST);
- HRESULT CreateViewObject(HWND, REFIID, PVOID*);
- HRESULT GetAttributesOf(UINT, LPCITEMIDLIST*, PULONG);
- HRESULT GetUIObjectOf(HWND, UINT, LPCITEMIDLIST*, REFIID, PUINT, PVOID*);
- HRESULT GetDisplayNameOf(LPCITEMIDLIST, DWORD, LPSTRRET);
- HRESULT SetNameOf(HWND, LPCITEMIDLIST, LPCOLESTR, DWORD, LPITEMIDLIST*);
HRESULT GetDefaultSearchGUID(GUID*);
HRESULT EnumSearches(IEnumExtraSearch*);
HRESULT GetDefaultColumn(DWORD, ULONG*, ULONG*);
*/
module core.sys.windows.shlwapi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "shlwapi");
*/
import core.sys.windows.objbase, core.sys.windows.shlobj;
-private import core.sys.windows.basetyps, core.sys.windows.objidl, core.sys.windows.unknwn, core.sys.windows.windef,
+import core.sys.windows.basetyps, core.sys.windows.objidl, core.sys.windows.unknwn, core.sys.windows.windef,
core.sys.windows.winbase, core.sys.windows.winreg;
enum DLLVER_PLATFORM_WINDOWS = 0x00000001;
*/
module core.sys.windows.snmp;
version (Windows):
+@system:
-private import core.sys.windows.basetsd /+: HANDLE+/;
-private import core.sys.windows.windef /+: BOOL, BYTE, DWORD, INT, LONG, UINT, ULONG+/;
-private import core.sys.windows.winnt /+: LPSTR, LPVOID, ULARGE_INTEGER, VOID+/;
+import core.sys.windows.basetsd /+: HANDLE+/;
+import core.sys.windows.windef /+: BOOL, BYTE, DWORD, INT, LONG, UINT, ULONG+/;
+import core.sys.windows.winnt /+: LPSTR, LPVOID, ULARGE_INTEGER, VOID+/;
// These are not documented on MSDN
enum {
*/
module core.sys.windows.sql;
version (Windows):
+@system:
public import core.sys.windows.sqltypes;
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum ODBCVER = 0x0351;
*/
module core.sys.windows.sqlext;
version (Windows):
+@system:
/* Conversion notes:
The MinGW file was a horrible mess. All of the #defines were sorted alphabetically,
*/
public import core.sys.windows.sql;
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum SQL_SPEC_MAJOR = 3;
enum SQL_SPEC_MINOR = 51;
*/
module core.sys.windows.sqltypes;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
It's assumed that ODBC >= 0x0300.
*/
-private import core.sys.windows.windef;
-private import core.sys.windows.basetyps; // for GUID
+import core.sys.windows.windef;
+import core.sys.windows.basetyps; // for GUID
alias byte SCHAR, SQLSCHAR;
alias int SDWORD, SLONG, SQLINTEGER;
*/
module core.sys.windows.sqlucode;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.sqlext;
+import core.sys.windows.sqlext;
enum SQL_WCHAR = -8;
enum SQL_WVARCHAR = -9;
*/
module core.sys.windows.sspi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
module core.sys.windows.stacktrace;
version (Windows):
+@system:
import core.demangle;
-import core.runtime;
import core.stdc.stdlib;
import core.stdc.string;
import core.sys.windows.dbghelp;
// do ... while so that we don't skip the first stackframe
do
{
- if ( stackframe.AddrPC.Offset == stackframe.AddrReturn.Offset )
- {
- debug(PRINTF) printf("Endless callstack\n");
- break;
- }
if (frameNum >= skip)
{
result ~= stackframe.AddrPC.Offset;
char[][] trace;
foreach (pc; addresses)
{
- if ( pc != 0 )
+ char[] res;
+ if (dbghelp.SymGetSymFromAddr64(hProcess, pc, null, symbol) &&
+ *symbol.Name.ptr)
{
- char[] res;
- if (dbghelp.SymGetSymFromAddr64(hProcess, pc, null, symbol) &&
- *symbol.Name.ptr)
- {
- DWORD disp;
- IMAGEHLP_LINEA64 line=void;
- line.SizeOfStruct = IMAGEHLP_LINEA64.sizeof;
-
- if (dbghelp.SymGetLineFromAddr64(hProcess, pc, &disp, &line))
- res = formatStackFrame(cast(void*)pc, symbol.Name.ptr,
- line.FileName, line.LineNumber);
- else
- res = formatStackFrame(cast(void*)pc, symbol.Name.ptr);
- }
+ DWORD disp;
+ IMAGEHLP_LINEA64 line=void;
+ line.SizeOfStruct = IMAGEHLP_LINEA64.sizeof;
+
+ if (dbghelp.SymGetLineFromAddr64(hProcess, pc, &disp, &line))
+ res = formatStackFrame(cast(void*)pc, symbol.Name.ptr,
+ line.FileName, line.LineNumber);
else
- res = formatStackFrame(cast(void*)pc);
- trace ~= res;
+ res = formatStackFrame(cast(void*)pc, symbol.Name.ptr);
}
+ else
+ res = formatStackFrame(cast(void*)pc);
+ trace ~= res;
}
return trace;
}
}
static char[] formatStackFrame(void* pc, char* symName,
- in char* fileName, uint lineNum)
+ const scope char* fileName, uint lineNum)
{
import core.stdc.stdio : snprintf;
char[11] buf=void;
version (Windows):
extern (C) nothrow @nogc:
+@system:
// Posix version is in core.sys.posix.sys.stat
--- /dev/null
+/**
+ * D header file for C99.
+ *
+ * $(C_HEADER_DESCRIPTION pubs.opengroup.org/onlinepubs/009695399/basedefs/_time.h.html, _time.h)
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2009.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly,
+ * Alex Rønne Petersen
+ * Source: $(DRUNTIMESRC core/stdc/_time.d)
+ * Standards: ISO/IEC 9899:1999 (E)
+ */
+
+module core.sys.windows.stdc.time;
+
+version (Windows):
+
+import core.stdc.config;
+
+extern (C):
+@trusted: // There are only a few functions here that use unsafe C strings.
+nothrow:
+@nogc:
+
+///
+struct tm
+{
+ int tm_sec; /// seconds after the minute - [0, 60]
+ int tm_min; /// minutes after the hour - [0, 59]
+ int tm_hour; /// hours since midnight - [0, 23]
+ int tm_mday; /// day of the month - [1, 31]
+ int tm_mon; /// months since January - [0, 11]
+ int tm_year; /// years since 1900
+ int tm_wday; /// days since Sunday - [0, 6]
+ int tm_yday; /// days since January 1 - [0, 365]
+ int tm_isdst; /// Daylight Saving Time flag
+}
+
+///
+alias c_long time_t;
+///
+alias c_long clock_t;
+
+enum clock_t CLOCKS_PER_SEC = 1000;
+clock_t clock();
+
+///
+void tzset(); // non-standard
+///
+void _tzset(); // non-standard
+///
+@system char* _strdate(return scope char* s); // non-standard
+///
+@system char* _strtime(return scope char* s); // non-standard
+
+///
+extern __gshared const(char)*[2] tzname; // non-standard
*/
module core.sys.windows.subauth;
version (Windows):
+@system:
-private import core.sys.windows.ntdef, core.sys.windows.windef;
+import core.sys.windows.ntdef, core.sys.windows.windef;
/+
alias LONG NTSTATUS;
*/
module core.sys.windows.threadaux;
version (Windows):
+@system:
import core.sys.windows.basetsd/+ : HANDLE+/;
import core.sys.windows.winbase/+ : CloseHandle, GetCurrentThreadId, GetCurrentProcessId,
*/
module core.sys.windows.tlhelp32;
version (Windows):
+@system:
pragma(lib, "kernel32");
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
enum : uint {
HF32_DEFAULT = 1,
*/
module core.sys.windows.tmschema;
version (Windows):
+@system:
/* BUTTON parts */
enum {
*/
module core.sys.windows.unknwn;
version (Windows):
+@system:
import core.sys.windows.objfwd, core.sys.windows.windef, core.sys.windows.wtypes;
-private import core.sys.windows.basetyps;
+import core.sys.windows.basetyps;
extern (Windows) {
void* MIDL_user_allocate(size_t);
module core.sys.windows.uuid;
version (Windows):
+@system:
import core.sys.windows.basetyps;
module core.sys.windows.vfw;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "vfw32");
*/
module core.sys.windows.w32api;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
* removed in order to simplify the bindings.
*/
version (Windows10) {
- enum uint _WIN32_WINNT = 0x604;
+ enum uint _WIN32_WINNT = 0xA00;
} else version (Windows8_1) { // also Windows2012R2
enum uint _WIN32_WINNT = 0x603;
} else version (Windows8) { // also Windows2012
enum uint _WIN32_WINNT = 0x501;
}
-version (IE10) {
+version (IE11) {
+ enum uint _WIN32_IE = 0xA00;
+} else version (IE10) {
enum uint _WIN32_IE = 0xA00;
} else version (IE9) {
enum uint _WIN32_IE = 0x900;
enum uint _WIN32_IE = 0x600;
} else version (IE56) {
enum uint _WIN32_IE = 0x560;
+} else version (IE55) {
+ enum uint _WIN32_IE = 0x550;
} else version (IE501) {
enum uint _WIN32_IE = 0x501;
} else version (IE5) {
enum uint _WIN32_IE = 0x400;
} else version (IE3) {
enum uint _WIN32_IE = 0x300;
+} else static if (_WIN32_WINNT >= 0x500) {
+ enum uint _WIN32_IE = 0x600;
} else static if (_WIN32_WINNT >= 0x410) {
enum uint _WIN32_IE = 0x400;
} else {
*/
module core.sys.windows.winbase;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "kernel32");
*/
import core.sys.windows.windef, core.sys.windows.winver;
-private import core.sys.windows.basetyps, core.sys.windows.w32api, core.sys.windows.winnt;
+import core.sys.windows.basetyps, core.sys.windows.w32api, core.sys.windows.winnt;
// FIXME:
//alias void va_list;
}
alias WIN32_STREAM_ID* LPWIN32_STREAM_ID;
-enum FINDEX_INFO_LEVELS {
- FindExInfoStandard,
- FindExInfoMaxInfoLevel
+static if (_WIN32_WINNT >= 0x601) {
+ enum FINDEX_INFO_LEVELS {
+ FindExInfoStandard,
+ FindExInfoBasic,
+ FindExInfoMaxInfoLevel,
+ }
+} else {
+ enum FINDEX_INFO_LEVELS {
+ FindExInfoStandard,
+ FindExInfoMaxInfoLevel,
+ }
}
enum FINDEX_SEARCH_OPS {
alias DWORD EXECUTION_STATE;
}
+// CreateSymbolicLink
+static if (_WIN32_WINNT >= 0x600) {
+ enum {
+ SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1,
+ SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2
+ }
+}
+
// Callbacks
extern (Windows) {
alias DWORD function(LPVOID) LPTHREAD_START_ROUTINE;
BOOL IsValidAcl(PACL);
BOOL IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR);
BOOL IsValidSid(PSID);
+ BOOL CreateWellKnownSid(WELL_KNOWN_SID_TYPE, PSID, PSID, PDWORD);
BOOL LockFileEx(HANDLE, DWORD, DWORD, DWORD, DWORD, LPOVERLAPPED);
BOOL LogonUserA(LPSTR, LPSTR, LPSTR, DWORD, DWORD, PHANDLE);
BOOL LogonUserW(LPWSTR, LPWSTR, LPWSTR, DWORD, DWORD, PHANDLE);
static if (_WIN32_WINNT >= 0x510) {
VOID RestoreLastError(DWORD);
}
+
+ static if (_WIN32_WINNT >= 0x600) {
+ BOOL CreateSymbolicLinkA(LPCSTR, LPCSTR, DWORD);
+ BOOL CreateSymbolicLinkW(LPCWSTR, LPCWSTR, DWORD);
+ }
}
// For compatibility with old core.sys.windows.windows:
alias GetDllDirectoryW GetDllDirectory;
}
+ static if (_WIN32_WINNT >= 0x600) {
+ alias CreateSymbolicLinkW CreateSymbolicLink;
+ }
+
} else {
//alias STARTUPINFOA STARTUPINFO;
alias WIN32_FIND_DATAA WIN32_FIND_DATA;
alias SetDllDirectoryA SetDllDirectory;
alias SetFirmwareEnvironmentVariableA SetFirmwareEnvironmentVariable;
}
+
+ static if (_WIN32_WINNT >= 0x600) {
+ alias CreateSymbolicLinkA CreateSymbolicLink;
+ }
}
alias STARTUPINFO* LPSTARTUPINFO;
*/
module core.sys.windows.winber;
version (Windows):
+@system:
/* Comment from MinGW
winber.h - Header file for the Windows LDAP Basic Encoding Rules API
*/
module core.sys.windows.wincon;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "kernel32");
-private import core.sys.windows.w32api, core.sys.windows.windef;
+import core.sys.windows.w32api, core.sys.windows.windef;
// FIXME: clean up Windows version support
*/
module core.sys.windows.wincrypt;
version (Windows):
+@system:
pragma(lib, "advapi32");
version (ANSI) {} else version = Unicode;
-private import core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.windef;
+import core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.windef;
/* FIXME:
* Types of some constants
*/
module core.sys.windows.windef;
version (Windows):
+@system:
public import core.sys.windows.winnt;
-private import core.sys.windows.w32api;
+import core.sys.windows.w32api;
enum size_t MAX_PATH = 260;
*/
module core.sys.windows.windows;
version (Windows):
+@system:
/*
windows.h - main header file for the Win32 API
*/
module core.sys.windows.winerror;
version (Windows):
+@system:
/* Comments from the Mingw header:
* WAIT_TIMEOUT is also defined in winbase.h
*/
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
alias int SCODE; // was in core.sys.windows.wtypes.
*/
module core.sys.windows.wingdi;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "gdi32");
// FIXME: clean up Windows version support
-private import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.winver;
+import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.winver;
// BITMAPINFOHEADER.biCompression
enum : DWORD {
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
-};
+}
alias RGBQUAD* LPRGBQUAD;
struct BITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD[1] bmiColors;
-};
+}
alias BITMAPINFO* PBITMAPINFO, LPBITMAPINFO;
alias int FXPT16DOT16;
*/
module core.sys.windows.winhttp;
version (Windows):
+@system:
pragma(lib, "winhttp");
// FIXME: Grouping of constants. Windows SDK doesn't make this entirely clear
// FIXME: Verify WINHTTP_STATUS_CALLBACK function declaration works correctly
*/
module core.sys.windows.wininet;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "wininet");
import core.sys.windows.winbase, core.sys.windows.windef;
+// From Winineti.h
+enum {
+ INTERNET_FLAG_BGUPDATE = 0x00000008,
+}
+
enum {
INTERNET_INVALID_PORT_NUMBER = 0,
INTERNET_DEFAULT_FTP_PORT = 21,
}
enum {
- INTERNET_REQFLAG_FROM_CACHE = 1,
- INTERNET_REQFLAG_ASYNC = 2
+ INTERNET_REQFLAG_FROM_CACHE = 0x00000001,
+ INTERNET_REQFLAG_ASYNC = 0x00000002,
+ INTERNET_REQFLAG_VIA_PROXY = 0x00000004,
+ INTERNET_REQFLAG_NO_HEADERS = 0x00000008,
+ INTERNET_REQFLAG_PASSIVE = 0x00000010,
+ INTERNET_REQFLAG_CACHE_WRITE_DISABLED = 0x00000040,
+ INTERNET_REQFLAG_NET_TIMEOUT = 0x00000080,
+}
+
+enum {
+ INTERNET_FLAG_IDN_DIRECT = 0x00000001,
+ INTERNET_FLAG_IDN_PROXY = 0x00000002
}
enum DWORD
INTERNET_FLAG_NO_CACHE_WRITE = 0x04000000,
INTERNET_FLAG_DONT_CACHE = INTERNET_FLAG_NO_CACHE_WRITE,
INTERNET_FLAG_MAKE_PERSISTENT = 0x02000000,
- INTERNET_FLAG_OFFLINE = 0x01000000,
+ INTERNET_FLAG_FROM_CACHE = 0x01000000,
+ INTERNET_FLAG_OFFLINE = INTERNET_FLAG_FROM_CACHE,
INTERNET_FLAG_SECURE = 0x00800000,
INTERNET_FLAG_KEEP_CONNECTION = 0x00400000,
INTERNET_FLAG_NO_AUTO_REDIRECT = 0x00200000,
INTERNET_FLAG_READ_PREFETCH = 0x00100000,
INTERNET_FLAG_NO_COOKIES = 0x00080000,
INTERNET_FLAG_NO_AUTH = 0x00040000,
+ INTERNET_FLAG_RESTRICTED_ZONE = 0x00020000,
+ INTERNET_FLAG_CACHE_IF_NET_FAIL = 0x00010000,
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP = 0x00008000,
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS = 0x00004000,
INTERNET_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000,
INTERNET_FLAG_HYPERLINK = 0x00000400,
INTERNET_FLAG_NO_UI = 0x00000200,
INTERNET_FLAG_PRAGMA_NOCACHE = 0x00000100,
- INTERNET_FLAG_MUST_CACHE_REQUEST = 0x00000010,
+ INTERNET_FLAG_CACHE_ASYNC = 0x00000080,
+ INTERNET_FLAG_FORMS_SUBMIT = 0x00000040,
+ INTERNET_FLAG_FWD_BACK = 0x00000020,
+ INTERNET_FLAG_NEED_FILE = 0x00000010,
+ INTERNET_FLAG_MUST_CACHE_REQUEST = INTERNET_FLAG_NEED_FILE,
INTERNET_FLAG_TRANSFER_ASCII = FTP_TRANSFER_TYPE_ASCII,
INTERNET_FLAG_TRANSFER_BINARY = FTP_TRANSFER_TYPE_BINARY,
- SECURITY_INTERNET_MASK = 0x0000F000,
+ SECURITY_INTERNET_MASK = INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
+ INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
+ INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS |
+ INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP,
+
SECURITY_SET_MASK = SECURITY_INTERNET_MASK,
- INTERNET_FLAGS_MASK = 0xFFFCFE13,
+ INTERNET_FLAGS_MASK = INTERNET_FLAG_RELOAD
+ | INTERNET_FLAG_RAW_DATA
+ | INTERNET_FLAG_EXISTING_CONNECT
+ | INTERNET_FLAG_ASYNC
+ | INTERNET_FLAG_PASSIVE
+ | INTERNET_FLAG_NO_CACHE_WRITE
+ | INTERNET_FLAG_MAKE_PERSISTENT
+ | INTERNET_FLAG_FROM_CACHE
+ | INTERNET_FLAG_SECURE
+ | INTERNET_FLAG_KEEP_CONNECTION
+ | INTERNET_FLAG_NO_AUTO_REDIRECT
+ | INTERNET_FLAG_READ_PREFETCH
+ | INTERNET_FLAG_NO_COOKIES
+ | INTERNET_FLAG_NO_AUTH
+ | INTERNET_FLAG_CACHE_IF_NET_FAIL
+ | SECURITY_INTERNET_MASK
+ | INTERNET_FLAG_RESYNCHRONIZE
+ | INTERNET_FLAG_HYPERLINK
+ | INTERNET_FLAG_NO_UI
+ | INTERNET_FLAG_PRAGMA_NOCACHE
+ | INTERNET_FLAG_CACHE_ASYNC
+ | INTERNET_FLAG_FORMS_SUBMIT
+ | INTERNET_FLAG_NEED_FILE
+ | INTERNET_FLAG_RESTRICTED_ZONE
+ | INTERNET_FLAG_TRANSFER_BINARY
+ | INTERNET_FLAG_TRANSFER_ASCII
+ | INTERNET_FLAG_FWD_BACK
+ | INTERNET_FLAG_BGUPDATE,
+
+ INTERNET_ERROR_MASK_INSERT_CDROM = 0x1,
+ INTERNET_ERROR_MASK_COMBINED_SEC_CERT = 0x2,
+ INTERNET_ERROR_MASK_NEED_MSN_SSPI_PKG = 0X4,
+ INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY = 0x8,
+
INTERNET_OPTIONS_MASK = ~INTERNET_FLAGS_MASK;
enum INTERNET_NO_CALLBACK = 0;
INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT = INTERNET_OPTION_RECEIVE_TIMEOUT,
INTERNET_OPTION_DATA_SEND_TIMEOUT,
INTERNET_OPTION_DATA_RECEIVE_TIMEOUT,
- INTERNET_OPTION_HANDLE_TYPE,
- INTERNET_OPTION_CONTEXT_VALUE,
- INTERNET_OPTION_LISTEN_TIMEOUT,
+ INTERNET_OPTION_HANDLE_TYPE = 9,
+ INTERNET_OPTION_LISTEN_TIMEOUT = 11,
INTERNET_OPTION_READ_BUFFER_SIZE,
INTERNET_OPTION_WRITE_BUFFER_SIZE, // = 13
INTERNET_OPTION_ASYNC_ID = 15,
INTERNET_OPTION_END_BROWSER_SESSION,
INTERNET_OPTION_PROXY_USERNAME,
INTERNET_OPTION_PROXY_PASSWORD, // = 44
- INTERNET_FIRST_OPTION = INTERNET_OPTION_CALLBACK,
- // why?
- INTERNET_LAST_OPTION = INTERNET_OPTION_USER_AGENT
+ INTERNET_OPTION_CONTEXT_VALUE = 45,
+ INTERNET_OPTION_CONNECT_LIMIT = 46,
+ INTERNET_OPTION_SECURITY_SELECT_CLIENT_CERT= 47,
+ INTERNET_OPTION_POLICY = 48,
+ INTERNET_OPTION_DISCONNECTED_TIMEOUT = 49,
+ INTERNET_OPTION_CONNECTED_STATE = 50,
+ INTERNET_OPTION_IDLE_STATE = 51,
+ INTERNET_OPTION_OFFLINE_SEMANTICS = 52,
+ INTERNET_OPTION_SECONDARY_CACHE_KEY = 53,
+ INTERNET_OPTION_CALLBACK_FILTER = 54,
+ INTERNET_OPTION_CONNECT_TIME = 55,
+ INTERNET_OPTION_SEND_THROUGHPUT = 56,
+ INTERNET_OPTION_RECEIVE_THROUGHPUT = 57,
+ INTERNET_OPTION_REQUEST_PRIORITY = 58,
+ INTERNET_OPTION_HTTP_VERSION = 59,
+ INTERNET_OPTION_RESET_URLCACHE_SESSION = 60,
+ INTERNET_OPTION_ERROR_MASK = 62,
+ INTERNET_OPTION_FROM_CACHE_TIMEOUT = 63,
+ INTERNET_OPTION_BYPASS_EDITED_ENTRY = 64,
+ INTERNET_OPTION_HTTP_DECODING = 65,
+ INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO = 67,
+ INTERNET_OPTION_CODEPAGE = 68,
+ INTERNET_OPTION_CACHE_TIMESTAMPS = 69,
+ INTERNET_OPTION_DISABLE_AUTODIAL = 70,
+ INTERNET_OPTION_MAX_CONNS_PER_SERVER = 73,
+ INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER= 74,
+ INTERNET_OPTION_PER_CONNECTION_OPTION = 75,
+ INTERNET_OPTION_DIGEST_AUTH_UNLOAD = 76,
+ INTERNET_OPTION_IGNORE_OFFLINE = 77,
+ INTERNET_OPTION_IDENTITY = 78,
+ INTERNET_OPTION_REMOVE_IDENTITY = 79,
+ INTERNET_OPTION_ALTER_IDENTITY = 80,
+ INTERNET_OPTION_SUPPRESS_BEHAVIOR = 81,
+ INTERNET_OPTION_AUTODIAL_MODE = 82,
+ INTERNET_OPTION_AUTODIAL_CONNECTION = 83,
+ INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84,
+ INTERNET_OPTION_AUTH_FLAGS = 85,
+ INTERNET_OPTION_COOKIES_3RD_PARTY = 86,
+ INTERNET_OPTION_DISABLE_PASSPORT_AUTH = 87,
+ INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY = 88,
+ INTERNET_OPTION_EXEMPT_CONNECTION_LIMIT = 89,
+ INTERNET_OPTION_ENABLE_PASSPORT_AUTH = 90,
+ INTERNET_OPTION_HIBERNATE_INACTIVE_WORKER_THREADS = 91,
+ INTERNET_OPTION_ACTIVATE_WORKER_THREADS = 92,
+ INTERNET_OPTION_RESTORE_WORKER_THREAD_DEFAULTS = 93,
+ INTERNET_OPTION_SOCKET_SEND_BUFFER_LENGTH = 94,
+ INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 95,
+ INTERNET_OPTION_DATAFILE_EXT = 96,
+ INTERNET_OPTION_CODEPAGE_PATH = 100,
+ INTERNET_OPTION_CODEPAGE_EXTRA = 101,
+ INTERNET_OPTION_IDN = 102,
+ INTERNET_OPTION_MAX_CONNS_PER_PROXY = 103,
+ INTERNET_OPTION_SUPPRESS_SERVER_AUTH = 104,
+ INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT = 105,
+ INTERNET_OPTION_ENABLE_REDIRECT_CACHE_READ = 122,
+ INTERNET_OPTION_COMPRESSED_CONTENT_LENGTH = 147,
+ INTERNET_OPTION_ENABLE_HTTP_PROTOCOL = 148,
+ INTERNET_OPTION_HTTP_PROTOCOL_USED = 149,
+ INTERNET_OPTION_ENCODE_EXTRA = 155,
+ INTERNET_OPTION_HSTS = 157,
+ INTERNET_OPTION_ENTERPRISE_CONTEXT = 159,
+ INTERNET_OPTION_CONNECTION_FILTER = 162,
+ INTERNET_OPTION_REFERER_TOKEN_BINDING_HOSTNAME = 163,
+ INTERNET_OPTION_TOKEN_BINDING_PUBLIC_KEY = 181,
+ INTERNET_OPTION_COOKIES_SAME_SITE_LEVEL = 187,
+ INTERNET_FIRST_OPTION = INTERNET_OPTION_CALLBACK,
+ INTERNET_LAST_OPTION = INTERNET_OPTION_COOKIES_SAME_SITE_LEVEL,
}
enum INTERNET_PRIORITY_FOREGROUND = 1000;
INTERNET_SCHEME_NEWS,
INTERNET_SCHEME_MAILTO,
INTERNET_SCHEME_SOCKS,
+ INTERNET_SCHEME_JAVASCRIPT,
+ INTERNET_SCHEME_VBSCRIPT,
+ INTERNET_SCHEME_RES,
INTERNET_SCHEME_FIRST = INTERNET_SCHEME_FTP,
- INTERNET_SCHEME_LAST = INTERNET_SCHEME_SOCKS
+ INTERNET_SCHEME_LAST = INTERNET_SCHEME_RES
}
alias INTERNET_SCHEME* LPINTERNET_SCHEME;
}
alias INTERNET_ASYNC_RESULT* LPINTERNET_ASYNC_RESULT;
+struct INTERNET_DIAGNOSTIC_SOCKET_INFO {
+ DWORD_PTR Socket;
+ DWORD SourcePort;
+ DWORD DestPort;
+ DWORD Flags;
+}
+alias INTERNET_DIAGNOSTIC_SOCKET_INFO* LPINTERNET_DIAGNOSTIC_SOCKET_INFO;
+
struct INTERNET_PREFETCH_STATUS {
DWORD dwStatus;
DWORD dwSize;
}
alias INTERNET_PROXY_INFO* LPINTERNET_PROXY_INFO;
+struct INTERNET_PER_CONN_OPTIONA {
+ DWORD dwOption;
+ union {
+ DWORD dwValue;
+ LPSTR pszValue;
+ FILETIME ftValue;
+ }
+}
+alias INTERNET_PER_CONN_OPTIONA* LPINTERNET_PER_CONN_OPTIONA;
+
+struct INTERNET_PER_CONN_OPTIONW {
+ DWORD dwOption;
+ union {
+ DWORD dwValue;
+ LPWSTR pszValue;
+ FILETIME ftValue;
+ }
+}
+alias INTERNET_PER_CONN_OPTIONW* LPINTERNET_PER_CONN_OPTIONW;
+
+struct INTERNET_PER_CONN_OPTION_LISTA {
+ DWORD dwSize;
+ LPSTR pszConnection;
+ DWORD dwOptionCount;
+ DWORD dwOptionError;
+ LPINTERNET_PER_CONN_OPTIONA pOptions;
+}
+alias INTERNET_PER_CONN_OPTION_LISTA* LPINTERNET_PER_CONN_OPTION_LISTA;
+
+struct INTERNET_PER_CONN_OPTION_LISTW {
+ DWORD dwSize;
+ LPWSTR pszConnection;
+ DWORD dwOptionCount;
+ DWORD dwOptionError;
+ LPINTERNET_PER_CONN_OPTIONW pOptions;
+}
+alias INTERNET_PER_CONN_OPTION_LISTW* LPINTERNET_PER_CONN_OPTION_LISTW;
+
+enum {
+ INTERNET_PER_CONN_FLAGS = 1,
+ INTERNET_PER_CONN_PROXY_SERVER = 2,
+ INTERNET_PER_CONN_PROXY_BYPASS = 3,
+ INTERNET_PER_CONN_AUTOCONFIG_URL = 4,
+ INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5,
+ INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL = 6,
+ INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS = 7,
+ INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME = 8,
+ INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL = 9,
+ INTERNET_PER_CONN_FLAGS_UI = 10,
+}
+
+enum {
+ PROXY_TYPE_DIRECT = 0x00000001,
+ PROXY_TYPE_PROXY = 0x00000002,
+ PROXY_TYPE_AUTO_PROXY_URL = 0x00000004,
+ PROXY_TYPE_AUTO_DETECT = 0x00000008,
+}
+
+enum {
+ AUTO_PROXY_FLAG_USER_SET = 0x00000001,
+ AUTO_PROXY_FLAG_ALWAYS_DETECT = 0x00000002,
+ AUTO_PROXY_FLAG_DETECTION_RUN = 0x00000004,
+ AUTO_PROXY_FLAG_MIGRATED = 0x00000008,
+ AUTO_PROXY_FLAG_DONT_CACHE_PROXY_RESULT = 0x00000010,
+ AUTO_PROXY_FLAG_CACHE_INIT_RUN = 0x00000020,
+ AUTO_PROXY_FLAG_DETECTION_SUSPECT = 0x00000040,
+}
+
struct INTERNET_VERSION_INFO {
DWORD dwMajorVersion;
DWORD dwMinorVersion;
}
version (Unicode) {
+ alias INTERNET_PER_CONN_OPTIONW INTERNET_PER_CONN_OPTION;
+ alias LPINTERNET_PER_CONN_OPTIONW LPINTERNET_PER_CONN_OPTION;
+ alias INTERNET_PER_CONN_OPTION_LISTW INTERNET_PER_CONN_OPTION_LIST;
+ alias LPINTERNET_PER_CONN_OPTION_LISTW LPINTERNET_PER_CONN_OPTION_LIST;
alias URL_COMPONENTSW URL_COMPONENTS;
alias LPURL_COMPONENTSW LPURL_COMPONENTS;
alias GOPHER_FIND_DATAW GOPHER_FIND_DATA;
alias GetUrlCacheGroupAttributeW GetUrlCacheGroupAttribute;
alias SetUrlCacheGroupAttributeW SetUrlCacheGroupAttribute;
} else {
+ alias INTERNET_PER_CONN_OPTIONA INTERNET_PER_CONN_OPTION;
+ alias LPINTERNET_PER_CONN_OPTIONA LPINTERNET_PER_CONN_OPTION;
+ alias INTERNET_PER_CONN_OPTION_LISTA INTERNET_PER_CONN_OPTION_LIST;
+ alias LPINTERNET_PER_CONN_OPTION_LISTA LPINTERNET_PER_CONN_OPTION_LIST;
alias URL_COMPONENTSA URL_COMPONENTS;
alias LPURL_COMPONENTSA LPURL_COMPONENTS;
alias GOPHER_FIND_DATAA GOPHER_FIND_DATA;
*/
module core.sys.windows.winioctl;
version (Windows):
+@system:
// FIXME: check types of some constants
-private import core.sys.windows.basetyps, core.sys.windows.windef;
+import core.sys.windows.basetyps, core.sys.windows.windef;
enum size_t
HIST_NO_OF_BUCKETS = 24,
*/
module core.sys.windows.winldap;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
*/
import core.sys.windows.schannel, core.sys.windows.winber;
-private import core.sys.windows.wincrypt, core.sys.windows.windef;
+import core.sys.windows.wincrypt, core.sys.windows.windef;
//align(4):
* Under Microsoft WinLDAP the function ldap_error is only stub.
* This macro uses LDAP structure to get error string and pass it to the user.
*/
-private extern (C) int printf(in char* format, ...);
+private extern (C) int printf(const scope char* format, ...);
int ldap_perror(LDAP* handle, char* message) {
return printf("%s: %s\n", message, handle.ld_error);
}
ULONG ldap_controls_freeW(LDAPControlW**);
ULONG ldap_free_controlsA(LDAPControlA**);
ULONG ldap_free_controlsW(LDAPControlW**);
- ULONG ldap_sasl_bindA(LDAP*, PCHAR, PCHAR, BERVAL*, PLDAPControlA*,
+ ULONG ldap_sasl_bindA(LDAP*, PCSTR, PCSTR, BERVAL*, PLDAPControlA*,
PLDAPControlA*, int*);
- ULONG ldap_sasl_bindW(LDAP*, PWCHAR, PWCHAR, BERVAL*, PLDAPControlW*,
+ ULONG ldap_sasl_bindW(LDAP*, PCWSTR, PCWSTR, BERVAL*, PLDAPControlW*,
PLDAPControlW*, int*);
- ULONG ldap_sasl_bind_sA(LDAP*, PCHAR, PCHAR, BERVAL*, PLDAPControlA*,
+ ULONG ldap_sasl_bind_sA(LDAP*, PCSTR, PCSTR, BERVAL*, PLDAPControlA*,
PLDAPControlA*, PBERVAL*);
- ULONG ldap_sasl_bind_sW(LDAP*, PWCHAR, PWCHAR, BERVAL*, PLDAPControlW*,
+ ULONG ldap_sasl_bind_sW(LDAP*, PCWSTR, PCWSTR, BERVAL*, PLDAPControlW*,
PLDAPControlW*, PBERVAL*);
- ULONG ldap_simple_bindA(LDAP*, PCHAR, PCHAR);
- ULONG ldap_simple_bindW(LDAP*, PWCHAR, PWCHAR);
- ULONG ldap_simple_bind_sA(LDAP*, PCHAR, PCHAR);
- ULONG ldap_simple_bind_sW(LDAP*, PWCHAR, PWCHAR);
+ ULONG ldap_simple_bindA(LDAP*, PSTR, PSTR);
+ ULONG ldap_simple_bindW(LDAP*, PWSTR, PWSTR);
+ ULONG ldap_simple_bind_sA(LDAP*, PSTR, PSTR);
+ ULONG ldap_simple_bind_sW(LDAP*, PWSTR, PWSTR);
ULONG ldap_unbind(LDAP*);
ULONG ldap_unbind_s(LDAP*);
- ULONG ldap_search_extA(LDAP*, PCHAR, ULONG, PCHAR, PCHAR[], ULONG,
+ ULONG ldap_search_extA(LDAP*, PCSTR, ULONG, PCSTR, PZPSTR, ULONG,
+ PLDAPControlA*, PLDAPControlA*, ULONG, ULONG, ULONG*);
+ ULONG ldap_search_extW(LDAP*, PCWSTR, ULONG, PCWSTR, PZPWSTR, ULONG,
PLDAPControlW*, PLDAPControlW*, ULONG, ULONG, ULONG*);
- ULONG ldap_search_extW(LDAP*, PWCHAR, ULONG, PWCHAR, PWCHAR[], ULONG,
- PLDAPControlW*, PLDAPControlW*, ULONG, ULONG, ULONG*);
- ULONG ldap_search_ext_sA(LDAP*, PCHAR, ULONG, PCHAR, PCHAR[], ULONG,
- PLDAPControlA*, PLDAPControlA*, LDAP_TIMEVAL*, ULONG, LDAPMessage**);
- ULONG ldap_search_ext_sW(LDAP*, PWCHAR, ULONG, PWCHAR, PWCHAR[], ULONG,
- PLDAPControlW*, PLDAPControlW*, LDAP_TIMEVAL*, ULONG, LDAPMessage**);
- ULONG ldap_searchA(LDAP*, PCHAR, ULONG, PCHAR, PCHAR[], ULONG);
- ULONG ldap_searchW(LDAP*, PWCHAR, ULONG, PWCHAR, PWCHAR[], ULONG);
- ULONG ldap_search_sA(LDAP*, PCHAR, ULONG, PCHAR, PCHAR[], ULONG,
- LDAPMessage**);
- ULONG ldap_search_sW(LDAP*, PWCHAR, ULONG, PWCHAR, PWCHAR[], ULONG,
- LDAPMessage**);
- ULONG ldap_search_stA(LDAP*, PCHAR, ULONG, PCHAR, PCHAR[], ULONG,
- LDAP_TIMEVAL*, LDAPMessage**);
- ULONG ldap_search_stW(LDAP*, PWCHAR, ULONG, PWCHAR, PWCHAR[], ULONG,
- LDAP_TIMEVAL*, LDAPMessage**);
- ULONG ldap_compare_extA(LDAP*, PCHAR, PCHAR, PCHAR, BerValue*,
+ ULONG ldap_search_ext_sA(LDAP*, PCSTR, ULONG, PCSTR, PZPSTR, ULONG,
+ PLDAPControlA*, PLDAPControlA*, LDAP_TIMEVAL*, ULONG, PLDAPMessage*);
+ ULONG ldap_search_ext_sW(LDAP*, PCWSTR, ULONG, PCWSTR, PZPWSTR, ULONG,
+ PLDAPControlW*, PLDAPControlW*, LDAP_TIMEVAL*, ULONG, PLDAPMessage*);
+ ULONG ldap_searchA(LDAP*, PCSTR, ULONG, PCSTR, PZPSTR, ULONG);
+ ULONG ldap_searchW(LDAP*, PCWSTR, ULONG, PCWSTR, PZPWSTR, ULONG);
+ ULONG ldap_search_sA(LDAP*, PCSTR, ULONG, PCSTR, PZPSTR, ULONG,
+ PLDAPMessage*);
+ ULONG ldap_search_sW(LDAP*, PCWSTR, ULONG, PCWSTR, PZPWSTR, ULONG,
+ PLDAPMessage*);
+ ULONG ldap_search_stA(LDAP*, PCSTR, ULONG, PCSTR, PZPSTR, ULONG,
+ LDAP_TIMEVAL*, PLDAPMessage*);
+ ULONG ldap_search_stW(LDAP*, PCWSTR, ULONG, PCWSTR, PZPWSTR, ULONG,
+ LDAP_TIMEVAL*, PLDAPMessage*);
+ ULONG ldap_compare_extA(LDAP*, PCSTR, PCSTR, PCSTR, BerValue*,
PLDAPControlA*, PLDAPControlA*, ULONG*);
- ULONG ldap_compare_extW(LDAP*, PWCHAR, PWCHAR, PWCHAR, BerValue*,
+ ULONG ldap_compare_extW(LDAP*, PCWSTR, PCWSTR, PCWSTR, BerValue*,
PLDAPControlW*, PLDAPControlW*, ULONG*);
- ULONG ldap_compare_ext_sA(LDAP*, PCHAR, PCHAR, PCHAR, BerValue*,
+ ULONG ldap_compare_ext_sA(LDAP*, PCSTR, PCSTR, PCSTR, BerValue*,
PLDAPControlA*, PLDAPControlA*);
- ULONG ldap_compare_ext_sW(LDAP*, PWCHAR, PWCHAR, PWCHAR, BerValue*,
+ ULONG ldap_compare_ext_sW(LDAP*, PCWSTR, PCWSTR, PCWSTR, BerValue*,
PLDAPControlW*, PLDAPControlW*);
- ULONG ldap_compareA(LDAP*, PCHAR, PCHAR, PCHAR);
- ULONG ldap_compareW(LDAP*, PWCHAR, PWCHAR, PWCHAR);
- ULONG ldap_compare_sA(LDAP*, PCHAR, PCHAR, PCHAR);
- ULONG ldap_compare_sW(LDAP*, PWCHAR, PWCHAR, PWCHAR);
- ULONG ldap_modify_extA(LDAP*, PCHAR, LDAPModA*[], PLDAPControlA*,
+ ULONG ldap_compareA(LDAP*, PCSTR, PCSTR, PCSTR);
+ ULONG ldap_compareW(LDAP*, PCWSTR, PCWSTR, PCWSTR);
+ ULONG ldap_compare_sA(LDAP*, PCSTR, PCSTR, PCSTR);
+ ULONG ldap_compare_sW(LDAP*, PCWSTR, PCWSTR, PCWSTR);
+ ULONG ldap_modify_extA(LDAP*, PCSTR, LDAPModA**, PLDAPControlA*,
PLDAPControlA*, ULONG*);
- ULONG ldap_modify_extW(LDAP*, PWCHAR, LDAPModW*[], PLDAPControlW*,
+ ULONG ldap_modify_extW(LDAP*, PCWSTR, LDAPModW**, PLDAPControlW*,
PLDAPControlW*, ULONG*);
- ULONG ldap_modify_ext_sA(LDAP*, PCHAR, LDAPModA*[], PLDAPControlA*,
+ ULONG ldap_modify_ext_sA(LDAP*, PCSTR, LDAPModA**, PLDAPControlA*,
PLDAPControlA*);
- ULONG ldap_modify_ext_sW(LDAP*, PWCHAR, LDAPModW*[], PLDAPControlW*,
+ ULONG ldap_modify_ext_sW(LDAP*, PCWSTR, LDAPModW**, PLDAPControlW*,
PLDAPControlW*);
- ULONG ldap_modifyA(LDAP*, PCHAR, LDAPModA*[]);
- ULONG ldap_modifyW(LDAP*, PWCHAR, LDAPModW*[]);
- ULONG ldap_modify_sA(LDAP*, PCHAR, LDAPModA*[]);
- ULONG ldap_modify_sW(LDAP*, PWCHAR, LDAPModW*[]);
- ULONG ldap_rename_extA(LDAP*, PCHAR, PCHAR, PCHAR, INT, PLDAPControlA*,
+ ULONG ldap_modifyA(LDAP*, PSTR, LDAPModA**);
+ ULONG ldap_modifyW(LDAP*, PWSTR, LDAPModW**);
+ ULONG ldap_modify_sA(LDAP*, PSTR, LDAPModA**);
+ ULONG ldap_modify_sW(LDAP*, PWSTR, LDAPModW**);
+ ULONG ldap_rename_extA(LDAP*, PCSTR, PCSTR, PCSTR, INT, PLDAPControlA*,
PLDAPControlA*, ULONG*);
- ULONG ldap_rename_extW(LDAP*, PWCHAR, PWCHAR, PWCHAR, INT, PLDAPControlW*,
+ ULONG ldap_rename_extW(LDAP*, PCWSTR, PCWSTR, PCWSTR, INT, PLDAPControlW*,
PLDAPControlW*, ULONG*);
- ULONG ldap_rename_ext_sA(LDAP*, PCHAR, PCHAR, PCHAR, INT,
+ ULONG ldap_rename_ext_sA(LDAP*, PCSTR, PCSTR, PCSTR, INT,
PLDAPControlA*, PLDAPControlA*);
- ULONG ldap_rename_ext_sW(LDAP*, PWCHAR, PWCHAR, PWCHAR, INT,
+ ULONG ldap_rename_ext_sW(LDAP*, PCWSTR, PCWSTR, PCWSTR, INT,
PLDAPControlW*, PLDAPControlW*);
- ULONG ldap_add_extA(LDAP*, PCHAR, LDAPModA*[], PLDAPControlA*,
+ ULONG ldap_add_extA(LDAP*, PCSTR, LDAPModA**, PLDAPControlA*,
PLDAPControlA*, ULONG*);
- ULONG ldap_add_extW(LDAP*, PWCHAR, LDAPModW*[], PLDAPControlW*,
+ ULONG ldap_add_extW(LDAP*, PCWSTR, LDAPModW**, PLDAPControlW*,
PLDAPControlW*, ULONG*);
- ULONG ldap_add_ext_sA(LDAP*, PCHAR, LDAPModA*[], PLDAPControlA*,
+ ULONG ldap_add_ext_sA(LDAP*, PCSTR, LDAPModA**, PLDAPControlA*,
PLDAPControlA*);
- ULONG ldap_add_ext_sW(LDAP*, PWCHAR, LDAPModW*[], PLDAPControlW*,
+ ULONG ldap_add_ext_sW(LDAP*, PCWSTR, LDAPModW**, PLDAPControlW*,
PLDAPControlW*);
- ULONG ldap_addA(LDAP*, PCHAR, LDAPModA*[]);
- ULONG ldap_addW(LDAP*, PWCHAR, LDAPModW*[]);
- ULONG ldap_add_sA(LDAP*, PCHAR, LDAPModA*[]);
- ULONG ldap_add_sW(LDAP*, PWCHAR, LDAPModW*[]);
- ULONG ldap_delete_extA(LDAP*, PCHAR, PLDAPControlA*, PLDAPControlA*,
+ ULONG ldap_addA(LDAP*, PSTR, LDAPModA**);
+ ULONG ldap_addW(LDAP*, PWSTR, LDAPModW**);
+ ULONG ldap_add_sA(LDAP*, PSTR, LDAPModA**);
+ ULONG ldap_add_sW(LDAP*, PWSTR, LDAPModW**);
+ ULONG ldap_delete_extA(LDAP*, PCSTR, PLDAPControlA*, PLDAPControlA*,
ULONG*);
- ULONG ldap_delete_extW(LDAP*, PWCHAR, PLDAPControlW*, PLDAPControlW*,
+ ULONG ldap_delete_extW(LDAP*, PCWSTR, PLDAPControlW*, PLDAPControlW*,
ULONG*);
- ULONG ldap_delete_ext_sA(LDAP*, PCHAR, PLDAPControlA*, PLDAPControlA*);
- ULONG ldap_delete_ext_sW(LDAP*, PWCHAR, PLDAPControlW*, PLDAPControlW*);
- ULONG ldap_deleteA(LDAP*, PCHAR);
- ULONG ldap_deleteW(LDAP*, PWCHAR);
- ULONG ldap_delete_sA(LDAP*, PCHAR);
- ULONG ldap_delete_sW(LDAP*, PWCHAR);
- ULONG ldap_extended_operationA(LDAP*, PCHAR, BerValue*, PLDAPControlA*,
+ ULONG ldap_delete_ext_sA(LDAP*, PCSTR, PLDAPControlA*, PLDAPControlA*);
+ ULONG ldap_delete_ext_sW(LDAP*, PCWSTR, PLDAPControlW*, PLDAPControlW*);
+ ULONG ldap_deleteA(LDAP*, PCSTR);
+ ULONG ldap_deleteW(LDAP*, PCWSTR);
+ ULONG ldap_delete_sA(LDAP*, PCSTR);
+ ULONG ldap_delete_sW(LDAP*, PCWSTR);
+ ULONG ldap_extended_operationA(LDAP*, PCSTR, BerValue*, PLDAPControlA*,
PLDAPControlA*, ULONG*);
- ULONG ldap_extended_operationW(LDAP*, PWCHAR, BerValue*, PLDAPControlW*,
+ ULONG ldap_extended_operationW(LDAP*, PCWSTR, BerValue*, PLDAPControlW*,
PLDAPControlW*, ULONG*);
- ULONG ldap_extended_operation_sA(LDAP*, PCHAR, BerValue*, PLDAPControlA*,
+ ULONG ldap_extended_operation_sA(LDAP*, PSTR, BerValue*, PLDAPControlA*,
PLDAPControlA*, PCHAR*, BerValue**);
- ULONG ldap_extended_operation_sW(LDAP*, PWCHAR, BerValue*, PLDAPControlW*,
+ ULONG ldap_extended_operation_sW(LDAP*, PWSTR, BerValue*, PLDAPControlW*,
PLDAPControlW*, PWCHAR*, BerValue**);
ULONG ldap_close_extended_op(LDAP*, ULONG);
ULONG ldap_abandon(LDAP*, ULONG);
ULONG ldap_result(LDAP*, ULONG, ULONG, LDAP_TIMEVAL*, LDAPMessage**);
ULONG ldap_msgfree(LDAPMessage*);
- ULONG ldap_parse_resultA(LDAP*, LDAPMessage*, ULONG*, PCHAR*, PCHAR*,
- PCHAR**, PLDAPControlA**, BOOLEAN);
- ULONG ldap_parse_resultW(LDAP*, LDAPMessage*, ULONG*, PWCHAR*, PWCHAR*,
- PWCHAR**, PLDAPControlW**, BOOLEAN);
- ULONG ldap_parse_extended_resultA(LDAP, LDAPMessage*, PCHAR*, BerValue**,
+ ULONG ldap_parse_resultA(LDAP*, LDAPMessage*, ULONG*, PSTR*, PSTR*,
+ PZPSTR*, PLDAPControlA**, BOOLEAN);
+ ULONG ldap_parse_resultW(LDAP*, LDAPMessage*, ULONG*, PWSTR*, PWSTR*,
+ PZPWSTR*, PLDAPControlW**, BOOLEAN);
+ ULONG ldap_parse_extended_resultA(LDAP, LDAPMessage*, PSTR*, BerValue**,
BOOLEAN);
- ULONG ldap_parse_extended_resultW(LDAP, LDAPMessage*, PWCHAR*, BerValue**,
+ ULONG ldap_parse_extended_resultW(LDAP, LDAPMessage*, PWSTR*, BerValue**,
BOOLEAN);
PCHAR ldap_err2stringA(ULONG);
PWCHAR ldap_err2stringW(ULONG);
PWCHAR ldap_next_attributeW(LDAP*, LDAPMessage*, BerElement*);
VOID ldap_memfreeA(PCHAR);
VOID ldap_memfreeW(PWCHAR);
- PCHAR* ldap_get_valuesA(LDAP*, LDAPMessage*, PCHAR);
- PWCHAR* ldap_get_valuesW(LDAP*, LDAPMessage*, PWCHAR);
- BerValue** ldap_get_values_lenA(LDAP*, LDAPMessage*, PCHAR);
- BerValue** ldap_get_values_lenW(LDAP*, LDAPMessage*, PWCHAR);
+ PCHAR* ldap_get_valuesA(LDAP*, LDAPMessage*, PCSTR);
+ PWCHAR* ldap_get_valuesW(LDAP*, LDAPMessage*, PCWSTR);
+ BerValue** ldap_get_values_lenA(LDAP*, LDAPMessage*, PCSTR);
+ BerValue** ldap_get_values_lenW(LDAP*, LDAPMessage*, PCWSTR);
ULONG ldap_count_valuesA(PCHAR*);
ULONG ldap_count_valuesW(PWCHAR*);
ULONG ldap_count_values_len(BerValue**);
ULONG ldap_value_free_len(BerValue**);
PCHAR ldap_get_dnA(LDAP*, LDAPMessage*);
PWCHAR ldap_get_dnW(LDAP*, LDAPMessage*);
- PCHAR ldap_explode_dnA(PCHAR, ULONG);
- PWCHAR ldap_explode_dnW(PWCHAR, ULONG);
- PCHAR ldap_dn2ufnA(PCHAR);
- PWCHAR ldap_dn2ufnW(PWCHAR);
- ULONG ldap_ufn2dnA(PCHAR, PCHAR*);
- ULONG ldap_ufn2dnW(PWCHAR, PWCHAR*);
+ PCHAR ldap_explode_dnA(PCSTR, ULONG);
+ PWCHAR ldap_explode_dnW(PCWSTR, ULONG);
+ PCHAR ldap_dn2ufnA(PCSTR);
+ PWCHAR ldap_dn2ufnW(PCWSTR);
+ ULONG ldap_ufn2dnA(PCSTR, PSTR*);
+ ULONG ldap_ufn2dnW(PCWSTR, PWSTR*);
ULONG ldap_parse_referenceA(LDAP*, LDAPMessage*, PCHAR**);
ULONG ldap_parse_referenceW(LDAP*, LDAPMessage*, PWCHAR**);
- ULONG ldap_check_filterA(LDAP*, PCHAR);
- ULONG ldap_check_filterW(LDAP*, PWCHAR);
+ ULONG ldap_check_filterA(LDAP*, PSTR);
+ ULONG ldap_check_filterW(LDAP*, PWSTR);
ULONG ldap_create_page_controlA(PLDAP, ULONG, BerValue*, UCHAR,
PLDAPControlA*);
ULONG ldap_create_page_controlW(PLDAP, ULONG, BerValue*, UCHAR,
PLDAPControlA*);
ULONG ldap_create_sort_controlW(PLDAP, PLDAPSortKeyW*, UCHAR,
PLDAPControlW*);
- INT ldap_create_vlv_controlA(LDAP*, LDAPVLVInfo*, UCHAR, LDAPControlA**);
- INT ldap_create_vlv_controlW(LDAP*, LDAPVLVInfo*, UCHAR, LDAPControlW**);
+ INT ldap_create_vlv_controlA(LDAP*, LDAPVLVInfo*, UCHAR, PLDAPControlA*);
+ INT ldap_create_vlv_controlW(LDAP*, LDAPVLVInfo*, UCHAR, PLDAPControlW*);
ULONG ldap_encode_sort_controlA(PLDAP, PLDAPSortKeyA*, PLDAPControlA,
BOOLEAN);
ULONG ldap_encode_sort_controlW(PLDAP, PLDAPSortKeyW*, PLDAPControlW,
ULONG ldap_parse_page_controlW(PLDAP, PLDAPControlW*, ULONG*, BerValue**);
ULONG ldap_parse_sort_controlA(PLDAP, PLDAPControlA*, ULONG*, PCHAR*);
ULONG ldap_parse_sort_controlW(PLDAP, PLDAPControlW*, ULONG*, PWCHAR*);
- INT ldap_parse_vlv_controlA(LDAP*, LDAPControlA**, uint*, uint*,
- BerValue**, int*);
- INT ldap_parse_vlv_controlW(LDAP*, LDAPControlW**, uint*, uint*,
- BerValue**, int*);
- PLDAPSearch ldap_search_init_pageA(PLDAP, PCHAR, ULONG, PCHAR, PCHAR[],
+ INT ldap_parse_vlv_controlA(PLDAP, PLDAPControlA*, PULONG, PULONG,
+ BerValue**, PINT);
+ INT ldap_parse_vlv_controlW(PLDAP, PLDAPControlW*, PULONG, PULONG,
+ BerValue**, PINT);
+ PLDAPSearch ldap_search_init_pageA(PLDAP, PCSTR, ULONG, PCSTR, PZPSTR,
ULONG, PLDAPControlA*, PLDAPControlA*, ULONG, ULONG, PLDAPSortKeyA*);
- PLDAPSearch ldap_search_init_pageW(PLDAP, PWCHAR, ULONG, PWCHAR, PWCHAR[],
+ PLDAPSearch ldap_search_init_pageW(PLDAP, PCWSTR, ULONG, PCWSTR, PZPWSTR,
ULONG, PLDAPControlW*, PLDAPControlW*, ULONG, ULONG, PLDAPSortKeyW*);
ULONG ldap_search_abandon_page(PLDAP, PLDAPSearch);
LDAP ldap_conn_from_msg(LDAP*, LDAPMessage*);
INT LdapUnicodeToUTF8(LPCWSTR, int, LPSTR, int);
INT LdapUTF8ToUnicode(LPCSTR, int, LPWSTR, int);
- deprecated {
- ULONG ldap_bindA(LDAP*, PCHAR, PCHAR, ULONG);
- ULONG ldap_bindW(LDAP*, PWCHAR, PWCHAR, ULONG);
- ULONG ldap_bind_sA(LDAP*, PCHAR, PCHAR, ULONG);
- ULONG ldap_bind_sW(LDAP*, PWCHAR, PWCHAR, ULONG);
- ULONG ldap_modrdnA(LDAP*, PCHAR, PCHAR);
- ULONG ldap_modrdnW(LDAP*, PWCHAR, PWCHAR);
- ULONG ldap_modrdn_sA(LDAP*, PCHAR, PCHAR);
- ULONG ldap_modrdn_sW(LDAP*, PWCHAR, PWCHAR);
- ULONG ldap_modrdn2A(LDAP*, PCHAR, PCHAR, INT);
- ULONG ldap_modrdn2W(LDAP*, PWCHAR, PWCHAR, INT);
- ULONG ldap_modrdn2_sA(LDAP*, PCHAR, PCHAR, INT);
- ULONG ldap_modrdn2_sW(LDAP*, PWCHAR, PWCHAR, INT);
+ ULONG ldap_bindA(LDAP*, PSTR, PCHAR, ULONG);
+ ULONG ldap_bindW(LDAP*, PWSTR, PWCHAR, ULONG);
+ ULONG ldap_bind_sA(LDAP*, PSTR, PCHAR, ULONG);
+ ULONG ldap_bind_sW(LDAP*, PWSTR, PWCHAR, ULONG);
+ deprecated ("For LDAP 3 or later, use the ldap_rename_ext or ldap_rename_ext_s functions") {
+ ULONG ldap_modrdnA(LDAP*, PCSTR, PCSTR);
+ ULONG ldap_modrdnW(LDAP*, PCWSTR, PCWSTR);
+ ULONG ldap_modrdn_sA(LDAP*, PCSTR, PCSTR);
+ ULONG ldap_modrdn_sW(LDAP*, PCWSTR, PCWSTR);
+ ULONG ldap_modrdn2A(LDAP*, PCSTR, PCSTR, INT);
+ ULONG ldap_modrdn2W(LDAP*, PCWSTR, PCWSTR, INT);
+ ULONG ldap_modrdn2_sA(LDAP*, PCSTR, PCSTR, INT);
+ ULONG ldap_modrdn2_sW(LDAP*, PCWSTR, PCWSTR, INT);
}
}
*/
module core.sys.windows.winnetwk;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "mpr");
-private import core.sys.windows.winbase, core.sys.windows.winerror, core.sys.windows.winnt;
+import core.sys.windows.winbase, core.sys.windows.winerror, core.sys.windows.winnt;
enum : DWORD {
WNNC_NET_MSNET = 0x00010000,
*/
module core.sys.windows.winnls;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "kernel32");
-private import core.sys.windows.basetsd, core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.windef;
+import core.sys.windows.basetsd, core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.windef;
alias DWORD LCTYPE, CALTYPE, CALID, LGRPID, GEOID, GEOTYPE, GEOCLASS;
*/
module core.sys.windows.winnt;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
public import core.sys.windows.basetsd, core.sys.windows.windef, core.sys.windows.winerror;
-private import core.sys.windows.w32api;
+import core.sys.windows.w32api;
/* Translation Notes:
The following macros are unneeded for D:
M128A Xmm13;
M128A Xmm14;
M128A Xmm15;
- };
- };
+ }
+ }
M128A[26] VectorRegister;
DWORD64 VectorControl;
DWORD64 DebugControl;
PSID Owner;
}
alias TOKEN_OWNER* PTOKEN_OWNER;
+enum SECURITY_MAX_SID_SIZE = 68;
struct TOKEN_PRIMARY_GROUP {
PSID PrimaryGroup;
}
alias TOKEN_USER* PTOKEN_USER;
+struct TOKEN_MANDATORY_LABEL {
+ SID_AND_ATTRIBUTES Label;
+}
+alias PTOKEN_MANDATORY_LABEL = TOKEN_MANDATORY_LABEL*;
alias DWORD SECURITY_INFORMATION;
alias SECURITY_INFORMATION* PSECURITY_INFORMATION;
alias WORD SECURITY_DESCRIPTOR_CONTROL;
PACL Dacl;
}
alias SECURITY_DESCRIPTOR* PSECURITY_DESCRIPTOR, PISECURITY_DESCRIPTOR;
+enum TOKEN_ELEVATION_TYPE {
+ TokenElevationTypeDefault = 1,
+ TokenElevationTypeFull,
+ TokenElevationTypeLimited
+}
+
+alias PTOKEN_ELEVATION_TYPE = TOKEN_ELEVATION_TYPE*;
+
+struct TOKEN_ELEVATION {
+ DWORD TokenIsElevated;
+}
+alias PTOKEN_ELEVATION = TOKEN_ELEVATION*;
enum TOKEN_INFORMATION_CLASS {
TokenUser = 1,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
- TokenOrigin
+ TokenOrigin,
+ TokenElevationType,
+ TokenLinkedToken,
+ TokenElevation,
+ TokenHasRestrictions,
+ TokenAccessInformation,
+ TokenVirtualizationAllowed,
+ TokenVirtualizationEnabled,
+ TokenIntegrityLevel,
+ TokenUIAccess,
+ TokenMandatoryPolicy,
+ TokenLogonSid,
+ TokenIsAppContainer,
+ TokenCapabilities,
+ TokenAppContainerSid,
+ TokenAppContainerNumber,
+ TokenUserClaimAttributes,
+ TokenDeviceClaimAttributes,
+ TokenRestrictedUserClaimAttributes,
+ TokenRestrictedDeviceClaimAttributes,
+ TokenDeviceGroups,
+ TokenRestrictedDeviceGroups,
+ TokenSecurityAttributes,
+ TokenIsRestricted,
+ TokenProcessTrustLevel,
+ MaxTokenInfoClass // MaxTokenInfoClass should always be the last enum
}
enum SID_NAME_USE {
}
alias SID_NAME_USE* PSID_NAME_USE;
+enum WELL_KNOWN_SID_TYPE {
+ WinNullSid = 0,
+ WinWorldSid = 1,
+ WinLocalSid = 2,
+ WinCreatorOwnerSid = 3,
+ WinCreatorGroupSid = 4,
+ WinCreatorOwnerServerSid = 5,
+ WinCreatorGroupServerSid = 6,
+ WinNtAuthoritySid = 7,
+ WinDialupSid = 8,
+ WinNetworkSid = 9,
+ WinBatchSid = 10,
+ WinInteractiveSid = 11,
+ WinServiceSid = 12,
+ WinAnonymousSid = 13,
+ WinProxySid = 14,
+ WinEnterpriseControllersSid = 15,
+ WinSelfSid = 16,
+ WinAuthenticatedUserSid = 17,
+ WinRestrictedCodeSid = 18,
+ WinTerminalServerSid = 19,
+ WinRemoteLogonIdSid = 20,
+ WinLogonIdsSid = 21,
+ WinLocalSystemSid = 22,
+ WinLocalServiceSid = 23,
+ WinNetworkServiceSid = 24,
+ WinBuiltinDomainSid = 25,
+ WinBuiltinAdministratorsSid = 26,
+ WinBuiltinUsersSid = 27,
+ WinBuiltinGuestsSid = 28,
+ WinBuiltinPowerUsersSid = 29,
+ WinBuiltinAccountOperatorsSid = 30,
+ WinBuiltinSystemOperatorsSid = 31,
+ WinBuiltinPrintOperatorsSid = 32,
+ WinBuiltinBackupOperatorsSid = 33,
+ WinBuiltinReplicatorSid = 34,
+ WinBuiltinPreWindows2000CompatibleAccessSid = 35,
+ WinBuiltinRemoteDesktopUsersSid = 36,
+ WinBuiltinNetworkConfigurationOperatorsSid = 37,
+ WinAccountAdministratorSid = 38,
+ WinAccountGuestSid = 39,
+ WinAccountKrbtgtSid = 40,
+ WinAccountDomainAdminsSid = 41,
+ WinAccountDomainUsersSid = 42,
+ WinAccountDomainGuestsSid = 43,
+ WinAccountComputersSid = 44,
+ WinAccountControllersSid = 45,
+ WinAccountCertAdminsSid = 46,
+ WinAccountSchemaAdminsSid = 47,
+ WinAccountEnterpriseAdminsSid = 48,
+ WinAccountPolicyAdminsSid = 49,
+ WinAccountRasAndIasServersSid = 50,
+ WinNTLMAuthenticationSid = 51,
+ WinDigestAuthenticationSid = 52,
+ WinSChannelAuthenticationSid = 53,
+ WinThisOrganizationSid = 54,
+ WinOtherOrganizationSid = 55,
+ WinBuiltinIncomingForestTrustBuildersSid = 56,
+ WinBuiltinPerfMonitoringUsersSid = 57,
+ WinBuiltinPerfLoggingUsersSid = 58,
+ WinBuiltinAuthorizationAccessSid = 59,
+ WinBuiltinTerminalServerLicenseServersSid = 60,
+ WinBuiltinDCOMUsersSid = 61,
+ WinBuiltinIUsersSid = 62,
+ WinIUserSid = 63,
+ WinBuiltinCryptoOperatorsSid = 64,
+ WinUntrustedLabelSid = 65,
+ WinLowLabelSid = 66,
+ WinMediumLabelSid = 67,
+ WinHighLabelSid = 68,
+ WinSystemLabelSid = 69,
+ WinWriteRestrictedCodeSid = 70,
+ WinCreatorOwnerRightsSid = 71,
+ WinCacheablePrincipalsGroupSid = 72,
+ WinNonCacheablePrincipalsGroupSid = 73,
+ WinEnterpriseReadonlyControllersSid = 74,
+ WinAccountReadonlyControllersSid = 75,
+ WinBuiltinEventLogReadersGroup = 76,
+ WinNewEnterpriseReadonlyControllersSid = 77,
+ WinBuiltinCertSvcDComAccessGroup = 78,
+ WinMediumPlusLabelSid = 79,
+ WinLocalLogonSid = 80,
+ WinConsoleLogonSid = 81,
+ WinThisOrganizationCertificateSid = 82,
+ WinApplicationPackageAuthoritySid = 83,
+ WinBuiltinAnyPackageSid = 84,
+ WinCapabilityInternetClientSid = 85,
+ WinCapabilityInternetClientServerSid = 86,
+ WinCapabilityPrivateNetworkClientServerSid = 87,
+ WinCapabilityPicturesLibrarySid = 88,
+ WinCapabilityVideosLibrarySid = 89,
+ WinCapabilityMusicLibrarySid = 90,
+ WinCapabilityDocumentsLibrarySid = 91,
+ WinCapabilitySharedUserCertificatesSid = 92,
+ WinCapabilityEnterpriseAuthenticationSid = 93,
+ WinCapabilityRemovableStorageSid = 94
+}
struct QUOTA_LIMITS {
SIZE_T PagedPoolLimit;
SIZE_T NonPagedPoolLimit;
ES_SYSTEM_REQUIRED = 0x00000001,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_USER_PRESENT = 0x00000004,
+ ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000;
enum LATENCY_TIME {
*/
module core.sys.windows.winperf;
version (Windows):
+@system:
import core.sys.windows.windef;
import core.sys.windows.winbase; // for SYSTEMTIME
*/
module core.sys.windows.winreg;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "advapi32");
-private import core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.windef;
+import core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.windef;
enum : HKEY { // for some reason, DMD errors if I don't give all the values explicitly
HKEY_CLASSES_ROOT = cast(HKEY) 0x80000000,
}
extern (Windows) nothrow @nogc {
- LONG RegCloseKey(in HKEY);
+ LONG RegCloseKey(const scope HKEY);
LONG RegConnectRegistryA(LPCSTR, HKEY, PHKEY);
LONG RegConnectRegistryW(LPCWSTR, HKEY, PHKEY);
- LONG RegCreateKeyExA(in HKEY, LPCSTR, DWORD, LPSTR, DWORD, REGSAM,
+ LONG RegCreateKeyExA(const scope HKEY, LPCSTR, DWORD, LPSTR, DWORD, REGSAM,
LPSECURITY_ATTRIBUTES, PHKEY, PDWORD);
- LONG RegCreateKeyExW(in HKEY, LPCWSTR, DWORD, LPWSTR, DWORD, REGSAM,
+ LONG RegCreateKeyExW(const scope HKEY, LPCWSTR, DWORD, LPWSTR, DWORD, REGSAM,
LPSECURITY_ATTRIBUTES, PHKEY, PDWORD);
- LONG RegDeleteKeyA(in HKEY, LPCSTR);
- LONG RegDeleteKeyW(in HKEY, LPCWSTR);
- LONG RegDeleteValueA(in HKEY, LPCSTR);
- LONG RegDeleteValueW(in HKEY, LPCWSTR);
- LONG RegEnumKeyExA(in HKEY, DWORD, LPSTR, PDWORD, PDWORD, LPSTR, PDWORD,
+ LONG RegDeleteKeyA(const scope HKEY, LPCSTR);
+ LONG RegDeleteKeyW(const scope HKEY, LPCWSTR);
+ LONG RegDeleteValueA(const scope HKEY, LPCSTR);
+ LONG RegDeleteValueW(const scope HKEY, LPCWSTR);
+ LONG RegEnumKeyExA(const scope HKEY, DWORD, LPSTR, PDWORD, PDWORD, LPSTR, PDWORD,
PFILETIME);
- LONG RegEnumKeyExW(in HKEY, DWORD, LPWSTR, PDWORD, PDWORD, LPWSTR, PDWORD,
+ LONG RegEnumKeyExW(const scope HKEY, DWORD, LPWSTR, PDWORD, PDWORD, LPWSTR, PDWORD,
PFILETIME);
- LONG RegEnumValueA(in HKEY, DWORD, LPSTR, PDWORD, PDWORD, PDWORD, LPBYTE,
+ LONG RegEnumValueA(const scope HKEY, DWORD, LPSTR, PDWORD, PDWORD, PDWORD, LPBYTE,
PDWORD);
- LONG RegEnumValueW(in HKEY, DWORD, LPWSTR, PDWORD, PDWORD, PDWORD, LPBYTE,
+ LONG RegEnumValueW(const scope HKEY, DWORD, LPWSTR, PDWORD, PDWORD, PDWORD, LPBYTE,
PDWORD);
- LONG RegFlushKey(in HKEY);
- LONG RegLoadKeyA(in HKEY, LPCSTR, LPCSTR);
- LONG RegLoadKeyW(in HKEY, LPCWSTR, LPCWSTR);
- LONG RegOpenKeyExA(in HKEY, LPCSTR, DWORD, REGSAM, PHKEY);
- LONG RegOpenKeyExW(in HKEY, LPCWSTR, DWORD, REGSAM, PHKEY);
- LONG RegQueryInfoKeyA(in HKEY, LPSTR, PDWORD, PDWORD, PDWORD, PDWORD,
+ LONG RegFlushKey(const scope HKEY);
+ LONG RegLoadKeyA(const scope HKEY, LPCSTR, LPCSTR);
+ LONG RegLoadKeyW(const scope HKEY, LPCWSTR, LPCWSTR);
+ LONG RegOpenKeyExA(const scope HKEY, LPCSTR, DWORD, REGSAM, PHKEY);
+ LONG RegOpenKeyExW(const scope HKEY, LPCWSTR, DWORD, REGSAM, PHKEY);
+ LONG RegQueryInfoKeyA(const scope HKEY, LPSTR, PDWORD, PDWORD, PDWORD, PDWORD,
PDWORD, PDWORD, PDWORD, PDWORD, PDWORD, PFILETIME);
- LONG RegQueryInfoKeyW(in HKEY, LPWSTR, PDWORD, PDWORD, PDWORD, PDWORD,
+ LONG RegQueryInfoKeyW(const scope HKEY, LPWSTR, PDWORD, PDWORD, PDWORD, PDWORD,
PDWORD, PDWORD, PDWORD, PDWORD, PDWORD, PFILETIME);
- LONG RegQueryMultipleValuesA(in HKEY, PVALENTA, DWORD, LPSTR, LPDWORD);
- LONG RegQueryMultipleValuesW(in HKEY, PVALENTW, DWORD, LPWSTR, LPDWORD);
- LONG RegQueryValueExA(in HKEY, LPCSTR, LPDWORD, LPDWORD, /*LPBYTE*/LPVOID, LPDWORD);
- LONG RegQueryValueExW(in HKEY, LPCWSTR, LPDWORD, LPDWORD, /*LPBYTE*/LPVOID, LPDWORD);
- LONG RegReplaceKeyA(in HKEY, LPCSTR, LPCSTR, LPCSTR);
- LONG RegReplaceKeyW(in HKEY, LPCWSTR, LPCWSTR, LPCWSTR);
- LONG RegSaveKeyA(in HKEY, LPCSTR, LPSECURITY_ATTRIBUTES);
- LONG RegSaveKeyW(in HKEY, LPCWSTR, LPSECURITY_ATTRIBUTES);
- LONG RegSetKeySecurity(in HKEY, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
- LONG RegSetValueExA(in HKEY, LPCSTR, DWORD, DWORD, const(BYTE)*, DWORD);
- LONG RegSetValueExW(in HKEY, LPCWSTR, DWORD, DWORD, const(BYTE)*, DWORD);
- LONG RegUnLoadKeyA(in HKEY, LPCSTR);
- LONG RegUnLoadKeyW(in HKEY, LPCWSTR);
- LONG RegNotifyChangeKeyValue(in HKEY, BOOL, DWORD, HANDLE, BOOL);
+ LONG RegQueryMultipleValuesA(const scope HKEY, PVALENTA, DWORD, LPSTR, LPDWORD);
+ LONG RegQueryMultipleValuesW(const scope HKEY, PVALENTW, DWORD, LPWSTR, LPDWORD);
+ LONG RegQueryValueExA(const scope HKEY, LPCSTR, LPDWORD, LPDWORD, /*LPBYTE*/LPVOID, LPDWORD);
+ LONG RegQueryValueExW(const scope HKEY, LPCWSTR, LPDWORD, LPDWORD, /*LPBYTE*/LPVOID, LPDWORD);
+ LONG RegReplaceKeyA(const scope HKEY, LPCSTR, LPCSTR, LPCSTR);
+ LONG RegReplaceKeyW(const scope HKEY, LPCWSTR, LPCWSTR, LPCWSTR);
+ LONG RegSaveKeyA(const scope HKEY, LPCSTR, LPSECURITY_ATTRIBUTES);
+ LONG RegSaveKeyW(const scope HKEY, LPCWSTR, LPSECURITY_ATTRIBUTES);
+ LONG RegSetKeySecurity(const scope HKEY, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
+ LONG RegSetValueExA(const scope HKEY, LPCSTR, DWORD, DWORD, const(BYTE)*, DWORD);
+ LONG RegSetValueExW(const scope HKEY, LPCWSTR, DWORD, DWORD, const(BYTE)*, DWORD);
+ LONG RegUnLoadKeyA(const scope HKEY, LPCSTR);
+ LONG RegUnLoadKeyW(const scope HKEY, LPCWSTR);
+ LONG RegNotifyChangeKeyValue(const scope HKEY, BOOL, DWORD, HANDLE, BOOL);
BOOL AbortSystemShutdownA(LPCSTR);
BOOL AbortSystemShutdownW(LPCWSTR);
BOOL InitiateSystemShutdownA(LPSTR, LPSTR, DWORD, BOOL, BOOL);
BOOL InitiateSystemShutdownW(LPWSTR, LPWSTR, DWORD, BOOL, BOOL);
- LONG RegGetKeySecurity(in HKEY, SECURITY_INFORMATION,
+ LONG RegGetKeySecurity(const scope HKEY, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR, PDWORD);
- LONG RegRestoreKeyA(in HKEY, LPCSTR, DWORD);
- LONG RegRestoreKeyW(in HKEY, LPCWSTR, DWORD);
- LONG RegSetKeySecurity(in HKEY, SECURITY_INFORMATION,
+ LONG RegRestoreKeyA(const scope HKEY, LPCSTR, DWORD);
+ LONG RegRestoreKeyW(const scope HKEY, LPCWSTR, DWORD);
+ LONG RegSetKeySecurity(const scope HKEY, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR);
static if (_WIN32_WINNT >= 0x500) {
}
static if (_WIN32_WINNT >= 0x501) {
- LONG RegSaveKeyExA(in HKEY, LPCSTR, LPSECURITY_ATTRIBUTES, DWORD);
- LONG RegSaveKeyExW(in HKEY, LPCWSTR, LPSECURITY_ATTRIBUTES, DWORD);
+ LONG RegSaveKeyExA(const scope HKEY, LPCSTR, LPSECURITY_ATTRIBUTES, DWORD);
+ LONG RegSaveKeyExW(const scope HKEY, LPCWSTR, LPSECURITY_ATTRIBUTES, DWORD);
}
static if (_WIN32_WINNT >= 0x600) {
- LONG RegGetValueA(in HKEY hkey, LPCSTR lpSubKey, LPCSTR lpValue,
+ LONG RegGetValueA(const scope HKEY hkey, LPCSTR lpSubKey, LPCSTR lpValue,
DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData);
- LONG RegGetValueW(in HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpValue,
+ LONG RegGetValueW(const scope HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpValue,
DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData);
}
//deprecated {
- LONG RegCreateKeyA(in HKEY, LPCSTR, PHKEY);
- LONG RegCreateKeyW(in HKEY, LPCWSTR, PHKEY);
- LONG RegEnumKeyA(in HKEY, DWORD, LPSTR, DWORD);
- LONG RegEnumKeyW(in HKEY, DWORD, LPWSTR, DWORD);
- LONG RegOpenKeyA(in HKEY, LPCSTR, PHKEY);
- LONG RegOpenKeyW(in HKEY, LPCWSTR, PHKEY);
- LONG RegQueryValueA(in HKEY, LPCSTR, LPSTR, PLONG);
- LONG RegQueryValueW(in HKEY, LPCWSTR, LPWSTR, PLONG);
- LONG RegSetValueA(in HKEY, LPCSTR, DWORD, LPCSTR, DWORD);
- LONG RegSetValueW(in HKEY, LPCWSTR, DWORD, LPCWSTR, DWORD);
+ LONG RegCreateKeyA(const scope HKEY, LPCSTR, PHKEY);
+ LONG RegCreateKeyW(const scope HKEY, LPCWSTR, PHKEY);
+ LONG RegEnumKeyA(const scope HKEY, DWORD, LPSTR, DWORD);
+ LONG RegEnumKeyW(const scope HKEY, DWORD, LPWSTR, DWORD);
+ LONG RegOpenKeyA(const scope HKEY, LPCSTR, PHKEY);
+ LONG RegOpenKeyW(const scope HKEY, LPCWSTR, PHKEY);
+ LONG RegQueryValueA(const scope HKEY, LPCSTR, LPSTR, PLONG);
+ LONG RegQueryValueW(const scope HKEY, LPCWSTR, LPWSTR, PLONG);
+ LONG RegSetValueA(const scope HKEY, LPCSTR, DWORD, LPCSTR, DWORD);
+ LONG RegSetValueW(const scope HKEY, LPCWSTR, DWORD, LPCWSTR, DWORD);
//}
}
module core.sys.windows.winsock2;
version (Windows):
+@system:
pragma(lib, "ws2_32");
*/
module core.sys.windows.winspool;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "winspool");
-private import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.wingdi;
-private import core.sys.windows.winbase; // for SYSTEMTIME
+import core.sys.windows.w32api, core.sys.windows.windef, core.sys.windows.wingdi;
+import core.sys.windows.winbase; // for SYSTEMTIME
// FIXME: clean up Windows version support
*/
module core.sys.windows.winsvc;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "advapi32");
-private import core.sys.windows.w32api, core.sys.windows.windef;
+import core.sys.windows.w32api, core.sys.windows.windef;
// FIXME: check Windows version support
*/
module core.sys.windows.winuser;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "user32");
//#define GetWindowTask(hWnd) ((HANDLE)GetWindowThreadProcessId(hWnd, NULL))
//#define DefHookProc(c, p, lp, h) CallNextHookEx((HHOOK)*h, c, p, lp)
-private import core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.wingdi;
-private import core.sys.windows.windef; // for HMONITOR
+import core.sys.windows.w32api, core.sys.windows.winbase, core.sys.windows.wingdi;
+import core.sys.windows.windef; // for HMONITOR
// FIXME: clean up Windows version support
p.y = HIWORD(ps);
}
-POINTS POINTTOPOINTS()(in POINT p) {
+POINTS POINTTOPOINTS()(const POINT p) {
return MAKELONG(p.x, p.y);
}
*/
module core.sys.windows.winver;
version (Windows):
+@system:
+import core.sys.windows.w32api;
+import core.sys.windows.winbase;
+import core.sys.windows.sdkddkver;
version (ANSI) {} else version = Unicode;
pragma(lib, "version");
-private import core.sys.windows.windef;
+import core.sys.windows.windef;
// FIXME: type weirdness
enum {
alias VerLanguageNameA VerLanguageName;
alias VerQueryValueA VerQueryValue;
}
+
+alias VERSIONHELPERAPI = BOOL;
+VERSIONHELPERAPI IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
+{
+ OSVERSIONINFOEXW osvi;
+ const DWORDLONG dwlConditionMask = VerSetConditionMask(
+ VerSetConditionMask(
+ VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),
+ VER_MINORVERSION,
+ VER_GREATER_EQUAL),
+ VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL
+ );
+ osvi.dwMajorVersion = wMajorVersion;
+ osvi.dwMinorVersion = wMinorVersion;
+ osvi.wServicePackMajor = wServicePackMajor;
+
+ return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
+}
+
+VERSIONHELPERAPI IsWindowsXPOrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0);
+}
+
+VERSIONHELPERAPI IsWindowsXPSP1OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1);
+}
+
+VERSIONHELPERAPI IsWindowsXPSP2OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2);
+}
+
+VERSIONHELPERAPI IsWindowsXPSP3OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3);
+}
+
+VERSIONHELPERAPI IsWindowsVistaOrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
+}
+
+VERSIONHELPERAPI IsWindowsVistaSP1OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
+}
+
+VERSIONHELPERAPI IsWindowsVistaSP2OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
+}
+
+VERSIONHELPERAPI IsWindows7OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
+}
+
+VERSIONHELPERAPI IsWindows7SP1OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
+}
+
+VERSIONHELPERAPI IsWindows8OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
+}
+
+VERSIONHELPERAPI IsWindows8Point1OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
+}
+
+VERSIONHELPERAPI IsWindows10OrGreater()
+{
+ return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0);
+}
+
+VERSIONHELPERAPI IsWindowsServer()
+{
+ OSVERSIONINFOEXW osvi = { OSVERSIONINFOEXW.sizeof, 0, 0, 0, 0, [0], 0, 0, 0, VER_NT_WORKSTATION };
+ const DWORDLONG dwlConditionMask = VerSetConditionMask( 0, VER_PRODUCT_TYPE, VER_EQUAL );
+
+ return !VerifyVersionInfoW(&osvi, VER_PRODUCT_TYPE, dwlConditionMask);
+}
*/
module core.sys.windows.wtsapi32;
version (Windows):
+@system:
version (ANSI) {} else version = Unicode;
pragma(lib, "wtsapi32");
-private import core.sys.windows.w32api;
+import core.sys.windows.w32api;
import core.sys.windows.windef;
enum {
*/
module core.sys.windows.wtypes;
version (Windows):
+@system:
import core.sys.windows.rpc, core.sys.windows.rpcndr;
-private import core.sys.windows.windef;
-private import core.sys.windows.uuid; // for GUID_NULL
+import core.sys.windows.windef;
+import core.sys.windows.uuid; // for GUID_NULL
alias GUID_NULL IID_NULL, CLSID_NULL;
VT_ILLEGAL = 0xffff,
VT_ILLEGALMASKED = 0xfff,
VT_TYPEMASK = 0xfff
-};
+}
struct BYTE_SIZEDARR {
uint clSize;
+++ /dev/null
-/**
- * The thread module provides support for thread creation and management.
- *
- * Copyright: Copyright Sean Kelly 2005 - 2012.
- * License: Distributed under the
- * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
- * (See accompanying file LICENSE)
- * Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
- * Source: $(DRUNTIMESRC core/_thread.d)
- */
-
-/* NOTE: This file has been patched from the original DMD distribution to
- * work with the GDC compiler.
- */
-module core.thread;
-
-
-public import core.time; // for Duration
-import core.exception : onOutOfMemoryError;
-
-version (OSX)
- version = Darwin;
-else version (iOS)
- version = Darwin;
-else version (TVOS)
- version = Darwin;
-else version (WatchOS)
- version = Darwin;
-
-private
-{
- // interface to rt.tlsgc
- import core.internal.traits : externDFunc;
-
- alias rt_tlsgc_init = externDFunc!("rt.tlsgc.init", void* function() nothrow @nogc);
- alias rt_tlsgc_destroy = externDFunc!("rt.tlsgc.destroy", void function(void*) nothrow @nogc);
-
- alias ScanDg = void delegate(void* pstart, void* pend) nothrow;
- alias rt_tlsgc_scan =
- externDFunc!("rt.tlsgc.scan", void function(void*, scope ScanDg) nothrow);
-
- alias rt_tlsgc_processGCMarks =
- externDFunc!("rt.tlsgc.processGCMarks", void function(void*, scope IsMarkedDg) nothrow);
-}
-
-version (Solaris)
-{
- import core.sys.solaris.sys.priocntl;
- import core.sys.solaris.sys.types;
-}
-
-version (GNU)
-{
- import gcc.builtins;
- import gcc.config;
- version (GNU_StackGrowsDown)
- version = StackGrowsDown;
-}
-else
-{
- // this should be true for most architectures
- version = StackGrowsDown;
-}
-
-/**
- * Returns the process ID of the calling process, which is guaranteed to be
- * unique on the system. This call is always successful.
- *
- * Example:
- * ---
- * writefln("Current process id: %s", getpid());
- * ---
- */
-version (Posix)
-{
- alias getpid = core.sys.posix.unistd.getpid;
-}
-else version (Windows)
-{
- alias getpid = core.sys.windows.windows.GetCurrentProcessId;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Thread and Fiber Exceptions
-///////////////////////////////////////////////////////////////////////////////
-
-
-/**
- * Base class for thread exceptions.
- */
-class ThreadException : Exception
-{
- @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
- {
- super(msg, file, line, next);
- }
-
- @safe pure nothrow this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
- {
- super(msg, file, line, next);
- }
-}
-
-
-/**
-* Base class for thread errors to be used for function inside GC when allocations are unavailable.
-*/
-class ThreadError : Error
-{
- @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
- {
- super(msg, file, line, next);
- }
-
- @safe pure nothrow this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
- {
- super(msg, file, line, next);
- }
-}
-
-private
-{
- import core.atomic, core.memory, core.sync.mutex;
-
- // Handling unaligned mutexes are not supported on all platforms, so we must
- // ensure that the address of all shared data are appropriately aligned.
- import core.internal.traits : classInstanceAlignment;
-
- enum mutexAlign = classInstanceAlignment!Mutex;
- enum mutexClassInstanceSize = __traits(classInstanceSize, Mutex);
-
- //
- // exposed by compiler runtime
- //
- extern (C) void rt_moduleTlsCtor();
- extern (C) void rt_moduleTlsDtor();
-
- /**
- * Hook for whatever EH implementation is used to save/restore some data
- * per stack.
- *
- * Params:
- * newContext = The return value of the prior call to this function
- * where the stack was last swapped out, or null when a fiber stack
- * is switched in for the first time.
- */
- extern(C) void* _d_eh_swapContext(void* newContext) nothrow @nogc;
-
- version (DigitalMars)
- {
- version (Windows)
- alias swapContext = _d_eh_swapContext;
- else
- {
- extern(C) void* _d_eh_swapContextDwarf(void* newContext) nothrow @nogc;
-
- void* swapContext(void* newContext) nothrow @nogc
- {
- /* Detect at runtime which scheme is being used.
- * Eventually, determine it statically.
- */
- static int which = 0;
- final switch (which)
- {
- case 0:
- {
- assert(newContext == null);
- auto p = _d_eh_swapContext(newContext);
- auto pdwarf = _d_eh_swapContextDwarf(newContext);
- if (p)
- {
- which = 1;
- return p;
- }
- else if (pdwarf)
- {
- which = 2;
- return pdwarf;
- }
- return null;
- }
- case 1:
- return _d_eh_swapContext(newContext);
- case 2:
- return _d_eh_swapContextDwarf(newContext);
- }
- }
- }
- }
- else
- alias swapContext = _d_eh_swapContext;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Thread Entry Point and Signal Handlers
-///////////////////////////////////////////////////////////////////////////////
-
-
-version (Windows)
-{
- private
- {
- import core.stdc.stdint : uintptr_t; // for _beginthreadex decl below
- import core.stdc.stdlib; // for malloc, atexit
- import core.sys.windows.windows;
- import core.sys.windows.threadaux; // for OpenThreadHandle
-
- extern (Windows) alias btex_fptr = uint function(void*);
- extern (C) uintptr_t _beginthreadex(void*, uint, btex_fptr, void*, uint, uint*) nothrow;
-
- //
- // Entry point for Windows threads
- //
- extern (Windows) uint thread_entryPoint( void* arg ) nothrow
- {
- Thread obj = cast(Thread) arg;
- assert( obj );
-
- assert( obj.m_curr is &obj.m_main );
- obj.m_main.bstack = getStackBottom();
- obj.m_main.tstack = obj.m_main.bstack;
- obj.m_tlsgcdata = rt_tlsgc_init();
-
- Thread.setThis(obj);
- Thread.add(obj);
- scope (exit)
- {
- Thread.remove(obj);
- }
- Thread.add(&obj.m_main);
-
- // NOTE: No GC allocations may occur until the stack pointers have
- // been set and Thread.getThis returns a valid reference to
- // this thread object (this latter condition is not strictly
- // necessary on Windows but it should be followed for the
- // sake of consistency).
-
- // TODO: Consider putting an auto exception object here (using
- // alloca) forOutOfMemoryError plus something to track
- // whether an exception is in-flight?
-
- void append( Throwable t )
- {
- if ( obj.m_unhandled is null )
- obj.m_unhandled = t;
- else
- {
- Throwable last = obj.m_unhandled;
- while ( last.next !is null )
- last = last.next;
- last.next = t;
- }
- }
-
- version (D_InlineAsm_X86)
- {
- asm nothrow @nogc { fninit; }
- }
-
- try
- {
- rt_moduleTlsCtor();
- try
- {
- obj.run();
- }
- catch ( Throwable t )
- {
- append( t );
- }
- rt_moduleTlsDtor();
- }
- catch ( Throwable t )
- {
- append( t );
- }
- return 0;
- }
-
-
- HANDLE GetCurrentThreadHandle() nothrow @nogc
- {
- const uint DUPLICATE_SAME_ACCESS = 0x00000002;
-
- HANDLE curr = GetCurrentThread(),
- proc = GetCurrentProcess(),
- hndl;
-
- DuplicateHandle( proc, curr, proc, &hndl, 0, TRUE, DUPLICATE_SAME_ACCESS );
- return hndl;
- }
- }
-}
-else version (Posix)
-{
- private
- {
- import core.stdc.errno;
- import core.sys.posix.semaphore;
- import core.sys.posix.stdlib; // for malloc, valloc, free, atexit
- import core.sys.posix.pthread;
- import core.sys.posix.signal;
- import core.sys.posix.time;
-
- version (Darwin)
- {
- import core.sys.darwin.mach.thread_act;
- import core.sys.darwin.pthread : pthread_mach_thread_np;
- }
-
- //
- // Entry point for POSIX threads
- //
- extern (C) void* thread_entryPoint( void* arg ) nothrow
- {
- version (Shared)
- {
- import rt.sections;
- Thread obj = cast(Thread)(cast(void**)arg)[0];
- auto loadedLibraries = (cast(void**)arg)[1];
- .free(arg);
- }
- else
- {
- Thread obj = cast(Thread)arg;
- }
- assert( obj );
-
- // loadedLibraries need to be inherited from parent thread
- // before initilizing GC for TLS (rt_tlsgc_init)
- version (Shared) inheritLoadedLibraries(loadedLibraries);
-
- assert( obj.m_curr is &obj.m_main );
- obj.m_main.bstack = getStackBottom();
- obj.m_main.tstack = obj.m_main.bstack;
- obj.m_tlsgcdata = rt_tlsgc_init();
-
- atomicStore!(MemoryOrder.raw)(obj.m_isRunning, true);
- Thread.setThis(obj); // allocates lazy TLS (see Issue 11981)
- Thread.add(obj); // can only receive signals from here on
- scope (exit)
- {
- Thread.remove(obj);
- atomicStore!(MemoryOrder.raw)(obj.m_isRunning, false);
- }
- Thread.add(&obj.m_main);
-
- static extern (C) void thread_cleanupHandler( void* arg ) nothrow @nogc
- {
- Thread obj = cast(Thread) arg;
- assert( obj );
-
- // NOTE: If the thread terminated abnormally, just set it as
- // not running and let thread_suspendAll remove it from
- // the thread list. This is safer and is consistent
- // with the Windows thread code.
- atomicStore!(MemoryOrder.raw)(obj.m_isRunning,false);
- }
-
- // NOTE: Using void to skip the initialization here relies on
- // knowledge of how pthread_cleanup is implemented. It may
- // not be appropriate for all platforms. However, it does
- // avoid the need to link the pthread module. If any
- // implementation actually requires default initialization
- // then pthread_cleanup should be restructured to maintain
- // the current lack of a link dependency.
- static if ( __traits( compiles, pthread_cleanup ) )
- {
- pthread_cleanup cleanup = void;
- cleanup.push( &thread_cleanupHandler, cast(void*) obj );
- }
- else static if ( __traits( compiles, pthread_cleanup_push ) )
- {
- pthread_cleanup_push( &thread_cleanupHandler, cast(void*) obj );
- }
- else
- {
- static assert( false, "Platform not supported." );
- }
-
- // NOTE: No GC allocations may occur until the stack pointers have
- // been set and Thread.getThis returns a valid reference to
- // this thread object (this latter condition is not strictly
- // necessary on Windows but it should be followed for the
- // sake of consistency).
-
- // TODO: Consider putting an auto exception object here (using
- // alloca) forOutOfMemoryError plus something to track
- // whether an exception is in-flight?
-
- void append( Throwable t )
- {
- if ( obj.m_unhandled is null )
- obj.m_unhandled = t;
- else
- {
- Throwable last = obj.m_unhandled;
- while ( last.next !is null )
- last = last.next;
- last.next = t;
- }
- }
-
- try
- {
- rt_moduleTlsCtor();
- try
- {
- obj.run();
- }
- catch ( Throwable t )
- {
- append( t );
- }
- rt_moduleTlsDtor();
- version (Shared) cleanupLoadedLibraries();
- }
- catch ( Throwable t )
- {
- append( t );
- }
-
- // NOTE: Normal cleanup is handled by scope(exit).
-
- static if ( __traits( compiles, pthread_cleanup ) )
- {
- cleanup.pop( 0 );
- }
- else static if ( __traits( compiles, pthread_cleanup_push ) )
- {
- pthread_cleanup_pop( 0 );
- }
-
- return null;
- }
-
-
- //
- // Used to track the number of suspended threads
- //
- __gshared sem_t suspendCount;
-
-
- extern (C) void thread_suspendHandler( int sig ) nothrow
- in
- {
- assert( sig == suspendSignalNumber );
- }
- body
- {
- void op(void* sp) nothrow
- {
- // NOTE: Since registers are being pushed and popped from the
- // stack, any other stack data used by this function should
- // be gone before the stack cleanup code is called below.
- Thread obj = Thread.getThis();
- assert(obj !is null);
-
- if ( !obj.m_lock )
- {
- obj.m_curr.tstack = getStackTop();
- }
-
- sigset_t sigres = void;
- int status;
-
- status = sigfillset( &sigres );
- assert( status == 0 );
-
- status = sigdelset( &sigres, resumeSignalNumber );
- assert( status == 0 );
-
- version (FreeBSD) obj.m_suspendagain = false;
- status = sem_post( &suspendCount );
- assert( status == 0 );
-
- sigsuspend( &sigres );
-
- if ( !obj.m_lock )
- {
- obj.m_curr.tstack = obj.m_curr.bstack;
- }
- }
-
- // avoid deadlocks on FreeBSD, see Issue 13416
- version (FreeBSD)
- {
- auto obj = Thread.getThis();
- if (THR_IN_CRITICAL(obj.m_addr))
- {
- obj.m_suspendagain = true;
- if (sem_post(&suspendCount)) assert(0);
- return;
- }
- }
-
- callWithStackShell(&op);
- }
-
-
- extern (C) void thread_resumeHandler( int sig ) nothrow
- in
- {
- assert( sig == resumeSignalNumber );
- }
- body
- {
-
- }
-
- // HACK libthr internal (thr_private.h) macro, used to
- // avoid deadlocks in signal handler, see Issue 13416
- version (FreeBSD) bool THR_IN_CRITICAL(pthread_t p) nothrow @nogc
- {
- import core.sys.posix.config : c_long;
- import core.sys.posix.sys.types : lwpid_t;
-
- // If the begin of pthread would be changed in libthr (unlikely)
- // we'll run into undefined behavior, compare with thr_private.h.
- static struct pthread
- {
- c_long tid;
- static struct umutex { lwpid_t owner; uint flags; uint[2] ceilings; uint[4] spare; }
- umutex lock;
- uint cycle;
- int locklevel;
- int critical_count;
- // ...
- }
- auto priv = cast(pthread*)p;
- return priv.locklevel > 0 || priv.critical_count > 0;
- }
- }
-}
-else
-{
- // NOTE: This is the only place threading versions are checked. If a new
- // version is added, the module code will need to be searched for
- // places where version-specific code may be required. This can be
- // easily accomlished by searching for 'Windows' or 'Posix'.
- static assert( false, "Unknown threading implementation." );
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Thread
-///////////////////////////////////////////////////////////////////////////////
-
-
-/**
- * This class encapsulates all threading functionality for the D
- * programming language. As thread manipulation is a required facility
- * for garbage collection, all user threads should derive from this
- * class, and instances of this class should never be explicitly deleted.
- * A new thread may be created using either derivation or composition, as
- * in the following example.
- */
-class Thread
-{
- ///////////////////////////////////////////////////////////////////////////
- // Initialization
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Initializes a thread object which is associated with a static
- * D function.
- *
- * Params:
- * fn = The thread function.
- * sz = The stack size for this thread.
- *
- * In:
- * fn must not be null.
- */
- this( void function() fn, size_t sz = 0 ) @safe pure nothrow @nogc
- in
- {
- assert( fn );
- }
- body
- {
- this(sz);
- () @trusted { m_fn = fn; }();
- m_call = Call.FN;
- m_curr = &m_main;
- }
-
-
- /**
- * Initializes a thread object which is associated with a dynamic
- * D function.
- *
- * Params:
- * dg = The thread function.
- * sz = The stack size for this thread.
- *
- * In:
- * dg must not be null.
- */
- this( void delegate() dg, size_t sz = 0 ) @safe pure nothrow @nogc
- in
- {
- assert( dg );
- }
- body
- {
- this(sz);
- () @trusted { m_dg = dg; }();
- m_call = Call.DG;
- m_curr = &m_main;
- }
-
-
- /**
- * Cleans up any remaining resources used by this object.
- */
- ~this() nothrow @nogc
- {
- if ( m_addr == m_addr.init )
- {
- return;
- }
-
- version (Windows)
- {
- m_addr = m_addr.init;
- CloseHandle( m_hndl );
- m_hndl = m_hndl.init;
- }
- else version (Posix)
- {
- pthread_detach( m_addr );
- m_addr = m_addr.init;
- }
- version (Darwin)
- {
- m_tmach = m_tmach.init;
- }
- rt_tlsgc_destroy( m_tlsgcdata );
- m_tlsgcdata = null;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // General Actions
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Starts the thread and invokes the function or delegate passed upon
- * construction.
- *
- * In:
- * This routine may only be called once per thread instance.
- *
- * Throws:
- * ThreadException if the thread fails to start.
- */
- final Thread start() nothrow
- in
- {
- assert( !next && !prev );
- }
- body
- {
- auto wasThreaded = multiThreadedFlag;
- multiThreadedFlag = true;
- scope( failure )
- {
- if ( !wasThreaded )
- multiThreadedFlag = false;
- }
-
- version (Windows) {} else
- version (Posix)
- {
- pthread_attr_t attr;
-
- if ( pthread_attr_init( &attr ) )
- onThreadError( "Error initializing thread attributes" );
- if ( m_sz && pthread_attr_setstacksize( &attr, m_sz ) )
- onThreadError( "Error initializing thread stack size" );
- }
-
- version (Windows)
- {
- // NOTE: If a thread is just executing DllMain()
- // while another thread is started here, it holds an OS internal
- // lock that serializes DllMain with CreateThread. As the code
- // might request a synchronization on slock (e.g. in thread_findByAddr()),
- // we cannot hold that lock while creating the thread without
- // creating a deadlock
- //
- // Solution: Create the thread in suspended state and then
- // add and resume it with slock acquired
- assert(m_sz <= uint.max, "m_sz must be less than or equal to uint.max");
- m_hndl = cast(HANDLE) _beginthreadex( null, cast(uint) m_sz, &thread_entryPoint, cast(void*) this, CREATE_SUSPENDED, &m_addr );
- if ( cast(size_t) m_hndl == 0 )
- onThreadError( "Error creating thread" );
- }
-
- slock.lock_nothrow();
- scope(exit) slock.unlock_nothrow();
- {
- ++nAboutToStart;
- pAboutToStart = cast(Thread*)realloc(pAboutToStart, Thread.sizeof * nAboutToStart);
- pAboutToStart[nAboutToStart - 1] = this;
- version (Windows)
- {
- if ( ResumeThread( m_hndl ) == -1 )
- onThreadError( "Error resuming thread" );
- }
- else version (Posix)
- {
- // NOTE: This is also set to true by thread_entryPoint, but set it
- // here as well so the calling thread will see the isRunning
- // state immediately.
- atomicStore!(MemoryOrder.raw)(m_isRunning, true);
- scope( failure ) atomicStore!(MemoryOrder.raw)(m_isRunning, false);
-
- version (Shared)
- {
- import rt.sections;
- auto libs = pinLoadedLibraries();
- auto ps = cast(void**).malloc(2 * size_t.sizeof);
- if (ps is null) onOutOfMemoryError();
- ps[0] = cast(void*)this;
- ps[1] = cast(void*)libs;
- if ( pthread_create( &m_addr, &attr, &thread_entryPoint, ps ) != 0 )
- {
- unpinLoadedLibraries(libs);
- .free(ps);
- onThreadError( "Error creating thread" );
- }
- }
- else
- {
- if ( pthread_create( &m_addr, &attr, &thread_entryPoint, cast(void*) this ) != 0 )
- onThreadError( "Error creating thread" );
- }
- }
- version (Darwin)
- {
- m_tmach = pthread_mach_thread_np( m_addr );
- if ( m_tmach == m_tmach.init )
- onThreadError( "Error creating thread" );
- }
-
- return this;
- }
- }
-
- /**
- * Waits for this thread to complete. If the thread terminated as the
- * result of an unhandled exception, this exception will be rethrown.
- *
- * Params:
- * rethrow = Rethrow any unhandled exception which may have caused this
- * thread to terminate.
- *
- * Throws:
- * ThreadException if the operation fails.
- * Any exception not handled by the joined thread.
- *
- * Returns:
- * Any exception not handled by this thread if rethrow = false, null
- * otherwise.
- */
- final Throwable join( bool rethrow = true )
- {
- version (Windows)
- {
- if ( WaitForSingleObject( m_hndl, INFINITE ) != WAIT_OBJECT_0 )
- throw new ThreadException( "Unable to join thread" );
- // NOTE: m_addr must be cleared before m_hndl is closed to avoid
- // a race condition with isRunning. The operation is done
- // with atomicStore to prevent compiler reordering.
- atomicStore!(MemoryOrder.raw)(*cast(shared)&m_addr, m_addr.init);
- CloseHandle( m_hndl );
- m_hndl = m_hndl.init;
- }
- else version (Posix)
- {
- if ( pthread_join( m_addr, null ) != 0 )
- throw new ThreadException( "Unable to join thread" );
- // NOTE: pthread_join acts as a substitute for pthread_detach,
- // which is normally called by the dtor. Setting m_addr
- // to zero ensures that pthread_detach will not be called
- // on object destruction.
- m_addr = m_addr.init;
- }
- if ( m_unhandled )
- {
- if ( rethrow )
- throw m_unhandled;
- return m_unhandled;
- }
- return null;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // General Properties
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Gets the OS identifier for this thread.
- *
- * Returns:
- * If the thread hasn't been started yet, returns $(LREF ThreadID)$(D.init).
- * Otherwise, returns the result of $(D GetCurrentThreadId) on Windows,
- * and $(D pthread_self) on POSIX.
- *
- * The value is unique for the current process.
- */
- final @property ThreadID id() @safe @nogc
- {
- synchronized( this )
- {
- return m_addr;
- }
- }
-
-
- /**
- * Gets the user-readable label for this thread.
- *
- * Returns:
- * The name of this thread.
- */
- final @property string name() @safe @nogc
- {
- synchronized( this )
- {
- return m_name;
- }
- }
-
-
- /**
- * Sets the user-readable label for this thread.
- *
- * Params:
- * val = The new name of this thread.
- */
- final @property void name( string val ) @safe @nogc
- {
- synchronized( this )
- {
- m_name = val;
- }
- }
-
-
- /**
- * Gets the daemon status for this thread. While the runtime will wait for
- * all normal threads to complete before tearing down the process, daemon
- * threads are effectively ignored and thus will not prevent the process
- * from terminating. In effect, daemon threads will be terminated
- * automatically by the OS when the process exits.
- *
- * Returns:
- * true if this is a daemon thread.
- */
- final @property bool isDaemon() @safe @nogc
- {
- synchronized( this )
- {
- return m_isDaemon;
- }
- }
-
-
- /**
- * Sets the daemon status for this thread. While the runtime will wait for
- * all normal threads to complete before tearing down the process, daemon
- * threads are effectively ignored and thus will not prevent the process
- * from terminating. In effect, daemon threads will be terminated
- * automatically by the OS when the process exits.
- *
- * Params:
- * val = The new daemon status for this thread.
- */
- final @property void isDaemon( bool val ) @safe @nogc
- {
- synchronized( this )
- {
- m_isDaemon = val;
- }
- }
-
-
- /**
- * Tests whether this thread is running.
- *
- * Returns:
- * true if the thread is running, false if not.
- */
- final @property bool isRunning() nothrow @nogc
- {
- if ( m_addr == m_addr.init )
- {
- return false;
- }
-
- version (Windows)
- {
- uint ecode = 0;
- GetExitCodeThread( m_hndl, &ecode );
- return ecode == STILL_ACTIVE;
- }
- else version (Posix)
- {
- return atomicLoad(m_isRunning);
- }
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Thread Priority Actions
- ///////////////////////////////////////////////////////////////////////////
-
- version (Windows)
- {
- @property static int PRIORITY_MIN() @nogc nothrow pure @safe
- {
- return THREAD_PRIORITY_IDLE;
- }
-
- @property static const(int) PRIORITY_MAX() @nogc nothrow pure @safe
- {
- return THREAD_PRIORITY_TIME_CRITICAL;
- }
-
- @property static int PRIORITY_DEFAULT() @nogc nothrow pure @safe
- {
- return THREAD_PRIORITY_NORMAL;
- }
- }
- else
- {
- private struct Priority
- {
- int PRIORITY_MIN = int.min;
- int PRIORITY_DEFAULT = int.min;
- int PRIORITY_MAX = int.min;
- }
-
- /*
- Lazily loads one of the members stored in a hidden global variable of
- type `Priority`. Upon the first access of either member, the entire
- `Priority` structure is initialized. Multiple initializations from
- different threads calling this function are tolerated.
-
- `which` must be one of `PRIORITY_MIN`, `PRIORITY_DEFAULT`,
- `PRIORITY_MAX`.
- */
- private static int loadGlobal(string which)()
- {
- static shared Priority cache;
- auto local = atomicLoad(mixin("cache." ~ which));
- if (local != local.min) return local;
- // There will be benign races
- cache = loadPriorities;
- return atomicLoad(mixin("cache." ~ which));
- }
-
- /*
- Loads all priorities and returns them as a `Priority` structure. This
- function is thread-neutral.
- */
- private static Priority loadPriorities() @nogc nothrow @trusted
- {
- Priority result;
- version (Solaris)
- {
- pcparms_t pcParms;
- pcinfo_t pcInfo;
-
- pcParms.pc_cid = PC_CLNULL;
- if (priocntl(idtype_t.P_PID, P_MYID, PC_GETPARMS, &pcParms) == -1)
- assert( 0, "Unable to get scheduling class" );
-
- pcInfo.pc_cid = pcParms.pc_cid;
- // PC_GETCLINFO ignores the first two args, use dummy values
- if (priocntl(idtype_t.P_PID, 0, PC_GETCLINFO, &pcInfo) == -1)
- assert( 0, "Unable to get scheduling class info" );
-
- pri_t* clparms = cast(pri_t*)&pcParms.pc_clparms;
- pri_t* clinfo = cast(pri_t*)&pcInfo.pc_clinfo;
-
- result.PRIORITY_MAX = clparms[0];
-
- if (pcInfo.pc_clname == "RT")
- {
- m_isRTClass = true;
-
- // For RT class, just assume it can't be changed
- result.PRIORITY_MIN = clparms[0];
- result.PRIORITY_DEFAULT = clparms[0];
- }
- else
- {
- m_isRTClass = false;
-
- // For all other scheduling classes, there are
- // two key values -- uprilim and maxupri.
- // maxupri is the maximum possible priority defined
- // for the scheduling class, and valid priorities
- // range are in [-maxupri, maxupri].
- //
- // However, uprilim is an upper limit that the
- // current thread can set for the current scheduling
- // class, which can be less than maxupri. As such,
- // use this value for priorityMax since this is
- // the effective maximum.
-
- // maxupri
- result.PRIORITY_MIN = -clinfo[0];
- // by definition
- result.PRIORITY_DEFAULT = 0;
- }
- }
- else version (Posix)
- {
- int policy;
- sched_param param;
- pthread_getschedparam( pthread_self(), &policy, ¶m ) == 0
- || assert(0, "Internal error in pthread_getschedparam");
-
- result.PRIORITY_MIN = sched_get_priority_min( policy );
- result.PRIORITY_MIN != -1
- || assert(0, "Internal error in sched_get_priority_min");
- result.PRIORITY_DEFAULT = param.sched_priority;
- result.PRIORITY_MAX = sched_get_priority_max( policy );
- result.PRIORITY_MAX != -1 ||
- assert(0, "Internal error in sched_get_priority_max");
- }
- else
- {
- static assert(0, "Your code here.");
- }
- return result;
- }
-
- /**
- * The minimum scheduling priority that may be set for a thread. On
- * systems where multiple scheduling policies are defined, this value
- * represents the minimum valid priority for the scheduling policy of
- * the process.
- */
- @property static int PRIORITY_MIN() @nogc nothrow pure @trusted
- {
- return (cast(int function() @nogc nothrow pure @safe)
- &loadGlobal!"PRIORITY_MIN")();
- }
-
- /**
- * The maximum scheduling priority that may be set for a thread. On
- * systems where multiple scheduling policies are defined, this value
- * represents the maximum valid priority for the scheduling policy of
- * the process.
- */
- @property static const(int) PRIORITY_MAX() @nogc nothrow pure @trusted
- {
- return (cast(int function() @nogc nothrow pure @safe)
- &loadGlobal!"PRIORITY_MAX")();
- }
-
- /**
- * The default scheduling priority that is set for a thread. On
- * systems where multiple scheduling policies are defined, this value
- * represents the default priority for the scheduling policy of
- * the process.
- */
- @property static int PRIORITY_DEFAULT() @nogc nothrow pure @trusted
- {
- return (cast(int function() @nogc nothrow pure @safe)
- &loadGlobal!"PRIORITY_DEFAULT")();
- }
- }
-
- version (NetBSD)
- {
- //NetBSD does not support priority for default policy
- // and it is not possible change policy without root access
- int fakePriority = int.max;
- }
-
- /**
- * Gets the scheduling priority for the associated thread.
- *
- * Note: Getting the priority of a thread that already terminated
- * might return the default priority.
- *
- * Returns:
- * The scheduling priority of this thread.
- */
- final @property int priority()
- {
- version (Windows)
- {
- return GetThreadPriority( m_hndl );
- }
- else version (NetBSD)
- {
- return fakePriority==int.max? PRIORITY_DEFAULT : fakePriority;
- }
- else version (Posix)
- {
- int policy;
- sched_param param;
-
- if (auto err = pthread_getschedparam(m_addr, &policy, ¶m))
- {
- // ignore error if thread is not running => Bugzilla 8960
- if (!atomicLoad(m_isRunning)) return PRIORITY_DEFAULT;
- throw new ThreadException("Unable to get thread priority");
- }
- return param.sched_priority;
- }
- }
-
-
- /**
- * Sets the scheduling priority for the associated thread.
- *
- * Note: Setting the priority of a thread that already terminated
- * might have no effect.
- *
- * Params:
- * val = The new scheduling priority of this thread.
- */
- final @property void priority( int val )
- in
- {
- assert(val >= PRIORITY_MIN);
- assert(val <= PRIORITY_MAX);
- }
- body
- {
- version (Windows)
- {
- if ( !SetThreadPriority( m_hndl, val ) )
- throw new ThreadException( "Unable to set thread priority" );
- }
- else version (Solaris)
- {
- // the pthread_setschedprio(3c) and pthread_setschedparam functions
- // are broken for the default (TS / time sharing) scheduling class.
- // instead, we use priocntl(2) which gives us the desired behavior.
-
- // We hardcode the min and max priorities to the current value
- // so this is a no-op for RT threads.
- if (m_isRTClass)
- return;
-
- pcparms_t pcparm;
-
- pcparm.pc_cid = PC_CLNULL;
- if (priocntl(idtype_t.P_LWPID, P_MYID, PC_GETPARMS, &pcparm) == -1)
- throw new ThreadException( "Unable to get scheduling class" );
-
- pri_t* clparms = cast(pri_t*)&pcparm.pc_clparms;
-
- // clparms is filled in by the PC_GETPARMS call, only necessary
- // to adjust the element that contains the thread priority
- clparms[1] = cast(pri_t) val;
-
- if (priocntl(idtype_t.P_LWPID, P_MYID, PC_SETPARMS, &pcparm) == -1)
- throw new ThreadException( "Unable to set scheduling class" );
- }
- else version (NetBSD)
- {
- fakePriority = val;
- }
- else version (Posix)
- {
- static if (__traits(compiles, pthread_setschedprio))
- {
- if (auto err = pthread_setschedprio(m_addr, val))
- {
- // ignore error if thread is not running => Bugzilla 8960
- if (!atomicLoad(m_isRunning)) return;
- throw new ThreadException("Unable to set thread priority");
- }
- }
- else
- {
- // NOTE: pthread_setschedprio is not implemented on Darwin, FreeBSD, OpenBSD,
- // or DragonFlyBSD, so use the more complicated get/set sequence below.
- int policy;
- sched_param param;
-
- if (auto err = pthread_getschedparam(m_addr, &policy, ¶m))
- {
- // ignore error if thread is not running => Bugzilla 8960
- if (!atomicLoad(m_isRunning)) return;
- throw new ThreadException("Unable to set thread priority");
- }
- param.sched_priority = val;
- if (auto err = pthread_setschedparam(m_addr, policy, ¶m))
- {
- // ignore error if thread is not running => Bugzilla 8960
- if (!atomicLoad(m_isRunning)) return;
- throw new ThreadException("Unable to set thread priority");
- }
- }
- }
- }
-
-
- unittest
- {
- auto thr = Thread.getThis();
- immutable prio = thr.priority;
- scope (exit) thr.priority = prio;
-
- assert(prio == PRIORITY_DEFAULT);
- assert(prio >= PRIORITY_MIN && prio <= PRIORITY_MAX);
- thr.priority = PRIORITY_MIN;
- assert(thr.priority == PRIORITY_MIN);
- thr.priority = PRIORITY_MAX;
- assert(thr.priority == PRIORITY_MAX);
- }
-
- unittest // Bugzilla 8960
- {
- import core.sync.semaphore;
-
- auto thr = new Thread({});
- thr.start();
- Thread.sleep(1.msecs); // wait a little so the thread likely has finished
- thr.priority = PRIORITY_MAX; // setting priority doesn't cause error
- auto prio = thr.priority; // getting priority doesn't cause error
- assert(prio >= PRIORITY_MIN && prio <= PRIORITY_MAX);
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Actions on Calling Thread
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Suspends the calling thread for at least the supplied period. This may
- * result in multiple OS calls if period is greater than the maximum sleep
- * duration supported by the operating system.
- *
- * Params:
- * val = The minimum duration the calling thread should be suspended.
- *
- * In:
- * period must be non-negative.
- *
- * Example:
- * ------------------------------------------------------------------------
- *
- * Thread.sleep( dur!("msecs")( 50 ) ); // sleep for 50 milliseconds
- * Thread.sleep( dur!("seconds")( 5 ) ); // sleep for 5 seconds
- *
- * ------------------------------------------------------------------------
- */
- static void sleep( Duration val ) @nogc nothrow
- in
- {
- assert( !val.isNegative );
- }
- body
- {
- version (Windows)
- {
- auto maxSleepMillis = dur!("msecs")( uint.max - 1 );
-
- // avoid a non-zero time to be round down to 0
- if ( val > dur!"msecs"( 0 ) && val < dur!"msecs"( 1 ) )
- val = dur!"msecs"( 1 );
-
- // NOTE: In instances where all other threads in the process have a
- // lower priority than the current thread, the current thread
- // will not yield with a sleep time of zero. However, unlike
- // yield(), the user is not asking for a yield to occur but
- // only for execution to suspend for the requested interval.
- // Therefore, expected performance may not be met if a yield
- // is forced upon the user.
- while ( val > maxSleepMillis )
- {
- Sleep( cast(uint)
- maxSleepMillis.total!"msecs" );
- val -= maxSleepMillis;
- }
- Sleep( cast(uint) val.total!"msecs" );
- }
- else version (Posix)
- {
- timespec tin = void;
- timespec tout = void;
-
- val.split!("seconds", "nsecs")(tin.tv_sec, tin.tv_nsec);
- if ( val.total!"seconds" > tin.tv_sec.max )
- tin.tv_sec = tin.tv_sec.max;
- while ( true )
- {
- if ( !nanosleep( &tin, &tout ) )
- return;
- if ( errno != EINTR )
- assert(0, "Unable to sleep for the specified duration");
- tin = tout;
- }
- }
- }
-
-
- /**
- * Forces a context switch to occur away from the calling thread.
- */
- static void yield() @nogc nothrow
- {
- version (Windows)
- SwitchToThread();
- else version (Posix)
- sched_yield();
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Thread Accessors
- ///////////////////////////////////////////////////////////////////////////
-
- /**
- * Provides a reference to the calling thread.
- *
- * Returns:
- * The thread object representing the calling thread. The result of
- * deleting this object is undefined. If the current thread is not
- * attached to the runtime, a null reference is returned.
- */
- static Thread getThis() @safe nothrow @nogc
- {
- // NOTE: This function may not be called until thread_init has
- // completed. See thread_suspendAll for more information
- // on why this might occur.
- return sm_this;
- }
-
-
- /**
- * Provides a list of all threads currently being tracked by the system.
- * Note that threads in the returned array might no longer run (see
- * $(D Thread.)$(LREF isRunning)).
- *
- * Returns:
- * An array containing references to all threads currently being
- * tracked by the system. The result of deleting any contained
- * objects is undefined.
- */
- static Thread[] getAll()
- {
- static void resize(ref Thread[] buf, size_t nlen)
- {
- buf.length = nlen;
- }
- return getAllImpl!resize();
- }
-
-
- /**
- * Operates on all threads currently being tracked by the system. The
- * result of deleting any Thread object is undefined.
- * Note that threads passed to the callback might no longer run (see
- * $(D Thread.)$(LREF isRunning)).
- *
- * Params:
- * dg = The supplied code as a delegate.
- *
- * Returns:
- * Zero if all elemented are visited, nonzero if not.
- */
- static int opApply(scope int delegate(ref Thread) dg)
- {
- import core.stdc.stdlib : free, realloc;
-
- static void resize(ref Thread[] buf, size_t nlen)
- {
- buf = (cast(Thread*)realloc(buf.ptr, nlen * Thread.sizeof))[0 .. nlen];
- }
- auto buf = getAllImpl!resize;
- scope(exit) if (buf.ptr) free(buf.ptr);
-
- foreach (t; buf)
- {
- if (auto res = dg(t))
- return res;
- }
- return 0;
- }
-
- unittest
- {
- auto t1 = new Thread({
- foreach (_; 0 .. 20)
- Thread.getAll;
- }).start;
- auto t2 = new Thread({
- foreach (_; 0 .. 20)
- GC.collect;
- }).start;
- t1.join();
- t2.join();
- }
-
- private static Thread[] getAllImpl(alias resize)()
- {
- import core.atomic;
-
- Thread[] buf;
- while (true)
- {
- immutable len = atomicLoad!(MemoryOrder.raw)(*cast(shared)&sm_tlen);
- resize(buf, len);
- assert(buf.length == len);
- synchronized (slock)
- {
- if (len == sm_tlen)
- {
- size_t pos;
- for (Thread t = sm_tbeg; t; t = t.next)
- buf[pos++] = t;
- return buf;
- }
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // Stuff That Should Go Away
- ///////////////////////////////////////////////////////////////////////////
-
-
-private:
- //
- // Initializes a thread object which has no associated executable function.
- // This is used for the main thread initialized in thread_init().
- //
- this(size_t sz = 0) @safe pure nothrow @nogc
- {
- if (sz)
- {
- version (Posix)
- {
- // stack size must be a multiple of PAGESIZE
- sz += PAGESIZE - 1;
- sz -= sz % PAGESIZE;
- // and at least PTHREAD_STACK_MIN
- if (PTHREAD_STACK_MIN > sz)
- sz = PTHREAD_STACK_MIN;
- }
- m_sz = sz;
- }
- m_call = Call.NO;
- m_curr = &m_main;
- }
-
-
- //
- // Thread entry point. Invokes the function or delegate passed on
- // construction (if any).
- //
- final void run()
- {
- switch ( m_call )
- {
- case Call.FN:
- m_fn();
- break;
- case Call.DG:
- m_dg();
- break;
- default:
- break;
- }
- }
-
-
-private:
- //
- // The type of routine passed on thread construction.
- //
- enum Call
- {
- NO,
- FN,
- DG
- }
-
-
- //
- // Standard types
- //
- version (Windows)
- {
- alias TLSKey = uint;
- }
- else version (Posix)
- {
- alias TLSKey = pthread_key_t;
- }
-
-
- //
- // Local storage
- //
- static Thread sm_this;
-
-
- //
- // Main process thread
- //
- __gshared Thread sm_main;
-
- version (FreeBSD)
- {
- // set when suspend failed and should be retried, see Issue 13416
- shared bool m_suspendagain;
- }
-
-
- //
- // Standard thread data
- //
- version (Windows)
- {
- HANDLE m_hndl;
- }
- else version (Darwin)
- {
- mach_port_t m_tmach;
- }
- ThreadID m_addr;
- Call m_call;
- string m_name;
- union
- {
- void function() m_fn;
- void delegate() m_dg;
- }
- size_t m_sz;
- version (Posix)
- {
- shared bool m_isRunning;
- }
- bool m_isDaemon;
- bool m_isInCriticalRegion;
- Throwable m_unhandled;
-
- version (Solaris)
- {
- __gshared bool m_isRTClass;
- }
-
-private:
- ///////////////////////////////////////////////////////////////////////////
- // Storage of Active Thread
- ///////////////////////////////////////////////////////////////////////////
-
-
- //
- // Sets a thread-local reference to the current thread object.
- //
- static void setThis( Thread t ) nothrow @nogc
- {
- sm_this = t;
- }
-
-
-private:
- ///////////////////////////////////////////////////////////////////////////
- // Thread Context and GC Scanning Support
- ///////////////////////////////////////////////////////////////////////////
-
-
- final void pushContext( Context* c ) nothrow @nogc
- in
- {
- assert( !c.within );
- }
- body
- {
- m_curr.ehContext = swapContext(c.ehContext);
- c.within = m_curr;
- m_curr = c;
- }
-
-
- final void popContext() nothrow @nogc
- in
- {
- assert( m_curr && m_curr.within );
- }
- body
- {
- Context* c = m_curr;
- m_curr = c.within;
- c.ehContext = swapContext(m_curr.ehContext);
- c.within = null;
- }
-
-
- final Context* topContext() nothrow @nogc
- in
- {
- assert( m_curr );
- }
- body
- {
- return m_curr;
- }
-
-
- static struct Context
- {
- void* bstack,
- tstack;
-
- /// Slot for the EH implementation to keep some state for each stack
- /// (will be necessary for exception chaining, etc.). Opaque as far as
- /// we are concerned here.
- void* ehContext;
-
- Context* within;
- Context* next,
- prev;
- }
-
-
- Context m_main;
- Context* m_curr;
- bool m_lock;
- void* m_tlsgcdata;
-
- version (Windows)
- {
- version (X86)
- {
- uint[8] m_reg; // edi,esi,ebp,esp,ebx,edx,ecx,eax
- }
- else version (X86_64)
- {
- ulong[16] m_reg; // rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax
- // r8,r9,r10,r11,r12,r13,r14,r15
- }
- else
- {
- static assert(false, "Architecture not supported." );
- }
- }
- else version (Darwin)
- {
- version (X86)
- {
- uint[8] m_reg; // edi,esi,ebp,esp,ebx,edx,ecx,eax
- }
- else version (X86_64)
- {
- ulong[16] m_reg; // rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax
- // r8,r9,r10,r11,r12,r13,r14,r15
- }
- else
- {
- static assert(false, "Architecture not supported." );
- }
- }
-
-
-private:
- ///////////////////////////////////////////////////////////////////////////
- // GC Scanning Support
- ///////////////////////////////////////////////////////////////////////////
-
-
- // NOTE: The GC scanning process works like so:
- //
- // 1. Suspend all threads.
- // 2. Scan the stacks of all suspended threads for roots.
- // 3. Resume all threads.
- //
- // Step 1 and 3 require a list of all threads in the system, while
- // step 2 requires a list of all thread stacks (each represented by
- // a Context struct). Traditionally, there was one stack per thread
- // and the Context structs were not necessary. However, Fibers have
- // changed things so that each thread has its own 'main' stack plus
- // an arbitrary number of nested stacks (normally referenced via
- // m_curr). Also, there may be 'free-floating' stacks in the system,
- // which are Fibers that are not currently executing on any specific
- // thread but are still being processed and still contain valid
- // roots.
- //
- // To support all of this, the Context struct has been created to
- // represent a stack range, and a global list of Context structs has
- // been added to enable scanning of these stack ranges. The lifetime
- // (and presence in the Context list) of a thread's 'main' stack will
- // be equivalent to the thread's lifetime. So the Ccontext will be
- // added to the list on thread entry, and removed from the list on
- // thread exit (which is essentially the same as the presence of a
- // Thread object in its own global list). The lifetime of a Fiber's
- // context, however, will be tied to the lifetime of the Fiber object
- // itself, and Fibers are expected to add/remove their Context struct
- // on construction/deletion.
-
-
- //
- // All use of the global thread lists/array should synchronize on this lock.
- //
- // Careful as the GC acquires this lock after the GC lock to suspend all
- // threads any GC usage with slock held can result in a deadlock through
- // lock order inversion.
- @property static Mutex slock() nothrow @nogc
- {
- return cast(Mutex)_slock.ptr;
- }
-
- @property static Mutex criticalRegionLock() nothrow @nogc
- {
- return cast(Mutex)_criticalRegionLock.ptr;
- }
-
- __gshared align(mutexAlign) void[mutexClassInstanceSize] _slock;
- __gshared align(mutexAlign) void[mutexClassInstanceSize] _criticalRegionLock;
-
- static void initLocks()
- {
- _slock[] = typeid(Mutex).initializer[];
- (cast(Mutex)_slock.ptr).__ctor();
-
- _criticalRegionLock[] = typeid(Mutex).initializer[];
- (cast(Mutex)_criticalRegionLock.ptr).__ctor();
- }
-
- static void termLocks()
- {
- (cast(Mutex)_slock.ptr).__dtor();
- (cast(Mutex)_criticalRegionLock.ptr).__dtor();
- }
-
- __gshared Context* sm_cbeg;
-
- __gshared Thread sm_tbeg;
- __gshared size_t sm_tlen;
-
- // can't use rt.util.array in public code
- __gshared Thread* pAboutToStart;
- __gshared size_t nAboutToStart;
-
- //
- // Used for ordering threads in the global thread list.
- //
- Thread prev;
- Thread next;
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Global Context List Operations
- ///////////////////////////////////////////////////////////////////////////
-
-
- //
- // Add a context to the global context list.
- //
- static void add( Context* c ) nothrow @nogc
- in
- {
- assert( c );
- assert( !c.next && !c.prev );
- }
- body
- {
- slock.lock_nothrow();
- scope(exit) slock.unlock_nothrow();
- assert(!suspendDepth); // must be 0 b/c it's only set with slock held
-
- if (sm_cbeg)
- {
- c.next = sm_cbeg;
- sm_cbeg.prev = c;
- }
- sm_cbeg = c;
- }
-
-
- //
- // Remove a context from the global context list.
- //
- // This assumes slock being acquired. This isn't done here to
- // avoid double locking when called from remove(Thread)
- static void remove( Context* c ) nothrow @nogc
- in
- {
- assert( c );
- assert( c.next || c.prev );
- }
- body
- {
- if ( c.prev )
- c.prev.next = c.next;
- if ( c.next )
- c.next.prev = c.prev;
- if ( sm_cbeg == c )
- sm_cbeg = c.next;
- // NOTE: Don't null out c.next or c.prev because opApply currently
- // follows c.next after removing a node. This could be easily
- // addressed by simply returning the next node from this
- // function, however, a context should never be re-added to the
- // list anyway and having next and prev be non-null is a good way
- // to ensure that.
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Global Thread List Operations
- ///////////////////////////////////////////////////////////////////////////
-
-
- //
- // Add a thread to the global thread list.
- //
- static void add( Thread t, bool rmAboutToStart = true ) nothrow @nogc
- in
- {
- assert( t );
- assert( !t.next && !t.prev );
- }
- body
- {
- slock.lock_nothrow();
- scope(exit) slock.unlock_nothrow();
- assert(t.isRunning); // check this with slock to ensure pthread_create already returned
- assert(!suspendDepth); // must be 0 b/c it's only set with slock held
-
- if (rmAboutToStart)
- {
- size_t idx = -1;
- foreach (i, thr; pAboutToStart[0 .. nAboutToStart])
- {
- if (thr is t)
- {
- idx = i;
- break;
- }
- }
- assert(idx != -1);
- import core.stdc.string : memmove;
- memmove(pAboutToStart + idx, pAboutToStart + idx + 1, Thread.sizeof * (nAboutToStart - idx - 1));
- pAboutToStart =
- cast(Thread*)realloc(pAboutToStart, Thread.sizeof * --nAboutToStart);
- }
-
- if (sm_tbeg)
- {
- t.next = sm_tbeg;
- sm_tbeg.prev = t;
- }
- sm_tbeg = t;
- ++sm_tlen;
- }
-
-
- //
- // Remove a thread from the global thread list.
- //
- static void remove( Thread t ) nothrow @nogc
- in
- {
- assert( t );
- }
- body
- {
- // Thread was already removed earlier, might happen b/c of thread_detachInstance
- if (!t.next && !t.prev)
- return;
- slock.lock_nothrow();
- {
- // NOTE: When a thread is removed from the global thread list its
- // main context is invalid and should be removed as well.
- // It is possible that t.m_curr could reference more
- // than just the main context if the thread exited abnormally
- // (if it was terminated), but we must assume that the user
- // retains a reference to them and that they may be re-used
- // elsewhere. Therefore, it is the responsibility of any
- // object that creates contexts to clean them up properly
- // when it is done with them.
- remove( &t.m_main );
-
- if ( t.prev )
- t.prev.next = t.next;
- if ( t.next )
- t.next.prev = t.prev;
- if ( sm_tbeg is t )
- sm_tbeg = t.next;
- t.prev = t.next = null;
- --sm_tlen;
- }
- // NOTE: Don't null out t.next or t.prev because opApply currently
- // follows t.next after removing a node. This could be easily
- // addressed by simply returning the next node from this
- // function, however, a thread should never be re-added to the
- // list anyway and having next and prev be non-null is a good way
- // to ensure that.
- slock.unlock_nothrow();
- }
-}
-
-///
-unittest
-{
- class DerivedThread : Thread
- {
- this()
- {
- super(&run);
- }
-
- private:
- void run()
- {
- // Derived thread running.
- }
- }
-
- void threadFunc()
- {
- // Composed thread running.
- }
-
- // create and start instances of each type
- auto derived = new DerivedThread().start();
- auto composed = new Thread(&threadFunc).start();
- new Thread({
- // Codes to run in the newly created thread.
- }).start();
-}
-
-unittest
-{
- int x = 0;
-
- new Thread(
- {
- x++;
- }).start().join();
- assert( x == 1 );
-}
-
-
-unittest
-{
- enum MSG = "Test message.";
- string caughtMsg;
-
- try
- {
- new Thread(
- {
- throw new Exception( MSG );
- }).start().join();
- assert( false, "Expected rethrown exception." );
- }
- catch ( Throwable t )
- {
- assert( t.msg == MSG );
- }
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// GC Support Routines
-///////////////////////////////////////////////////////////////////////////////
-
-version (CoreDdoc)
-{
- /**
- * Instruct the thread module, when initialized, to use a different set of
- * signals besides SIGUSR1 and SIGUSR2 for suspension and resumption of threads.
- * This function should be called at most once, prior to thread_init().
- * This function is Posix-only.
- */
- extern (C) void thread_setGCSignals(int suspendSignalNo, int resumeSignalNo) nothrow @nogc
- {
- }
-}
-else version (Posix)
-{
- extern (C) void thread_setGCSignals(int suspendSignalNo, int resumeSignalNo) nothrow @nogc
- in
- {
- assert(suspendSignalNumber == 0);
- assert(resumeSignalNumber == 0);
- assert(suspendSignalNo != 0);
- assert(resumeSignalNo != 0);
- }
- out
- {
- assert(suspendSignalNumber != 0);
- assert(resumeSignalNumber != 0);
- }
- body
- {
- suspendSignalNumber = suspendSignalNo;
- resumeSignalNumber = resumeSignalNo;
- }
-}
-
-version (Posix)
-{
- __gshared int suspendSignalNumber;
- __gshared int resumeSignalNumber;
-}
-
-/**
- * Initializes the thread module. This function must be called by the
- * garbage collector on startup and before any other thread routines
- * are called.
- */
-extern (C) void thread_init()
-{
- // NOTE: If thread_init itself performs any allocations then the thread
- // routines reserved for garbage collector use may be called while
- // thread_init is being processed. However, since no memory should
- // exist to be scanned at this point, it is sufficient for these
- // functions to detect the condition and return immediately.
-
- Thread.initLocks();
- // The Android VM runtime intercepts SIGUSR1 and apparently doesn't allow
- // its signal handler to run, so swap the two signals on Android, since
- // thread_resumeHandler does nothing.
- version (Android) thread_setGCSignals(SIGUSR2, SIGUSR1);
-
- version (Darwin)
- {
- }
- else version (Posix)
- {
- if ( suspendSignalNumber == 0 )
- {
- suspendSignalNumber = SIGUSR1;
- }
-
- if ( resumeSignalNumber == 0 )
- {
- resumeSignalNumber = SIGUSR2;
- }
-
- int status;
- sigaction_t sigusr1 = void;
- sigaction_t sigusr2 = void;
-
- // This is a quick way to zero-initialize the structs without using
- // memset or creating a link dependency on their static initializer.
- (cast(byte*) &sigusr1)[0 .. sigaction_t.sizeof] = 0;
- (cast(byte*) &sigusr2)[0 .. sigaction_t.sizeof] = 0;
-
- // NOTE: SA_RESTART indicates that system calls should restart if they
- // are interrupted by a signal, but this is not available on all
- // Posix systems, even those that support multithreading.
- static if ( __traits( compiles, SA_RESTART ) )
- sigusr1.sa_flags = SA_RESTART;
- else
- sigusr1.sa_flags = 0;
- sigusr1.sa_handler = &thread_suspendHandler;
- // NOTE: We want to ignore all signals while in this handler, so fill
- // sa_mask to indicate this.
- status = sigfillset( &sigusr1.sa_mask );
- assert( status == 0 );
-
- // NOTE: Since resumeSignalNumber should only be issued for threads within the
- // suspend handler, we don't want this signal to trigger a
- // restart.
- sigusr2.sa_flags = 0;
- sigusr2.sa_handler = &thread_resumeHandler;
- // NOTE: We want to ignore all signals while in this handler, so fill
- // sa_mask to indicate this.
- status = sigfillset( &sigusr2.sa_mask );
- assert( status == 0 );
-
- status = sigaction( suspendSignalNumber, &sigusr1, null );
- assert( status == 0 );
-
- status = sigaction( resumeSignalNumber, &sigusr2, null );
- assert( status == 0 );
-
- status = sem_init( &suspendCount, 0, 0 );
- assert( status == 0 );
- }
- Thread.sm_main = thread_attachThis();
-}
-
-
-/**
- * Terminates the thread module. No other thread routine may be called
- * afterwards.
- */
-extern (C) void thread_term()
-{
- assert(Thread.sm_tbeg && Thread.sm_tlen == 1);
- assert(!Thread.nAboutToStart);
- if (Thread.pAboutToStart) // in case realloc(p, 0) doesn't return null
- {
- free(Thread.pAboutToStart);
- Thread.pAboutToStart = null;
- }
- Thread.termLocks();
-}
-
-
-/**
- *
- */
-extern (C) bool thread_isMainThread() nothrow @nogc
-{
- return Thread.getThis() is Thread.sm_main;
-}
-
-
-/**
- * Registers the calling thread for use with the D Runtime. If this routine
- * is called for a thread which is already registered, no action is performed.
- *
- * NOTE: This routine does not run thread-local static constructors when called.
- * If full functionality as a D thread is desired, the following function
- * must be called after thread_attachThis:
- *
- * extern (C) void rt_moduleTlsCtor();
- */
-extern (C) Thread thread_attachThis()
-{
- GC.disable(); scope(exit) GC.enable();
-
- if (auto t = Thread.getThis())
- return t;
-
- Thread thisThread = new Thread();
- Thread.Context* thisContext = &thisThread.m_main;
- assert( thisContext == thisThread.m_curr );
-
- version (Windows)
- {
- thisThread.m_addr = GetCurrentThreadId();
- thisThread.m_hndl = GetCurrentThreadHandle();
- thisContext.bstack = getStackBottom();
- thisContext.tstack = thisContext.bstack;
- }
- else version (Posix)
- {
- thisThread.m_addr = pthread_self();
- thisContext.bstack = getStackBottom();
- thisContext.tstack = thisContext.bstack;
-
- atomicStore!(MemoryOrder.raw)(thisThread.m_isRunning, true);
- }
- thisThread.m_isDaemon = true;
- thisThread.m_tlsgcdata = rt_tlsgc_init();
- Thread.setThis( thisThread );
-
- version (Darwin)
- {
- thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr );
- assert( thisThread.m_tmach != thisThread.m_tmach.init );
- }
-
- Thread.add( thisThread, false );
- Thread.add( thisContext );
- if ( Thread.sm_main !is null )
- multiThreadedFlag = true;
- return thisThread;
-}
-
-
-version (Windows)
-{
- // NOTE: These calls are not safe on Posix systems that use signals to
- // perform garbage collection. The suspendHandler uses getThis()
- // to get the thread handle so getThis() must be a simple call.
- // Mutexes can't safely be acquired inside signal handlers, and
- // even if they could, the mutex needed (Thread.slock) is held by
- // thread_suspendAll(). So in short, these routines will remain
- // Windows-specific. If they are truly needed elsewhere, the
- // suspendHandler will need a way to call a version of getThis()
- // that only does the TLS lookup without the fancy fallback stuff.
-
- /// ditto
- extern (C) Thread thread_attachByAddr( ThreadID addr )
- {
- return thread_attachByAddrB( addr, getThreadStackBottom( addr ) );
- }
-
-
- /// ditto
- extern (C) Thread thread_attachByAddrB( ThreadID addr, void* bstack )
- {
- GC.disable(); scope(exit) GC.enable();
-
- if (auto t = thread_findByAddr(addr))
- return t;
-
- Thread thisThread = new Thread();
- Thread.Context* thisContext = &thisThread.m_main;
- assert( thisContext == thisThread.m_curr );
-
- thisThread.m_addr = addr;
- thisContext.bstack = bstack;
- thisContext.tstack = thisContext.bstack;
-
- thisThread.m_isDaemon = true;
-
- if ( addr == GetCurrentThreadId() )
- {
- thisThread.m_hndl = GetCurrentThreadHandle();
- thisThread.m_tlsgcdata = rt_tlsgc_init();
- Thread.setThis( thisThread );
- }
- else
- {
- thisThread.m_hndl = OpenThreadHandle( addr );
- impersonate_thread(addr,
- {
- thisThread.m_tlsgcdata = rt_tlsgc_init();
- Thread.setThis( thisThread );
- });
- }
-
- Thread.add( thisThread, false );
- Thread.add( thisContext );
- if ( Thread.sm_main !is null )
- multiThreadedFlag = true;
- return thisThread;
- }
-}
-
-
-/**
- * Deregisters the calling thread from use with the runtime. If this routine
- * is called for a thread which is not registered, the result is undefined.
- *
- * NOTE: This routine does not run thread-local static destructors when called.
- * If full functionality as a D thread is desired, the following function
- * must be called after thread_detachThis, particularly if the thread is
- * being detached at some indeterminate time before program termination:
- *
- * $(D extern(C) void rt_moduleTlsDtor();)
- */
-extern (C) void thread_detachThis() nothrow @nogc
-{
- if (auto t = Thread.getThis())
- Thread.remove(t);
-}
-
-
-/**
- * Deregisters the given thread from use with the runtime. If this routine
- * is called for a thread which is not registered, the result is undefined.
- *
- * NOTE: This routine does not run thread-local static destructors when called.
- * If full functionality as a D thread is desired, the following function
- * must be called by the detached thread, particularly if the thread is
- * being detached at some indeterminate time before program termination:
- *
- * $(D extern(C) void rt_moduleTlsDtor();)
- */
-extern (C) void thread_detachByAddr( ThreadID addr )
-{
- if ( auto t = thread_findByAddr( addr ) )
- Thread.remove( t );
-}
-
-
-/// ditto
-extern (C) void thread_detachInstance( Thread t ) nothrow @nogc
-{
- Thread.remove( t );
-}
-
-
-unittest
-{
- import core.sync.semaphore;
- auto sem = new Semaphore();
-
- auto t = new Thread(
- {
- sem.notify();
- Thread.sleep(100.msecs);
- }).start();
-
- sem.wait(); // thread cannot be detached while being started
- thread_detachInstance(t);
- foreach (t2; Thread)
- assert(t !is t2);
- t.join();
-}
-
-
-/**
- * Search the list of all threads for a thread with the given thread identifier.
- *
- * Params:
- * addr = The thread identifier to search for.
- * Returns:
- * The thread object associated with the thread identifier, null if not found.
- */
-static Thread thread_findByAddr( ThreadID addr )
-{
- Thread.slock.lock_nothrow();
- scope(exit) Thread.slock.unlock_nothrow();
-
- // also return just spawned thread so that
- // DLL_THREAD_ATTACH knows it's a D thread
- foreach (t; Thread.pAboutToStart[0 .. Thread.nAboutToStart])
- if (t.m_addr == addr)
- return t;
-
- foreach (t; Thread)
- if (t.m_addr == addr)
- return t;
-
- return null;
-}
-
-
-/**
- * Sets the current thread to a specific reference. Only to be used
- * when dealing with externally-created threads (in e.g. C code).
- * The primary use of this function is when Thread.getThis() must
- * return a sensible value in, for example, TLS destructors. In
- * other words, don't touch this unless you know what you're doing.
- *
- * Params:
- * t = A reference to the current thread. May be null.
- */
-extern (C) void thread_setThis(Thread t) nothrow @nogc
-{
- Thread.setThis(t);
-}
-
-
-/**
- * Joins all non-daemon threads that are currently running. This is done by
- * performing successive scans through the thread list until a scan consists
- * of only daemon threads.
- */
-extern (C) void thread_joinAll()
-{
- Lagain:
- Thread.slock.lock_nothrow();
- // wait for just spawned threads
- if (Thread.nAboutToStart)
- {
- Thread.slock.unlock_nothrow();
- Thread.yield();
- goto Lagain;
- }
-
- // join all non-daemon threads, the main thread is also a daemon
- auto t = Thread.sm_tbeg;
- while (t)
- {
- if (!t.isRunning)
- {
- auto tn = t.next;
- Thread.remove(t);
- t = tn;
- }
- else if (t.isDaemon)
- {
- t = t.next;
- }
- else
- {
- Thread.slock.unlock_nothrow();
- t.join(); // might rethrow
- goto Lagain; // must restart iteration b/c of unlock
- }
- }
- Thread.slock.unlock_nothrow();
-}
-
-
-/**
- * Performs intermediate shutdown of the thread module.
- */
-shared static ~this()
-{
- // NOTE: The functionality related to garbage collection must be minimally
- // operable after this dtor completes. Therefore, only minimal
- // cleanup may occur.
- auto t = Thread.sm_tbeg;
- while (t)
- {
- auto tn = t.next;
- if (!t.isRunning)
- Thread.remove(t);
- t = tn;
- }
-}
-
-
-// Used for needLock below.
-private __gshared bool multiThreadedFlag = false;
-
-// Calls the given delegate, passing the current thread's stack pointer to it.
-private void callWithStackShell(scope void delegate(void* sp) nothrow fn) nothrow
-in
-{
- assert(fn);
-}
-body
-{
- // The purpose of the 'shell' is to ensure all the registers get
- // put on the stack so they'll be scanned. We only need to push
- // the callee-save registers.
- void *sp = void;
-
- version (GNU)
- {
- __builtin_unwind_init();
- sp = &sp;
- }
- else version (AsmX86_Posix)
- {
- size_t[3] regs = void;
- asm pure nothrow @nogc
- {
- mov [regs + 0 * 4], EBX;
- mov [regs + 1 * 4], ESI;
- mov [regs + 2 * 4], EDI;
-
- mov sp[EBP], ESP;
- }
- }
- else version (AsmX86_Windows)
- {
- size_t[3] regs = void;
- asm pure nothrow @nogc
- {
- mov [regs + 0 * 4], EBX;
- mov [regs + 1 * 4], ESI;
- mov [regs + 2 * 4], EDI;
-
- mov sp[EBP], ESP;
- }
- }
- else version (AsmX86_64_Posix)
- {
- size_t[5] regs = void;
- asm pure nothrow @nogc
- {
- mov [regs + 0 * 8], RBX;
- mov [regs + 1 * 8], R12;
- mov [regs + 2 * 8], R13;
- mov [regs + 3 * 8], R14;
- mov [regs + 4 * 8], R15;
-
- mov sp[RBP], RSP;
- }
- }
- else version (AsmX86_64_Windows)
- {
- size_t[7] regs = void;
- asm pure nothrow @nogc
- {
- mov [regs + 0 * 8], RBX;
- mov [regs + 1 * 8], RSI;
- mov [regs + 2 * 8], RDI;
- mov [regs + 3 * 8], R12;
- mov [regs + 4 * 8], R13;
- mov [regs + 5 * 8], R14;
- mov [regs + 6 * 8], R15;
-
- mov sp[RBP], RSP;
- }
- }
- else
- {
- static assert(false, "Architecture not supported.");
- }
-
- fn(sp);
-}
-
-// Used for suspendAll/resumeAll below.
-private __gshared uint suspendDepth = 0;
-
-/**
- * Suspend the specified thread and load stack and register information for
- * use by thread_scanAll. If the supplied thread is the calling thread,
- * stack and register information will be loaded but the thread will not
- * be suspended. If the suspend operation fails and the thread is not
- * running then it will be removed from the global thread list, otherwise
- * an exception will be thrown.
- *
- * Params:
- * t = The thread to suspend.
- *
- * Throws:
- * ThreadError if the suspend operation fails for a running thread.
- * Returns:
- * Whether the thread is now suspended (true) or terminated (false).
- */
-private bool suspend( Thread t ) nothrow
-{
- Duration waittime = dur!"usecs"(10);
- Lagain:
- if (!t.isRunning)
- {
- Thread.remove(t);
- return false;
- }
- else if (t.m_isInCriticalRegion)
- {
- Thread.criticalRegionLock.unlock_nothrow();
- Thread.sleep(waittime);
- if (waittime < dur!"msecs"(10)) waittime *= 2;
- Thread.criticalRegionLock.lock_nothrow();
- goto Lagain;
- }
-
- version (Windows)
- {
- if ( t.m_addr != GetCurrentThreadId() && SuspendThread( t.m_hndl ) == 0xFFFFFFFF )
- {
- if ( !t.isRunning )
- {
- Thread.remove( t );
- return false;
- }
- onThreadError( "Unable to suspend thread" );
- }
-
- CONTEXT context = void;
- context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
-
- if ( !GetThreadContext( t.m_hndl, &context ) )
- onThreadError( "Unable to load thread context" );
- version (X86)
- {
- if ( !t.m_lock )
- t.m_curr.tstack = cast(void*) context.Esp;
- // eax,ebx,ecx,edx,edi,esi,ebp,esp
- t.m_reg[0] = context.Eax;
- t.m_reg[1] = context.Ebx;
- t.m_reg[2] = context.Ecx;
- t.m_reg[3] = context.Edx;
- t.m_reg[4] = context.Edi;
- t.m_reg[5] = context.Esi;
- t.m_reg[6] = context.Ebp;
- t.m_reg[7] = context.Esp;
- }
- else version (X86_64)
- {
- if ( !t.m_lock )
- t.m_curr.tstack = cast(void*) context.Rsp;
- // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp
- t.m_reg[0] = context.Rax;
- t.m_reg[1] = context.Rbx;
- t.m_reg[2] = context.Rcx;
- t.m_reg[3] = context.Rdx;
- t.m_reg[4] = context.Rdi;
- t.m_reg[5] = context.Rsi;
- t.m_reg[6] = context.Rbp;
- t.m_reg[7] = context.Rsp;
- // r8,r9,r10,r11,r12,r13,r14,r15
- t.m_reg[8] = context.R8;
- t.m_reg[9] = context.R9;
- t.m_reg[10] = context.R10;
- t.m_reg[11] = context.R11;
- t.m_reg[12] = context.R12;
- t.m_reg[13] = context.R13;
- t.m_reg[14] = context.R14;
- t.m_reg[15] = context.R15;
- }
- else
- {
- static assert(false, "Architecture not supported." );
- }
- }
- else version (Darwin)
- {
- if ( t.m_addr != pthread_self() && thread_suspend( t.m_tmach ) != KERN_SUCCESS )
- {
- if ( !t.isRunning )
- {
- Thread.remove( t );
- return false;
- }
- onThreadError( "Unable to suspend thread" );
- }
-
- version (X86)
- {
- x86_thread_state32_t state = void;
- mach_msg_type_number_t count = x86_THREAD_STATE32_COUNT;
-
- if ( thread_get_state( t.m_tmach, x86_THREAD_STATE32, &state, &count ) != KERN_SUCCESS )
- onThreadError( "Unable to load thread state" );
- if ( !t.m_lock )
- t.m_curr.tstack = cast(void*) state.esp;
- // eax,ebx,ecx,edx,edi,esi,ebp,esp
- t.m_reg[0] = state.eax;
- t.m_reg[1] = state.ebx;
- t.m_reg[2] = state.ecx;
- t.m_reg[3] = state.edx;
- t.m_reg[4] = state.edi;
- t.m_reg[5] = state.esi;
- t.m_reg[6] = state.ebp;
- t.m_reg[7] = state.esp;
- }
- else version (X86_64)
- {
- x86_thread_state64_t state = void;
- mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
-
- if ( thread_get_state( t.m_tmach, x86_THREAD_STATE64, &state, &count ) != KERN_SUCCESS )
- onThreadError( "Unable to load thread state" );
- if ( !t.m_lock )
- t.m_curr.tstack = cast(void*) state.rsp;
- // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp
- t.m_reg[0] = state.rax;
- t.m_reg[1] = state.rbx;
- t.m_reg[2] = state.rcx;
- t.m_reg[3] = state.rdx;
- t.m_reg[4] = state.rdi;
- t.m_reg[5] = state.rsi;
- t.m_reg[6] = state.rbp;
- t.m_reg[7] = state.rsp;
- // r8,r9,r10,r11,r12,r13,r14,r15
- t.m_reg[8] = state.r8;
- t.m_reg[9] = state.r9;
- t.m_reg[10] = state.r10;
- t.m_reg[11] = state.r11;
- t.m_reg[12] = state.r12;
- t.m_reg[13] = state.r13;
- t.m_reg[14] = state.r14;
- t.m_reg[15] = state.r15;
- }
- else
- {
- static assert(false, "Architecture not supported." );
- }
- }
- else version (Posix)
- {
- if ( t.m_addr != pthread_self() )
- {
- if ( pthread_kill( t.m_addr, suspendSignalNumber ) != 0 )
- {
- if ( !t.isRunning )
- {
- Thread.remove( t );
- return false;
- }
- onThreadError( "Unable to suspend thread" );
- }
- }
- else if ( !t.m_lock )
- {
- t.m_curr.tstack = getStackTop();
- }
- }
- return true;
-}
-
-/**
- * Suspend all threads but the calling thread for "stop the world" garbage
- * collection runs. This function may be called multiple times, and must
- * be followed by a matching number of calls to thread_resumeAll before
- * processing is resumed.
- *
- * Throws:
- * ThreadError if the suspend operation fails for a running thread.
- */
-extern (C) void thread_suspendAll() nothrow
-{
- // NOTE: We've got an odd chicken & egg problem here, because while the GC
- // is required to call thread_init before calling any other thread
- // routines, thread_init may allocate memory which could in turn
- // trigger a collection. Thus, thread_suspendAll, thread_scanAll,
- // and thread_resumeAll must be callable before thread_init
- // completes, with the assumption that no other GC memory has yet
- // been allocated by the system, and thus there is no risk of losing
- // data if the global thread list is empty. The check of
- // Thread.sm_tbeg below is done to ensure thread_init has completed,
- // and therefore that calling Thread.getThis will not result in an
- // error. For the short time when Thread.sm_tbeg is null, there is
- // no reason not to simply call the multithreaded code below, with
- // the expectation that the foreach loop will never be entered.
- if ( !multiThreadedFlag && Thread.sm_tbeg )
- {
- if ( ++suspendDepth == 1 )
- suspend( Thread.getThis() );
-
- return;
- }
-
- Thread.slock.lock_nothrow();
- {
- if ( ++suspendDepth > 1 )
- return;
-
- Thread.criticalRegionLock.lock_nothrow();
- scope (exit) Thread.criticalRegionLock.unlock_nothrow();
- size_t cnt;
- auto t = Thread.sm_tbeg;
- while (t)
- {
- auto tn = t.next;
- if (suspend(t))
- ++cnt;
- t = tn;
- }
-
- version (Darwin)
- {}
- else version (Posix)
- {
- // subtract own thread
- assert(cnt >= 1);
- --cnt;
- Lagain:
- // wait for semaphore notifications
- for (; cnt; --cnt)
- {
- while (sem_wait(&suspendCount) != 0)
- {
- if (errno != EINTR)
- onThreadError("Unable to wait for semaphore");
- errno = 0;
- }
- }
- version (FreeBSD)
- {
- // avoid deadlocks, see Issue 13416
- t = Thread.sm_tbeg;
- while (t)
- {
- auto tn = t.next;
- if (t.m_suspendagain && suspend(t))
- ++cnt;
- t = tn;
- }
- if (cnt)
- goto Lagain;
- }
- }
- }
-}
-
-/**
- * Resume the specified thread and unload stack and register information.
- * If the supplied thread is the calling thread, stack and register
- * information will be unloaded but the thread will not be resumed. If
- * the resume operation fails and the thread is not running then it will
- * be removed from the global thread list, otherwise an exception will be
- * thrown.
- *
- * Params:
- * t = The thread to resume.
- *
- * Throws:
- * ThreadError if the resume fails for a running thread.
- */
-private void resume( Thread t ) nothrow
-{
- version (Windows)
- {
- if ( t.m_addr != GetCurrentThreadId() && ResumeThread( t.m_hndl ) == 0xFFFFFFFF )
- {
- if ( !t.isRunning )
- {
- Thread.remove( t );
- return;
- }
- onThreadError( "Unable to resume thread" );
- }
-
- if ( !t.m_lock )
- t.m_curr.tstack = t.m_curr.bstack;
- t.m_reg[0 .. $] = 0;
- }
- else version (Darwin)
- {
- if ( t.m_addr != pthread_self() && thread_resume( t.m_tmach ) != KERN_SUCCESS )
- {
- if ( !t.isRunning )
- {
- Thread.remove( t );
- return;
- }
- onThreadError( "Unable to resume thread" );
- }
-
- if ( !t.m_lock )
- t.m_curr.tstack = t.m_curr.bstack;
- t.m_reg[0 .. $] = 0;
- }
- else version (Posix)
- {
- if ( t.m_addr != pthread_self() )
- {
- if ( pthread_kill( t.m_addr, resumeSignalNumber ) != 0 )
- {
- if ( !t.isRunning )
- {
- Thread.remove( t );
- return;
- }
- onThreadError( "Unable to resume thread" );
- }
- }
- else if ( !t.m_lock )
- {
- t.m_curr.tstack = t.m_curr.bstack;
- }
- }
-}
-
-/**
- * Resume all threads but the calling thread for "stop the world" garbage
- * collection runs. This function must be called once for each preceding
- * call to thread_suspendAll before the threads are actually resumed.
- *
- * In:
- * This routine must be preceded by a call to thread_suspendAll.
- *
- * Throws:
- * ThreadError if the resume operation fails for a running thread.
- */
-extern (C) void thread_resumeAll() nothrow
-in
-{
- assert( suspendDepth > 0 );
-}
-body
-{
- // NOTE: See thread_suspendAll for the logic behind this.
- if ( !multiThreadedFlag && Thread.sm_tbeg )
- {
- if ( --suspendDepth == 0 )
- resume( Thread.getThis() );
- return;
- }
-
- scope(exit) Thread.slock.unlock_nothrow();
- {
- if ( --suspendDepth > 0 )
- return;
-
- for ( Thread t = Thread.sm_tbeg; t; t = t.next )
- {
- // NOTE: We do not need to care about critical regions at all
- // here. thread_suspendAll takes care of everything.
- resume( t );
- }
- }
-}
-
-/**
- * Indicates the kind of scan being performed by $(D thread_scanAllType).
- */
-enum ScanType
-{
- stack, /// The stack and/or registers are being scanned.
- tls, /// TLS data is being scanned.
-}
-
-alias ScanAllThreadsFn = void delegate(void*, void*) nothrow; /// The scanning function.
-alias ScanAllThreadsTypeFn = void delegate(ScanType, void*, void*) nothrow; /// ditto
-
-/**
- * The main entry point for garbage collection. The supplied delegate
- * will be passed ranges representing both stack and register values.
- *
- * Params:
- * scan = The scanner function. It should scan from p1 through p2 - 1.
- *
- * In:
- * This routine must be preceded by a call to thread_suspendAll.
- */
-extern (C) void thread_scanAllType( scope ScanAllThreadsTypeFn scan ) nothrow
-in
-{
- assert( suspendDepth > 0 );
-}
-body
-{
- callWithStackShell(sp => scanAllTypeImpl(scan, sp));
-}
-
-
-private void scanAllTypeImpl( scope ScanAllThreadsTypeFn scan, void* curStackTop ) nothrow
-{
- Thread thisThread = null;
- void* oldStackTop = null;
-
- if ( Thread.sm_tbeg )
- {
- thisThread = Thread.getThis();
- if ( !thisThread.m_lock )
- {
- oldStackTop = thisThread.m_curr.tstack;
- thisThread.m_curr.tstack = curStackTop;
- }
- }
-
- scope( exit )
- {
- if ( Thread.sm_tbeg )
- {
- if ( !thisThread.m_lock )
- {
- thisThread.m_curr.tstack = oldStackTop;
- }
- }
- }
-
- // NOTE: Synchronizing on Thread.slock is not needed because this
- // function may only be called after all other threads have
- // been suspended from within the same lock.
- if (Thread.nAboutToStart)
- scan(ScanType.stack, Thread.pAboutToStart, Thread.pAboutToStart + Thread.nAboutToStart);
-
- for ( Thread.Context* c = Thread.sm_cbeg; c; c = c.next )
- {
- version (StackGrowsDown)
- {
- // NOTE: We can't index past the bottom of the stack
- // so don't do the "+1" for StackGrowsDown.
- if ( c.tstack && c.tstack < c.bstack )
- scan( ScanType.stack, c.tstack, c.bstack );
- }
- else
- {
- if ( c.bstack && c.bstack < c.tstack )
- scan( ScanType.stack, c.bstack, c.tstack + 1 );
- }
- }
-
- for ( Thread t = Thread.sm_tbeg; t; t = t.next )
- {
- version (Windows)
- {
- // Ideally, we'd pass ScanType.regs or something like that, but this
- // would make portability annoying because it only makes sense on Windows.
- scan( ScanType.stack, t.m_reg.ptr, t.m_reg.ptr + t.m_reg.length );
- }
-
- if (t.m_tlsgcdata !is null)
- rt_tlsgc_scan(t.m_tlsgcdata, (p1, p2) => scan(ScanType.tls, p1, p2));
- }
-}
-
-/**
- * The main entry point for garbage collection. The supplied delegate
- * will be passed ranges representing both stack and register values.
- *
- * Params:
- * scan = The scanner function. It should scan from p1 through p2 - 1.
- *
- * In:
- * This routine must be preceded by a call to thread_suspendAll.
- */
-extern (C) void thread_scanAll( scope ScanAllThreadsFn scan ) nothrow
-{
- thread_scanAllType((type, p1, p2) => scan(p1, p2));
-}
-
-
-/**
- * Signals that the code following this call is a critical region. Any code in
- * this region must finish running before the calling thread can be suspended
- * by a call to thread_suspendAll.
- *
- * This function is, in particular, meant to help maintain garbage collector
- * invariants when a lock is not used.
- *
- * A critical region is exited with thread_exitCriticalRegion.
- *
- * $(RED Warning):
- * Using critical regions is extremely error-prone. For instance, using locks
- * inside a critical region can easily result in a deadlock when another thread
- * holding the lock already got suspended.
- *
- * The term and concept of a 'critical region' comes from
- * $(LINK2 https://github.com/mono/mono/blob/521f4a198e442573c400835ef19bbb36b60b0ebb/mono/metadata/sgen-gc.h#L925 Mono's SGen garbage collector).
- *
- * In:
- * The calling thread must be attached to the runtime.
- */
-extern (C) void thread_enterCriticalRegion() @nogc
-in
-{
- assert(Thread.getThis());
-}
-body
-{
- synchronized (Thread.criticalRegionLock)
- Thread.getThis().m_isInCriticalRegion = true;
-}
-
-
-/**
- * Signals that the calling thread is no longer in a critical region. Following
- * a call to this function, the thread can once again be suspended.
- *
- * In:
- * The calling thread must be attached to the runtime.
- */
-extern (C) void thread_exitCriticalRegion() @nogc
-in
-{
- assert(Thread.getThis());
-}
-body
-{
- synchronized (Thread.criticalRegionLock)
- Thread.getThis().m_isInCriticalRegion = false;
-}
-
-
-/**
- * Returns true if the current thread is in a critical region; otherwise, false.
- *
- * In:
- * The calling thread must be attached to the runtime.
- */
-extern (C) bool thread_inCriticalRegion() @nogc
-in
-{
- assert(Thread.getThis());
-}
-body
-{
- synchronized (Thread.criticalRegionLock)
- return Thread.getThis().m_isInCriticalRegion;
-}
-
-
-/**
-* A callback for thread errors in D during collections. Since an allocation is not possible
-* a preallocated ThreadError will be used as the Error instance
-*
-* Throws:
-* ThreadError.
-*/
-private void onThreadError(string msg = null, Throwable next = null) nothrow
-{
- __gshared ThreadError error = new ThreadError(null);
- error.msg = msg;
- error.next = next;
- import core.exception : SuppressTraceInfo;
- error.info = SuppressTraceInfo.instance;
- throw error;
-}
-
-
-unittest
-{
- assert(!thread_inCriticalRegion());
-
- {
- thread_enterCriticalRegion();
-
- scope (exit)
- thread_exitCriticalRegion();
-
- assert(thread_inCriticalRegion());
- }
-
- assert(!thread_inCriticalRegion());
-}
-
-unittest
-{
- // NOTE: This entire test is based on the assumption that no
- // memory is allocated after the child thread is
- // started. If an allocation happens, a collection could
- // trigger, which would cause the synchronization below
- // to cause a deadlock.
- // NOTE: DO NOT USE LOCKS IN CRITICAL REGIONS IN NORMAL CODE.
-
- import core.sync.semaphore;
-
- auto sema = new Semaphore(),
- semb = new Semaphore();
-
- auto thr = new Thread(
- {
- thread_enterCriticalRegion();
- assert(thread_inCriticalRegion());
- sema.notify();
-
- semb.wait();
- assert(thread_inCriticalRegion());
-
- thread_exitCriticalRegion();
- assert(!thread_inCriticalRegion());
- sema.notify();
-
- semb.wait();
- assert(!thread_inCriticalRegion());
- });
-
- thr.start();
-
- sema.wait();
- synchronized (Thread.criticalRegionLock)
- assert(thr.m_isInCriticalRegion);
- semb.notify();
-
- sema.wait();
- synchronized (Thread.criticalRegionLock)
- assert(!thr.m_isInCriticalRegion);
- semb.notify();
-
- thr.join();
-}
-
-unittest
-{
- import core.sync.semaphore;
-
- shared bool inCriticalRegion;
- auto sema = new Semaphore(),
- semb = new Semaphore();
-
- auto thr = new Thread(
- {
- thread_enterCriticalRegion();
- inCriticalRegion = true;
- sema.notify();
- semb.wait();
-
- Thread.sleep(dur!"msecs"(1));
- inCriticalRegion = false;
- thread_exitCriticalRegion();
- });
- thr.start();
-
- sema.wait();
- assert(inCriticalRegion);
- semb.notify();
-
- thread_suspendAll();
- assert(!inCriticalRegion);
- thread_resumeAll();
-}
-
-/**
- * Indicates whether an address has been marked by the GC.
- */
-enum IsMarked : int
-{
- no, /// Address is not marked.
- yes, /// Address is marked.
- unknown, /// Address is not managed by the GC.
-}
-
-alias IsMarkedDg = int delegate( void* addr ) nothrow; /// The isMarked callback function.
-
-/**
- * This routine allows the runtime to process any special per-thread handling
- * for the GC. This is needed for taking into account any memory that is
- * referenced by non-scanned pointers but is about to be freed. That currently
- * means the array append cache.
- *
- * Params:
- * isMarked = The function used to check if $(D addr) is marked.
- *
- * In:
- * This routine must be called just prior to resuming all threads.
- */
-extern(C) void thread_processGCMarks( scope IsMarkedDg isMarked ) nothrow
-{
- for ( Thread t = Thread.sm_tbeg; t; t = t.next )
- {
- /* Can be null if collection was triggered between adding a
- * thread and calling rt_tlsgc_init.
- */
- if (t.m_tlsgcdata !is null)
- rt_tlsgc_processGCMarks(t.m_tlsgcdata, isMarked);
- }
-}
-
-
-extern (C) @nogc nothrow
-{
- version (CRuntime_Glibc) int pthread_getattr_np(pthread_t thread, pthread_attr_t* attr);
- version (FreeBSD) int pthread_attr_get_np(pthread_t thread, pthread_attr_t* attr);
- version (NetBSD) int pthread_attr_get_np(pthread_t thread, pthread_attr_t* attr);
- version (OpenBSD) int pthread_stackseg_np(pthread_t thread, stack_t* sinfo);
- version (DragonFlyBSD) int pthread_attr_get_np(pthread_t thread, pthread_attr_t* attr);
- version (Solaris) int thr_stksegment(stack_t* stk);
- version (CRuntime_Bionic) int pthread_getattr_np(pthread_t thid, pthread_attr_t* attr);
- version (CRuntime_Musl) int pthread_getattr_np(pthread_t, pthread_attr_t*);
- version (CRuntime_UClibc) int pthread_getattr_np(pthread_t thread, pthread_attr_t* attr);
-}
-
-
-private void* getStackTop() nothrow @nogc
-{
- version (D_InlineAsm_X86)
- asm pure nothrow @nogc { naked; mov EAX, ESP; ret; }
- else version (D_InlineAsm_X86_64)
- asm pure nothrow @nogc { naked; mov RAX, RSP; ret; }
- else version (GNU)
- return __builtin_frame_address(0);
- else
- static assert(false, "Architecture not supported.");
-}
-
-
-private void* getStackBottom() nothrow @nogc
-{
- version (Windows)
- {
- version (D_InlineAsm_X86)
- asm pure nothrow @nogc { naked; mov EAX, FS:4; ret; }
- else version (D_InlineAsm_X86_64)
- asm pure nothrow @nogc
- { naked;
- mov RAX, 8;
- mov RAX, GS:[RAX];
- ret;
- }
- else version (GNU_InlineAsm)
- {
- void *bottom;
-
- version (X86)
- asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" bottom; }
- else version (X86_64)
- asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" bottom; }
- else
- static assert(false, "Platform not supported.");
-
- return bottom;
- }
- else
- static assert(false, "Architecture not supported.");
- }
- else version (Darwin)
- {
- import core.sys.darwin.pthread;
- return pthread_get_stackaddr_np(pthread_self());
- }
- else version (CRuntime_Glibc)
- {
- pthread_attr_t attr;
- void* addr; size_t size;
-
- pthread_getattr_np(pthread_self(), &attr);
- pthread_attr_getstack(&attr, &addr, &size);
- pthread_attr_destroy(&attr);
- version (StackGrowsDown)
- addr += size;
- return addr;
- }
- else version (FreeBSD)
- {
- pthread_attr_t attr;
- void* addr; size_t size;
-
- pthread_attr_init(&attr);
- pthread_attr_get_np(pthread_self(), &attr);
- pthread_attr_getstack(&attr, &addr, &size);
- pthread_attr_destroy(&attr);
- version (StackGrowsDown)
- addr += size;
- return addr;
- }
- else version (NetBSD)
- {
- pthread_attr_t attr;
- void* addr; size_t size;
-
- pthread_attr_init(&attr);
- pthread_attr_get_np(pthread_self(), &attr);
- pthread_attr_getstack(&attr, &addr, &size);
- pthread_attr_destroy(&attr);
- version (StackGrowsDown)
- addr += size;
- return addr;
- }
- else version (OpenBSD)
- {
- stack_t stk;
-
- pthread_stackseg_np(pthread_self(), &stk);
- return stk.ss_sp;
- }
- else version (DragonFlyBSD)
- {
- pthread_attr_t attr;
- void* addr; size_t size;
-
- pthread_attr_init(&attr);
- pthread_attr_get_np(pthread_self(), &attr);
- pthread_attr_getstack(&attr, &addr, &size);
- pthread_attr_destroy(&attr);
- version (StackGrowsDown)
- addr += size;
- return addr;
- }
- else version (Solaris)
- {
- stack_t stk;
-
- thr_stksegment(&stk);
- return stk.ss_sp;
- }
- else version (CRuntime_Bionic)
- {
- pthread_attr_t attr;
- void* addr; size_t size;
-
- pthread_getattr_np(pthread_self(), &attr);
- pthread_attr_getstack(&attr, &addr, &size);
- pthread_attr_destroy(&attr);
- version (StackGrowsDown)
- addr += size;
- return addr;
- }
- else version (CRuntime_Musl)
- {
- pthread_attr_t attr;
- void* addr; size_t size;
-
- pthread_getattr_np(pthread_self(), &attr);
- pthread_attr_getstack(&attr, &addr, &size);
- pthread_attr_destroy(&attr);
- version (StackGrowsDown)
- addr += size;
- return addr;
- }
- else version (CRuntime_UClibc)
- {
- pthread_attr_t attr;
- void* addr; size_t size;
-
- pthread_getattr_np(pthread_self(), &attr);
- pthread_attr_getstack(&attr, &addr, &size);
- pthread_attr_destroy(&attr);
- version (StackGrowsDown)
- addr += size;
- return addr;
- }
- else
- static assert(false, "Platform not supported.");
-}
-
-
-/**
- * Returns the stack top of the currently active stack within the calling
- * thread.
- *
- * In:
- * The calling thread must be attached to the runtime.
- *
- * Returns:
- * The address of the stack top.
- */
-extern (C) void* thread_stackTop() nothrow @nogc
-in
-{
- // Not strictly required, but it gives us more flexibility.
- assert(Thread.getThis());
-}
-body
-{
- return getStackTop();
-}
-
-
-/**
- * Returns the stack bottom of the currently active stack within the calling
- * thread.
- *
- * In:
- * The calling thread must be attached to the runtime.
- *
- * Returns:
- * The address of the stack bottom.
- */
-extern (C) void* thread_stackBottom() nothrow @nogc
-in
-{
- assert(Thread.getThis());
-}
-body
-{
- return Thread.getThis().topContext().bstack;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Thread Group
-///////////////////////////////////////////////////////////////////////////////
-
-
-/**
- * This class is intended to simplify certain common programming techniques.
- */
-class ThreadGroup
-{
- /**
- * Creates and starts a new Thread object that executes fn and adds it to
- * the list of tracked threads.
- *
- * Params:
- * fn = The thread function.
- *
- * Returns:
- * A reference to the newly created thread.
- */
- final Thread create( void function() fn )
- {
- Thread t = new Thread( fn ).start();
-
- synchronized( this )
- {
- m_all[t] = t;
- }
- return t;
- }
-
-
- /**
- * Creates and starts a new Thread object that executes dg and adds it to
- * the list of tracked threads.
- *
- * Params:
- * dg = The thread function.
- *
- * Returns:
- * A reference to the newly created thread.
- */
- final Thread create( void delegate() dg )
- {
- Thread t = new Thread( dg ).start();
-
- synchronized( this )
- {
- m_all[t] = t;
- }
- return t;
- }
-
-
- /**
- * Add t to the list of tracked threads if it is not already being tracked.
- *
- * Params:
- * t = The thread to add.
- *
- * In:
- * t must not be null.
- */
- final void add( Thread t )
- in
- {
- assert( t );
- }
- body
- {
- synchronized( this )
- {
- m_all[t] = t;
- }
- }
-
-
- /**
- * Removes t from the list of tracked threads. No operation will be
- * performed if t is not currently being tracked by this object.
- *
- * Params:
- * t = The thread to remove.
- *
- * In:
- * t must not be null.
- */
- final void remove( Thread t )
- in
- {
- assert( t );
- }
- body
- {
- synchronized( this )
- {
- m_all.remove( t );
- }
- }
-
-
- /**
- * Operates on all threads currently tracked by this object.
- */
- final int opApply( scope int delegate( ref Thread ) dg )
- {
- synchronized( this )
- {
- int ret = 0;
-
- // NOTE: This loop relies on the knowledge that m_all uses the
- // Thread object for both the key and the mapped value.
- foreach ( Thread t; m_all.keys )
- {
- ret = dg( t );
- if ( ret )
- break;
- }
- return ret;
- }
- }
-
-
- /**
- * Iteratively joins all tracked threads. This function will block add,
- * remove, and opApply until it completes.
- *
- * Params:
- * rethrow = Rethrow any unhandled exception which may have caused the
- * current thread to terminate.
- *
- * Throws:
- * Any exception not handled by the joined threads.
- */
- final void joinAll( bool rethrow = true )
- {
- synchronized( this )
- {
- // NOTE: This loop relies on the knowledge that m_all uses the
- // Thread object for both the key and the mapped value.
- foreach ( Thread t; m_all.keys )
- {
- t.join( rethrow );
- }
- }
- }
-
-
-private:
- Thread[Thread] m_all;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Fiber Platform Detection and Memory Allocation
-///////////////////////////////////////////////////////////////////////////////
-
-
-private
-{
- version (D_InlineAsm_X86)
- {
- version (Windows)
- version = AsmX86_Windows;
- else version (Posix)
- version = AsmX86_Posix;
-
- version (Darwin)
- version = AlignFiberStackTo16Byte;
- }
- else version (D_InlineAsm_X86_64)
- {
- version (Windows)
- {
- version = AsmX86_64_Windows;
- version = AlignFiberStackTo16Byte;
- }
- else version (Posix)
- {
- version = AsmX86_64_Posix;
- version = AlignFiberStackTo16Byte;
- }
- }
- else version (X86)
- {
- version = AlignFiberStackTo16Byte;
-
- version (CET)
- {
- // fiber_switchContext does not support shadow stack from
- // Intel CET. So use ucontext implementation.
- }
- else
- {
- version = AsmExternal;
-
- version (MinGW)
- version = GNU_AsmX86_Windows;
- else version (Posix)
- version = AsmX86_Posix;
- }
- }
- else version (X86_64)
- {
- version = AlignFiberStackTo16Byte;
-
- version (CET)
- {
- // fiber_switchContext does not support shadow stack from
- // Intel CET. So use ucontext implementation.
- }
- else version (D_X32)
- {
- // let X32 be handled by ucontext swapcontext
- }
- else
- {
- version = AsmExternal;
-
- version (MinGW)
- version = GNU_AsmX86_64_Windows;
- else version (Posix)
- version = AsmX86_64_Posix;
- }
- }
- else version (PPC)
- {
- version (Posix)
- {
- version = AsmPPC_Posix;
- version = AsmExternal;
- }
- }
- else version (PPC64)
- {
- version (Posix)
- {
- version = AlignFiberStackTo16Byte;
- }
- }
- else version (MIPS_O32)
- {
- version (Posix)
- {
- version = AsmMIPS_O32_Posix;
- version = AsmExternal;
- }
- }
- else version (AArch64)
- {
- version (Posix)
- {
- version = AsmAArch64_Posix;
- version = AsmExternal;
- version = AlignFiberStackTo16Byte;
- }
- }
- else version (ARM)
- {
- version (Posix)
- {
- version = AsmARM_Posix;
- version = AsmExternal;
- }
- }
- else version (SPARC)
- {
- // NOTE: The SPARC ABI specifies only doubleword alignment.
- version = AlignFiberStackTo16Byte;
- }
- else version (SPARC64)
- {
- version = AlignFiberStackTo16Byte;
- }
-
- version (Posix)
- {
- import core.sys.posix.unistd; // for sysconf
-
- version (AsmX86_Windows) {} else
- version (AsmX86_Posix) {} else
- version (AsmX86_64_Windows) {} else
- version (AsmX86_64_Posix) {} else
- version (AsmExternal) {} else
- {
- // NOTE: The ucontext implementation requires architecture specific
- // data definitions to operate so testing for it must be done
- // by checking for the existence of ucontext_t rather than by
- // a version identifier. Please note that this is considered
- // an obsolescent feature according to the POSIX spec, so a
- // custom solution is still preferred.
- import core.sys.posix.ucontext;
- }
- }
-
- static immutable size_t PAGESIZE;
- version (Posix) static immutable size_t PTHREAD_STACK_MIN;
-}
-
-
-shared static this()
-{
- version (Windows)
- {
- SYSTEM_INFO info;
- GetSystemInfo(&info);
-
- PAGESIZE = info.dwPageSize;
- assert(PAGESIZE < int.max);
- }
- else version (Posix)
- {
- PAGESIZE = cast(size_t)sysconf(_SC_PAGESIZE);
- PTHREAD_STACK_MIN = cast(size_t)sysconf(_SC_THREAD_STACK_MIN);
- }
- else
- {
- static assert(0, "unimplemented");
- }
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Fiber Entry Point and Context Switch
-///////////////////////////////////////////////////////////////////////////////
-
-
-private
-{
- extern (C) void fiber_entryPoint() nothrow
- {
- Fiber obj = Fiber.getThis();
- assert( obj );
-
- assert( Thread.getThis().m_curr is obj.m_ctxt );
- atomicStore!(MemoryOrder.raw)(*cast(shared)&Thread.getThis().m_lock, false);
- obj.m_ctxt.tstack = obj.m_ctxt.bstack;
- obj.m_state = Fiber.State.EXEC;
-
- try
- {
- obj.run();
- }
- catch ( Throwable t )
- {
- obj.m_unhandled = t;
- }
-
- static if ( __traits( compiles, ucontext_t ) )
- obj.m_ucur = &obj.m_utxt;
-
- obj.m_state = Fiber.State.TERM;
- obj.switchOut();
- }
-
- // Look above the definition of 'class Fiber' for some information about the implementation of this routine
- version (AsmExternal)
- {
- extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc;
- version (AArch64)
- extern (C) void fiber_trampoline() nothrow;
- }
- else
- extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc
- {
- // NOTE: The data pushed and popped in this routine must match the
- // default stack created by Fiber.initStack or the initial
- // switch into a new context will fail.
-
- version (AsmX86_Windows)
- {
- asm pure nothrow @nogc
- {
- naked;
-
- // save current stack state
- push EBP;
- mov EBP, ESP;
- push EDI;
- push ESI;
- push EBX;
- push dword ptr FS:[0];
- push dword ptr FS:[4];
- push dword ptr FS:[8];
- push EAX;
-
- // store oldp again with more accurate address
- mov EAX, dword ptr 8[EBP];
- mov [EAX], ESP;
- // load newp to begin context switch
- mov ESP, dword ptr 12[EBP];
-
- // load saved state from new stack
- pop EAX;
- pop dword ptr FS:[8];
- pop dword ptr FS:[4];
- pop dword ptr FS:[0];
- pop EBX;
- pop ESI;
- pop EDI;
- pop EBP;
-
- // 'return' to complete switch
- pop ECX;
- jmp ECX;
- }
- }
- else version (AsmX86_64_Windows)
- {
- asm pure nothrow @nogc
- {
- naked;
-
- // save current stack state
- // NOTE: When changing the layout of registers on the stack,
- // make sure that the XMM registers are still aligned.
- // On function entry, the stack is guaranteed to not
- // be aligned to 16 bytes because of the return address
- // on the stack.
- push RBP;
- mov RBP, RSP;
- push R12;
- push R13;
- push R14;
- push R15;
- push RDI;
- push RSI;
- // 7 registers = 56 bytes; stack is now aligned to 16 bytes
- sub RSP, 160;
- movdqa [RSP + 144], XMM6;
- movdqa [RSP + 128], XMM7;
- movdqa [RSP + 112], XMM8;
- movdqa [RSP + 96], XMM9;
- movdqa [RSP + 80], XMM10;
- movdqa [RSP + 64], XMM11;
- movdqa [RSP + 48], XMM12;
- movdqa [RSP + 32], XMM13;
- movdqa [RSP + 16], XMM14;
- movdqa [RSP], XMM15;
- push RBX;
- xor RAX,RAX;
- push qword ptr GS:[RAX];
- push qword ptr GS:8[RAX];
- push qword ptr GS:16[RAX];
-
- // store oldp
- mov [RCX], RSP;
- // load newp to begin context switch
- mov RSP, RDX;
-
- // load saved state from new stack
- pop qword ptr GS:16[RAX];
- pop qword ptr GS:8[RAX];
- pop qword ptr GS:[RAX];
- pop RBX;
- movdqa XMM15, [RSP];
- movdqa XMM14, [RSP + 16];
- movdqa XMM13, [RSP + 32];
- movdqa XMM12, [RSP + 48];
- movdqa XMM11, [RSP + 64];
- movdqa XMM10, [RSP + 80];
- movdqa XMM9, [RSP + 96];
- movdqa XMM8, [RSP + 112];
- movdqa XMM7, [RSP + 128];
- movdqa XMM6, [RSP + 144];
- add RSP, 160;
- pop RSI;
- pop RDI;
- pop R15;
- pop R14;
- pop R13;
- pop R12;
- pop RBP;
-
- // 'return' to complete switch
- pop RCX;
- jmp RCX;
- }
- }
- else version (AsmX86_Posix)
- {
- asm pure nothrow @nogc
- {
- naked;
-
- // save current stack state
- push EBP;
- mov EBP, ESP;
- push EDI;
- push ESI;
- push EBX;
- push EAX;
-
- // store oldp again with more accurate address
- mov EAX, dword ptr 8[EBP];
- mov [EAX], ESP;
- // load newp to begin context switch
- mov ESP, dword ptr 12[EBP];
-
- // load saved state from new stack
- pop EAX;
- pop EBX;
- pop ESI;
- pop EDI;
- pop EBP;
-
- // 'return' to complete switch
- pop ECX;
- jmp ECX;
- }
- }
- else version (AsmX86_64_Posix)
- {
- asm pure nothrow @nogc
- {
- naked;
-
- // save current stack state
- push RBP;
- mov RBP, RSP;
- push RBX;
- push R12;
- push R13;
- push R14;
- push R15;
-
- // store oldp
- mov [RDI], RSP;
- // load newp to begin context switch
- mov RSP, RSI;
-
- // load saved state from new stack
- pop R15;
- pop R14;
- pop R13;
- pop R12;
- pop RBX;
- pop RBP;
-
- // 'return' to complete switch
- pop RCX;
- jmp RCX;
- }
- }
- else static if ( __traits( compiles, ucontext_t ) )
- {
- Fiber cfib = Fiber.getThis();
- void* ucur = cfib.m_ucur;
-
- *oldp = &ucur;
- swapcontext( **(cast(ucontext_t***) oldp),
- *(cast(ucontext_t**) newp) );
- }
- else
- static assert(0, "Not implemented");
- }
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Fiber
-///////////////////////////////////////////////////////////////////////////////
-/*
- * Documentation of Fiber internals:
- *
- * The main routines to implement when porting Fibers to new architectures are
- * fiber_switchContext and initStack. Some version constants have to be defined
- * for the new platform as well, search for "Fiber Platform Detection and Memory Allocation".
- *
- * Fibers are based on a concept called 'Context'. A Context describes the execution
- * state of a Fiber or main thread which is fully described by the stack, some
- * registers and a return address at which the Fiber/Thread should continue executing.
- * Please note that not only each Fiber has a Context, but each thread also has got a
- * Context which describes the threads stack and state. If you call Fiber fib; fib.call
- * the first time in a thread you switch from Threads Context into the Fibers Context.
- * If you call fib.yield in that Fiber you switch out of the Fibers context and back
- * into the Thread Context. (However, this is not always the case. You can call a Fiber
- * from within another Fiber, then you switch Contexts between the Fibers and the Thread
- * Context is not involved)
- *
- * In all current implementations the registers and the return address are actually
- * saved on a Contexts stack.
- *
- * The fiber_switchContext routine has got two parameters:
- * void** a: This is the _location_ where we have to store the current stack pointer,
- * the stack pointer of the currently executing Context (Fiber or Thread).
- * void* b: This is the pointer to the stack of the Context which we want to switch into.
- * Note that we get the same pointer here as the one we stored into the void** a
- * in a previous call to fiber_switchContext.
- *
- * In the simplest case, a fiber_switchContext rountine looks like this:
- * fiber_switchContext:
- * push {return Address}
- * push {registers}
- * copy {stack pointer} into {location pointed to by a}
- * //We have now switch to the stack of a different Context!
- * copy {b} into {stack pointer}
- * pop {registers}
- * pop {return Address}
- * jump to {return Address}
- *
- * The GC uses the value returned in parameter a to scan the Fibers stack. It scans from
- * the stack base to that value. As the GC dislikes false pointers we can actually optimize
- * this a little: By storing registers which can not contain references to memory managed
- * by the GC outside of the region marked by the stack base pointer and the stack pointer
- * saved in fiber_switchContext we can prevent the GC from scanning them.
- * Such registers are usually floating point registers and the return address. In order to
- * implement this, we return a modified stack pointer from fiber_switchContext. However,
- * we have to remember that when we restore the registers from the stack!
- *
- * --------------------------- <= Stack Base
- * | Frame | <= Many other stack frames
- * | Frame |
- * |-------------------------| <= The last stack frame. This one is created by fiber_switchContext
- * | registers with pointers |
- * | | <= Stack pointer. GC stops scanning here
- * | return address |
- * |floating point registers |
- * --------------------------- <= Real Stack End
- *
- * fiber_switchContext:
- * push {registers with pointers}
- * copy {stack pointer} into {location pointed to by a}
- * push {return Address}
- * push {Floating point registers}
- * //We have now switch to the stack of a different Context!
- * copy {b} into {stack pointer}
- * //We now have to adjust the stack pointer to point to 'Real Stack End' so we can pop
- * //the FP registers
- * //+ or - depends on if your stack grows downwards or upwards
- * {stack pointer} = {stack pointer} +- ({FPRegisters}.sizeof + {return address}.sizeof}
- * pop {Floating point registers}
- * pop {return Address}
- * pop {registers with pointers}
- * jump to {return Address}
- *
- * So the question now is which registers need to be saved? This depends on the specific
- * architecture ABI of course, but here are some general guidelines:
- * - If a register is callee-save (if the callee modifies the register it must saved and
- * restored by the callee) it needs to be saved/restored in switchContext
- * - If a register is caller-save it needn't be saved/restored. (Calling fiber_switchContext
- * is a function call and the compiler therefore already must save these registers before
- * calling fiber_switchContext)
- * - Argument registers used for passing parameters to functions needn't be saved/restored
- * - The return register needn't be saved/restored (fiber_switchContext hasn't got a return type)
- * - All scratch registers needn't be saved/restored
- * - The link register usually needn't be saved/restored (but sometimes it must be cleared -
- * see below for details)
- * - The frame pointer register - if it exists - is usually callee-save
- * - All current implementations do not save control registers
- *
- * What happens on the first switch into a Fiber? We never saved a state for this fiber before,
- * but the initial state is prepared in the initStack routine. (This routine will also be called
- * when a Fiber is being resetted). initStack must produce exactly the same stack layout as the
- * part of fiber_switchContext which saves the registers. Pay special attention to set the stack
- * pointer correctly if you use the GC optimization mentioned before. the return Address saved in
- * initStack must be the address of fiber_entrypoint.
- *
- * There's now a small but important difference between the first context switch into a fiber and
- * further context switches. On the first switch, Fiber.call is used and the returnAddress in
- * fiber_switchContext will point to fiber_entrypoint. The important thing here is that this jump
- * is a _function call_, we call fiber_entrypoint by jumping before it's function prologue. On later
- * calls, the user used yield() in a function, and therefore the return address points into a user
- * function, after the yield call. So here the jump in fiber_switchContext is a _function return_,
- * not a function call!
- *
- * The most important result of this is that on entering a function, i.e. fiber_entrypoint, we
- * would have to provide a return address / set the link register once fiber_entrypoint
- * returns. Now fiber_entrypoint does never return and therefore the actual value of the return
- * address / link register is never read/used and therefore doesn't matter. When fiber_switchContext
- * performs a _function return_ the value in the link register doesn't matter either.
- * However, the link register will still be saved to the stack in fiber_entrypoint and some
- * exception handling / stack unwinding code might read it from this stack location and crash.
- * The exact solution depends on your architecture, but see the ARM implementation for a way
- * to deal with this issue.
- *
- * The ARM implementation is meant to be used as a kind of documented example implementation.
- * Look there for a concrete example.
- *
- * FIXME: fiber_entrypoint might benefit from a @noreturn attribute, but D doesn't have one.
- */
-
-/**
- * This class provides a cooperative concurrency mechanism integrated with the
- * threading and garbage collection functionality. Calling a fiber may be
- * considered a blocking operation that returns when the fiber yields (via
- * Fiber.yield()). Execution occurs within the context of the calling thread
- * so synchronization is not necessary to guarantee memory visibility so long
- * as the same thread calls the fiber each time. Please note that there is no
- * requirement that a fiber be bound to one specific thread. Rather, fibers
- * may be freely passed between threads so long as they are not currently
- * executing. Like threads, a new fiber thread may be created using either
- * derivation or composition, as in the following example.
- *
- * Warning:
- * Status registers are not saved by the current implementations. This means
- * floating point exception status bits (overflow, divide by 0), rounding mode
- * and similar stuff is set per-thread, not per Fiber!
- *
- * Warning:
- * On ARM FPU registers are not saved if druntime was compiled as ARM_SoftFloat.
- * If such a build is used on a ARM_SoftFP system which actually has got a FPU
- * and other libraries are using the FPU registers (other code is compiled
- * as ARM_SoftFP) this can cause problems. Druntime must be compiled as
- * ARM_SoftFP in this case.
- *
- * Example:
- * ----------------------------------------------------------------------
- *
- * class DerivedFiber : Fiber
- * {
- * this()
- * {
- * super( &run );
- * }
- *
- * private :
- * void run()
- * {
- * printf( "Derived fiber running.\n" );
- * }
- * }
- *
- * void fiberFunc()
- * {
- * printf( "Composed fiber running.\n" );
- * Fiber.yield();
- * printf( "Composed fiber running.\n" );
- * }
- *
- * // create instances of each type
- * Fiber derived = new DerivedFiber();
- * Fiber composed = new Fiber( &fiberFunc );
- *
- * // call both fibers once
- * derived.call();
- * composed.call();
- * printf( "Execution returned to calling context.\n" );
- * composed.call();
- *
- * // since each fiber has run to completion, each should have state TERM
- * assert( derived.state == Fiber.State.TERM );
- * assert( composed.state == Fiber.State.TERM );
- *
- * ----------------------------------------------------------------------
- *
- * Authors: Based on a design by Mikola Lysenko.
- */
-class Fiber
-{
- ///////////////////////////////////////////////////////////////////////////
- // Initialization
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Initializes a fiber object which is associated with a static
- * D function.
- *
- * Params:
- * fn = The fiber function.
- * sz = The stack size for this fiber.
- * guardPageSize = size of the guard page to trap fiber's stack
- * overflows
- *
- * In:
- * fn must not be null.
- */
- this( void function() fn, size_t sz = PAGESIZE*4,
- size_t guardPageSize = PAGESIZE ) nothrow
- in
- {
- assert( fn );
- }
- body
- {
- allocStack( sz, guardPageSize );
- reset( fn );
- }
-
-
- /**
- * Initializes a fiber object which is associated with a dynamic
- * D function.
- *
- * Params:
- * dg = The fiber function.
- * sz = The stack size for this fiber.
- * guardPageSize = size of the guard page to trap fiber's stack
- * overflows
- *
- * In:
- * dg must not be null.
- */
- this( void delegate() dg, size_t sz = PAGESIZE*4,
- size_t guardPageSize = PAGESIZE ) nothrow
- in
- {
- assert( dg );
- }
- body
- {
- allocStack( sz, guardPageSize);
- reset( dg );
- }
-
-
- /**
- * Cleans up any remaining resources used by this object.
- */
- ~this() nothrow @nogc
- {
- // NOTE: A live reference to this object will exist on its associated
- // stack from the first time its call() method has been called
- // until its execution completes with State.TERM. Thus, the only
- // times this dtor should be called are either if the fiber has
- // terminated (and therefore has no active stack) or if the user
- // explicitly deletes this object. The latter case is an error
- // but is not easily tested for, since State.HOLD may imply that
- // the fiber was just created but has never been run. There is
- // not a compelling case to create a State.INIT just to offer a
- // means of ensuring the user isn't violating this object's
- // contract, so for now this requirement will be enforced by
- // documentation only.
- freeStack();
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // General Actions
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Transfers execution to this fiber object. The calling context will be
- * suspended until the fiber calls Fiber.yield() or until it terminates
- * via an unhandled exception.
- *
- * Params:
- * rethrow = Rethrow any unhandled exception which may have caused this
- * fiber to terminate.
- *
- * In:
- * This fiber must be in state HOLD.
- *
- * Throws:
- * Any exception not handled by the joined thread.
- *
- * Returns:
- * Any exception not handled by this fiber if rethrow = false, null
- * otherwise.
- */
- // Not marked with any attributes, even though `nothrow @nogc` works
- // because it calls arbitrary user code. Most of the implementation
- // is already `@nogc nothrow`, but in order for `Fiber.call` to
- // propagate the attributes of the user's function, the Fiber
- // class needs to be templated.
- final Throwable call( Rethrow rethrow = Rethrow.yes )
- {
- return rethrow ? call!(Rethrow.yes)() : call!(Rethrow.no);
- }
-
- /// ditto
- final Throwable call( Rethrow rethrow )()
- {
- callImpl();
- if ( m_unhandled )
- {
- Throwable t = m_unhandled;
- m_unhandled = null;
- static if ( rethrow )
- throw t;
- else
- return t;
- }
- return null;
- }
-
- /// ditto
- deprecated("Please pass Fiber.Rethrow.yes or .no instead of a boolean.")
- final Throwable call( bool rethrow )
- {
- return rethrow ? call!(Rethrow.yes)() : call!(Rethrow.no);
- }
-
- private void callImpl() nothrow @nogc
- in
- {
- assert( m_state == State.HOLD );
- }
- body
- {
- Fiber cur = getThis();
-
- static if ( __traits( compiles, ucontext_t ) )
- m_ucur = cur ? &cur.m_utxt : &Fiber.sm_utxt;
-
- setThis( this );
- this.switchIn();
- setThis( cur );
-
- static if ( __traits( compiles, ucontext_t ) )
- m_ucur = null;
-
- // NOTE: If the fiber has terminated then the stack pointers must be
- // reset. This ensures that the stack for this fiber is not
- // scanned if the fiber has terminated. This is necessary to
- // prevent any references lingering on the stack from delaying
- // the collection of otherwise dead objects. The most notable
- // being the current object, which is referenced at the top of
- // fiber_entryPoint.
- if ( m_state == State.TERM )
- {
- m_ctxt.tstack = m_ctxt.bstack;
- }
- }
-
- /// Flag to control rethrow behavior of $(D $(LREF call))
- enum Rethrow : bool { no, yes }
-
- /**
- * Resets this fiber so that it may be re-used, optionally with a
- * new function/delegate. This routine should only be called for
- * fibers that have terminated, as doing otherwise could result in
- * scope-dependent functionality that is not executed.
- * Stack-based classes, for example, may not be cleaned up
- * properly if a fiber is reset before it has terminated.
- *
- * In:
- * This fiber must be in state TERM or HOLD.
- */
- final void reset() nothrow @nogc
- in
- {
- assert( m_state == State.TERM || m_state == State.HOLD );
- }
- body
- {
- m_ctxt.tstack = m_ctxt.bstack;
- m_state = State.HOLD;
- initStack();
- m_unhandled = null;
- }
-
- /// ditto
- final void reset( void function() fn ) nothrow @nogc
- {
- reset();
- m_fn = fn;
- m_call = Call.FN;
- }
-
- /// ditto
- final void reset( void delegate() dg ) nothrow @nogc
- {
- reset();
- m_dg = dg;
- m_call = Call.DG;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- // General Properties
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * A fiber may occupy one of three states: HOLD, EXEC, and TERM. The HOLD
- * state applies to any fiber that is suspended and ready to be called.
- * The EXEC state will be set for any fiber that is currently executing.
- * And the TERM state is set when a fiber terminates. Once a fiber
- * terminates, it must be reset before it may be called again.
- */
- enum State
- {
- HOLD, ///
- EXEC, ///
- TERM ///
- }
-
-
- /**
- * Gets the current state of this fiber.
- *
- * Returns:
- * The state of this fiber as an enumerated value.
- */
- final @property State state() const @safe pure nothrow @nogc
- {
- return m_state;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Actions on Calling Fiber
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Forces a context switch to occur away from the calling fiber.
- */
- static void yield() nothrow @nogc
- {
- Fiber cur = getThis();
- assert( cur, "Fiber.yield() called with no active fiber" );
- assert( cur.m_state == State.EXEC );
-
- static if ( __traits( compiles, ucontext_t ) )
- cur.m_ucur = &cur.m_utxt;
-
- cur.m_state = State.HOLD;
- cur.switchOut();
- cur.m_state = State.EXEC;
- }
-
-
- /**
- * Forces a context switch to occur away from the calling fiber and then
- * throws obj in the calling fiber.
- *
- * Params:
- * t = The object to throw.
- *
- * In:
- * t must not be null.
- */
- static void yieldAndThrow( Throwable t ) nothrow @nogc
- in
- {
- assert( t );
- }
- body
- {
- Fiber cur = getThis();
- assert( cur, "Fiber.yield() called with no active fiber" );
- assert( cur.m_state == State.EXEC );
-
- static if ( __traits( compiles, ucontext_t ) )
- cur.m_ucur = &cur.m_utxt;
-
- cur.m_unhandled = t;
- cur.m_state = State.HOLD;
- cur.switchOut();
- cur.m_state = State.EXEC;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Fiber Accessors
- ///////////////////////////////////////////////////////////////////////////
-
-
- /**
- * Provides a reference to the calling fiber or null if no fiber is
- * currently active.
- *
- * Returns:
- * The fiber object representing the calling fiber or null if no fiber
- * is currently active within this thread. The result of deleting this object is undefined.
- */
- static Fiber getThis() @safe nothrow @nogc
- {
- return sm_this;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////
- // Static Initialization
- ///////////////////////////////////////////////////////////////////////////
-
-
- version (Posix)
- {
- static this()
- {
- static if ( __traits( compiles, ucontext_t ) )
- {
- int status = getcontext( &sm_utxt );
- assert( status == 0 );
- }
- }
- }
-
-private:
- //
- // Initializes a fiber object which has no associated executable function.
- //
- this() @safe pure nothrow @nogc
- {
- m_call = Call.NO;
- }
-
-
- //
- // Fiber entry point. Invokes the function or delegate passed on
- // construction (if any).
- //
- final void run()
- {
- switch ( m_call )
- {
- case Call.FN:
- m_fn();
- break;
- case Call.DG:
- m_dg();
- break;
- default:
- break;
- }
- }
-
-
-private:
- //
- // The type of routine passed on fiber construction.
- //
- enum Call
- {
- NO,
- FN,
- DG
- }
-
-
- //
- // Standard fiber data
- //
- Call m_call;
- union
- {
- void function() m_fn;
- void delegate() m_dg;
- }
- bool m_isRunning;
- Throwable m_unhandled;
- State m_state;
-
-
-private:
- ///////////////////////////////////////////////////////////////////////////
- // Stack Management
- ///////////////////////////////////////////////////////////////////////////
-
-
- //
- // Allocate a new stack for this fiber.
- //
- final void allocStack( size_t sz, size_t guardPageSize ) nothrow
- in
- {
- assert( !m_pmem && !m_ctxt );
- }
- body
- {
- // adjust alloc size to a multiple of PAGESIZE
- sz += PAGESIZE - 1;
- sz -= sz % PAGESIZE;
-
- // NOTE: This instance of Thread.Context is dynamic so Fiber objects
- // can be collected by the GC so long as no user level references
- // to the object exist. If m_ctxt were not dynamic then its
- // presence in the global context list would be enough to keep
- // this object alive indefinitely. An alternative to allocating
- // room for this struct explicitly would be to mash it into the
- // base of the stack being allocated below. However, doing so
- // requires too much special logic to be worthwhile.
- m_ctxt = new Thread.Context;
-
- static if ( __traits( compiles, VirtualAlloc ) )
- {
- // reserve memory for stack
- m_pmem = VirtualAlloc( null,
- sz + guardPageSize,
- MEM_RESERVE,
- PAGE_NOACCESS );
- if ( !m_pmem )
- onOutOfMemoryError();
-
- version (StackGrowsDown)
- {
- void* stack = m_pmem + guardPageSize;
- void* guard = m_pmem;
- void* pbase = stack + sz;
- }
- else
- {
- void* stack = m_pmem;
- void* guard = m_pmem + sz;
- void* pbase = stack;
- }
-
- // allocate reserved stack segment
- stack = VirtualAlloc( stack,
- sz,
- MEM_COMMIT,
- PAGE_READWRITE );
- if ( !stack )
- onOutOfMemoryError();
-
- if (guardPageSize)
- {
- // allocate reserved guard page
- guard = VirtualAlloc( guard,
- guardPageSize,
- MEM_COMMIT,
- PAGE_READWRITE | PAGE_GUARD );
- if ( !guard )
- onOutOfMemoryError();
- }
-
- m_ctxt.bstack = pbase;
- m_ctxt.tstack = pbase;
- m_size = sz;
- }
- else
- {
- version (Posix) import core.sys.posix.sys.mman; // mmap
- version (FreeBSD) import core.sys.freebsd.sys.mman : MAP_ANON;
- version (NetBSD) import core.sys.netbsd.sys.mman : MAP_ANON;
- version (OpenBSD) import core.sys.openbsd.sys.mman : MAP_ANON;
- version (DragonFlyBSD) import core.sys.dragonflybsd.sys.mman : MAP_ANON;
- version (CRuntime_Glibc) import core.sys.linux.sys.mman : MAP_ANON;
- version (Darwin) import core.sys.darwin.sys.mman : MAP_ANON;
- version (CRuntime_UClibc) import core.sys.linux.sys.mman : MAP_ANON;
-
- static if ( __traits( compiles, mmap ) )
- {
- // Allocate more for the memory guard
- sz += guardPageSize;
-
- m_pmem = mmap( null,
- sz,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON,
- -1,
- 0 );
- if ( m_pmem == MAP_FAILED )
- m_pmem = null;
- }
- else static if ( __traits( compiles, valloc ) )
- {
- m_pmem = valloc( sz );
- }
- else static if ( __traits( compiles, malloc ) )
- {
- m_pmem = malloc( sz );
- }
- else
- {
- m_pmem = null;
- }
-
- if ( !m_pmem )
- onOutOfMemoryError();
-
- version (StackGrowsDown)
- {
- m_ctxt.bstack = m_pmem + sz;
- m_ctxt.tstack = m_pmem + sz;
- void* guard = m_pmem;
- }
- else
- {
- m_ctxt.bstack = m_pmem;
- m_ctxt.tstack = m_pmem;
- void* guard = m_pmem + sz - guardPageSize;
- }
- m_size = sz;
-
- static if ( __traits( compiles, mmap ) )
- {
- if (guardPageSize)
- {
- // protect end of stack
- if ( mprotect(guard, guardPageSize, PROT_NONE) == -1 )
- abort();
- }
- }
- else
- {
- // Supported only for mmap allocated memory - results are
- // undefined if applied to memory not obtained by mmap
- }
- }
-
- Thread.add( m_ctxt );
- }
-
-
- //
- // Free this fiber's stack.
- //
- final void freeStack() nothrow @nogc
- in
- {
- assert( m_pmem && m_ctxt );
- }
- body
- {
- // NOTE: m_ctxt is guaranteed to be alive because it is held in the
- // global context list.
- Thread.slock.lock_nothrow();
- scope(exit) Thread.slock.unlock_nothrow();
- Thread.remove( m_ctxt );
-
- static if ( __traits( compiles, VirtualAlloc ) )
- {
- VirtualFree( m_pmem, 0, MEM_RELEASE );
- }
- else
- {
- import core.sys.posix.sys.mman; // munmap
-
- static if ( __traits( compiles, mmap ) )
- {
- munmap( m_pmem, m_size );
- }
- else static if ( __traits( compiles, valloc ) )
- {
- free( m_pmem );
- }
- else static if ( __traits( compiles, malloc ) )
- {
- free( m_pmem );
- }
- }
- m_pmem = null;
- m_ctxt = null;
- }
-
-
- //
- // Initialize the allocated stack.
- // Look above the definition of 'class Fiber' for some information about the implementation of this routine
- //
- final void initStack() nothrow @nogc
- in
- {
- assert( m_ctxt.tstack && m_ctxt.tstack == m_ctxt.bstack );
- assert( cast(size_t) m_ctxt.bstack % (void*).sizeof == 0 );
- }
- body
- {
- void* pstack = m_ctxt.tstack;
- scope( exit ) m_ctxt.tstack = pstack;
-
- void push( size_t val ) nothrow
- {
- version (StackGrowsDown)
- {
- pstack -= size_t.sizeof;
- *(cast(size_t*) pstack) = val;
- }
- else
- {
- pstack += size_t.sizeof;
- *(cast(size_t*) pstack) = val;
- }
- }
-
- // NOTE: On OS X the stack must be 16-byte aligned according
- // to the IA-32 call spec. For x86_64 the stack also needs to
- // be aligned to 16-byte according to SysV AMD64 ABI.
- version (AlignFiberStackTo16Byte)
- {
- version (StackGrowsDown)
- {
- pstack = cast(void*)(cast(size_t)(pstack) - (cast(size_t)(pstack) & 0x0F));
- }
- else
- {
- pstack = cast(void*)(cast(size_t)(pstack) + (cast(size_t)(pstack) & 0x0F));
- }
- }
-
- version (AsmX86_Windows)
- {
- version (StackGrowsDown) {} else static assert( false );
-
- // On Windows Server 2008 and 2008 R2, an exploit mitigation
- // technique known as SEHOP is activated by default. To avoid
- // hijacking of the exception handler chain, the presence of a
- // Windows-internal handler (ntdll.dll!FinalExceptionHandler) at
- // its end is tested by RaiseException. If it is not present, all
- // handlers are disregarded, and the program is thus aborted
- // (see http://blogs.technet.com/b/srd/archive/2009/02/02/
- // preventing-the-exploitation-of-seh-overwrites-with-sehop.aspx).
- // For new threads, this handler is installed by Windows immediately
- // after creation. To make exception handling work in fibers, we
- // have to insert it for our new stacks manually as well.
- //
- // To do this, we first determine the handler by traversing the SEH
- // chain of the current thread until its end, and then construct a
- // registration block for the last handler on the newly created
- // thread. We then continue to push all the initial register values
- // for the first context switch as for the other implementations.
- //
- // Note that this handler is never actually invoked, as we install
- // our own one on top of it in the fiber entry point function.
- // Thus, it should not have any effects on OSes not implementing
- // exception chain verification.
-
- alias fp_t = void function(); // Actual signature not relevant.
- static struct EXCEPTION_REGISTRATION
- {
- EXCEPTION_REGISTRATION* next; // sehChainEnd if last one.
- fp_t handler;
- }
- enum sehChainEnd = cast(EXCEPTION_REGISTRATION*) 0xFFFFFFFF;
-
- __gshared static fp_t finalHandler = null;
- if ( finalHandler is null )
- {
- static EXCEPTION_REGISTRATION* fs0() nothrow
- {
- asm pure nothrow @nogc
- {
- naked;
- mov EAX, FS:[0];
- ret;
- }
- }
- auto reg = fs0();
- while ( reg.next != sehChainEnd ) reg = reg.next;
-
- // Benign races are okay here, just to avoid re-lookup on every
- // fiber creation.
- finalHandler = reg.handler;
- }
-
- // When linking with /safeseh (supported by LDC, but not DMD)
- // the exception chain must not extend to the very top
- // of the stack, otherwise the exception chain is also considered
- // invalid. Reserving additional 4 bytes at the top of the stack will
- // keep the EXCEPTION_REGISTRATION below that limit
- size_t reserve = EXCEPTION_REGISTRATION.sizeof + 4;
- pstack -= reserve;
- *(cast(EXCEPTION_REGISTRATION*)pstack) =
- EXCEPTION_REGISTRATION( sehChainEnd, finalHandler );
-
- push( cast(size_t) &fiber_entryPoint ); // EIP
- push( cast(size_t) m_ctxt.bstack - reserve ); // EBP
- push( 0x00000000 ); // EDI
- push( 0x00000000 ); // ESI
- push( 0x00000000 ); // EBX
- push( cast(size_t) m_ctxt.bstack - reserve ); // FS:[0]
- push( cast(size_t) m_ctxt.bstack ); // FS:[4]
- push( cast(size_t) m_ctxt.bstack - m_size ); // FS:[8]
- push( 0x00000000 ); // EAX
- }
- else version (AsmX86_64_Windows)
- {
- // Using this trampoline instead of the raw fiber_entryPoint
- // ensures that during context switches, source and destination
- // stacks have the same alignment. Otherwise, the stack would need
- // to be shifted by 8 bytes for the first call, as fiber_entryPoint
- // is an actual function expecting a stack which is not aligned
- // to 16 bytes.
- static void trampoline()
- {
- asm pure nothrow @nogc
- {
- naked;
- sub RSP, 32; // Shadow space (Win64 calling convention)
- call fiber_entryPoint;
- xor RCX, RCX; // This should never be reached, as
- jmp RCX; // fiber_entryPoint must never return.
- }
- }
-
- push( cast(size_t) &trampoline ); // RIP
- push( 0x00000000_00000000 ); // RBP
- push( 0x00000000_00000000 ); // R12
- push( 0x00000000_00000000 ); // R13
- push( 0x00000000_00000000 ); // R14
- push( 0x00000000_00000000 ); // R15
- push( 0x00000000_00000000 ); // RDI
- push( 0x00000000_00000000 ); // RSI
- push( 0x00000000_00000000 ); // XMM6 (high)
- push( 0x00000000_00000000 ); // XMM6 (low)
- push( 0x00000000_00000000 ); // XMM7 (high)
- push( 0x00000000_00000000 ); // XMM7 (low)
- push( 0x00000000_00000000 ); // XMM8 (high)
- push( 0x00000000_00000000 ); // XMM8 (low)
- push( 0x00000000_00000000 ); // XMM9 (high)
- push( 0x00000000_00000000 ); // XMM9 (low)
- push( 0x00000000_00000000 ); // XMM10 (high)
- push( 0x00000000_00000000 ); // XMM10 (low)
- push( 0x00000000_00000000 ); // XMM11 (high)
- push( 0x00000000_00000000 ); // XMM11 (low)
- push( 0x00000000_00000000 ); // XMM12 (high)
- push( 0x00000000_00000000 ); // XMM12 (low)
- push( 0x00000000_00000000 ); // XMM13 (high)
- push( 0x00000000_00000000 ); // XMM13 (low)
- push( 0x00000000_00000000 ); // XMM14 (high)
- push( 0x00000000_00000000 ); // XMM14 (low)
- push( 0x00000000_00000000 ); // XMM15 (high)
- push( 0x00000000_00000000 ); // XMM15 (low)
- push( 0x00000000_00000000 ); // RBX
- push( 0xFFFFFFFF_FFFFFFFF ); // GS:[0]
- version (StackGrowsDown)
- {
- push( cast(size_t) m_ctxt.bstack ); // GS:[8]
- push( cast(size_t) m_ctxt.bstack - m_size ); // GS:[16]
- }
- else
- {
- push( cast(size_t) m_ctxt.bstack ); // GS:[8]
- push( cast(size_t) m_ctxt.bstack + m_size ); // GS:[16]
- }
- }
- else version (AsmX86_Posix)
- {
- push( 0x00000000 ); // Return address of fiber_entryPoint call
- push( cast(size_t) &fiber_entryPoint ); // EIP
- push( cast(size_t) m_ctxt.bstack ); // EBP
- push( 0x00000000 ); // EDI
- push( 0x00000000 ); // ESI
- push( 0x00000000 ); // EBX
- push( 0x00000000 ); // EAX
- }
- else version (AsmX86_64_Posix)
- {
- push( 0x00000000_00000000 ); // Return address of fiber_entryPoint call
- push( cast(size_t) &fiber_entryPoint ); // RIP
- push( cast(size_t) m_ctxt.bstack ); // RBP
- push( 0x00000000_00000000 ); // RBX
- push( 0x00000000_00000000 ); // R12
- push( 0x00000000_00000000 ); // R13
- push( 0x00000000_00000000 ); // R14
- push( 0x00000000_00000000 ); // R15
- }
- else version (AsmPPC_Posix)
- {
- version (StackGrowsDown)
- {
- pstack -= int.sizeof * 5;
- }
- else
- {
- pstack += int.sizeof * 5;
- }
-
- push( cast(size_t) &fiber_entryPoint ); // link register
- push( 0x00000000 ); // control register
- push( 0x00000000 ); // old stack pointer
-
- // GPR values
- version (StackGrowsDown)
- {
- pstack -= int.sizeof * 20;
- }
- else
- {
- pstack += int.sizeof * 20;
- }
-
- assert( (cast(size_t) pstack & 0x0f) == 0 );
- }
- else version (AsmMIPS_O32_Posix)
- {
- version (StackGrowsDown) {}
- else static assert(0);
-
- /* We keep the FP registers and the return address below
- * the stack pointer, so they don't get scanned by the
- * GC. The last frame before swapping the stack pointer is
- * organized like the following.
- *
- * |-----------|<= frame pointer
- * | $gp |
- * | $s0-8 |
- * |-----------|<= stack pointer
- * | $ra |
- * | align(8) |
- * | $f20-30 |
- * |-----------|
- *
- */
- enum SZ_GP = 10 * size_t.sizeof; // $gp + $s0-8
- enum SZ_RA = size_t.sizeof; // $ra
- version (MIPS_HardFloat)
- {
- enum SZ_FP = 6 * 8; // $f20-30
- enum ALIGN = -(SZ_FP + SZ_RA) & (8 - 1);
- }
- else
- {
- enum SZ_FP = 0;
- enum ALIGN = 0;
- }
-
- enum BELOW = SZ_FP + ALIGN + SZ_RA;
- enum ABOVE = SZ_GP;
- enum SZ = BELOW + ABOVE;
-
- (cast(ubyte*)pstack - SZ)[0 .. SZ] = 0;
- pstack -= ABOVE;
- *cast(size_t*)(pstack - SZ_RA) = cast(size_t)&fiber_entryPoint;
- }
- else version (AsmAArch64_Posix)
- {
- // Like others, FP registers and return address (lr) are kept
- // below the saved stack top (tstack) to hide from GC scanning.
- // fiber_switchContext expects newp sp to look like this:
- // 19: x19
- // ...
- // 9: x29 (fp) <-- newp tstack
- // 8: x30 (lr) [&fiber_entryPoint]
- // 7: d8
- // ...
- // 0: d15
-
- version (StackGrowsDown) {}
- else
- static assert(false, "Only full descending stacks supported on AArch64");
-
- // Only need to set return address (lr). Everything else is fine
- // zero initialized.
- pstack -= size_t.sizeof * 11; // skip past x19-x29
- push(cast(size_t) &fiber_trampoline); // see threadasm.S for docs
- pstack += size_t.sizeof; // adjust sp (newp) above lr
- }
- else version (AsmARM_Posix)
- {
- /* We keep the FP registers and the return address below
- * the stack pointer, so they don't get scanned by the
- * GC. The last frame before swapping the stack pointer is
- * organized like the following.
- *
- * | |-----------|<= 'frame starts here'
- * | | fp | (the actual frame pointer, r11 isn't
- * | | r10-r4 | updated and still points to the previous frame)
- * | |-----------|<= stack pointer
- * | | lr |
- * | | 4byte pad |
- * | | d15-d8 |(if FP supported)
- * | |-----------|
- * Y
- * stack grows down: The pointer value here is smaller than some lines above
- */
- // frame pointer can be zero, r10-r4 also zero initialized
- version (StackGrowsDown)
- pstack -= int.sizeof * 8;
- else
- static assert(false, "Only full descending stacks supported on ARM");
-
- // link register
- push( cast(size_t) &fiber_entryPoint );
- /*
- * We do not push padding and d15-d8 as those are zero initialized anyway
- * Position the stack pointer above the lr register
- */
- pstack += int.sizeof * 1;
- }
- else version (GNU_AsmX86_Windows)
- {
- version (StackGrowsDown) {} else static assert( false );
-
- // Currently, MinGW doesn't utilize SEH exceptions.
- // See DMD AsmX86_Windows If this code ever becomes fails and SEH is used.
-
- push( 0x00000000 ); // Return address of fiber_entryPoint call
- push( cast(size_t) &fiber_entryPoint ); // EIP
- push( 0x00000000 ); // EBP
- push( 0x00000000 ); // EDI
- push( 0x00000000 ); // ESI
- push( 0x00000000 ); // EBX
- push( 0xFFFFFFFF ); // FS:[0] - Current SEH frame
- push( cast(size_t) m_ctxt.bstack ); // FS:[4] - Top of stack
- push( cast(size_t) m_ctxt.bstack - m_size ); // FS:[8] - Bottom of stack
- push( 0x00000000 ); // EAX
- }
- else version (GNU_AsmX86_64_Windows)
- {
- push( 0x00000000_00000000 ); // Return address of fiber_entryPoint call
- push( cast(size_t) &fiber_entryPoint ); // RIP
- push( 0x00000000_00000000 ); // RBP
- push( 0x00000000_00000000 ); // RBX
- push( 0x00000000_00000000 ); // R12
- push( 0x00000000_00000000 ); // R13
- push( 0x00000000_00000000 ); // R14
- push( 0x00000000_00000000 ); // R15
- push( 0xFFFFFFFF_FFFFFFFF ); // GS:[0] - Current SEH frame
- version (StackGrowsDown)
- {
- push( cast(size_t) m_ctxt.bstack ); // GS:[8] - Top of stack
- push( cast(size_t) m_ctxt.bstack - m_size ); // GS:[16] - Bottom of stack
- }
- else
- {
- push( cast(size_t) m_ctxt.bstack ); // GS:[8] - Top of stack
- push( cast(size_t) m_ctxt.bstack + m_size ); // GS:[16] - Bottom of stack
- }
- }
- else static if ( __traits( compiles, ucontext_t ) )
- {
- getcontext( &m_utxt );
- m_utxt.uc_stack.ss_sp = m_pmem;
- m_utxt.uc_stack.ss_size = m_size;
- makecontext( &m_utxt, &fiber_entryPoint, 0 );
- // NOTE: If ucontext is being used then the top of the stack will
- // be a pointer to the ucontext_t struct for that fiber.
- push( cast(size_t) &m_utxt );
- }
- else
- static assert(0, "Not implemented");
- }
-
-
- Thread.Context* m_ctxt;
- size_t m_size;
- void* m_pmem;
-
- static if ( __traits( compiles, ucontext_t ) )
- {
- // NOTE: The static ucontext instance is used to represent the context
- // of the executing thread.
- static ucontext_t sm_utxt = void;
- ucontext_t m_utxt = void;
- ucontext_t* m_ucur = null;
- }
- else static if (GNU_Enable_CET)
- {
- // When libphobos was built with --enable-cet, these fields need to
- // always be present in the Fiber class layout.
- import core.sys.posix.ucontext;
- static ucontext_t sm_utxt = void;
- ucontext_t m_utxt = void;
- ucontext_t* m_ucur = null;
- }
-
-
-private:
- ///////////////////////////////////////////////////////////////////////////
- // Storage of Active Fiber
- ///////////////////////////////////////////////////////////////////////////
-
-
- //
- // Sets a thread-local reference to the current fiber object.
- //
- static void setThis( Fiber f ) nothrow @nogc
- {
- sm_this = f;
- }
-
- static Fiber sm_this;
-
-
-private:
- ///////////////////////////////////////////////////////////////////////////
- // Context Switching
- ///////////////////////////////////////////////////////////////////////////
-
-
- //
- // Switches into the stack held by this fiber.
- //
- final void switchIn() nothrow @nogc
- {
- Thread tobj = Thread.getThis();
- void** oldp = &tobj.m_curr.tstack;
- void* newp = m_ctxt.tstack;
-
- // NOTE: The order of operations here is very important. The current
- // stack top must be stored before m_lock is set, and pushContext
- // must not be called until after m_lock is set. This process
- // is intended to prevent a race condition with the suspend
- // mechanism used for garbage collection. If it is not followed,
- // a badly timed collection could cause the GC to scan from the
- // bottom of one stack to the top of another, or to miss scanning
- // a stack that still contains valid data. The old stack pointer
- // oldp will be set again before the context switch to guarantee
- // that it points to exactly the correct stack location so the
- // successive pop operations will succeed.
- *oldp = getStackTop();
- atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, true);
- tobj.pushContext( m_ctxt );
-
- fiber_switchContext( oldp, newp );
-
- // NOTE: As above, these operations must be performed in a strict order
- // to prevent Bad Things from happening.
- tobj.popContext();
- atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
- tobj.m_curr.tstack = tobj.m_curr.bstack;
- }
-
-
- //
- // Switches out of the current stack and into the enclosing stack.
- //
- final void switchOut() nothrow @nogc
- {
- Thread tobj = Thread.getThis();
- void** oldp = &m_ctxt.tstack;
- void* newp = tobj.m_curr.within.tstack;
-
- // NOTE: The order of operations here is very important. The current
- // stack top must be stored before m_lock is set, and pushContext
- // must not be called until after m_lock is set. This process
- // is intended to prevent a race condition with the suspend
- // mechanism used for garbage collection. If it is not followed,
- // a badly timed collection could cause the GC to scan from the
- // bottom of one stack to the top of another, or to miss scanning
- // a stack that still contains valid data. The old stack pointer
- // oldp will be set again before the context switch to guarantee
- // that it points to exactly the correct stack location so the
- // successive pop operations will succeed.
- *oldp = getStackTop();
- atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, true);
-
- fiber_switchContext( oldp, newp );
-
- // NOTE: As above, these operations must be performed in a strict order
- // to prevent Bad Things from happening.
- // NOTE: If use of this fiber is multiplexed across threads, the thread
- // executing here may be different from the one above, so get the
- // current thread handle before unlocking, etc.
- tobj = Thread.getThis();
- atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
- tobj.m_curr.tstack = tobj.m_curr.bstack;
- }
-}
-
-
-version (unittest)
-{
- class TestFiber : Fiber
- {
- this()
- {
- super(&run);
- }
-
- void run()
- {
- foreach (i; 0 .. 1000)
- {
- sum += i;
- Fiber.yield();
- }
- }
-
- enum expSum = 1000 * 999 / 2;
- size_t sum;
- }
-
- void runTen()
- {
- TestFiber[10] fibs;
- foreach (ref fib; fibs)
- fib = new TestFiber();
-
- bool cont;
- do {
- cont = false;
- foreach (fib; fibs) {
- if (fib.state == Fiber.State.HOLD)
- {
- fib.call();
- cont |= fib.state != Fiber.State.TERM;
- }
- }
- } while (cont);
-
- foreach (fib; fibs)
- {
- assert(fib.sum == TestFiber.expSum);
- }
- }
-}
-
-
-// Single thread running separate fibers
-unittest
-{
- runTen();
-}
-
-
-// Multiple threads running separate fibers
-unittest
-{
- auto group = new ThreadGroup();
- foreach (_; 0 .. 4)
- {
- group.create(&runTen);
- }
- group.joinAll();
-}
-
-
-// Multiple threads running shared fibers
-version (PPC) version = UnsafeFiberMigration;
-version (PPC64) version = UnsafeFiberMigration;
-
-version (UnsafeFiberMigration)
-{
- // XBUG: core.thread fibers are supposed to be safe to migrate across
- // threads, however, there is a problem: GCC always assumes that the
- // address of thread-local variables don't change while on a given stack.
- // In consequence, migrating fibers between threads currently is an unsafe
- // thing to do, and will break on some targets (possibly PR26461).
-}
-else
-{
- version = FiberMigrationUnittest;
-}
-
-version (FiberMigrationUnittest)
-unittest
-{
- shared bool[10] locks;
- TestFiber[10] fibs;
-
- void runShared()
- {
- bool cont;
- do {
- cont = false;
- foreach (idx; 0 .. 10)
- {
- if (cas(&locks[idx], false, true))
- {
- if (fibs[idx].state == Fiber.State.HOLD)
- {
- fibs[idx].call();
- cont |= fibs[idx].state != Fiber.State.TERM;
- }
- locks[idx] = false;
- }
- else
- {
- cont = true;
- }
- }
- } while (cont);
- }
-
- foreach (ref fib; fibs)
- {
- fib = new TestFiber();
- }
-
- auto group = new ThreadGroup();
- foreach (_; 0 .. 4)
- {
- group.create(&runShared);
- }
- group.joinAll();
-
- foreach (fib; fibs)
- {
- assert(fib.sum == TestFiber.expSum);
- }
-}
-
-
-// Test exception handling inside fibers.
-version (Win32) {
- // broken on win32 under windows server 2012: bug 13821
-} else unittest {
- enum MSG = "Test message.";
- string caughtMsg;
- (new Fiber({
- try
- {
- throw new Exception(MSG);
- }
- catch (Exception e)
- {
- caughtMsg = e.msg;
- }
- })).call();
- assert(caughtMsg == MSG);
-}
-
-
-unittest
-{
- int x = 0;
-
- (new Fiber({
- x++;
- })).call();
- assert( x == 1 );
-}
-
-nothrow unittest
-{
- new Fiber({}).call!(Fiber.Rethrow.no)();
-}
-
-unittest
-{
- new Fiber({}).call(Fiber.Rethrow.yes);
- new Fiber({}).call(Fiber.Rethrow.no);
-}
-
-deprecated unittest
-{
- new Fiber({}).call(true);
- new Fiber({}).call(false);
-}
-
-version (Win32) {
- // broken on win32 under windows server 2012: bug 13821
-} else unittest {
- enum MSG = "Test message.";
-
- try
- {
- (new Fiber({
- throw new Exception( MSG );
- })).call();
- assert( false, "Expected rethrown exception." );
- }
- catch ( Throwable t )
- {
- assert( t.msg == MSG );
- }
-}
-
-// Test exception chaining when switching contexts in finally blocks.
-unittest
-{
- static void throwAndYield(string msg) {
- try {
- throw new Exception(msg);
- } finally {
- Fiber.yield();
- }
- }
-
- static void fiber(string name) {
- try {
- try {
- throwAndYield(name ~ ".1");
- } finally {
- throwAndYield(name ~ ".2");
- }
- } catch (Exception e) {
- assert(e.msg == name ~ ".1");
- assert(e.next);
- assert(e.next.msg == name ~ ".2");
- assert(!e.next.next);
- }
- }
-
- auto first = new Fiber(() => fiber("first"));
- auto second = new Fiber(() => fiber("second"));
- first.call();
- second.call();
- first.call();
- second.call();
- first.call();
- second.call();
- assert(first.state == Fiber.State.TERM);
- assert(second.state == Fiber.State.TERM);
-}
-
-// Test Fiber resetting
-unittest
-{
- static string method;
-
- static void foo()
- {
- method = "foo";
- }
-
- void bar()
- {
- method = "bar";
- }
-
- static void expect(Fiber fib, string s)
- {
- assert(fib.state == Fiber.State.HOLD);
- fib.call();
- assert(fib.state == Fiber.State.TERM);
- assert(method == s); method = null;
- }
- auto fib = new Fiber(&foo);
- expect(fib, "foo");
-
- fib.reset();
- expect(fib, "foo");
-
- fib.reset(&foo);
- expect(fib, "foo");
-
- fib.reset(&bar);
- expect(fib, "bar");
-
- fib.reset(function void(){method = "function";});
- expect(fib, "function");
-
- fib.reset(delegate void(){method = "delegate";});
- expect(fib, "delegate");
-}
-
-// Test unsafe reset in hold state
-unittest
-{
- auto fib = new Fiber(function {ubyte[2048] buf = void; Fiber.yield();}, 4096);
- foreach (_; 0 .. 10)
- {
- fib.call();
- assert(fib.state == Fiber.State.HOLD);
- fib.reset();
- }
-}
-
-// stress testing GC stack scanning
-unittest
-{
- import core.memory;
-
- static void unreferencedThreadObject()
- {
- static void sleep() { Thread.sleep(dur!"msecs"(100)); }
- auto thread = new Thread(&sleep).start();
- }
- unreferencedThreadObject();
- GC.collect();
-
- static class Foo
- {
- this(int value)
- {
- _value = value;
- }
-
- int bar()
- {
- return _value;
- }
-
- int _value;
- }
-
- static void collect()
- {
- auto foo = new Foo(2);
- assert(foo.bar() == 2);
- GC.collect();
- Fiber.yield();
- GC.collect();
- assert(foo.bar() == 2);
- }
-
- auto fiber = new Fiber(&collect);
-
- fiber.call();
- GC.collect();
- fiber.call();
-
- // thread reference
- auto foo = new Foo(2);
-
- void collect2()
- {
- assert(foo.bar() == 2);
- GC.collect();
- Fiber.yield();
- GC.collect();
- assert(foo.bar() == 2);
- }
-
- fiber = new Fiber(&collect2);
-
- fiber.call();
- GC.collect();
- fiber.call();
-
- static void recurse(size_t cnt)
- {
- --cnt;
- Fiber.yield();
- if (cnt)
- {
- auto fib = new Fiber(() { recurse(cnt); });
- fib.call();
- GC.collect();
- fib.call();
- }
- }
- fiber = new Fiber(() { recurse(20); });
- fiber.call();
-}
-
-
-version (AsmX86_64_Windows)
-{
- // Test Windows x64 calling convention
- unittest
- {
- void testNonvolatileRegister(alias REG)()
- {
- auto zeroRegister = new Fiber(() {
- mixin("asm pure nothrow @nogc { naked; xor "~REG~", "~REG~"; ret; }");
- });
- long after;
-
- mixin("asm pure nothrow @nogc { mov "~REG~", 0xFFFFFFFFFFFFFFFF; }");
- zeroRegister.call();
- mixin("asm pure nothrow @nogc { mov after, "~REG~"; }");
-
- assert(after == -1);
- }
-
- void testNonvolatileRegisterSSE(alias REG)()
- {
- auto zeroRegister = new Fiber(() {
- mixin("asm pure nothrow @nogc { naked; xorpd "~REG~", "~REG~"; ret; }");
- });
- long[2] before = [0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF], after;
-
- mixin("asm pure nothrow @nogc { movdqu "~REG~", before; }");
- zeroRegister.call();
- mixin("asm pure nothrow @nogc { movdqu after, "~REG~"; }");
-
- assert(before == after);
- }
-
- testNonvolatileRegister!("R12")();
- testNonvolatileRegister!("R13")();
- testNonvolatileRegister!("R14")();
- testNonvolatileRegister!("R15")();
- testNonvolatileRegister!("RDI")();
- testNonvolatileRegister!("RSI")();
- testNonvolatileRegister!("RBX")();
-
- testNonvolatileRegisterSSE!("XMM6")();
- testNonvolatileRegisterSSE!("XMM7")();
- testNonvolatileRegisterSSE!("XMM8")();
- testNonvolatileRegisterSSE!("XMM9")();
- testNonvolatileRegisterSSE!("XMM10")();
- testNonvolatileRegisterSSE!("XMM11")();
- testNonvolatileRegisterSSE!("XMM12")();
- testNonvolatileRegisterSSE!("XMM13")();
- testNonvolatileRegisterSSE!("XMM14")();
- testNonvolatileRegisterSSE!("XMM15")();
- }
-}
-
-
-version (D_InlineAsm_X86_64)
-{
- unittest
- {
- void testStackAlignment()
- {
- void* pRSP;
- asm pure nothrow @nogc
- {
- mov pRSP, RSP;
- }
- assert((cast(size_t)pRSP & 0xF) == 0);
- }
-
- auto fib = new Fiber(&testStackAlignment);
- fib.call();
- }
-}
-
-// regression test for Issue 13416
-version (FreeBSD) unittest
-{
- static void loop()
- {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- auto thr = pthread_self();
- foreach (i; 0 .. 50)
- pthread_attr_get_np(thr, &attr);
- pthread_attr_destroy(&attr);
- }
-
- auto thr = new Thread(&loop).start();
- foreach (i; 0 .. 50)
- {
- thread_suspendAll();
- thread_resumeAll();
- }
- thr.join();
-}
-
-version (DragonFlyBSD) unittest
-{
- static void loop()
- {
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- auto thr = pthread_self();
- foreach (i; 0 .. 50)
- pthread_attr_get_np(thr, &attr);
- pthread_attr_destroy(&attr);
- }
-
- auto thr = new Thread(&loop).start();
- foreach (i; 0 .. 50)
- {
- thread_suspendAll();
- thread_resumeAll();
- }
- thr.join();
-}
-
-unittest
-{
- // use >PAGESIZE to avoid stack overflow (e.g. in an syscall)
- auto thr = new Thread(function{}, 4096 + 1).start();
- thr.join();
-}
-
-/**
- * Represents the ID of a thread, as returned by $(D Thread.)$(LREF id).
- * The exact type varies from platform to platform.
- */
-version (Windows)
- alias ThreadID = uint;
-else
-version (Posix)
- alias ThreadID = pthread_t;
--- /dev/null
+/**
+ * The thread module provides support for thread creation and management.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2012.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
+ * Source: $(DRUNTIMESRC core/thread/package.d)
+ */
+
+module core.thread.context;
+
+struct StackContext
+{
+ void* bstack, tstack;
+
+ /// Slot for the EH implementation to keep some state for each stack
+ /// (will be necessary for exception chaining, etc.). Opaque as far as
+ /// we are concerned here.
+ void* ehContext;
+ StackContext* within;
+ StackContext* next, prev;
+}
+
+struct Callable
+{
+ void opAssign(void function() fn) pure nothrow @nogc @safe
+ {
+ () @trusted { m_fn = fn; }();
+ m_type = Call.FN;
+ }
+ void opAssign(void delegate() dg) pure nothrow @nogc @safe
+ {
+ () @trusted { m_dg = dg; }();
+ m_type = Call.DG;
+ }
+ void opCall()
+ {
+ switch (m_type)
+ {
+ case Call.FN:
+ m_fn();
+ break;
+ case Call.DG:
+ m_dg();
+ break;
+ default:
+ break;
+ }
+ }
+private:
+ enum Call
+ {
+ NO,
+ FN,
+ DG
+ }
+ Call m_type = Call.NO;
+ union
+ {
+ void function() m_fn;
+ void delegate() m_dg;
+ }
+}
--- /dev/null
+/**
+ * The fiber module provides OS-indepedent lightweight threads aka fibers.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2012.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
+ * Source: $(DRUNTIMESRC core/thread/fiber.d)
+ */
+
+/* NOTE: This file has been patched from the original DMD distribution to
+ * work with the GDC compiler.
+ */
+module core.thread.fiber;
+
+import core.thread.osthread;
+import core.thread.threadgroup;
+import core.thread.types;
+import core.thread.context;
+
+///////////////////////////////////////////////////////////////////////////////
+// Fiber Platform Detection
+///////////////////////////////////////////////////////////////////////////////
+
+version (GNU)
+{
+ import gcc.builtins;
+ import gcc.config;
+ version (GNU_StackGrowsDown)
+ version = StackGrowsDown;
+}
+else
+{
+ // this should be true for most architectures
+ version = StackGrowsDown;
+}
+
+version (Windows)
+{
+ import core.stdc.stdlib : malloc, free;
+ import core.sys.windows.winbase;
+ import core.sys.windows.winnt;
+}
+
+private
+{
+ version (D_InlineAsm_X86)
+ {
+ version (Windows)
+ version = AsmX86_Windows;
+ else version (Posix)
+ version = AsmX86_Posix;
+
+ version = AlignFiberStackTo16Byte;
+ }
+ else version (D_InlineAsm_X86_64)
+ {
+ version (Windows)
+ {
+ version = AsmX86_64_Windows;
+ version = AlignFiberStackTo16Byte;
+ }
+ else version (Posix)
+ {
+ version = AsmX86_64_Posix;
+ version = AlignFiberStackTo16Byte;
+ }
+ }
+ else version (X86)
+ {
+ version = AlignFiberStackTo16Byte;
+
+ version (CET)
+ {
+ // fiber_switchContext does not support shadow stack from
+ // Intel CET. So use ucontext implementation.
+ }
+ else
+ {
+ version = AsmExternal;
+
+ version (MinGW)
+ version = GNU_AsmX86_Windows;
+ else version (Posix)
+ version = AsmX86_Posix;
+ }
+ }
+ else version (X86_64)
+ {
+ version = AlignFiberStackTo16Byte;
+
+ version (CET)
+ {
+ // fiber_switchContext does not support shadow stack from
+ // Intel CET. So use ucontext implementation.
+ }
+ else version (D_X32)
+ {
+ // let X32 be handled by ucontext swapcontext
+ }
+ else
+ {
+ version = AsmExternal;
+
+ version (MinGW)
+ version = GNU_AsmX86_64_Windows;
+ else version (Posix)
+ version = AsmX86_64_Posix;
+ }
+ }
+ else version (PPC)
+ {
+ version (Posix)
+ {
+ version = AsmPPC_Posix;
+ version = AsmExternal;
+ }
+ }
+ else version (PPC64)
+ {
+ version (Posix)
+ {
+ version = AlignFiberStackTo16Byte;
+ }
+ }
+ else version (MIPS_O32)
+ {
+ version (Posix)
+ {
+ version = AsmMIPS_O32_Posix;
+ version = AsmExternal;
+ }
+ }
+ else version (AArch64)
+ {
+ version (Posix)
+ {
+ version = AsmAArch64_Posix;
+ version = AsmExternal;
+ version = AlignFiberStackTo16Byte;
+ }
+ }
+ else version (ARM)
+ {
+ version (Posix)
+ {
+ version = AsmARM_Posix;
+ version = AsmExternal;
+ }
+ }
+ else version (SPARC)
+ {
+ // NOTE: The SPARC ABI specifies only doubleword alignment.
+ version = AlignFiberStackTo16Byte;
+ }
+ else version (SPARC64)
+ {
+ version = AlignFiberStackTo16Byte;
+ }
+
+ version (Posix)
+ {
+ version (AsmX86_Windows) {} else
+ version (AsmX86_Posix) {} else
+ version (AsmX86_64_Windows) {} else
+ version (AsmX86_64_Posix) {} else
+ version (AsmExternal) {} else
+ {
+ // NOTE: The ucontext implementation requires architecture specific
+ // data definitions to operate so testing for it must be done
+ // by checking for the existence of ucontext_t rather than by
+ // a version identifier. Please note that this is considered
+ // an obsolescent feature according to the POSIX spec, so a
+ // custom solution is still preferred.
+ import core.sys.posix.ucontext;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Fiber Entry Point and Context Switch
+///////////////////////////////////////////////////////////////////////////////
+
+private
+{
+ import core.atomic : atomicStore, cas, MemoryOrder;
+ import core.exception : onOutOfMemoryError;
+ import core.stdc.stdlib : abort;
+
+ extern (C) void fiber_entryPoint() nothrow
+ {
+ Fiber obj = Fiber.getThis();
+ assert( obj );
+
+ assert( Thread.getThis().m_curr is obj.m_ctxt );
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&Thread.getThis().m_lock, false);
+ obj.m_ctxt.tstack = obj.m_ctxt.bstack;
+ obj.m_state = Fiber.State.EXEC;
+
+ try
+ {
+ obj.run();
+ }
+ catch ( Throwable t )
+ {
+ obj.m_unhandled = t;
+ }
+
+ static if ( __traits( compiles, ucontext_t ) )
+ obj.m_ucur = &obj.m_utxt;
+
+ obj.m_state = Fiber.State.TERM;
+ obj.switchOut();
+ }
+
+ // Look above the definition of 'class Fiber' for some information about the implementation of this routine
+ version (AsmExternal)
+ {
+ extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc;
+ version (AArch64)
+ extern (C) void fiber_trampoline() nothrow;
+ }
+ else
+ extern (C) void fiber_switchContext( void** oldp, void* newp ) nothrow @nogc
+ {
+ // NOTE: The data pushed and popped in this routine must match the
+ // default stack created by Fiber.initStack or the initial
+ // switch into a new context will fail.
+
+ version (AsmX86_Windows)
+ {
+ asm pure nothrow @nogc
+ {
+ naked;
+
+ // save current stack state
+ push EBP;
+ mov EBP, ESP;
+ push EDI;
+ push ESI;
+ push EBX;
+ push dword ptr FS:[0];
+ push dword ptr FS:[4];
+ push dword ptr FS:[8];
+ push EAX;
+
+ // store oldp again with more accurate address
+ mov EAX, dword ptr 8[EBP];
+ mov [EAX], ESP;
+ // load newp to begin context switch
+ mov ESP, dword ptr 12[EBP];
+
+ // load saved state from new stack
+ pop EAX;
+ pop dword ptr FS:[8];
+ pop dword ptr FS:[4];
+ pop dword ptr FS:[0];
+ pop EBX;
+ pop ESI;
+ pop EDI;
+ pop EBP;
+
+ // 'return' to complete switch
+ pop ECX;
+ jmp ECX;
+ }
+ }
+ else version (AsmX86_64_Windows)
+ {
+ asm pure nothrow @nogc
+ {
+ naked;
+
+ // save current stack state
+ // NOTE: When changing the layout of registers on the stack,
+ // make sure that the XMM registers are still aligned.
+ // On function entry, the stack is guaranteed to not
+ // be aligned to 16 bytes because of the return address
+ // on the stack.
+ push RBP;
+ mov RBP, RSP;
+ push R12;
+ push R13;
+ push R14;
+ push R15;
+ push RDI;
+ push RSI;
+ // 7 registers = 56 bytes; stack is now aligned to 16 bytes
+ sub RSP, 160;
+ movdqa [RSP + 144], XMM6;
+ movdqa [RSP + 128], XMM7;
+ movdqa [RSP + 112], XMM8;
+ movdqa [RSP + 96], XMM9;
+ movdqa [RSP + 80], XMM10;
+ movdqa [RSP + 64], XMM11;
+ movdqa [RSP + 48], XMM12;
+ movdqa [RSP + 32], XMM13;
+ movdqa [RSP + 16], XMM14;
+ movdqa [RSP], XMM15;
+ push RBX;
+ xor RAX,RAX;
+ push qword ptr GS:[RAX];
+ push qword ptr GS:8[RAX];
+ push qword ptr GS:16[RAX];
+
+ // store oldp
+ mov [RCX], RSP;
+ // load newp to begin context switch
+ mov RSP, RDX;
+
+ // load saved state from new stack
+ pop qword ptr GS:16[RAX];
+ pop qword ptr GS:8[RAX];
+ pop qword ptr GS:[RAX];
+ pop RBX;
+ movdqa XMM15, [RSP];
+ movdqa XMM14, [RSP + 16];
+ movdqa XMM13, [RSP + 32];
+ movdqa XMM12, [RSP + 48];
+ movdqa XMM11, [RSP + 64];
+ movdqa XMM10, [RSP + 80];
+ movdqa XMM9, [RSP + 96];
+ movdqa XMM8, [RSP + 112];
+ movdqa XMM7, [RSP + 128];
+ movdqa XMM6, [RSP + 144];
+ add RSP, 160;
+ pop RSI;
+ pop RDI;
+ pop R15;
+ pop R14;
+ pop R13;
+ pop R12;
+ pop RBP;
+
+ // 'return' to complete switch
+ pop RCX;
+ jmp RCX;
+ }
+ }
+ else version (AsmX86_Posix)
+ {
+ asm pure nothrow @nogc
+ {
+ naked;
+
+ // save current stack state
+ push EBP;
+ mov EBP, ESP;
+ push EDI;
+ push ESI;
+ push EBX;
+ push EAX;
+
+ // store oldp again with more accurate address
+ mov EAX, dword ptr 8[EBP];
+ mov [EAX], ESP;
+ // load newp to begin context switch
+ mov ESP, dword ptr 12[EBP];
+
+ // load saved state from new stack
+ pop EAX;
+ pop EBX;
+ pop ESI;
+ pop EDI;
+ pop EBP;
+
+ // 'return' to complete switch
+ pop ECX;
+ jmp ECX;
+ }
+ }
+ else version (AsmX86_64_Posix)
+ {
+ asm pure nothrow @nogc
+ {
+ naked;
+
+ // save current stack state
+ push RBP;
+ mov RBP, RSP;
+ push RBX;
+ push R12;
+ push R13;
+ push R14;
+ push R15;
+
+ // store oldp
+ mov [RDI], RSP;
+ // load newp to begin context switch
+ mov RSP, RSI;
+
+ // load saved state from new stack
+ pop R15;
+ pop R14;
+ pop R13;
+ pop R12;
+ pop RBX;
+ pop RBP;
+
+ // 'return' to complete switch
+ pop RCX;
+ jmp RCX;
+ }
+ }
+ else static if ( __traits( compiles, ucontext_t ) )
+ {
+ Fiber cfib = Fiber.getThis();
+ void* ucur = cfib.m_ucur;
+
+ *oldp = &ucur;
+ swapcontext( **(cast(ucontext_t***) oldp),
+ *(cast(ucontext_t**) newp) );
+ }
+ else
+ static assert(0, "Not implemented");
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Fiber
+///////////////////////////////////////////////////////////////////////////////
+/*
+ * Documentation of Fiber internals:
+ *
+ * The main routines to implement when porting Fibers to new architectures are
+ * fiber_switchContext and initStack. Some version constants have to be defined
+ * for the new platform as well, search for "Fiber Platform Detection and Memory Allocation".
+ *
+ * Fibers are based on a concept called 'Context'. A Context describes the execution
+ * state of a Fiber or main thread which is fully described by the stack, some
+ * registers and a return address at which the Fiber/Thread should continue executing.
+ * Please note that not only each Fiber has a Context, but each thread also has got a
+ * Context which describes the threads stack and state. If you call Fiber fib; fib.call
+ * the first time in a thread you switch from Threads Context into the Fibers Context.
+ * If you call fib.yield in that Fiber you switch out of the Fibers context and back
+ * into the Thread Context. (However, this is not always the case. You can call a Fiber
+ * from within another Fiber, then you switch Contexts between the Fibers and the Thread
+ * Context is not involved)
+ *
+ * In all current implementations the registers and the return address are actually
+ * saved on a Contexts stack.
+ *
+ * The fiber_switchContext routine has got two parameters:
+ * void** a: This is the _location_ where we have to store the current stack pointer,
+ * the stack pointer of the currently executing Context (Fiber or Thread).
+ * void* b: This is the pointer to the stack of the Context which we want to switch into.
+ * Note that we get the same pointer here as the one we stored into the void** a
+ * in a previous call to fiber_switchContext.
+ *
+ * In the simplest case, a fiber_switchContext rountine looks like this:
+ * fiber_switchContext:
+ * push {return Address}
+ * push {registers}
+ * copy {stack pointer} into {location pointed to by a}
+ * //We have now switch to the stack of a different Context!
+ * copy {b} into {stack pointer}
+ * pop {registers}
+ * pop {return Address}
+ * jump to {return Address}
+ *
+ * The GC uses the value returned in parameter a to scan the Fibers stack. It scans from
+ * the stack base to that value. As the GC dislikes false pointers we can actually optimize
+ * this a little: By storing registers which can not contain references to memory managed
+ * by the GC outside of the region marked by the stack base pointer and the stack pointer
+ * saved in fiber_switchContext we can prevent the GC from scanning them.
+ * Such registers are usually floating point registers and the return address. In order to
+ * implement this, we return a modified stack pointer from fiber_switchContext. However,
+ * we have to remember that when we restore the registers from the stack!
+ *
+ * --------------------------- <= Stack Base
+ * | Frame | <= Many other stack frames
+ * | Frame |
+ * |-------------------------| <= The last stack frame. This one is created by fiber_switchContext
+ * | registers with pointers |
+ * | | <= Stack pointer. GC stops scanning here
+ * | return address |
+ * |floating point registers |
+ * --------------------------- <= Real Stack End
+ *
+ * fiber_switchContext:
+ * push {registers with pointers}
+ * copy {stack pointer} into {location pointed to by a}
+ * push {return Address}
+ * push {Floating point registers}
+ * //We have now switch to the stack of a different Context!
+ * copy {b} into {stack pointer}
+ * //We now have to adjust the stack pointer to point to 'Real Stack End' so we can pop
+ * //the FP registers
+ * //+ or - depends on if your stack grows downwards or upwards
+ * {stack pointer} = {stack pointer} +- ({FPRegisters}.sizeof + {return address}.sizeof}
+ * pop {Floating point registers}
+ * pop {return Address}
+ * pop {registers with pointers}
+ * jump to {return Address}
+ *
+ * So the question now is which registers need to be saved? This depends on the specific
+ * architecture ABI of course, but here are some general guidelines:
+ * - If a register is callee-save (if the callee modifies the register it must saved and
+ * restored by the callee) it needs to be saved/restored in switchContext
+ * - If a register is caller-save it needn't be saved/restored. (Calling fiber_switchContext
+ * is a function call and the compiler therefore already must save these registers before
+ * calling fiber_switchContext)
+ * - Argument registers used for passing parameters to functions needn't be saved/restored
+ * - The return register needn't be saved/restored (fiber_switchContext hasn't got a return type)
+ * - All scratch registers needn't be saved/restored
+ * - The link register usually needn't be saved/restored (but sometimes it must be cleared -
+ * see below for details)
+ * - The frame pointer register - if it exists - is usually callee-save
+ * - All current implementations do not save control registers
+ *
+ * What happens on the first switch into a Fiber? We never saved a state for this fiber before,
+ * but the initial state is prepared in the initStack routine. (This routine will also be called
+ * when a Fiber is being resetted). initStack must produce exactly the same stack layout as the
+ * part of fiber_switchContext which saves the registers. Pay special attention to set the stack
+ * pointer correctly if you use the GC optimization mentioned before. the return Address saved in
+ * initStack must be the address of fiber_entrypoint.
+ *
+ * There's now a small but important difference between the first context switch into a fiber and
+ * further context switches. On the first switch, Fiber.call is used and the returnAddress in
+ * fiber_switchContext will point to fiber_entrypoint. The important thing here is that this jump
+ * is a _function call_, we call fiber_entrypoint by jumping before it's function prologue. On later
+ * calls, the user used yield() in a function, and therefore the return address points into a user
+ * function, after the yield call. So here the jump in fiber_switchContext is a _function return_,
+ * not a function call!
+ *
+ * The most important result of this is that on entering a function, i.e. fiber_entrypoint, we
+ * would have to provide a return address / set the link register once fiber_entrypoint
+ * returns. Now fiber_entrypoint does never return and therefore the actual value of the return
+ * address / link register is never read/used and therefore doesn't matter. When fiber_switchContext
+ * performs a _function return_ the value in the link register doesn't matter either.
+ * However, the link register will still be saved to the stack in fiber_entrypoint and some
+ * exception handling / stack unwinding code might read it from this stack location and crash.
+ * The exact solution depends on your architecture, but see the ARM implementation for a way
+ * to deal with this issue.
+ *
+ * The ARM implementation is meant to be used as a kind of documented example implementation.
+ * Look there for a concrete example.
+ *
+ * FIXME: fiber_entrypoint might benefit from a @noreturn attribute, but D doesn't have one.
+ */
+
+/**
+ * This class provides a cooperative concurrency mechanism integrated with the
+ * threading and garbage collection functionality. Calling a fiber may be
+ * considered a blocking operation that returns when the fiber yields (via
+ * Fiber.yield()). Execution occurs within the context of the calling thread
+ * so synchronization is not necessary to guarantee memory visibility so long
+ * as the same thread calls the fiber each time. Please note that there is no
+ * requirement that a fiber be bound to one specific thread. Rather, fibers
+ * may be freely passed between threads so long as they are not currently
+ * executing. Like threads, a new fiber thread may be created using either
+ * derivation or composition, as in the following example.
+ *
+ * Warning:
+ * Status registers are not saved by the current implementations. This means
+ * floating point exception status bits (overflow, divide by 0), rounding mode
+ * and similar stuff is set per-thread, not per Fiber!
+ *
+ * Warning:
+ * On ARM FPU registers are not saved if druntime was compiled as ARM_SoftFloat.
+ * If such a build is used on a ARM_SoftFP system which actually has got a FPU
+ * and other libraries are using the FPU registers (other code is compiled
+ * as ARM_SoftFP) this can cause problems. Druntime must be compiled as
+ * ARM_SoftFP in this case.
+ *
+ * Authors: Based on a design by Mikola Lysenko.
+ */
+class Fiber
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Initialization
+ ///////////////////////////////////////////////////////////////////////////
+
+ version (Windows)
+ // exception handling walks the stack, invoking DbgHelp.dll which
+ // needs up to 16k of stack space depending on the version of DbgHelp.dll,
+ // the existence of debug symbols and other conditions. Avoid causing
+ // stack overflows by defaulting to a larger stack size
+ enum defaultStackPages = 8;
+ else
+ enum defaultStackPages = 4;
+
+ /**
+ * Initializes a fiber object which is associated with a static
+ * D function.
+ *
+ * Params:
+ * fn = The fiber function.
+ * sz = The stack size for this fiber.
+ * guardPageSize = size of the guard page to trap fiber's stack
+ * overflows. Beware that using this will increase
+ * the number of mmaped regions on platforms using mmap
+ * so an OS-imposed limit may be hit.
+ *
+ * In:
+ * fn must not be null.
+ */
+ this( void function() fn, size_t sz = PAGESIZE * defaultStackPages,
+ size_t guardPageSize = PAGESIZE ) nothrow
+ in
+ {
+ assert( fn );
+ }
+ do
+ {
+ allocStack( sz, guardPageSize );
+ reset( fn );
+ }
+
+
+ /**
+ * Initializes a fiber object which is associated with a dynamic
+ * D function.
+ *
+ * Params:
+ * dg = The fiber function.
+ * sz = The stack size for this fiber.
+ * guardPageSize = size of the guard page to trap fiber's stack
+ * overflows. Beware that using this will increase
+ * the number of mmaped regions on platforms using mmap
+ * so an OS-imposed limit may be hit.
+ *
+ * In:
+ * dg must not be null.
+ */
+ this( void delegate() dg, size_t sz = PAGESIZE * defaultStackPages,
+ size_t guardPageSize = PAGESIZE ) nothrow
+ in
+ {
+ assert( dg );
+ }
+ do
+ {
+ allocStack( sz, guardPageSize );
+ reset( dg );
+ }
+
+
+ /**
+ * Cleans up any remaining resources used by this object.
+ */
+ ~this() nothrow @nogc
+ {
+ // NOTE: A live reference to this object will exist on its associated
+ // stack from the first time its call() method has been called
+ // until its execution completes with State.TERM. Thus, the only
+ // times this dtor should be called are either if the fiber has
+ // terminated (and therefore has no active stack) or if the user
+ // explicitly deletes this object. The latter case is an error
+ // but is not easily tested for, since State.HOLD may imply that
+ // the fiber was just created but has never been run. There is
+ // not a compelling case to create a State.INIT just to offer a
+ // means of ensuring the user isn't violating this object's
+ // contract, so for now this requirement will be enforced by
+ // documentation only.
+ freeStack();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // General Actions
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Transfers execution to this fiber object. The calling context will be
+ * suspended until the fiber calls Fiber.yield() or until it terminates
+ * via an unhandled exception.
+ *
+ * Params:
+ * rethrow = Rethrow any unhandled exception which may have caused this
+ * fiber to terminate.
+ *
+ * In:
+ * This fiber must be in state HOLD.
+ *
+ * Throws:
+ * Any exception not handled by the joined thread.
+ *
+ * Returns:
+ * Any exception not handled by this fiber if rethrow = false, null
+ * otherwise.
+ */
+ // Not marked with any attributes, even though `nothrow @nogc` works
+ // because it calls arbitrary user code. Most of the implementation
+ // is already `@nogc nothrow`, but in order for `Fiber.call` to
+ // propagate the attributes of the user's function, the Fiber
+ // class needs to be templated.
+ final Throwable call( Rethrow rethrow = Rethrow.yes )
+ {
+ return rethrow ? call!(Rethrow.yes)() : call!(Rethrow.no);
+ }
+
+ /// ditto
+ final Throwable call( Rethrow rethrow )()
+ {
+ callImpl();
+ if ( m_unhandled )
+ {
+ Throwable t = m_unhandled;
+ m_unhandled = null;
+ static if ( rethrow )
+ throw t;
+ else
+ return t;
+ }
+ return null;
+ }
+
+ private void callImpl() nothrow @nogc
+ in
+ {
+ assert( m_state == State.HOLD );
+ }
+ do
+ {
+ Fiber cur = getThis();
+
+ static if ( __traits( compiles, ucontext_t ) )
+ m_ucur = cur ? &cur.m_utxt : &Fiber.sm_utxt;
+
+ setThis( this );
+ this.switchIn();
+ setThis( cur );
+
+ static if ( __traits( compiles, ucontext_t ) )
+ m_ucur = null;
+
+ // NOTE: If the fiber has terminated then the stack pointers must be
+ // reset. This ensures that the stack for this fiber is not
+ // scanned if the fiber has terminated. This is necessary to
+ // prevent any references lingering on the stack from delaying
+ // the collection of otherwise dead objects. The most notable
+ // being the current object, which is referenced at the top of
+ // fiber_entryPoint.
+ if ( m_state == State.TERM )
+ {
+ m_ctxt.tstack = m_ctxt.bstack;
+ }
+ }
+
+ /// Flag to control rethrow behavior of $(D $(LREF call))
+ enum Rethrow : bool { no, yes }
+
+ /**
+ * Resets this fiber so that it may be re-used, optionally with a
+ * new function/delegate. This routine should only be called for
+ * fibers that have terminated, as doing otherwise could result in
+ * scope-dependent functionality that is not executed.
+ * Stack-based classes, for example, may not be cleaned up
+ * properly if a fiber is reset before it has terminated.
+ *
+ * In:
+ * This fiber must be in state TERM or HOLD.
+ */
+ final void reset() nothrow @nogc
+ in
+ {
+ assert( m_state == State.TERM || m_state == State.HOLD );
+ }
+ do
+ {
+ m_ctxt.tstack = m_ctxt.bstack;
+ m_state = State.HOLD;
+ initStack();
+ m_unhandled = null;
+ }
+
+ /// ditto
+ final void reset( void function() fn ) nothrow @nogc
+ {
+ reset();
+ m_call = fn;
+ }
+
+ /// ditto
+ final void reset( void delegate() dg ) nothrow @nogc
+ {
+ reset();
+ m_call = dg;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // General Properties
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /// A fiber may occupy one of three states: HOLD, EXEC, and TERM.
+ enum State
+ {
+ /** The HOLD state applies to any fiber that is suspended and ready to
+ be called. */
+ HOLD,
+ /** The EXEC state will be set for any fiber that is currently
+ executing. */
+ EXEC,
+ /** The TERM state is set when a fiber terminates. Once a fiber
+ terminates, it must be reset before it may be called again. */
+ TERM
+ }
+
+
+ /**
+ * Gets the current state of this fiber.
+ *
+ * Returns:
+ * The state of this fiber as an enumerated value.
+ */
+ final @property State state() const @safe pure nothrow @nogc
+ {
+ return m_state;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Actions on Calling Fiber
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Forces a context switch to occur away from the calling fiber.
+ */
+ static void yield() nothrow @nogc
+ {
+ Fiber cur = getThis();
+ assert( cur, "Fiber.yield() called with no active fiber" );
+ assert( cur.m_state == State.EXEC );
+
+ static if ( __traits( compiles, ucontext_t ) )
+ cur.m_ucur = &cur.m_utxt;
+
+ cur.m_state = State.HOLD;
+ cur.switchOut();
+ cur.m_state = State.EXEC;
+ }
+
+
+ /**
+ * Forces a context switch to occur away from the calling fiber and then
+ * throws obj in the calling fiber.
+ *
+ * Params:
+ * t = The object to throw.
+ *
+ * In:
+ * t must not be null.
+ */
+ static void yieldAndThrow( Throwable t ) nothrow @nogc
+ in
+ {
+ assert( t );
+ }
+ do
+ {
+ Fiber cur = getThis();
+ assert( cur, "Fiber.yield() called with no active fiber" );
+ assert( cur.m_state == State.EXEC );
+
+ static if ( __traits( compiles, ucontext_t ) )
+ cur.m_ucur = &cur.m_utxt;
+
+ cur.m_unhandled = t;
+ cur.m_state = State.HOLD;
+ cur.switchOut();
+ cur.m_state = State.EXEC;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Fiber Accessors
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Provides a reference to the calling fiber or null if no fiber is
+ * currently active.
+ *
+ * Returns:
+ * The fiber object representing the calling fiber or null if no fiber
+ * is currently active within this thread. The result of deleting this object is undefined.
+ */
+ static Fiber getThis() @safe nothrow @nogc
+ {
+ return sm_this;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Static Initialization
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ version (Posix)
+ {
+ static this()
+ {
+ static if ( __traits( compiles, ucontext_t ) )
+ {
+ int status = getcontext( &sm_utxt );
+ assert( status == 0 );
+ }
+ }
+ }
+
+private:
+
+ //
+ // Fiber entry point. Invokes the function or delegate passed on
+ // construction (if any).
+ //
+ final void run()
+ {
+ m_call();
+ }
+
+ //
+ // Standard fiber data
+ //
+ Callable m_call;
+ bool m_isRunning;
+ Throwable m_unhandled;
+ State m_state;
+
+
+private:
+ ///////////////////////////////////////////////////////////////////////////
+ // Stack Management
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Allocate a new stack for this fiber.
+ //
+ final void allocStack( size_t sz, size_t guardPageSize ) nothrow
+ in
+ {
+ assert( !m_pmem && !m_ctxt );
+ }
+ do
+ {
+ // adjust alloc size to a multiple of PAGESIZE
+ sz += PAGESIZE - 1;
+ sz -= sz % PAGESIZE;
+
+ // NOTE: This instance of Thread.Context is dynamic so Fiber objects
+ // can be collected by the GC so long as no user level references
+ // to the object exist. If m_ctxt were not dynamic then its
+ // presence in the global context list would be enough to keep
+ // this object alive indefinitely. An alternative to allocating
+ // room for this struct explicitly would be to mash it into the
+ // base of the stack being allocated below. However, doing so
+ // requires too much special logic to be worthwhile.
+ m_ctxt = new StackContext;
+
+ version (Windows)
+ {
+ // reserve memory for stack
+ m_pmem = VirtualAlloc( null,
+ sz + guardPageSize,
+ MEM_RESERVE,
+ PAGE_NOACCESS );
+ if ( !m_pmem )
+ onOutOfMemoryError();
+
+ version (StackGrowsDown)
+ {
+ void* stack = m_pmem + guardPageSize;
+ void* guard = m_pmem;
+ void* pbase = stack + sz;
+ }
+ else
+ {
+ void* stack = m_pmem;
+ void* guard = m_pmem + sz;
+ void* pbase = stack;
+ }
+
+ // allocate reserved stack segment
+ stack = VirtualAlloc( stack,
+ sz,
+ MEM_COMMIT,
+ PAGE_READWRITE );
+ if ( !stack )
+ onOutOfMemoryError();
+
+ if (guardPageSize)
+ {
+ // allocate reserved guard page
+ guard = VirtualAlloc( guard,
+ guardPageSize,
+ MEM_COMMIT,
+ PAGE_READWRITE | PAGE_GUARD );
+ if ( !guard )
+ onOutOfMemoryError();
+ }
+
+ m_ctxt.bstack = pbase;
+ m_ctxt.tstack = pbase;
+ m_size = sz;
+ }
+ else
+ {
+ version (Posix) import core.sys.posix.sys.mman; // mmap, MAP_ANON
+
+ static if ( __traits( compiles, ucontext_t ) )
+ {
+ // Stack size must be at least the minimum allowable by the OS.
+ if (sz < MINSIGSTKSZ)
+ sz = MINSIGSTKSZ;
+ }
+
+ static if ( __traits( compiles, mmap ) )
+ {
+ // Allocate more for the memory guard
+ sz += guardPageSize;
+
+ m_pmem = mmap( null,
+ sz,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0 );
+ if ( m_pmem == MAP_FAILED )
+ m_pmem = null;
+ }
+ else static if ( __traits( compiles, valloc ) )
+ {
+ m_pmem = valloc( sz );
+ }
+ else static if ( __traits( compiles, malloc ) )
+ {
+ m_pmem = malloc( sz );
+ }
+ else
+ {
+ m_pmem = null;
+ }
+
+ if ( !m_pmem )
+ onOutOfMemoryError();
+
+ version (StackGrowsDown)
+ {
+ m_ctxt.bstack = m_pmem + sz;
+ m_ctxt.tstack = m_pmem + sz;
+ void* guard = m_pmem;
+ }
+ else
+ {
+ m_ctxt.bstack = m_pmem;
+ m_ctxt.tstack = m_pmem;
+ void* guard = m_pmem + sz - guardPageSize;
+ }
+ m_size = sz;
+
+ static if ( __traits( compiles, mmap ) )
+ {
+ if (guardPageSize)
+ {
+ // protect end of stack
+ if ( mprotect(guard, guardPageSize, PROT_NONE) == -1 )
+ abort();
+ }
+ }
+ else
+ {
+ // Supported only for mmap allocated memory - results are
+ // undefined if applied to memory not obtained by mmap
+ }
+ }
+
+ Thread.add( m_ctxt );
+ }
+
+
+ //
+ // Free this fiber's stack.
+ //
+ final void freeStack() nothrow @nogc
+ in
+ {
+ assert( m_pmem && m_ctxt );
+ }
+ do
+ {
+ // NOTE: m_ctxt is guaranteed to be alive because it is held in the
+ // global context list.
+ Thread.slock.lock_nothrow();
+ scope(exit) Thread.slock.unlock_nothrow();
+ Thread.remove( m_ctxt );
+
+ version (Windows)
+ {
+ VirtualFree( m_pmem, 0, MEM_RELEASE );
+ }
+ else
+ {
+ import core.sys.posix.sys.mman; // munmap
+
+ static if ( __traits( compiles, mmap ) )
+ {
+ munmap( m_pmem, m_size );
+ }
+ else static if ( __traits( compiles, valloc ) )
+ {
+ free( m_pmem );
+ }
+ else static if ( __traits( compiles, malloc ) )
+ {
+ free( m_pmem );
+ }
+ }
+ m_pmem = null;
+ m_ctxt = null;
+ }
+
+
+ //
+ // Initialize the allocated stack.
+ // Look above the definition of 'class Fiber' for some information about the implementation of this routine
+ //
+ final void initStack() nothrow @nogc
+ in
+ {
+ assert( m_ctxt.tstack && m_ctxt.tstack == m_ctxt.bstack );
+ assert( cast(size_t) m_ctxt.bstack % (void*).sizeof == 0 );
+ }
+ do
+ {
+ void* pstack = m_ctxt.tstack;
+ scope( exit ) m_ctxt.tstack = pstack;
+
+ void push( size_t val ) nothrow
+ {
+ version (StackGrowsDown)
+ {
+ pstack -= size_t.sizeof;
+ *(cast(size_t*) pstack) = val;
+ }
+ else
+ {
+ pstack += size_t.sizeof;
+ *(cast(size_t*) pstack) = val;
+ }
+ }
+
+ // NOTE: On OS X the stack must be 16-byte aligned according
+ // to the IA-32 call spec. For x86_64 the stack also needs to
+ // be aligned to 16-byte according to SysV AMD64 ABI.
+ version (AlignFiberStackTo16Byte)
+ {
+ version (StackGrowsDown)
+ {
+ pstack = cast(void*)(cast(size_t)(pstack) - (cast(size_t)(pstack) & 0x0F));
+ }
+ else
+ {
+ pstack = cast(void*)(cast(size_t)(pstack) + (cast(size_t)(pstack) & 0x0F));
+ }
+ }
+
+ version (AsmX86_Windows)
+ {
+ version (StackGrowsDown) {} else static assert( false );
+
+ // On Windows Server 2008 and 2008 R2, an exploit mitigation
+ // technique known as SEHOP is activated by default. To avoid
+ // hijacking of the exception handler chain, the presence of a
+ // Windows-internal handler (ntdll.dll!FinalExceptionHandler) at
+ // its end is tested by RaiseException. If it is not present, all
+ // handlers are disregarded, and the program is thus aborted
+ // (see http://blogs.technet.com/b/srd/archive/2009/02/02/
+ // preventing-the-exploitation-of-seh-overwrites-with-sehop.aspx).
+ // For new threads, this handler is installed by Windows immediately
+ // after creation. To make exception handling work in fibers, we
+ // have to insert it for our new stacks manually as well.
+ //
+ // To do this, we first determine the handler by traversing the SEH
+ // chain of the current thread until its end, and then construct a
+ // registration block for the last handler on the newly created
+ // thread. We then continue to push all the initial register values
+ // for the first context switch as for the other implementations.
+ //
+ // Note that this handler is never actually invoked, as we install
+ // our own one on top of it in the fiber entry point function.
+ // Thus, it should not have any effects on OSes not implementing
+ // exception chain verification.
+
+ alias fp_t = void function(); // Actual signature not relevant.
+ static struct EXCEPTION_REGISTRATION
+ {
+ EXCEPTION_REGISTRATION* next; // sehChainEnd if last one.
+ fp_t handler;
+ }
+ enum sehChainEnd = cast(EXCEPTION_REGISTRATION*) 0xFFFFFFFF;
+
+ __gshared static fp_t finalHandler = null;
+ if ( finalHandler is null )
+ {
+ static EXCEPTION_REGISTRATION* fs0() nothrow
+ {
+ asm pure nothrow @nogc
+ {
+ naked;
+ mov EAX, FS:[0];
+ ret;
+ }
+ }
+ auto reg = fs0();
+ while ( reg.next != sehChainEnd ) reg = reg.next;
+
+ // Benign races are okay here, just to avoid re-lookup on every
+ // fiber creation.
+ finalHandler = reg.handler;
+ }
+
+ // When linking with /safeseh (supported by LDC, but not DMD)
+ // the exception chain must not extend to the very top
+ // of the stack, otherwise the exception chain is also considered
+ // invalid. Reserving additional 4 bytes at the top of the stack will
+ // keep the EXCEPTION_REGISTRATION below that limit
+ size_t reserve = EXCEPTION_REGISTRATION.sizeof + 4;
+ pstack -= reserve;
+ *(cast(EXCEPTION_REGISTRATION*)pstack) =
+ EXCEPTION_REGISTRATION( sehChainEnd, finalHandler );
+ auto pChainEnd = pstack;
+
+ push( cast(size_t) &fiber_entryPoint ); // EIP
+ push( cast(size_t) m_ctxt.bstack - reserve ); // EBP
+ push( 0x00000000 ); // EDI
+ push( 0x00000000 ); // ESI
+ push( 0x00000000 ); // EBX
+ push( cast(size_t) pChainEnd ); // FS:[0]
+ push( cast(size_t) m_ctxt.bstack ); // FS:[4]
+ push( cast(size_t) m_ctxt.bstack - m_size ); // FS:[8]
+ push( 0x00000000 ); // EAX
+ }
+ else version (AsmX86_64_Windows)
+ {
+ // Using this trampoline instead of the raw fiber_entryPoint
+ // ensures that during context switches, source and destination
+ // stacks have the same alignment. Otherwise, the stack would need
+ // to be shifted by 8 bytes for the first call, as fiber_entryPoint
+ // is an actual function expecting a stack which is not aligned
+ // to 16 bytes.
+ static void trampoline()
+ {
+ asm pure nothrow @nogc
+ {
+ naked;
+ sub RSP, 32; // Shadow space (Win64 calling convention)
+ call fiber_entryPoint;
+ xor RCX, RCX; // This should never be reached, as
+ jmp RCX; // fiber_entryPoint must never return.
+ }
+ }
+
+ push( cast(size_t) &trampoline ); // RIP
+ push( 0x00000000_00000000 ); // RBP
+ push( 0x00000000_00000000 ); // R12
+ push( 0x00000000_00000000 ); // R13
+ push( 0x00000000_00000000 ); // R14
+ push( 0x00000000_00000000 ); // R15
+ push( 0x00000000_00000000 ); // RDI
+ push( 0x00000000_00000000 ); // RSI
+ push( 0x00000000_00000000 ); // XMM6 (high)
+ push( 0x00000000_00000000 ); // XMM6 (low)
+ push( 0x00000000_00000000 ); // XMM7 (high)
+ push( 0x00000000_00000000 ); // XMM7 (low)
+ push( 0x00000000_00000000 ); // XMM8 (high)
+ push( 0x00000000_00000000 ); // XMM8 (low)
+ push( 0x00000000_00000000 ); // XMM9 (high)
+ push( 0x00000000_00000000 ); // XMM9 (low)
+ push( 0x00000000_00000000 ); // XMM10 (high)
+ push( 0x00000000_00000000 ); // XMM10 (low)
+ push( 0x00000000_00000000 ); // XMM11 (high)
+ push( 0x00000000_00000000 ); // XMM11 (low)
+ push( 0x00000000_00000000 ); // XMM12 (high)
+ push( 0x00000000_00000000 ); // XMM12 (low)
+ push( 0x00000000_00000000 ); // XMM13 (high)
+ push( 0x00000000_00000000 ); // XMM13 (low)
+ push( 0x00000000_00000000 ); // XMM14 (high)
+ push( 0x00000000_00000000 ); // XMM14 (low)
+ push( 0x00000000_00000000 ); // XMM15 (high)
+ push( 0x00000000_00000000 ); // XMM15 (low)
+ push( 0x00000000_00000000 ); // RBX
+ push( 0xFFFFFFFF_FFFFFFFF ); // GS:[0]
+ version (StackGrowsDown)
+ {
+ push( cast(size_t) m_ctxt.bstack ); // GS:[8]
+ push( cast(size_t) m_ctxt.bstack - m_size ); // GS:[16]
+ }
+ else
+ {
+ push( cast(size_t) m_ctxt.bstack ); // GS:[8]
+ push( cast(size_t) m_ctxt.bstack + m_size ); // GS:[16]
+ }
+ }
+ else version (AsmX86_Posix)
+ {
+ push( 0x00000000 ); // Return address of fiber_entryPoint call
+ push( cast(size_t) &fiber_entryPoint ); // EIP
+ push( cast(size_t) m_ctxt.bstack ); // EBP
+ push( 0x00000000 ); // EDI
+ push( 0x00000000 ); // ESI
+ push( 0x00000000 ); // EBX
+ push( 0x00000000 ); // EAX
+ }
+ else version (AsmX86_64_Posix)
+ {
+ push( 0x00000000_00000000 ); // Return address of fiber_entryPoint call
+ push( cast(size_t) &fiber_entryPoint ); // RIP
+ push( cast(size_t) m_ctxt.bstack ); // RBP
+ push( 0x00000000_00000000 ); // RBX
+ push( 0x00000000_00000000 ); // R12
+ push( 0x00000000_00000000 ); // R13
+ push( 0x00000000_00000000 ); // R14
+ push( 0x00000000_00000000 ); // R15
+ }
+ else version (AsmPPC_Posix)
+ {
+ version (StackGrowsDown)
+ {
+ pstack -= int.sizeof * 5;
+ }
+ else
+ {
+ pstack += int.sizeof * 5;
+ }
+
+ push( cast(size_t) &fiber_entryPoint ); // link register
+ push( 0x00000000 ); // control register
+ push( 0x00000000 ); // old stack pointer
+
+ // GPR values
+ version (StackGrowsDown)
+ {
+ pstack -= int.sizeof * 20;
+ }
+ else
+ {
+ pstack += int.sizeof * 20;
+ }
+
+ assert( (cast(size_t) pstack & 0x0f) == 0 );
+ }
+ else version (AsmMIPS_O32_Posix)
+ {
+ version (StackGrowsDown) {}
+ else static assert(0);
+
+ /* We keep the FP registers and the return address below
+ * the stack pointer, so they don't get scanned by the
+ * GC. The last frame before swapping the stack pointer is
+ * organized like the following.
+ *
+ * |-----------|<= frame pointer
+ * | $gp |
+ * | $s0-8 |
+ * |-----------|<= stack pointer
+ * | $ra |
+ * | align(8) |
+ * | $f20-30 |
+ * |-----------|
+ *
+ */
+ enum SZ_GP = 10 * size_t.sizeof; // $gp + $s0-8
+ enum SZ_RA = size_t.sizeof; // $ra
+ version (MIPS_HardFloat)
+ {
+ enum SZ_FP = 6 * 8; // $f20-30
+ enum ALIGN = -(SZ_FP + SZ_RA) & (8 - 1);
+ }
+ else
+ {
+ enum SZ_FP = 0;
+ enum ALIGN = 0;
+ }
+
+ enum BELOW = SZ_FP + ALIGN + SZ_RA;
+ enum ABOVE = SZ_GP;
+ enum SZ = BELOW + ABOVE;
+
+ (cast(ubyte*)pstack - SZ)[0 .. SZ] = 0;
+ pstack -= ABOVE;
+ *cast(size_t*)(pstack - SZ_RA) = cast(size_t)&fiber_entryPoint;
+ }
+ else version (AsmAArch64_Posix)
+ {
+ // Like others, FP registers and return address (lr) are kept
+ // below the saved stack top (tstack) to hide from GC scanning.
+ // fiber_switchContext expects newp sp to look like this:
+ // 19: x19
+ // ...
+ // 9: x29 (fp) <-- newp tstack
+ // 8: x30 (lr) [&fiber_entryPoint]
+ // 7: d8
+ // ...
+ // 0: d15
+
+ version (StackGrowsDown) {}
+ else
+ static assert(false, "Only full descending stacks supported on AArch64");
+
+ // Only need to set return address (lr). Everything else is fine
+ // zero initialized.
+ pstack -= size_t.sizeof * 11; // skip past x19-x29
+ push(cast(size_t) &fiber_trampoline); // see threadasm.S for docs
+ pstack += size_t.sizeof; // adjust sp (newp) above lr
+ }
+ else version (AsmARM_Posix)
+ {
+ /* We keep the FP registers and the return address below
+ * the stack pointer, so they don't get scanned by the
+ * GC. The last frame before swapping the stack pointer is
+ * organized like the following.
+ *
+ * | |-----------|<= 'frame starts here'
+ * | | fp | (the actual frame pointer, r11 isn't
+ * | | r10-r4 | updated and still points to the previous frame)
+ * | |-----------|<= stack pointer
+ * | | lr |
+ * | | 4byte pad |
+ * | | d15-d8 |(if FP supported)
+ * | |-----------|
+ * Y
+ * stack grows down: The pointer value here is smaller than some lines above
+ */
+ // frame pointer can be zero, r10-r4 also zero initialized
+ version (StackGrowsDown)
+ pstack -= int.sizeof * 8;
+ else
+ static assert(false, "Only full descending stacks supported on ARM");
+
+ // link register
+ push( cast(size_t) &fiber_entryPoint );
+ /*
+ * We do not push padding and d15-d8 as those are zero initialized anyway
+ * Position the stack pointer above the lr register
+ */
+ pstack += int.sizeof * 1;
+ }
+ else version (GNU_AsmX86_Windows)
+ {
+ version (StackGrowsDown) {} else static assert( false );
+
+ // Currently, MinGW doesn't utilize SEH exceptions.
+ // See DMD AsmX86_Windows If this code ever becomes fails and SEH is used.
+
+ push( 0x00000000 ); // Return address of fiber_entryPoint call
+ push( cast(size_t) &fiber_entryPoint ); // EIP
+ push( 0x00000000 ); // EBP
+ push( 0x00000000 ); // EDI
+ push( 0x00000000 ); // ESI
+ push( 0x00000000 ); // EBX
+ push( 0xFFFFFFFF ); // FS:[0] - Current SEH frame
+ push( cast(size_t) m_ctxt.bstack ); // FS:[4] - Top of stack
+ push( cast(size_t) m_ctxt.bstack - m_size ); // FS:[8] - Bottom of stack
+ push( 0x00000000 ); // EAX
+ }
+ else version (GNU_AsmX86_64_Windows)
+ {
+ push( 0x00000000_00000000 ); // Return address of fiber_entryPoint call
+ push( cast(size_t) &fiber_entryPoint ); // RIP
+ push( 0x00000000_00000000 ); // RBP
+ push( 0x00000000_00000000 ); // RBX
+ push( 0x00000000_00000000 ); // R12
+ push( 0x00000000_00000000 ); // R13
+ push( 0x00000000_00000000 ); // R14
+ push( 0x00000000_00000000 ); // R15
+ push( 0xFFFFFFFF_FFFFFFFF ); // GS:[0] - Current SEH frame
+ version (StackGrowsDown)
+ {
+ push( cast(size_t) m_ctxt.bstack ); // GS:[8] - Top of stack
+ push( cast(size_t) m_ctxt.bstack - m_size ); // GS:[16] - Bottom of stack
+ }
+ else
+ {
+ push( cast(size_t) m_ctxt.bstack ); // GS:[8] - Top of stack
+ push( cast(size_t) m_ctxt.bstack + m_size ); // GS:[16] - Bottom of stack
+ }
+ }
+ else static if ( __traits( compiles, ucontext_t ) )
+ {
+ getcontext( &m_utxt );
+ m_utxt.uc_stack.ss_sp = m_pmem;
+ m_utxt.uc_stack.ss_size = m_size;
+ makecontext( &m_utxt, &fiber_entryPoint, 0 );
+ // NOTE: If ucontext is being used then the top of the stack will
+ // be a pointer to the ucontext_t struct for that fiber.
+ push( cast(size_t) &m_utxt );
+ }
+ else
+ static assert(0, "Not implemented");
+ }
+
+
+ StackContext* m_ctxt;
+ size_t m_size;
+ void* m_pmem;
+
+ static if ( __traits( compiles, ucontext_t ) )
+ {
+ // NOTE: The static ucontext instance is used to represent the context
+ // of the executing thread.
+ static ucontext_t sm_utxt = void;
+ ucontext_t m_utxt = void;
+ ucontext_t* m_ucur = null;
+ }
+ else static if (GNU_Enable_CET)
+ {
+ // When libphobos was built with --enable-cet, these fields need to
+ // always be present in the Fiber class layout.
+ import core.sys.posix.ucontext;
+ static ucontext_t sm_utxt = void;
+ ucontext_t m_utxt = void;
+ ucontext_t* m_ucur = null;
+ }
+
+
+private:
+ ///////////////////////////////////////////////////////////////////////////
+ // Storage of Active Fiber
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Sets a thread-local reference to the current fiber object.
+ //
+ static void setThis( Fiber f ) nothrow @nogc
+ {
+ sm_this = f;
+ }
+
+ static Fiber sm_this;
+
+
+private:
+ ///////////////////////////////////////////////////////////////////////////
+ // Context Switching
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Switches into the stack held by this fiber.
+ //
+ final void switchIn() nothrow @nogc
+ {
+ Thread tobj = Thread.getThis();
+ void** oldp = &tobj.m_curr.tstack;
+ void* newp = m_ctxt.tstack;
+
+ // NOTE: The order of operations here is very important. The current
+ // stack top must be stored before m_lock is set, and pushContext
+ // must not be called until after m_lock is set. This process
+ // is intended to prevent a race condition with the suspend
+ // mechanism used for garbage collection. If it is not followed,
+ // a badly timed collection could cause the GC to scan from the
+ // bottom of one stack to the top of another, or to miss scanning
+ // a stack that still contains valid data. The old stack pointer
+ // oldp will be set again before the context switch to guarantee
+ // that it points to exactly the correct stack location so the
+ // successive pop operations will succeed.
+ *oldp = getStackTop();
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, true);
+ tobj.pushContext( m_ctxt );
+
+ fiber_switchContext( oldp, newp );
+
+ // NOTE: As above, these operations must be performed in a strict order
+ // to prevent Bad Things from happening.
+ tobj.popContext();
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
+ tobj.m_curr.tstack = tobj.m_curr.bstack;
+ }
+
+
+ //
+ // Switches out of the current stack and into the enclosing stack.
+ //
+ final void switchOut() nothrow @nogc
+ {
+ Thread tobj = Thread.getThis();
+ void** oldp = &m_ctxt.tstack;
+ void* newp = tobj.m_curr.within.tstack;
+
+ // NOTE: The order of operations here is very important. The current
+ // stack top must be stored before m_lock is set, and pushContext
+ // must not be called until after m_lock is set. This process
+ // is intended to prevent a race condition with the suspend
+ // mechanism used for garbage collection. If it is not followed,
+ // a badly timed collection could cause the GC to scan from the
+ // bottom of one stack to the top of another, or to miss scanning
+ // a stack that still contains valid data. The old stack pointer
+ // oldp will be set again before the context switch to guarantee
+ // that it points to exactly the correct stack location so the
+ // successive pop operations will succeed.
+ *oldp = getStackTop();
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, true);
+
+ fiber_switchContext( oldp, newp );
+
+ // NOTE: As above, these operations must be performed in a strict order
+ // to prevent Bad Things from happening.
+ // NOTE: If use of this fiber is multiplexed across threads, the thread
+ // executing here may be different from the one above, so get the
+ // current thread handle before unlocking, etc.
+ tobj = Thread.getThis();
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&tobj.m_lock, false);
+ tobj.m_curr.tstack = tobj.m_curr.bstack;
+ }
+}
+
+///
+unittest {
+ int counter;
+
+ class DerivedFiber : Fiber
+ {
+ this()
+ {
+ super( &run );
+ }
+
+ private :
+ void run()
+ {
+ counter += 2;
+ }
+ }
+
+ void fiberFunc()
+ {
+ counter += 4;
+ Fiber.yield();
+ counter += 8;
+ }
+
+ // create instances of each type
+ Fiber derived = new DerivedFiber();
+ Fiber composed = new Fiber( &fiberFunc );
+
+ assert( counter == 0 );
+
+ derived.call();
+ assert( counter == 2, "Derived fiber increment." );
+
+ composed.call();
+ assert( counter == 6, "First composed fiber increment." );
+
+ counter += 16;
+ assert( counter == 22, "Calling context increment." );
+
+ composed.call();
+ assert( counter == 30, "Second composed fiber increment." );
+
+ // since each fiber has run to completion, each should have state TERM
+ assert( derived.state == Fiber.State.TERM );
+ assert( composed.state == Fiber.State.TERM );
+}
+
+version (unittest)
+{
+ class TestFiber : Fiber
+ {
+ this()
+ {
+ super(&run);
+ }
+
+ void run()
+ {
+ foreach (i; 0 .. 1000)
+ {
+ sum += i;
+ Fiber.yield();
+ }
+ }
+
+ enum expSum = 1000 * 999 / 2;
+ size_t sum;
+ }
+
+ void runTen()
+ {
+ TestFiber[10] fibs;
+ foreach (ref fib; fibs)
+ fib = new TestFiber();
+
+ bool cont;
+ do {
+ cont = false;
+ foreach (fib; fibs) {
+ if (fib.state == Fiber.State.HOLD)
+ {
+ fib.call();
+ cont |= fib.state != Fiber.State.TERM;
+ }
+ }
+ } while (cont);
+
+ foreach (fib; fibs)
+ {
+ assert(fib.sum == TestFiber.expSum);
+ }
+ }
+}
+
+
+// Single thread running separate fibers
+unittest
+{
+ runTen();
+}
+
+
+// Multiple threads running separate fibers
+unittest
+{
+ auto group = new ThreadGroup();
+ foreach (_; 0 .. 4)
+ {
+ group.create(&runTen);
+ }
+ group.joinAll();
+}
+
+
+// Multiple threads running shared fibers
+version (PPC) version = UnsafeFiberMigration;
+version (PPC64) version = UnsafeFiberMigration;
+
+version (UnsafeFiberMigration)
+{
+ // XBUG: core.thread fibers are supposed to be safe to migrate across
+ // threads, however, there is a problem: GCC always assumes that the
+ // address of thread-local variables don't change while on a given stack.
+ // In consequence, migrating fibers between threads currently is an unsafe
+ // thing to do, and will break on some targets (possibly PR26461).
+}
+else
+{
+ version = FiberMigrationUnittest;
+}
+
+version (FiberMigrationUnittest)
+unittest
+{
+ shared bool[10] locks;
+ TestFiber[10] fibs;
+
+ void runShared()
+ {
+ bool cont;
+ do {
+ cont = false;
+ foreach (idx; 0 .. 10)
+ {
+ if (cas(&locks[idx], false, true))
+ {
+ if (fibs[idx].state == Fiber.State.HOLD)
+ {
+ fibs[idx].call();
+ cont |= fibs[idx].state != Fiber.State.TERM;
+ }
+ locks[idx] = false;
+ }
+ else
+ {
+ cont = true;
+ }
+ }
+ } while (cont);
+ }
+
+ foreach (ref fib; fibs)
+ {
+ fib = new TestFiber();
+ }
+
+ auto group = new ThreadGroup();
+ foreach (_; 0 .. 4)
+ {
+ group.create(&runShared);
+ }
+ group.joinAll();
+
+ foreach (fib; fibs)
+ {
+ assert(fib.sum == TestFiber.expSum);
+ }
+}
+
+
+// Test exception handling inside fibers.
+unittest
+{
+ enum MSG = "Test message.";
+ string caughtMsg;
+ (new Fiber({
+ try
+ {
+ throw new Exception(MSG);
+ }
+ catch (Exception e)
+ {
+ caughtMsg = e.msg;
+ }
+ })).call();
+ assert(caughtMsg == MSG);
+}
+
+
+unittest
+{
+ int x = 0;
+
+ (new Fiber({
+ x++;
+ })).call();
+ assert( x == 1 );
+}
+
+nothrow unittest
+{
+ new Fiber({}).call!(Fiber.Rethrow.no)();
+}
+
+unittest
+{
+ new Fiber({}).call(Fiber.Rethrow.yes);
+ new Fiber({}).call(Fiber.Rethrow.no);
+}
+
+unittest
+{
+ enum MSG = "Test message.";
+
+ try
+ {
+ (new Fiber({
+ throw new Exception( MSG );
+ })).call();
+ assert( false, "Expected rethrown exception." );
+ }
+ catch ( Throwable t )
+ {
+ assert( t.msg == MSG );
+ }
+}
+
+// Test exception chaining when switching contexts in finally blocks.
+unittest
+{
+ static void throwAndYield(string msg) {
+ try {
+ throw new Exception(msg);
+ } finally {
+ Fiber.yield();
+ }
+ }
+
+ static void fiber(string name) {
+ try {
+ try {
+ throwAndYield(name ~ ".1");
+ } finally {
+ throwAndYield(name ~ ".2");
+ }
+ } catch (Exception e) {
+ assert(e.msg == name ~ ".1");
+ assert(e.next);
+ assert(e.next.msg == name ~ ".2");
+ assert(!e.next.next);
+ }
+ }
+
+ auto first = new Fiber(() => fiber("first"));
+ auto second = new Fiber(() => fiber("second"));
+ first.call();
+ second.call();
+ first.call();
+ second.call();
+ first.call();
+ second.call();
+ assert(first.state == Fiber.State.TERM);
+ assert(second.state == Fiber.State.TERM);
+}
+
+// Test Fiber resetting
+unittest
+{
+ static string method;
+
+ static void foo()
+ {
+ method = "foo";
+ }
+
+ void bar()
+ {
+ method = "bar";
+ }
+
+ static void expect(Fiber fib, string s)
+ {
+ assert(fib.state == Fiber.State.HOLD);
+ fib.call();
+ assert(fib.state == Fiber.State.TERM);
+ assert(method == s); method = null;
+ }
+ auto fib = new Fiber(&foo);
+ expect(fib, "foo");
+
+ fib.reset();
+ expect(fib, "foo");
+
+ fib.reset(&foo);
+ expect(fib, "foo");
+
+ fib.reset(&bar);
+ expect(fib, "bar");
+
+ fib.reset(function void(){method = "function";});
+ expect(fib, "function");
+
+ fib.reset(delegate void(){method = "delegate";});
+ expect(fib, "delegate");
+}
+
+// Test unsafe reset in hold state
+unittest
+{
+ auto fib = new Fiber(function {ubyte[2048] buf = void; Fiber.yield();}, 4096);
+ foreach (_; 0 .. 10)
+ {
+ fib.call();
+ assert(fib.state == Fiber.State.HOLD);
+ fib.reset();
+ }
+}
+
+// stress testing GC stack scanning
+unittest
+{
+ import core.memory;
+ import core.time : dur;
+
+ static void unreferencedThreadObject()
+ {
+ static void sleep() { Thread.sleep(dur!"msecs"(100)); }
+ auto thread = new Thread(&sleep).start();
+ }
+ unreferencedThreadObject();
+ GC.collect();
+
+ static class Foo
+ {
+ this(int value)
+ {
+ _value = value;
+ }
+
+ int bar()
+ {
+ return _value;
+ }
+
+ int _value;
+ }
+
+ static void collect()
+ {
+ auto foo = new Foo(2);
+ assert(foo.bar() == 2);
+ GC.collect();
+ Fiber.yield();
+ GC.collect();
+ assert(foo.bar() == 2);
+ }
+
+ auto fiber = new Fiber(&collect);
+
+ fiber.call();
+ GC.collect();
+ fiber.call();
+
+ // thread reference
+ auto foo = new Foo(2);
+
+ void collect2()
+ {
+ assert(foo.bar() == 2);
+ GC.collect();
+ Fiber.yield();
+ GC.collect();
+ assert(foo.bar() == 2);
+ }
+
+ fiber = new Fiber(&collect2);
+
+ fiber.call();
+ GC.collect();
+ fiber.call();
+
+ static void recurse(size_t cnt)
+ {
+ --cnt;
+ Fiber.yield();
+ if (cnt)
+ {
+ auto fib = new Fiber(() { recurse(cnt); });
+ fib.call();
+ GC.collect();
+ fib.call();
+ }
+ }
+ fiber = new Fiber(() { recurse(20); });
+ fiber.call();
+}
+
+
+version (AsmX86_64_Windows)
+{
+ // Test Windows x64 calling convention
+ unittest
+ {
+ void testNonvolatileRegister(alias REG)()
+ {
+ auto zeroRegister = new Fiber(() {
+ mixin("asm pure nothrow @nogc { naked; xor "~REG~", "~REG~"; ret; }");
+ });
+ long after;
+
+ mixin("asm pure nothrow @nogc { mov "~REG~", 0xFFFFFFFFFFFFFFFF; }");
+ zeroRegister.call();
+ mixin("asm pure nothrow @nogc { mov after, "~REG~"; }");
+
+ assert(after == -1);
+ }
+
+ void testNonvolatileRegisterSSE(alias REG)()
+ {
+ auto zeroRegister = new Fiber(() {
+ mixin("asm pure nothrow @nogc { naked; xorpd "~REG~", "~REG~"; ret; }");
+ });
+ long[2] before = [0xFFFFFFFF_FFFFFFFF, 0xFFFFFFFF_FFFFFFFF], after;
+
+ mixin("asm pure nothrow @nogc { movdqu "~REG~", before; }");
+ zeroRegister.call();
+ mixin("asm pure nothrow @nogc { movdqu after, "~REG~"; }");
+
+ assert(before == after);
+ }
+
+ testNonvolatileRegister!("R12")();
+ testNonvolatileRegister!("R13")();
+ testNonvolatileRegister!("R14")();
+ testNonvolatileRegister!("R15")();
+ testNonvolatileRegister!("RDI")();
+ testNonvolatileRegister!("RSI")();
+ testNonvolatileRegister!("RBX")();
+
+ testNonvolatileRegisterSSE!("XMM6")();
+ testNonvolatileRegisterSSE!("XMM7")();
+ testNonvolatileRegisterSSE!("XMM8")();
+ testNonvolatileRegisterSSE!("XMM9")();
+ testNonvolatileRegisterSSE!("XMM10")();
+ testNonvolatileRegisterSSE!("XMM11")();
+ testNonvolatileRegisterSSE!("XMM12")();
+ testNonvolatileRegisterSSE!("XMM13")();
+ testNonvolatileRegisterSSE!("XMM14")();
+ testNonvolatileRegisterSSE!("XMM15")();
+ }
+}
+
+
+version (D_InlineAsm_X86_64)
+{
+ unittest
+ {
+ void testStackAlignment()
+ {
+ void* pRSP;
+ asm pure nothrow @nogc
+ {
+ mov pRSP, RSP;
+ }
+ assert((cast(size_t)pRSP & 0xF) == 0);
+ }
+
+ auto fib = new Fiber(&testStackAlignment);
+ fib.call();
+ }
+}
--- /dev/null
+/**
+ * The osthread module provides low-level, OS-dependent code
+ * for thread creation and management.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2012.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
+ * Source: $(DRUNTIMESRC core/thread/osthread.d)
+ */
+
+/* NOTE: This file has been patched from the original DMD distribution to
+ * work with the GDC compiler.
+ */
+module core.thread.osthread;
+
+import core.thread.threadbase;
+import core.thread.context;
+import core.thread.types;
+import core.atomic;
+import core.memory : GC;
+import core.time;
+import core.exception : onOutOfMemoryError;
+import core.internal.traits : externDFunc;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Platform Detection and Memory Allocation
+///////////////////////////////////////////////////////////////////////////////
+
+version (OSX)
+ version = Darwin;
+else version (iOS)
+ version = Darwin;
+else version (TVOS)
+ version = Darwin;
+else version (WatchOS)
+ version = Darwin;
+
+version (Shared)
+ version (GNU)
+ version = GNUShared;
+
+version (D_InlineAsm_X86)
+{
+ version (Windows)
+ version = AsmX86_Windows;
+ else version (Posix)
+ version = AsmX86_Posix;
+}
+else version (D_InlineAsm_X86_64)
+{
+ version (Windows)
+ {
+ version = AsmX86_64_Windows;
+ }
+ else version (Posix)
+ {
+ version = AsmX86_64_Posix;
+ }
+}
+else version (X86)
+{
+ version (CET) {} else
+ {
+ version = AsmExternal;
+ }
+}
+else version (X86_64)
+{
+ version (CET) {} else
+ version (D_X32) {} else
+ {
+ version = AsmExternal;
+ }
+}
+else version (PPC)
+{
+ version (Posix)
+ {
+ version = AsmExternal;
+ }
+}
+else version (MIPS_O32)
+{
+ version (Posix)
+ {
+ version = AsmExternal;
+ }
+}
+else version (AArch64)
+{
+ version (Posix)
+ {
+ version = AsmExternal;
+ }
+}
+else version (ARM)
+{
+ version (Posix)
+ {
+ version = AsmExternal;
+ }
+}
+
+version (Posix)
+{
+ version (AsmX86_Windows) {} else
+ version (AsmX86_Posix) {} else
+ version (AsmX86_64_Windows) {} else
+ version (AsmX86_64_Posix) {} else
+ version (AsmExternal) {} else
+ {
+ // NOTE: The ucontext implementation requires architecture specific
+ // data definitions to operate so testing for it must be done
+ // by checking for the existence of ucontext_t rather than by
+ // a version identifier. Please note that this is considered
+ // an obsolescent feature according to the POSIX spec, so a
+ // custom solution is still preferred.
+ import core.sys.posix.ucontext;
+ }
+}
+
+version (Windows)
+{
+ import core.stdc.stdint : uintptr_t; // for _beginthreadex decl below
+ import core.stdc.stdlib; // for malloc, atexit
+ import core.sys.windows.basetsd /+: HANDLE+/;
+ import core.sys.windows.threadaux /+: getThreadStackBottom, impersonate_thread, OpenThreadHandle+/;
+ import core.sys.windows.winbase /+: CloseHandle, CREATE_SUSPENDED, DuplicateHandle, GetCurrentThread,
+ GetCurrentThreadId, GetCurrentProcess, GetExitCodeThread, GetSystemInfo, GetThreadContext,
+ GetThreadPriority, INFINITE, ResumeThread, SetThreadPriority, Sleep, STILL_ACTIVE,
+ SuspendThread, SwitchToThread, SYSTEM_INFO, THREAD_PRIORITY_IDLE, THREAD_PRIORITY_NORMAL,
+ THREAD_PRIORITY_TIME_CRITICAL, WAIT_OBJECT_0, WaitForSingleObject+/;
+ import core.sys.windows.windef /+: TRUE+/;
+ import core.sys.windows.winnt /+: CONTEXT, CONTEXT_CONTROL, CONTEXT_INTEGER+/;
+
+ private extern (Windows) alias btex_fptr = uint function(void*);
+ private extern (C) uintptr_t _beginthreadex(void*, uint, btex_fptr, void*, uint, uint*) nothrow @nogc;
+}
+else version (Posix)
+{
+ import core.stdc.errno;
+ import core.sys.posix.semaphore;
+ import core.sys.posix.stdlib; // for malloc, valloc, free, atexit
+ import core.sys.posix.pthread;
+ import core.sys.posix.signal;
+ import core.sys.posix.time;
+
+ version (Darwin)
+ {
+ import core.sys.darwin.mach.thread_act;
+ import core.sys.darwin.pthread : pthread_mach_thread_np;
+ }
+}
+
+version (Solaris)
+{
+ import core.sys.solaris.sys.priocntl;
+ import core.sys.solaris.sys.types;
+ import core.sys.posix.sys.wait : idtype_t;
+}
+
+version (GNU)
+{
+ import gcc.builtins;
+}
+
+/**
+ * Hook for whatever EH implementation is used to save/restore some data
+ * per stack.
+ *
+ * Params:
+ * newContext = The return value of the prior call to this function
+ * where the stack was last swapped out, or null when a fiber stack
+ * is switched in for the first time.
+ */
+private extern(C) void* _d_eh_swapContext(void* newContext) nothrow @nogc;
+
+version (DigitalMars)
+{
+ version (Windows)
+ {
+ extern(D) void* swapContext(void* newContext) nothrow @nogc
+ {
+ return _d_eh_swapContext(newContext);
+ }
+ }
+ else
+ {
+ extern(C) void* _d_eh_swapContextDwarf(void* newContext) nothrow @nogc;
+
+ extern(D) void* swapContext(void* newContext) nothrow @nogc
+ {
+ /* Detect at runtime which scheme is being used.
+ * Eventually, determine it statically.
+ */
+ static int which = 0;
+ final switch (which)
+ {
+ case 0:
+ {
+ assert(newContext == null);
+ auto p = _d_eh_swapContext(newContext);
+ auto pdwarf = _d_eh_swapContextDwarf(newContext);
+ if (p)
+ {
+ which = 1;
+ return p;
+ }
+ else if (pdwarf)
+ {
+ which = 2;
+ return pdwarf;
+ }
+ return null;
+ }
+ case 1:
+ return _d_eh_swapContext(newContext);
+ case 2:
+ return _d_eh_swapContextDwarf(newContext);
+ }
+ }
+ }
+}
+else
+{
+ extern(D) void* swapContext(void* newContext) nothrow @nogc
+ {
+ return _d_eh_swapContext(newContext);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * This class encapsulates all threading functionality for the D
+ * programming language. As thread manipulation is a required facility
+ * for garbage collection, all user threads should derive from this
+ * class, and instances of this class should never be explicitly deleted.
+ * A new thread may be created using either derivation or composition, as
+ * in the following example.
+ */
+class Thread : ThreadBase
+{
+ //
+ // Main process thread
+ //
+ version (FreeBSD)
+ {
+ // set when suspend failed and should be retried, see Issue 13416
+ private shared bool m_suspendagain;
+ }
+
+ //
+ // Standard thread data
+ //
+ version (Windows)
+ {
+ private HANDLE m_hndl;
+ }
+
+ version (Posix)
+ {
+ private shared bool m_isRunning;
+ }
+
+ version (Darwin)
+ {
+ private mach_port_t m_tmach;
+ }
+
+ version (Solaris)
+ {
+ private __gshared bool m_isRTClass;
+ }
+
+ //
+ // Standard types
+ //
+ version (Windows)
+ {
+ alias TLSKey = uint;
+ }
+ else version (Posix)
+ {
+ alias TLSKey = pthread_key_t;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Initialization
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Initializes a thread object which is associated with a static
+ * D function.
+ *
+ * Params:
+ * fn = The thread function.
+ * sz = The stack size for this thread.
+ *
+ * In:
+ * fn must not be null.
+ */
+ this( void function() fn, size_t sz = 0 ) @safe pure nothrow @nogc
+ {
+ super(fn, sz);
+ }
+
+
+ /**
+ * Initializes a thread object which is associated with a dynamic
+ * D function.
+ *
+ * Params:
+ * dg = The thread function.
+ * sz = The stack size for this thread.
+ *
+ * In:
+ * dg must not be null.
+ */
+ this( void delegate() dg, size_t sz = 0 ) @safe pure nothrow @nogc
+ {
+ super(dg, sz);
+ }
+
+ package this( size_t sz = 0 ) @safe pure nothrow @nogc
+ {
+ super(sz);
+ }
+
+ /**
+ * Cleans up any remaining resources used by this object.
+ */
+ ~this() nothrow @nogc
+ {
+ if (super.destructBeforeDtor())
+ return;
+
+ version (Windows)
+ {
+ m_addr = m_addr.init;
+ CloseHandle( m_hndl );
+ m_hndl = m_hndl.init;
+ }
+ else version (Posix)
+ {
+ pthread_detach( m_addr );
+ m_addr = m_addr.init;
+ }
+ version (Darwin)
+ {
+ m_tmach = m_tmach.init;
+ }
+ }
+
+ //
+ // Thread entry point. Invokes the function or delegate passed on
+ // construction (if any).
+ //
+ private final void run()
+ {
+ super.run();
+ }
+
+ /**
+ * Provides a reference to the calling thread.
+ *
+ * Returns:
+ * The thread object representing the calling thread. The result of
+ * deleting this object is undefined. If the current thread is not
+ * attached to the runtime, a null reference is returned.
+ */
+ static Thread getThis() @safe nothrow @nogc
+ {
+ return ThreadBase.getThis().toThread;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Thread Context and GC Scanning Support
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ version (Windows)
+ {
+ version (X86)
+ {
+ uint[8] m_reg; // edi,esi,ebp,esp,ebx,edx,ecx,eax
+ }
+ else version (X86_64)
+ {
+ ulong[16] m_reg; // rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax
+ // r8,r9,r10,r11,r12,r13,r14,r15
+ }
+ else
+ {
+ static assert(false, "Architecture not supported." );
+ }
+ }
+ else version (Darwin)
+ {
+ version (X86)
+ {
+ uint[8] m_reg; // edi,esi,ebp,esp,ebx,edx,ecx,eax
+ }
+ else version (X86_64)
+ {
+ ulong[16] m_reg; // rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax
+ // r8,r9,r10,r11,r12,r13,r14,r15
+ }
+ else version (AArch64)
+ {
+ ulong[33] m_reg; // x0-x31, pc
+ }
+ else version (ARM)
+ {
+ uint[16] m_reg; // r0-r15
+ }
+ else
+ {
+ static assert(false, "Architecture not supported." );
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // General Actions
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Starts the thread and invokes the function or delegate passed upon
+ * construction.
+ *
+ * In:
+ * This routine may only be called once per thread instance.
+ *
+ * Throws:
+ * ThreadException if the thread fails to start.
+ */
+ final Thread start() nothrow
+ in
+ {
+ assert( !next && !prev );
+ }
+ do
+ {
+ auto wasThreaded = multiThreadedFlag;
+ multiThreadedFlag = true;
+ scope( failure )
+ {
+ if ( !wasThreaded )
+ multiThreadedFlag = false;
+ }
+
+ version (Windows) {} else
+ version (Posix)
+ {
+ size_t stksz = adjustStackSize( m_sz );
+
+ pthread_attr_t attr;
+
+ if ( pthread_attr_init( &attr ) )
+ onThreadError( "Error initializing thread attributes" );
+ if ( stksz && pthread_attr_setstacksize( &attr, stksz ) )
+ onThreadError( "Error initializing thread stack size" );
+ }
+
+ version (Windows)
+ {
+ // NOTE: If a thread is just executing DllMain()
+ // while another thread is started here, it holds an OS internal
+ // lock that serializes DllMain with CreateThread. As the code
+ // might request a synchronization on slock (e.g. in thread_findByAddr()),
+ // we cannot hold that lock while creating the thread without
+ // creating a deadlock
+ //
+ // Solution: Create the thread in suspended state and then
+ // add and resume it with slock acquired
+ assert(m_sz <= uint.max, "m_sz must be less than or equal to uint.max");
+ m_hndl = cast(HANDLE) _beginthreadex( null, cast(uint) m_sz, &thread_entryPoint, cast(void*) this, CREATE_SUSPENDED, &m_addr );
+ if ( cast(size_t) m_hndl == 0 )
+ onThreadError( "Error creating thread" );
+ }
+
+ slock.lock_nothrow();
+ scope(exit) slock.unlock_nothrow();
+ {
+ ++nAboutToStart;
+ pAboutToStart = cast(ThreadBase*)realloc(pAboutToStart, Thread.sizeof * nAboutToStart);
+ pAboutToStart[nAboutToStart - 1] = this;
+ version (Windows)
+ {
+ if ( ResumeThread( m_hndl ) == -1 )
+ onThreadError( "Error resuming thread" );
+ }
+ else version (Posix)
+ {
+ // NOTE: This is also set to true by thread_entryPoint, but set it
+ // here as well so the calling thread will see the isRunning
+ // state immediately.
+ atomicStore!(MemoryOrder.raw)(m_isRunning, true);
+ scope( failure ) atomicStore!(MemoryOrder.raw)(m_isRunning, false);
+
+ version (Shared)
+ {
+ version (GNU)
+ {
+ auto libs = externDFunc!("gcc.sections.elf_shared.pinLoadedLibraries",
+ void* function() @nogc nothrow)();
+ }
+ else
+ {
+ auto libs = externDFunc!("rt.sections_elf_shared.pinLoadedLibraries",
+ void* function() @nogc nothrow)();
+ }
+
+ auto ps = cast(void**).malloc(2 * size_t.sizeof);
+ if (ps is null) onOutOfMemoryError();
+ ps[0] = cast(void*)this;
+ ps[1] = cast(void*)libs;
+ if ( pthread_create( &m_addr, &attr, &thread_entryPoint, ps ) != 0 )
+ {
+ version (GNU)
+ {
+ externDFunc!("gcc.sections.elf_shared.unpinLoadedLibraries",
+ void function(void*) @nogc nothrow)(libs);
+ }
+ else
+ {
+ externDFunc!("rt.sections_elf_shared.unpinLoadedLibraries",
+ void function(void*) @nogc nothrow)(libs);
+ }
+ .free(ps);
+ onThreadError( "Error creating thread" );
+ }
+ }
+ else
+ {
+ if ( pthread_create( &m_addr, &attr, &thread_entryPoint, cast(void*) this ) != 0 )
+ onThreadError( "Error creating thread" );
+ }
+ if ( pthread_attr_destroy( &attr ) != 0 )
+ onThreadError( "Error destroying thread attributes" );
+ }
+ version (Darwin)
+ {
+ m_tmach = pthread_mach_thread_np( m_addr );
+ if ( m_tmach == m_tmach.init )
+ onThreadError( "Error creating thread" );
+ }
+
+ return this;
+ }
+ }
+
+ /**
+ * Waits for this thread to complete. If the thread terminated as the
+ * result of an unhandled exception, this exception will be rethrown.
+ *
+ * Params:
+ * rethrow = Rethrow any unhandled exception which may have caused this
+ * thread to terminate.
+ *
+ * Throws:
+ * ThreadException if the operation fails.
+ * Any exception not handled by the joined thread.
+ *
+ * Returns:
+ * Any exception not handled by this thread if rethrow = false, null
+ * otherwise.
+ */
+ override final Throwable join( bool rethrow = true )
+ {
+ version (Windows)
+ {
+ if ( WaitForSingleObject( m_hndl, INFINITE ) != WAIT_OBJECT_0 )
+ throw new ThreadException( "Unable to join thread" );
+ // NOTE: m_addr must be cleared before m_hndl is closed to avoid
+ // a race condition with isRunning. The operation is done
+ // with atomicStore to prevent compiler reordering.
+ atomicStore!(MemoryOrder.raw)(*cast(shared)&m_addr, m_addr.init);
+ CloseHandle( m_hndl );
+ m_hndl = m_hndl.init;
+ }
+ else version (Posix)
+ {
+ if ( pthread_join( m_addr, null ) != 0 )
+ throw new ThreadException( "Unable to join thread" );
+ // NOTE: pthread_join acts as a substitute for pthread_detach,
+ // which is normally called by the dtor. Setting m_addr
+ // to zero ensures that pthread_detach will not be called
+ // on object destruction.
+ m_addr = m_addr.init;
+ }
+ if ( m_unhandled )
+ {
+ if ( rethrow )
+ throw m_unhandled;
+ return m_unhandled;
+ }
+ return null;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Thread Priority Actions
+ ///////////////////////////////////////////////////////////////////////////
+
+ version (Windows)
+ {
+ @property static int PRIORITY_MIN() @nogc nothrow pure @safe
+ {
+ return THREAD_PRIORITY_IDLE;
+ }
+
+ @property static const(int) PRIORITY_MAX() @nogc nothrow pure @safe
+ {
+ return THREAD_PRIORITY_TIME_CRITICAL;
+ }
+
+ @property static int PRIORITY_DEFAULT() @nogc nothrow pure @safe
+ {
+ return THREAD_PRIORITY_NORMAL;
+ }
+ }
+ else
+ {
+ private struct Priority
+ {
+ int PRIORITY_MIN = int.min;
+ int PRIORITY_DEFAULT = int.min;
+ int PRIORITY_MAX = int.min;
+ }
+
+ /*
+ Lazily loads one of the members stored in a hidden global variable of
+ type `Priority`. Upon the first access of either member, the entire
+ `Priority` structure is initialized. Multiple initializations from
+ different threads calling this function are tolerated.
+
+ `which` must be one of `PRIORITY_MIN`, `PRIORITY_DEFAULT`,
+ `PRIORITY_MAX`.
+ */
+ private static shared Priority cache;
+ private static int loadGlobal(string which)()
+ {
+ auto local = atomicLoad(mixin("cache." ~ which));
+ if (local != local.min) return local;
+ // There will be benign races
+ cache = loadPriorities;
+ return atomicLoad(mixin("cache." ~ which));
+ }
+
+ /*
+ Loads all priorities and returns them as a `Priority` structure. This
+ function is thread-neutral.
+ */
+ private static Priority loadPriorities() @nogc nothrow @trusted
+ {
+ Priority result;
+ version (Solaris)
+ {
+ pcparms_t pcParms;
+ pcinfo_t pcInfo;
+
+ pcParms.pc_cid = PC_CLNULL;
+ if (priocntl(idtype_t.P_PID, P_MYID, PC_GETPARMS, &pcParms) == -1)
+ assert( 0, "Unable to get scheduling class" );
+
+ pcInfo.pc_cid = pcParms.pc_cid;
+ // PC_GETCLINFO ignores the first two args, use dummy values
+ if (priocntl(idtype_t.P_PID, 0, PC_GETCLINFO, &pcInfo) == -1)
+ assert( 0, "Unable to get scheduling class info" );
+
+ pri_t* clparms = cast(pri_t*)&pcParms.pc_clparms;
+ pri_t* clinfo = cast(pri_t*)&pcInfo.pc_clinfo;
+
+ result.PRIORITY_MAX = clparms[0];
+
+ if (pcInfo.pc_clname == "RT")
+ {
+ m_isRTClass = true;
+
+ // For RT class, just assume it can't be changed
+ result.PRIORITY_MIN = clparms[0];
+ result.PRIORITY_DEFAULT = clparms[0];
+ }
+ else
+ {
+ m_isRTClass = false;
+
+ // For all other scheduling classes, there are
+ // two key values -- uprilim and maxupri.
+ // maxupri is the maximum possible priority defined
+ // for the scheduling class, and valid priorities
+ // range are in [-maxupri, maxupri].
+ //
+ // However, uprilim is an upper limit that the
+ // current thread can set for the current scheduling
+ // class, which can be less than maxupri. As such,
+ // use this value for priorityMax since this is
+ // the effective maximum.
+
+ // maxupri
+ result.PRIORITY_MIN = -clinfo[0];
+ // by definition
+ result.PRIORITY_DEFAULT = 0;
+ }
+ }
+ else version (Posix)
+ {
+ int policy;
+ sched_param param;
+ pthread_getschedparam( pthread_self(), &policy, ¶m ) == 0
+ || assert(0, "Internal error in pthread_getschedparam");
+
+ result.PRIORITY_MIN = sched_get_priority_min( policy );
+ result.PRIORITY_MIN != -1
+ || assert(0, "Internal error in sched_get_priority_min");
+ result.PRIORITY_DEFAULT = param.sched_priority;
+ result.PRIORITY_MAX = sched_get_priority_max( policy );
+ result.PRIORITY_MAX != -1 ||
+ assert(0, "Internal error in sched_get_priority_max");
+ }
+ else
+ {
+ static assert(0, "Your code here.");
+ }
+ return result;
+ }
+
+ /**
+ * The minimum scheduling priority that may be set for a thread. On
+ * systems where multiple scheduling policies are defined, this value
+ * represents the minimum valid priority for the scheduling policy of
+ * the process.
+ */
+ @property static int PRIORITY_MIN() @nogc nothrow pure @trusted
+ {
+ return (cast(int function() @nogc nothrow pure @safe)
+ &loadGlobal!"PRIORITY_MIN")();
+ }
+
+ /**
+ * The maximum scheduling priority that may be set for a thread. On
+ * systems where multiple scheduling policies are defined, this value
+ * represents the maximum valid priority for the scheduling policy of
+ * the process.
+ */
+ @property static const(int) PRIORITY_MAX() @nogc nothrow pure @trusted
+ {
+ return (cast(int function() @nogc nothrow pure @safe)
+ &loadGlobal!"PRIORITY_MAX")();
+ }
+
+ /**
+ * The default scheduling priority that is set for a thread. On
+ * systems where multiple scheduling policies are defined, this value
+ * represents the default priority for the scheduling policy of
+ * the process.
+ */
+ @property static int PRIORITY_DEFAULT() @nogc nothrow pure @trusted
+ {
+ return (cast(int function() @nogc nothrow pure @safe)
+ &loadGlobal!"PRIORITY_DEFAULT")();
+ }
+ }
+
+ version (NetBSD)
+ {
+ //NetBSD does not support priority for default policy
+ // and it is not possible change policy without root access
+ int fakePriority = int.max;
+ }
+
+ /**
+ * Gets the scheduling priority for the associated thread.
+ *
+ * Note: Getting the priority of a thread that already terminated
+ * might return the default priority.
+ *
+ * Returns:
+ * The scheduling priority of this thread.
+ */
+ final @property int priority()
+ {
+ version (Windows)
+ {
+ return GetThreadPriority( m_hndl );
+ }
+ else version (NetBSD)
+ {
+ return fakePriority==int.max? PRIORITY_DEFAULT : fakePriority;
+ }
+ else version (Posix)
+ {
+ int policy;
+ sched_param param;
+
+ if (auto err = pthread_getschedparam(m_addr, &policy, ¶m))
+ {
+ // ignore error if thread is not running => Bugzilla 8960
+ if (!atomicLoad(m_isRunning)) return PRIORITY_DEFAULT;
+ throw new ThreadException("Unable to get thread priority");
+ }
+ return param.sched_priority;
+ }
+ }
+
+
+ /**
+ * Sets the scheduling priority for the associated thread.
+ *
+ * Note: Setting the priority of a thread that already terminated
+ * might have no effect.
+ *
+ * Params:
+ * val = The new scheduling priority of this thread.
+ */
+ final @property void priority( int val )
+ in
+ {
+ assert(val >= PRIORITY_MIN);
+ assert(val <= PRIORITY_MAX);
+ }
+ do
+ {
+ version (Windows)
+ {
+ if ( !SetThreadPriority( m_hndl, val ) )
+ throw new ThreadException( "Unable to set thread priority" );
+ }
+ else version (Solaris)
+ {
+ // the pthread_setschedprio(3c) and pthread_setschedparam functions
+ // are broken for the default (TS / time sharing) scheduling class.
+ // instead, we use priocntl(2) which gives us the desired behavior.
+
+ // We hardcode the min and max priorities to the current value
+ // so this is a no-op for RT threads.
+ if (m_isRTClass)
+ return;
+
+ pcparms_t pcparm;
+
+ pcparm.pc_cid = PC_CLNULL;
+ if (priocntl(idtype_t.P_LWPID, P_MYID, PC_GETPARMS, &pcparm) == -1)
+ throw new ThreadException( "Unable to get scheduling class" );
+
+ pri_t* clparms = cast(pri_t*)&pcparm.pc_clparms;
+
+ // clparms is filled in by the PC_GETPARMS call, only necessary
+ // to adjust the element that contains the thread priority
+ clparms[1] = cast(pri_t) val;
+
+ if (priocntl(idtype_t.P_LWPID, P_MYID, PC_SETPARMS, &pcparm) == -1)
+ throw new ThreadException( "Unable to set scheduling class" );
+ }
+ else version (NetBSD)
+ {
+ fakePriority = val;
+ }
+ else version (Posix)
+ {
+ static if (__traits(compiles, pthread_setschedprio))
+ {
+ if (auto err = pthread_setschedprio(m_addr, val))
+ {
+ // ignore error if thread is not running => Bugzilla 8960
+ if (!atomicLoad(m_isRunning)) return;
+ throw new ThreadException("Unable to set thread priority");
+ }
+ }
+ else
+ {
+ // NOTE: pthread_setschedprio is not implemented on Darwin, FreeBSD, OpenBSD,
+ // or DragonFlyBSD, so use the more complicated get/set sequence below.
+ int policy;
+ sched_param param;
+
+ if (auto err = pthread_getschedparam(m_addr, &policy, ¶m))
+ {
+ // ignore error if thread is not running => Bugzilla 8960
+ if (!atomicLoad(m_isRunning)) return;
+ throw new ThreadException("Unable to set thread priority");
+ }
+ param.sched_priority = val;
+ if (auto err = pthread_setschedparam(m_addr, policy, ¶m))
+ {
+ // ignore error if thread is not running => Bugzilla 8960
+ if (!atomicLoad(m_isRunning)) return;
+ throw new ThreadException("Unable to set thread priority");
+ }
+ }
+ }
+ }
+
+
+ unittest
+ {
+ auto thr = Thread.getThis();
+ immutable prio = thr.priority;
+ scope (exit) thr.priority = prio;
+
+ assert(prio == PRIORITY_DEFAULT);
+ assert(prio >= PRIORITY_MIN && prio <= PRIORITY_MAX);
+ thr.priority = PRIORITY_MIN;
+ assert(thr.priority == PRIORITY_MIN);
+ thr.priority = PRIORITY_MAX;
+ assert(thr.priority == PRIORITY_MAX);
+ }
+
+ unittest // Bugzilla 8960
+ {
+ import core.sync.semaphore;
+
+ auto thr = new Thread({});
+ thr.start();
+ Thread.sleep(1.msecs); // wait a little so the thread likely has finished
+ thr.priority = PRIORITY_MAX; // setting priority doesn't cause error
+ auto prio = thr.priority; // getting priority doesn't cause error
+ assert(prio >= PRIORITY_MIN && prio <= PRIORITY_MAX);
+ }
+
+ /**
+ * Tests whether this thread is running.
+ *
+ * Returns:
+ * true if the thread is running, false if not.
+ */
+ override final @property bool isRunning() nothrow @nogc
+ {
+ if (!super.isRunning())
+ return false;
+
+ version (Windows)
+ {
+ uint ecode = 0;
+ GetExitCodeThread( m_hndl, &ecode );
+ return ecode == STILL_ACTIVE;
+ }
+ else version (Posix)
+ {
+ return atomicLoad(m_isRunning);
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Actions on Calling Thread
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Suspends the calling thread for at least the supplied period. This may
+ * result in multiple OS calls if period is greater than the maximum sleep
+ * duration supported by the operating system.
+ *
+ * Params:
+ * val = The minimum duration the calling thread should be suspended.
+ *
+ * In:
+ * period must be non-negative.
+ *
+ * Example:
+ * ------------------------------------------------------------------------
+ *
+ * Thread.sleep( dur!("msecs")( 50 ) ); // sleep for 50 milliseconds
+ * Thread.sleep( dur!("seconds")( 5 ) ); // sleep for 5 seconds
+ *
+ * ------------------------------------------------------------------------
+ */
+ static void sleep( Duration val ) @nogc nothrow
+ in
+ {
+ assert( !val.isNegative );
+ }
+ do
+ {
+ version (Windows)
+ {
+ auto maxSleepMillis = dur!("msecs")( uint.max - 1 );
+
+ // avoid a non-zero time to be round down to 0
+ if ( val > dur!"msecs"( 0 ) && val < dur!"msecs"( 1 ) )
+ val = dur!"msecs"( 1 );
+
+ // NOTE: In instances where all other threads in the process have a
+ // lower priority than the current thread, the current thread
+ // will not yield with a sleep time of zero. However, unlike
+ // yield(), the user is not asking for a yield to occur but
+ // only for execution to suspend for the requested interval.
+ // Therefore, expected performance may not be met if a yield
+ // is forced upon the user.
+ while ( val > maxSleepMillis )
+ {
+ Sleep( cast(uint)
+ maxSleepMillis.total!"msecs" );
+ val -= maxSleepMillis;
+ }
+ Sleep( cast(uint) val.total!"msecs" );
+ }
+ else version (Posix)
+ {
+ timespec tin = void;
+ timespec tout = void;
+
+ val.split!("seconds", "nsecs")(tin.tv_sec, tin.tv_nsec);
+ if ( val.total!"seconds" > tin.tv_sec.max )
+ tin.tv_sec = tin.tv_sec.max;
+ while ( true )
+ {
+ if ( !nanosleep( &tin, &tout ) )
+ return;
+ if ( errno != EINTR )
+ assert(0, "Unable to sleep for the specified duration");
+ tin = tout;
+ }
+ }
+ }
+
+
+ /**
+ * Forces a context switch to occur away from the calling thread.
+ */
+ static void yield() @nogc nothrow
+ {
+ version (Windows)
+ SwitchToThread();
+ else version (Posix)
+ sched_yield();
+ }
+}
+
+private Thread toThread(ThreadBase t) @trusted nothrow @nogc pure
+{
+ return cast(Thread) cast(void*) t;
+}
+
+private extern(D) static void thread_yield() @nogc nothrow
+{
+ Thread.yield();
+}
+
+///
+unittest
+{
+ class DerivedThread : Thread
+ {
+ this()
+ {
+ super(&run);
+ }
+
+ private:
+ void run()
+ {
+ // Derived thread running.
+ }
+ }
+
+ void threadFunc()
+ {
+ // Composed thread running.
+ }
+
+ // create and start instances of each type
+ auto derived = new DerivedThread().start();
+ auto composed = new Thread(&threadFunc).start();
+ new Thread({
+ // Codes to run in the newly created thread.
+ }).start();
+}
+
+unittest
+{
+ int x = 0;
+
+ new Thread(
+ {
+ x++;
+ }).start().join();
+ assert( x == 1 );
+}
+
+
+unittest
+{
+ enum MSG = "Test message.";
+ string caughtMsg;
+
+ try
+ {
+ new Thread(
+ {
+ throw new Exception( MSG );
+ }).start().join();
+ assert( false, "Expected rethrown exception." );
+ }
+ catch ( Throwable t )
+ {
+ assert( t.msg == MSG );
+ }
+}
+
+
+unittest
+{
+ // use >PAGESIZE to avoid stack overflow (e.g. in an syscall)
+ auto thr = new Thread(function{}, 4096 + 1).start();
+ thr.join();
+}
+
+
+unittest
+{
+ import core.memory : GC;
+
+ auto t1 = new Thread({
+ foreach (_; 0 .. 20)
+ ThreadBase.getAll;
+ }).start;
+ auto t2 = new Thread({
+ foreach (_; 0 .. 20)
+ GC.collect;
+ }).start;
+ t1.join();
+ t2.join();
+}
+
+unittest
+{
+ import core.sync.semaphore;
+ auto sem = new Semaphore();
+
+ auto t = new Thread(
+ {
+ sem.notify();
+ Thread.sleep(100.msecs);
+ }).start();
+
+ sem.wait(); // thread cannot be detached while being started
+ thread_detachInstance(t);
+ foreach (t2; Thread)
+ assert(t !is t2);
+ t.join();
+}
+
+unittest
+{
+ // NOTE: This entire test is based on the assumption that no
+ // memory is allocated after the child thread is
+ // started. If an allocation happens, a collection could
+ // trigger, which would cause the synchronization below
+ // to cause a deadlock.
+ // NOTE: DO NOT USE LOCKS IN CRITICAL REGIONS IN NORMAL CODE.
+
+ import core.sync.semaphore;
+
+ auto sema = new Semaphore(),
+ semb = new Semaphore();
+
+ auto thr = new Thread(
+ {
+ thread_enterCriticalRegion();
+ assert(thread_inCriticalRegion());
+ sema.notify();
+
+ semb.wait();
+ assert(thread_inCriticalRegion());
+
+ thread_exitCriticalRegion();
+ assert(!thread_inCriticalRegion());
+ sema.notify();
+
+ semb.wait();
+ assert(!thread_inCriticalRegion());
+ });
+
+ thr.start();
+
+ sema.wait();
+ synchronized (ThreadBase.criticalRegionLock)
+ assert(thr.m_isInCriticalRegion);
+ semb.notify();
+
+ sema.wait();
+ synchronized (ThreadBase.criticalRegionLock)
+ assert(!thr.m_isInCriticalRegion);
+ semb.notify();
+
+ thr.join();
+}
+
+unittest
+{
+ import core.sync.semaphore;
+
+ shared bool inCriticalRegion;
+ auto sema = new Semaphore(),
+ semb = new Semaphore();
+
+ auto thr = new Thread(
+ {
+ thread_enterCriticalRegion();
+ inCriticalRegion = true;
+ sema.notify();
+ semb.wait();
+
+ Thread.sleep(dur!"msecs"(1));
+ inCriticalRegion = false;
+ thread_exitCriticalRegion();
+ });
+ thr.start();
+
+ sema.wait();
+ assert(inCriticalRegion);
+ semb.notify();
+
+ thread_suspendAll();
+ assert(!inCriticalRegion);
+ thread_resumeAll();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// GC Support Routines
+///////////////////////////////////////////////////////////////////////////////
+
+version (CoreDdoc)
+{
+ /**
+ * Instruct the thread module, when initialized, to use a different set of
+ * signals besides SIGUSR1 and SIGUSR2 for suspension and resumption of threads.
+ * This function should be called at most once, prior to thread_init().
+ * This function is Posix-only.
+ */
+ extern (C) void thread_setGCSignals(int suspendSignalNo, int resumeSignalNo) nothrow @nogc
+ {
+ }
+}
+else version (Posix)
+{
+ extern (C) void thread_setGCSignals(int suspendSignalNo, int resumeSignalNo) nothrow @nogc
+ in
+ {
+ assert(suspendSignalNo != 0);
+ assert(resumeSignalNo != 0);
+ }
+ out
+ {
+ assert(suspendSignalNumber != 0);
+ assert(resumeSignalNumber != 0);
+ }
+ do
+ {
+ suspendSignalNumber = suspendSignalNo;
+ resumeSignalNumber = resumeSignalNo;
+ }
+}
+
+version (Posix)
+{
+ private __gshared int suspendSignalNumber = SIGUSR1;
+ private __gshared int resumeSignalNumber = SIGUSR2;
+}
+
+private extern (D) ThreadBase attachThread(ThreadBase _thisThread) @nogc nothrow
+{
+ Thread thisThread = _thisThread.toThread();
+
+ StackContext* thisContext = &thisThread.m_main;
+ assert( thisContext == thisThread.m_curr );
+
+ version (Windows)
+ {
+ thisThread.m_addr = GetCurrentThreadId();
+ thisThread.m_hndl = GetCurrentThreadHandle();
+ thisContext.bstack = getStackBottom();
+ thisContext.tstack = thisContext.bstack;
+ }
+ else version (Posix)
+ {
+ thisThread.m_addr = pthread_self();
+ thisContext.bstack = getStackBottom();
+ thisContext.tstack = thisContext.bstack;
+
+ atomicStore!(MemoryOrder.raw)(thisThread.toThread.m_isRunning, true);
+ }
+ thisThread.m_isDaemon = true;
+ thisThread.tlsGCdataInit();
+ Thread.setThis( thisThread );
+
+ version (Darwin)
+ {
+ thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr );
+ assert( thisThread.m_tmach != thisThread.m_tmach.init );
+ }
+
+ Thread.add( thisThread, false );
+ Thread.add( thisContext );
+ if ( Thread.sm_main !is null )
+ multiThreadedFlag = true;
+ return thisThread;
+}
+
+/**
+ * Registers the calling thread for use with the D Runtime. If this routine
+ * is called for a thread which is already registered, no action is performed.
+ *
+ * NOTE: This routine does not run thread-local static constructors when called.
+ * If full functionality as a D thread is desired, the following function
+ * must be called after thread_attachThis:
+ *
+ * extern (C) void rt_moduleTlsCtor();
+ */
+extern(C) Thread thread_attachThis()
+{
+ return thread_attachThis_tpl!Thread();
+}
+
+
+version (Windows)
+{
+ // NOTE: These calls are not safe on Posix systems that use signals to
+ // perform garbage collection. The suspendHandler uses getThis()
+ // to get the thread handle so getThis() must be a simple call.
+ // Mutexes can't safely be acquired inside signal handlers, and
+ // even if they could, the mutex needed (Thread.slock) is held by
+ // thread_suspendAll(). So in short, these routines will remain
+ // Windows-specific. If they are truly needed elsewhere, the
+ // suspendHandler will need a way to call a version of getThis()
+ // that only does the TLS lookup without the fancy fallback stuff.
+
+ /// ditto
+ extern (C) Thread thread_attachByAddr( ThreadID addr )
+ {
+ return thread_attachByAddrB( addr, getThreadStackBottom( addr ) );
+ }
+
+
+ /// ditto
+ extern (C) Thread thread_attachByAddrB( ThreadID addr, void* bstack )
+ {
+ GC.disable(); scope(exit) GC.enable();
+
+ if (auto t = thread_findByAddr(addr).toThread)
+ return t;
+
+ Thread thisThread = new Thread();
+ StackContext* thisContext = &thisThread.m_main;
+ assert( thisContext == thisThread.m_curr );
+
+ thisThread.m_addr = addr;
+ thisContext.bstack = bstack;
+ thisContext.tstack = thisContext.bstack;
+
+ thisThread.m_isDaemon = true;
+
+ if ( addr == GetCurrentThreadId() )
+ {
+ thisThread.m_hndl = GetCurrentThreadHandle();
+ thisThread.tlsGCdataInit();
+ Thread.setThis( thisThread );
+ }
+ else
+ {
+ thisThread.m_hndl = OpenThreadHandle( addr );
+ impersonate_thread(addr,
+ {
+ thisThread.tlsGCdataInit();
+ Thread.setThis( thisThread );
+ });
+ }
+
+ Thread.add( thisThread, false );
+ Thread.add( thisContext );
+ if ( Thread.sm_main !is null )
+ multiThreadedFlag = true;
+ return thisThread;
+ }
+}
+
+
+// Calls the given delegate, passing the current thread's stack pointer to it.
+package extern(D) void callWithStackShell(scope callWithStackShellDg fn) nothrow
+in (fn)
+{
+ // The purpose of the 'shell' is to ensure all the registers get
+ // put on the stack so they'll be scanned. We only need to push
+ // the callee-save registers.
+ void *sp = void;
+ version (GNU)
+ {
+ __builtin_unwind_init();
+ sp = &sp;
+ }
+ else version (AsmX86_Posix)
+ {
+ size_t[3] regs = void;
+ asm pure nothrow @nogc
+ {
+ mov [regs + 0 * 4], EBX;
+ mov [regs + 1 * 4], ESI;
+ mov [regs + 2 * 4], EDI;
+
+ mov sp[EBP], ESP;
+ }
+ }
+ else version (AsmX86_Windows)
+ {
+ size_t[3] regs = void;
+ asm pure nothrow @nogc
+ {
+ mov [regs + 0 * 4], EBX;
+ mov [regs + 1 * 4], ESI;
+ mov [regs + 2 * 4], EDI;
+
+ mov sp[EBP], ESP;
+ }
+ }
+ else version (AsmX86_64_Posix)
+ {
+ size_t[5] regs = void;
+ asm pure nothrow @nogc
+ {
+ mov [regs + 0 * 8], RBX;
+ mov [regs + 1 * 8], R12;
+ mov [regs + 2 * 8], R13;
+ mov [regs + 3 * 8], R14;
+ mov [regs + 4 * 8], R15;
+
+ mov sp[RBP], RSP;
+ }
+ }
+ else version (AsmX86_64_Windows)
+ {
+ size_t[7] regs = void;
+ asm pure nothrow @nogc
+ {
+ mov [regs + 0 * 8], RBX;
+ mov [regs + 1 * 8], RSI;
+ mov [regs + 2 * 8], RDI;
+ mov [regs + 3 * 8], R12;
+ mov [regs + 4 * 8], R13;
+ mov [regs + 5 * 8], R14;
+ mov [regs + 6 * 8], R15;
+
+ mov sp[RBP], RSP;
+ }
+ }
+ else
+ {
+ static assert(false, "Architecture not supported.");
+ }
+
+ fn(sp);
+}
+
+version (Solaris)
+{
+ import core.sys.solaris.sys.priocntl;
+ import core.sys.solaris.sys.types;
+ import core.sys.posix.sys.wait : idtype_t;
+}
+
+
+version (Windows)
+private extern (D) void scanWindowsOnly(scope ScanAllThreadsTypeFn scan, ThreadBase _t) nothrow
+{
+ auto t = _t.toThread;
+
+ scan( ScanType.stack, t.m_reg.ptr, t.m_reg.ptr + t.m_reg.length );
+}
+
+
+/**
+ * Returns the process ID of the calling process, which is guaranteed to be
+ * unique on the system. This call is always successful.
+ *
+ * Example:
+ * ---
+ * writefln("Current process id: %s", getpid());
+ * ---
+ */
+version (Posix)
+{
+ import core.sys.posix.unistd;
+
+ alias getpid = core.sys.posix.unistd.getpid;
+}
+else version (Windows)
+{
+ alias getpid = core.sys.windows.winbase.GetCurrentProcessId;
+}
+
+extern (C) @nogc nothrow
+{
+ version (CRuntime_Glibc) version = PThread_Getattr_NP;
+ version (CRuntime_Bionic) version = PThread_Getattr_NP;
+ version (CRuntime_Musl) version = PThread_Getattr_NP;
+ version (CRuntime_UClibc) version = PThread_Getattr_NP;
+
+ version (FreeBSD) version = PThread_Attr_Get_NP;
+ version (NetBSD) version = PThread_Attr_Get_NP;
+ version (DragonFlyBSD) version = PThread_Attr_Get_NP;
+
+ version (PThread_Getattr_NP) int pthread_getattr_np(pthread_t thread, pthread_attr_t* attr);
+ version (PThread_Attr_Get_NP) int pthread_attr_get_np(pthread_t thread, pthread_attr_t* attr);
+ version (Solaris) int thr_stksegment(stack_t* stk);
+ version (OpenBSD) int pthread_stackseg_np(pthread_t thread, stack_t* sinfo);
+}
+
+
+package extern(D) void* getStackTop() nothrow @nogc
+{
+ version (D_InlineAsm_X86)
+ asm pure nothrow @nogc { naked; mov EAX, ESP; ret; }
+ else version (D_InlineAsm_X86_64)
+ asm pure nothrow @nogc { naked; mov RAX, RSP; ret; }
+ else version (GNU)
+ return __builtin_frame_address(0);
+ else
+ static assert(false, "Architecture not supported.");
+}
+
+
+package extern(D) void* getStackBottom() nothrow @nogc
+{
+ version (Windows)
+ {
+ version (D_InlineAsm_X86)
+ asm pure nothrow @nogc { naked; mov EAX, FS:4; ret; }
+ else version (D_InlineAsm_X86_64)
+ asm pure nothrow @nogc
+ { naked;
+ mov RAX, 8;
+ mov RAX, GS:[RAX];
+ ret;
+ }
+ else version (GNU_InlineAsm)
+ {
+ void *bottom;
+
+ version (X86)
+ asm pure nothrow @nogc { "movl %%fs:4, %0;" : "=r" bottom; }
+ else version (X86_64)
+ asm pure nothrow @nogc { "movq %%gs:8, %0;" : "=r" bottom; }
+ else
+ static assert(false, "Platform not supported.");
+
+ return bottom;
+ }
+ else
+ static assert(false, "Architecture not supported.");
+ }
+ else version (Darwin)
+ {
+ import core.sys.darwin.pthread;
+ return pthread_get_stackaddr_np(pthread_self());
+ }
+ else version (PThread_Getattr_NP)
+ {
+ pthread_attr_t attr;
+ void* addr; size_t size;
+
+ pthread_attr_init(&attr);
+ pthread_getattr_np(pthread_self(), &attr);
+ pthread_attr_getstack(&attr, &addr, &size);
+ pthread_attr_destroy(&attr);
+ static if (isStackGrowingDown)
+ addr += size;
+ return addr;
+ }
+ else version (PThread_Attr_Get_NP)
+ {
+ pthread_attr_t attr;
+ void* addr; size_t size;
+
+ pthread_attr_init(&attr);
+ pthread_attr_get_np(pthread_self(), &attr);
+ pthread_attr_getstack(&attr, &addr, &size);
+ pthread_attr_destroy(&attr);
+ static if (isStackGrowingDown)
+ addr += size;
+ return addr;
+ }
+ else version (OpenBSD)
+ {
+ stack_t stk;
+
+ pthread_stackseg_np(pthread_self(), &stk);
+ return stk.ss_sp;
+ }
+ else version (Solaris)
+ {
+ stack_t stk;
+
+ thr_stksegment(&stk);
+ return stk.ss_sp;
+ }
+ else
+ static assert(false, "Platform not supported.");
+}
+
+/**
+ * Suspend the specified thread and load stack and register information for
+ * use by thread_scanAll. If the supplied thread is the calling thread,
+ * stack and register information will be loaded but the thread will not
+ * be suspended. If the suspend operation fails and the thread is not
+ * running then it will be removed from the global thread list, otherwise
+ * an exception will be thrown.
+ *
+ * Params:
+ * t = The thread to suspend.
+ *
+ * Throws:
+ * ThreadError if the suspend operation fails for a running thread.
+ * Returns:
+ * Whether the thread is now suspended (true) or terminated (false).
+ */
+private extern (D) bool suspend( Thread t ) nothrow @nogc
+{
+ Duration waittime = dur!"usecs"(10);
+ Lagain:
+ if (!t.isRunning)
+ {
+ Thread.remove(t);
+ return false;
+ }
+ else if (t.m_isInCriticalRegion)
+ {
+ Thread.criticalRegionLock.unlock_nothrow();
+ Thread.sleep(waittime);
+ if (waittime < dur!"msecs"(10)) waittime *= 2;
+ Thread.criticalRegionLock.lock_nothrow();
+ goto Lagain;
+ }
+
+ version (Windows)
+ {
+ if ( t.m_addr != GetCurrentThreadId() && SuspendThread( t.m_hndl ) == 0xFFFFFFFF )
+ {
+ if ( !t.isRunning )
+ {
+ Thread.remove( t );
+ return false;
+ }
+ onThreadError( "Unable to suspend thread" );
+ }
+
+ CONTEXT context = void;
+ context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
+
+ if ( !GetThreadContext( t.m_hndl, &context ) )
+ onThreadError( "Unable to load thread context" );
+ version (X86)
+ {
+ if ( !t.m_lock )
+ t.m_curr.tstack = cast(void*) context.Esp;
+ // eax,ebx,ecx,edx,edi,esi,ebp,esp
+ t.m_reg[0] = context.Eax;
+ t.m_reg[1] = context.Ebx;
+ t.m_reg[2] = context.Ecx;
+ t.m_reg[3] = context.Edx;
+ t.m_reg[4] = context.Edi;
+ t.m_reg[5] = context.Esi;
+ t.m_reg[6] = context.Ebp;
+ t.m_reg[7] = context.Esp;
+ }
+ else version (X86_64)
+ {
+ if ( !t.m_lock )
+ t.m_curr.tstack = cast(void*) context.Rsp;
+ // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp
+ t.m_reg[0] = context.Rax;
+ t.m_reg[1] = context.Rbx;
+ t.m_reg[2] = context.Rcx;
+ t.m_reg[3] = context.Rdx;
+ t.m_reg[4] = context.Rdi;
+ t.m_reg[5] = context.Rsi;
+ t.m_reg[6] = context.Rbp;
+ t.m_reg[7] = context.Rsp;
+ // r8,r9,r10,r11,r12,r13,r14,r15
+ t.m_reg[8] = context.R8;
+ t.m_reg[9] = context.R9;
+ t.m_reg[10] = context.R10;
+ t.m_reg[11] = context.R11;
+ t.m_reg[12] = context.R12;
+ t.m_reg[13] = context.R13;
+ t.m_reg[14] = context.R14;
+ t.m_reg[15] = context.R15;
+ }
+ else
+ {
+ static assert(false, "Architecture not supported." );
+ }
+ }
+ else version (Darwin)
+ {
+ if ( t.m_addr != pthread_self() && thread_suspend( t.m_tmach ) != KERN_SUCCESS )
+ {
+ if ( !t.isRunning )
+ {
+ Thread.remove( t );
+ return false;
+ }
+ onThreadError( "Unable to suspend thread" );
+ }
+
+ version (X86)
+ {
+ x86_thread_state32_t state = void;
+ mach_msg_type_number_t count = x86_THREAD_STATE32_COUNT;
+
+ if ( thread_get_state( t.m_tmach, x86_THREAD_STATE32, &state, &count ) != KERN_SUCCESS )
+ onThreadError( "Unable to load thread state" );
+ if ( !t.m_lock )
+ t.m_curr.tstack = cast(void*) state.esp;
+ // eax,ebx,ecx,edx,edi,esi,ebp,esp
+ t.m_reg[0] = state.eax;
+ t.m_reg[1] = state.ebx;
+ t.m_reg[2] = state.ecx;
+ t.m_reg[3] = state.edx;
+ t.m_reg[4] = state.edi;
+ t.m_reg[5] = state.esi;
+ t.m_reg[6] = state.ebp;
+ t.m_reg[7] = state.esp;
+ }
+ else version (X86_64)
+ {
+ x86_thread_state64_t state = void;
+ mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
+
+ if ( thread_get_state( t.m_tmach, x86_THREAD_STATE64, &state, &count ) != KERN_SUCCESS )
+ onThreadError( "Unable to load thread state" );
+ if ( !t.m_lock )
+ t.m_curr.tstack = cast(void*) state.rsp;
+ // rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp
+ t.m_reg[0] = state.rax;
+ t.m_reg[1] = state.rbx;
+ t.m_reg[2] = state.rcx;
+ t.m_reg[3] = state.rdx;
+ t.m_reg[4] = state.rdi;
+ t.m_reg[5] = state.rsi;
+ t.m_reg[6] = state.rbp;
+ t.m_reg[7] = state.rsp;
+ // r8,r9,r10,r11,r12,r13,r14,r15
+ t.m_reg[8] = state.r8;
+ t.m_reg[9] = state.r9;
+ t.m_reg[10] = state.r10;
+ t.m_reg[11] = state.r11;
+ t.m_reg[12] = state.r12;
+ t.m_reg[13] = state.r13;
+ t.m_reg[14] = state.r14;
+ t.m_reg[15] = state.r15;
+ }
+ else version (AArch64)
+ {
+ arm_thread_state64_t state = void;
+ mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT;
+
+ if (thread_get_state(t.m_tmach, ARM_THREAD_STATE64, &state, &count) != KERN_SUCCESS)
+ onThreadError("Unable to load thread state");
+ // TODO: ThreadException here recurses forever! Does it
+ //still using onThreadError?
+ //printf("state count %d (expect %d)\n", count ,ARM_THREAD_STATE64_COUNT);
+ if (!t.m_lock)
+ t.m_curr.tstack = cast(void*) state.sp;
+
+ t.m_reg[0..29] = state.x; // x0-x28
+ t.m_reg[29] = state.fp; // x29
+ t.m_reg[30] = state.lr; // x30
+ t.m_reg[31] = state.sp; // x31
+ t.m_reg[32] = state.pc;
+ }
+ else version (ARM)
+ {
+ arm_thread_state32_t state = void;
+ mach_msg_type_number_t count = ARM_THREAD_STATE32_COUNT;
+
+ // Thought this would be ARM_THREAD_STATE32, but that fails.
+ // Mystery
+ if (thread_get_state(t.m_tmach, ARM_THREAD_STATE, &state, &count) != KERN_SUCCESS)
+ onThreadError("Unable to load thread state");
+ // TODO: in past, ThreadException here recurses forever! Does it
+ //still using onThreadError?
+ //printf("state count %d (expect %d)\n", count ,ARM_THREAD_STATE32_COUNT);
+ if (!t.m_lock)
+ t.m_curr.tstack = cast(void*) state.sp;
+
+ t.m_reg[0..13] = state.r; // r0 - r13
+ t.m_reg[13] = state.sp;
+ t.m_reg[14] = state.lr;
+ t.m_reg[15] = state.pc;
+ }
+ else
+ {
+ static assert(false, "Architecture not supported." );
+ }
+ }
+ else version (Posix)
+ {
+ if ( t.m_addr != pthread_self() )
+ {
+ if ( pthread_kill( t.m_addr, suspendSignalNumber ) != 0 )
+ {
+ if ( !t.isRunning )
+ {
+ Thread.remove( t );
+ return false;
+ }
+ onThreadError( "Unable to suspend thread" );
+ }
+ }
+ else if ( !t.m_lock )
+ {
+ t.m_curr.tstack = getStackTop();
+ }
+ }
+ return true;
+}
+
+/**
+ * Suspend all threads but the calling thread for "stop the world" garbage
+ * collection runs. This function may be called multiple times, and must
+ * be followed by a matching number of calls to thread_resumeAll before
+ * processing is resumed.
+ *
+ * Throws:
+ * ThreadError if the suspend operation fails for a running thread.
+ */
+extern (C) void thread_suspendAll() nothrow
+{
+ // NOTE: We've got an odd chicken & egg problem here, because while the GC
+ // is required to call thread_init before calling any other thread
+ // routines, thread_init may allocate memory which could in turn
+ // trigger a collection. Thus, thread_suspendAll, thread_scanAll,
+ // and thread_resumeAll must be callable before thread_init
+ // completes, with the assumption that no other GC memory has yet
+ // been allocated by the system, and thus there is no risk of losing
+ // data if the global thread list is empty. The check of
+ // Thread.sm_tbeg below is done to ensure thread_init has completed,
+ // and therefore that calling Thread.getThis will not result in an
+ // error. For the short time when Thread.sm_tbeg is null, there is
+ // no reason not to simply call the multithreaded code below, with
+ // the expectation that the foreach loop will never be entered.
+ if ( !multiThreadedFlag && Thread.sm_tbeg )
+ {
+ if ( ++suspendDepth == 1 )
+ suspend( Thread.getThis() );
+
+ return;
+ }
+
+ Thread.slock.lock_nothrow();
+ {
+ if ( ++suspendDepth > 1 )
+ return;
+
+ Thread.criticalRegionLock.lock_nothrow();
+ scope (exit) Thread.criticalRegionLock.unlock_nothrow();
+ size_t cnt;
+ Thread t = ThreadBase.sm_tbeg.toThread;
+ while (t)
+ {
+ auto tn = t.next.toThread;
+ if (suspend(t))
+ ++cnt;
+ t = tn;
+ }
+
+ version (Darwin)
+ {}
+ else version (Posix)
+ {
+ // subtract own thread
+ assert(cnt >= 1);
+ --cnt;
+ Lagain:
+ // wait for semaphore notifications
+ for (; cnt; --cnt)
+ {
+ while (sem_wait(&suspendCount) != 0)
+ {
+ if (errno != EINTR)
+ onThreadError("Unable to wait for semaphore");
+ errno = 0;
+ }
+ }
+ version (FreeBSD)
+ {
+ // avoid deadlocks, see Issue 13416
+ t = ThreadBase.sm_tbeg.toThread;
+ while (t)
+ {
+ auto tn = t.next;
+ if (t.m_suspendagain && suspend(t))
+ ++cnt;
+ t = tn.toThread;
+ }
+ if (cnt)
+ goto Lagain;
+ }
+ }
+ }
+}
+
+/**
+ * Resume the specified thread and unload stack and register information.
+ * If the supplied thread is the calling thread, stack and register
+ * information will be unloaded but the thread will not be resumed. If
+ * the resume operation fails and the thread is not running then it will
+ * be removed from the global thread list, otherwise an exception will be
+ * thrown.
+ *
+ * Params:
+ * t = The thread to resume.
+ *
+ * Throws:
+ * ThreadError if the resume fails for a running thread.
+ */
+private extern (D) void resume(ThreadBase _t) nothrow @nogc
+{
+ Thread t = _t.toThread;
+
+ version (Windows)
+ {
+ if ( t.m_addr != GetCurrentThreadId() && ResumeThread( t.m_hndl ) == 0xFFFFFFFF )
+ {
+ if ( !t.isRunning )
+ {
+ Thread.remove( t );
+ return;
+ }
+ onThreadError( "Unable to resume thread" );
+ }
+
+ if ( !t.m_lock )
+ t.m_curr.tstack = t.m_curr.bstack;
+ t.m_reg[0 .. $] = 0;
+ }
+ else version (Darwin)
+ {
+ if ( t.m_addr != pthread_self() && thread_resume( t.m_tmach ) != KERN_SUCCESS )
+ {
+ if ( !t.isRunning )
+ {
+ Thread.remove( t );
+ return;
+ }
+ onThreadError( "Unable to resume thread" );
+ }
+
+ if ( !t.m_lock )
+ t.m_curr.tstack = t.m_curr.bstack;
+ t.m_reg[0 .. $] = 0;
+ }
+ else version (Posix)
+ {
+ if ( t.m_addr != pthread_self() )
+ {
+ if ( pthread_kill( t.m_addr, resumeSignalNumber ) != 0 )
+ {
+ if ( !t.isRunning )
+ {
+ Thread.remove( t );
+ return;
+ }
+ onThreadError( "Unable to resume thread" );
+ }
+ }
+ else if ( !t.m_lock )
+ {
+ t.m_curr.tstack = t.m_curr.bstack;
+ }
+ }
+}
+
+
+/**
+ * Initializes the thread module. This function must be called by the
+ * garbage collector on startup and before any other thread routines
+ * are called.
+ */
+extern (C) void thread_init() @nogc
+{
+ // NOTE: If thread_init itself performs any allocations then the thread
+ // routines reserved for garbage collector use may be called while
+ // thread_init is being processed. However, since no memory should
+ // exist to be scanned at this point, it is sufficient for these
+ // functions to detect the condition and return immediately.
+
+ initLowlevelThreads();
+ Thread.initLocks();
+
+ // The Android VM runtime intercepts SIGUSR1 and apparently doesn't allow
+ // its signal handler to run, so swap the two signals on Android, since
+ // thread_resumeHandler does nothing.
+ version (Android) thread_setGCSignals(SIGUSR2, SIGUSR1);
+
+ version (Darwin)
+ {
+ // thread id different in forked child process
+ static extern(C) void initChildAfterFork()
+ {
+ auto thisThread = Thread.getThis();
+ thisThread.m_addr = pthread_self();
+ assert( thisThread.m_addr != thisThread.m_addr.init );
+ thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr );
+ assert( thisThread.m_tmach != thisThread.m_tmach.init );
+ }
+ pthread_atfork(null, null, &initChildAfterFork);
+ }
+ else version (Posix)
+ {
+ int status;
+ sigaction_t suspend = void;
+ sigaction_t resume = void;
+
+ // This is a quick way to zero-initialize the structs without using
+ // memset or creating a link dependency on their static initializer.
+ (cast(byte*) &suspend)[0 .. sigaction_t.sizeof] = 0;
+ (cast(byte*) &resume)[0 .. sigaction_t.sizeof] = 0;
+
+ // NOTE: SA_RESTART indicates that system calls should restart if they
+ // are interrupted by a signal, but this is not available on all
+ // Posix systems, even those that support multithreading.
+ static if ( __traits( compiles, SA_RESTART ) )
+ suspend.sa_flags = SA_RESTART;
+
+ suspend.sa_handler = &thread_suspendHandler;
+ // NOTE: We want to ignore all signals while in this handler, so fill
+ // sa_mask to indicate this.
+ status = sigfillset( &suspend.sa_mask );
+ assert( status == 0 );
+
+ // NOTE: Since resumeSignalNumber should only be issued for threads within the
+ // suspend handler, we don't want this signal to trigger a
+ // restart.
+ resume.sa_flags = 0;
+ resume.sa_handler = &thread_resumeHandler;
+ // NOTE: We want to ignore all signals while in this handler, so fill
+ // sa_mask to indicate this.
+ status = sigfillset( &resume.sa_mask );
+ assert( status == 0 );
+
+ status = sigaction( suspendSignalNumber, &suspend, null );
+ assert( status == 0 );
+
+ status = sigaction( resumeSignalNumber, &resume, null );
+ assert( status == 0 );
+
+ status = sem_init( &suspendCount, 0, 0 );
+ assert( status == 0 );
+ }
+ if (typeid(Thread).initializer.ptr)
+ _mainThreadStore[] = typeid(Thread).initializer[];
+ Thread.sm_main = attachThread((cast(Thread)_mainThreadStore.ptr).__ctor());
+}
+
+private alias MainThreadStore = void[__traits(classInstanceSize, Thread)];
+package __gshared align(Thread.alignof) MainThreadStore _mainThreadStore;
+
+/**
+ * Terminates the thread module. No other thread routine may be called
+ * afterwards.
+ */
+extern (C) void thread_term() @nogc
+{
+ thread_term_tpl!(Thread)(_mainThreadStore);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread Entry Point and Signal Handlers
+///////////////////////////////////////////////////////////////////////////////
+
+
+version (Windows)
+{
+ private
+ {
+ //
+ // Entry point for Windows threads
+ //
+ extern (Windows) uint thread_entryPoint( void* arg ) nothrow
+ {
+ Thread obj = cast(Thread) arg;
+ assert( obj );
+
+ obj.initDataStorage();
+
+ Thread.setThis(obj);
+ Thread.add(obj);
+ scope (exit)
+ {
+ Thread.remove(obj);
+ obj.destroyDataStorage();
+ }
+ Thread.add(&obj.m_main);
+
+ // NOTE: No GC allocations may occur until the stack pointers have
+ // been set and Thread.getThis returns a valid reference to
+ // this thread object (this latter condition is not strictly
+ // necessary on Windows but it should be followed for the
+ // sake of consistency).
+
+ // TODO: Consider putting an auto exception object here (using
+ // alloca) forOutOfMemoryError plus something to track
+ // whether an exception is in-flight?
+
+ void append( Throwable t )
+ {
+ if ( obj.m_unhandled is null )
+ obj.m_unhandled = t;
+ else
+ {
+ Throwable last = obj.m_unhandled;
+ while ( last.next !is null )
+ last = last.next;
+ last.next = t;
+ }
+ }
+
+ version (D_InlineAsm_X86)
+ {
+ asm nothrow @nogc { fninit; }
+ }
+
+ try
+ {
+ rt_moduleTlsCtor();
+ try
+ {
+ obj.run();
+ }
+ catch ( Throwable t )
+ {
+ append( t );
+ }
+ rt_moduleTlsDtor();
+ }
+ catch ( Throwable t )
+ {
+ append( t );
+ }
+ return 0;
+ }
+
+
+ HANDLE GetCurrentThreadHandle() nothrow @nogc
+ {
+ const uint DUPLICATE_SAME_ACCESS = 0x00000002;
+
+ HANDLE curr = GetCurrentThread(),
+ proc = GetCurrentProcess(),
+ hndl;
+
+ DuplicateHandle( proc, curr, proc, &hndl, 0, TRUE, DUPLICATE_SAME_ACCESS );
+ return hndl;
+ }
+ }
+}
+else version (Posix)
+{
+ private
+ {
+ import core.stdc.errno;
+ import core.sys.posix.semaphore;
+ import core.sys.posix.stdlib; // for malloc, valloc, free, atexit
+ import core.sys.posix.pthread;
+ import core.sys.posix.signal;
+ import core.sys.posix.time;
+
+ version (Darwin)
+ {
+ import core.sys.darwin.mach.thread_act;
+ import core.sys.darwin.pthread : pthread_mach_thread_np;
+ }
+
+ //
+ // Entry point for POSIX threads
+ //
+ extern (C) void* thread_entryPoint( void* arg ) nothrow
+ {
+ version (Shared)
+ {
+ Thread obj = cast(Thread)(cast(void**)arg)[0];
+ auto loadedLibraries = (cast(void**)arg)[1];
+ .free(arg);
+ }
+ else
+ {
+ Thread obj = cast(Thread)arg;
+ }
+ assert( obj );
+
+ // loadedLibraries need to be inherited from parent thread
+ // before initilizing GC for TLS (rt_tlsgc_init)
+ version (GNUShared)
+ {
+ externDFunc!("gcc.sections.elf_shared.inheritLoadedLibraries",
+ void function(void*) @nogc nothrow)(loadedLibraries);
+ }
+ else version (Shared)
+ {
+ externDFunc!("rt.sections_elf_shared.inheritLoadedLibraries",
+ void function(void*) @nogc nothrow)(loadedLibraries);
+ }
+
+ obj.initDataStorage();
+
+ atomicStore!(MemoryOrder.raw)(obj.m_isRunning, true);
+ Thread.setThis(obj); // allocates lazy TLS (see Issue 11981)
+ Thread.add(obj); // can only receive signals from here on
+ scope (exit)
+ {
+ Thread.remove(obj);
+ atomicStore!(MemoryOrder.raw)(obj.m_isRunning, false);
+ obj.destroyDataStorage();
+ }
+ Thread.add(&obj.m_main);
+
+ static extern (C) void thread_cleanupHandler( void* arg ) nothrow @nogc
+ {
+ Thread obj = cast(Thread) arg;
+ assert( obj );
+
+ // NOTE: If the thread terminated abnormally, just set it as
+ // not running and let thread_suspendAll remove it from
+ // the thread list. This is safer and is consistent
+ // with the Windows thread code.
+ atomicStore!(MemoryOrder.raw)(obj.m_isRunning,false);
+ }
+
+ // NOTE: Using void to skip the initialization here relies on
+ // knowledge of how pthread_cleanup is implemented. It may
+ // not be appropriate for all platforms. However, it does
+ // avoid the need to link the pthread module. If any
+ // implementation actually requires default initialization
+ // then pthread_cleanup should be restructured to maintain
+ // the current lack of a link dependency.
+ static if ( __traits( compiles, pthread_cleanup ) )
+ {
+ pthread_cleanup cleanup = void;
+ cleanup.push( &thread_cleanupHandler, cast(void*) obj );
+ }
+ else static if ( __traits( compiles, pthread_cleanup_push ) )
+ {
+ pthread_cleanup_push( &thread_cleanupHandler, cast(void*) obj );
+ }
+ else
+ {
+ static assert( false, "Platform not supported." );
+ }
+
+ // NOTE: No GC allocations may occur until the stack pointers have
+ // been set and Thread.getThis returns a valid reference to
+ // this thread object (this latter condition is not strictly
+ // necessary on Windows but it should be followed for the
+ // sake of consistency).
+
+ // TODO: Consider putting an auto exception object here (using
+ // alloca) forOutOfMemoryError plus something to track
+ // whether an exception is in-flight?
+
+ void append( Throwable t )
+ {
+ if ( obj.m_unhandled is null )
+ obj.m_unhandled = t;
+ else
+ {
+ Throwable last = obj.m_unhandled;
+ while ( last.next !is null )
+ last = last.next;
+ last.next = t;
+ }
+ }
+ try
+ {
+ rt_moduleTlsCtor();
+ try
+ {
+ obj.run();
+ }
+ catch ( Throwable t )
+ {
+ append( t );
+ }
+ rt_moduleTlsDtor();
+ version (GNUShared)
+ {
+ externDFunc!("gcc.sections.elf_shared.cleanupLoadedLibraries",
+ void function() @nogc nothrow)();
+ }
+ else version (Shared)
+ {
+ externDFunc!("rt.sections_elf_shared.cleanupLoadedLibraries",
+ void function() @nogc nothrow)();
+ }
+ }
+ catch ( Throwable t )
+ {
+ append( t );
+ }
+
+ // NOTE: Normal cleanup is handled by scope(exit).
+
+ static if ( __traits( compiles, pthread_cleanup ) )
+ {
+ cleanup.pop( 0 );
+ }
+ else static if ( __traits( compiles, pthread_cleanup_push ) )
+ {
+ pthread_cleanup_pop( 0 );
+ }
+
+ return null;
+ }
+
+
+ //
+ // Used to track the number of suspended threads
+ //
+ __gshared sem_t suspendCount;
+
+
+ extern (C) void thread_suspendHandler( int sig ) nothrow
+ in
+ {
+ assert( sig == suspendSignalNumber );
+ }
+ do
+ {
+ void op(void* sp) nothrow
+ {
+ // NOTE: Since registers are being pushed and popped from the
+ // stack, any other stack data used by this function should
+ // be gone before the stack cleanup code is called below.
+ Thread obj = Thread.getThis();
+ assert(obj !is null);
+
+ if ( !obj.m_lock )
+ {
+ obj.m_curr.tstack = getStackTop();
+ }
+
+ sigset_t sigres = void;
+ int status;
+
+ status = sigfillset( &sigres );
+ assert( status == 0 );
+
+ status = sigdelset( &sigres, resumeSignalNumber );
+ assert( status == 0 );
+
+ version (FreeBSD) obj.m_suspendagain = false;
+ status = sem_post( &suspendCount );
+ assert( status == 0 );
+
+ sigsuspend( &sigres );
+
+ if ( !obj.m_lock )
+ {
+ obj.m_curr.tstack = obj.m_curr.bstack;
+ }
+ }
+
+ // avoid deadlocks on FreeBSD, see Issue 13416
+ version (FreeBSD)
+ {
+ auto obj = Thread.getThis();
+ if (THR_IN_CRITICAL(obj.m_addr))
+ {
+ obj.m_suspendagain = true;
+ if (sem_post(&suspendCount)) assert(0);
+ return;
+ }
+ }
+
+ callWithStackShell(&op);
+ }
+
+
+ extern (C) void thread_resumeHandler( int sig ) nothrow
+ in
+ {
+ assert( sig == resumeSignalNumber );
+ }
+ do
+ {
+
+ }
+
+ // HACK libthr internal (thr_private.h) macro, used to
+ // avoid deadlocks in signal handler, see Issue 13416
+ version (FreeBSD) bool THR_IN_CRITICAL(pthread_t p) nothrow @nogc
+ {
+ import core.sys.posix.config : c_long;
+ import core.sys.posix.sys.types : lwpid_t;
+
+ // If the begin of pthread would be changed in libthr (unlikely)
+ // we'll run into undefined behavior, compare with thr_private.h.
+ static struct pthread
+ {
+ c_long tid;
+ static struct umutex { lwpid_t owner; uint flags; uint[2] ceilings; uint[4] spare; }
+ umutex lock;
+ uint cycle;
+ int locklevel;
+ int critical_count;
+ // ...
+ }
+ auto priv = cast(pthread*)p;
+ return priv.locklevel > 0 || priv.critical_count > 0;
+ }
+ }
+}
+else
+{
+ // NOTE: This is the only place threading versions are checked. If a new
+ // version is added, the module code will need to be searched for
+ // places where version-specific code may be required. This can be
+ // easily accomlished by searching for 'Windows' or 'Posix'.
+ static assert( false, "Unknown threading implementation." );
+}
+
+//
+// exposed by compiler runtime
+//
+extern (C) void rt_moduleTlsCtor();
+extern (C) void rt_moduleTlsDtor();
+
+
+// regression test for Issue 13416
+version (FreeBSD) unittest
+{
+ static void loop()
+ {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ auto thr = pthread_self();
+ foreach (i; 0 .. 50)
+ pthread_attr_get_np(thr, &attr);
+ pthread_attr_destroy(&attr);
+ }
+
+ auto thr = new Thread(&loop).start();
+ foreach (i; 0 .. 50)
+ {
+ thread_suspendAll();
+ thread_resumeAll();
+ }
+ thr.join();
+}
+
+version (DragonFlyBSD) unittest
+{
+ static void loop()
+ {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ auto thr = pthread_self();
+ foreach (i; 0 .. 50)
+ pthread_attr_get_np(thr, &attr);
+ pthread_attr_destroy(&attr);
+ }
+
+ auto thr = new Thread(&loop).start();
+ foreach (i; 0 .. 50)
+ {
+ thread_suspendAll();
+ thread_resumeAll();
+ }
+ thr.join();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// lowlovel threading support
+///////////////////////////////////////////////////////////////////////////////
+
+private
+{
+ version (Windows):
+ // If the runtime is dynamically loaded as a DLL, there is a problem with
+ // threads still running when the DLL is supposed to be unloaded:
+ //
+ // - with the VC runtime starting with VS2015 (i.e. using the Universal CRT)
+ // a thread created with _beginthreadex increments the DLL reference count
+ // and decrements it when done, so that the DLL is no longer unloaded unless
+ // all the threads have terminated. With the DLL reference count held up
+ // by a thread that is only stopped by a signal from a static destructor or
+ // the termination of the runtime will cause the DLL to never be unloaded.
+ //
+ // - with the DigitalMars runtime and VC runtime up to VS2013, the thread
+ // continues to run, but crashes once the DLL is unloaded from memory as
+ // the code memory is no longer accessible. Stopping the threads is not possible
+ // from within the runtime termination as it is invoked from
+ // DllMain(DLL_PROCESS_DETACH) holding a lock that prevents threads from
+ // terminating.
+ //
+ // Solution: start a watchdog thread that keeps the DLL reference count above 0 and
+ // checks it periodically. If it is equal to 1 (plus the number of started threads), no
+ // external references to the DLL exist anymore, threads can be stopped
+ // and runtime termination and DLL unload can be invoked via FreeLibraryAndExitThread.
+ // Note: runtime termination is then performed by a different thread than at startup.
+ //
+ // Note: if the DLL is never unloaded, process termination kills all threads
+ // and signals their handles before unconditionally calling DllMain(DLL_PROCESS_DETACH).
+
+ import core.sys.windows.winbase : FreeLibraryAndExitThread, GetModuleHandleExW,
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
+ import core.sys.windows.windef : HMODULE;
+ import core.sys.windows.dll : dll_getRefCount;
+
+ version (CRuntime_Microsoft)
+ extern(C) extern __gshared ubyte msvcUsesUCRT; // from rt/msvc.d
+
+ /// set during termination of a DLL on Windows, i.e. while executing DllMain(DLL_PROCESS_DETACH)
+ public __gshared bool thread_DLLProcessDetaching;
+
+ __gshared HMODULE ll_dllModule;
+ __gshared ThreadID ll_dllMonitorThread;
+
+ int ll_countLowLevelThreadsWithDLLUnloadCallback() nothrow
+ {
+ lowlevelLock.lock_nothrow();
+ scope(exit) lowlevelLock.unlock_nothrow();
+
+ int cnt = 0;
+ foreach (i; 0 .. ll_nThreads)
+ if (ll_pThreads[i].cbDllUnload)
+ cnt++;
+ return cnt;
+ }
+
+ bool ll_dllHasExternalReferences() nothrow
+ {
+ version (CRuntime_DigitalMars)
+ enum internalReferences = 1; // only the watchdog thread
+ else
+ int internalReferences = msvcUsesUCRT ? 1 + ll_countLowLevelThreadsWithDLLUnloadCallback() : 1;
+
+ int refcnt = dll_getRefCount(ll_dllModule);
+ return refcnt > internalReferences;
+ }
+
+ private void monitorDLLRefCnt() nothrow
+ {
+ // this thread keeps the DLL alive until all external references are gone
+ while (ll_dllHasExternalReferences())
+ {
+ Thread.sleep(100.msecs);
+ }
+
+ // the current thread will be terminated below
+ ll_removeThread(GetCurrentThreadId());
+
+ for (;;)
+ {
+ ThreadID tid;
+ void delegate() nothrow cbDllUnload;
+ {
+ lowlevelLock.lock_nothrow();
+ scope(exit) lowlevelLock.unlock_nothrow();
+
+ foreach (i; 0 .. ll_nThreads)
+ if (ll_pThreads[i].cbDllUnload)
+ {
+ cbDllUnload = ll_pThreads[i].cbDllUnload;
+ tid = ll_pThreads[0].tid;
+ }
+ }
+ if (!cbDllUnload)
+ break;
+ cbDllUnload();
+ assert(!findLowLevelThread(tid));
+ }
+
+ FreeLibraryAndExitThread(ll_dllModule, 0);
+ }
+
+ int ll_getDLLRefCount() nothrow @nogc
+ {
+ if (!ll_dllModule &&
+ !GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ cast(const(wchar)*) &ll_getDLLRefCount, &ll_dllModule))
+ return -1;
+ return dll_getRefCount(ll_dllModule);
+ }
+
+ bool ll_startDLLUnloadThread() nothrow @nogc
+ {
+ int refcnt = ll_getDLLRefCount();
+ if (refcnt < 0)
+ return false; // not a dynamically loaded DLL
+
+ if (ll_dllMonitorThread !is ThreadID.init)
+ return true;
+
+ // if a thread is created from a DLL, the MS runtime (starting with VC2015) increments the DLL reference count
+ // to avoid the DLL being unloaded while the thread is still running. Mimick this behavior here for all
+ // runtimes not doing this
+ version (CRuntime_DigitalMars)
+ enum needRef = true;
+ else
+ bool needRef = !msvcUsesUCRT;
+
+ if (needRef)
+ {
+ HMODULE hmod;
+ GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, cast(const(wchar)*) &ll_getDLLRefCount, &hmod);
+ }
+
+ ll_dllMonitorThread = createLowLevelThread(() { monitorDLLRefCnt(); });
+ return ll_dllMonitorThread != ThreadID.init;
+ }
+}
+
+/**
+ * Create a thread not under control of the runtime, i.e. TLS module constructors are
+ * not run and the GC does not suspend it during a collection.
+ *
+ * Params:
+ * dg = delegate to execute in the created thread.
+ * stacksize = size of the stack of the created thread. The default of 0 will select the
+ * platform-specific default size.
+ * cbDllUnload = Windows only: if running in a dynamically loaded DLL, this delegate will be called
+ * if the DLL is supposed to be unloaded, but the thread is still running.
+ * The thread must be terminated via `joinLowLevelThread` by the callback.
+ *
+ * Returns: the platform specific thread ID of the new thread. If an error occurs, `ThreadID.init`
+ * is returned.
+ */
+ThreadID createLowLevelThread(void delegate() nothrow dg, uint stacksize = 0,
+ void delegate() nothrow cbDllUnload = null) nothrow @nogc
+{
+ void delegate() nothrow* context = cast(void delegate() nothrow*)malloc(dg.sizeof);
+ *context = dg;
+
+ ThreadID tid;
+ version (Windows)
+ {
+ // the thread won't start until after the DLL is unloaded
+ if (thread_DLLProcessDetaching)
+ return ThreadID.init;
+
+ static extern (Windows) uint thread_lowlevelEntry(void* ctx) nothrow
+ {
+ auto dg = *cast(void delegate() nothrow*)ctx;
+ free(ctx);
+
+ dg();
+ ll_removeThread(GetCurrentThreadId());
+ return 0;
+ }
+
+ // see Thread.start() for why thread is created in suspended state
+ HANDLE hThread = cast(HANDLE) _beginthreadex(null, stacksize, &thread_lowlevelEntry,
+ context, CREATE_SUSPENDED, &tid);
+ if (!hThread)
+ return ThreadID.init;
+ }
+
+ lowlevelLock.lock_nothrow();
+ scope(exit) lowlevelLock.unlock_nothrow();
+
+ ll_nThreads++;
+ ll_pThreads = cast(ll_ThreadData*)realloc(ll_pThreads, ll_ThreadData.sizeof * ll_nThreads);
+
+ version (Windows)
+ {
+ ll_pThreads[ll_nThreads - 1].tid = tid;
+ ll_pThreads[ll_nThreads - 1].cbDllUnload = cbDllUnload;
+ if (ResumeThread(hThread) == -1)
+ onThreadError("Error resuming thread");
+ CloseHandle(hThread);
+
+ if (cbDllUnload)
+ ll_startDLLUnloadThread();
+ }
+ else version (Posix)
+ {
+ static extern (C) void* thread_lowlevelEntry(void* ctx) nothrow
+ {
+ auto dg = *cast(void delegate() nothrow*)ctx;
+ free(ctx);
+
+ dg();
+ ll_removeThread(pthread_self());
+ return null;
+ }
+
+ size_t stksz = adjustStackSize(stacksize);
+
+ pthread_attr_t attr;
+
+ int rc;
+ if ((rc = pthread_attr_init(&attr)) != 0)
+ return ThreadID.init;
+ if (stksz && (rc = pthread_attr_setstacksize(&attr, stksz)) != 0)
+ return ThreadID.init;
+ if ((rc = pthread_create(&tid, &attr, &thread_lowlevelEntry, context)) != 0)
+ return ThreadID.init;
+ if ((rc = pthread_attr_destroy(&attr)) != 0)
+ return ThreadID.init;
+
+ ll_pThreads[ll_nThreads - 1].tid = tid;
+ }
+ return tid;
+}
+
+/**
+ * Wait for a thread created with `createLowLevelThread` to terminate.
+ *
+ * Note: In a Windows DLL, if this function is called via DllMain with
+ * argument DLL_PROCESS_DETACH, the thread is terminated forcefully
+ * without proper cleanup as a deadlock would happen otherwise.
+ *
+ * Params:
+ * tid = the thread ID returned by `createLowLevelThread`.
+ */
+void joinLowLevelThread(ThreadID tid) nothrow @nogc
+{
+ version (Windows)
+ {
+ HANDLE handle = OpenThreadHandle(tid);
+ if (!handle)
+ return;
+
+ if (thread_DLLProcessDetaching)
+ {
+ // When being called from DllMain/DLL_DETACH_PROCESS, threads cannot stop
+ // due to the loader lock being held by the current thread.
+ // On the other hand, the thread must not continue to run as it will crash
+ // if the DLL is unloaded. The best guess is to terminate it immediately.
+ TerminateThread(handle, 1);
+ WaitForSingleObject(handle, 10); // give it some time to terminate, but don't wait indefinitely
+ }
+ else
+ WaitForSingleObject(handle, INFINITE);
+ CloseHandle(handle);
+ }
+ else version (Posix)
+ {
+ if (pthread_join(tid, null) != 0)
+ onThreadError("Unable to join thread");
+ }
+}
+
+nothrow @nogc unittest
+{
+ struct TaskWithContect
+ {
+ shared int n = 0;
+ void run() nothrow
+ {
+ n.atomicOp!"+="(1);
+ }
+ }
+ TaskWithContect task;
+
+ ThreadID[8] tids;
+ for (int i = 0; i < tids.length; i++)
+ {
+ tids[i] = createLowLevelThread(&task.run);
+ assert(tids[i] != ThreadID.init);
+ }
+
+ for (int i = 0; i < tids.length; i++)
+ joinLowLevelThread(tids[i]);
+
+ assert(task.n == tids.length);
+}
+
+version (Posix)
+private size_t adjustStackSize(size_t sz) nothrow @nogc
+{
+ if (sz == 0)
+ return 0;
+
+ // stack size must be at least PTHREAD_STACK_MIN for most platforms.
+ if (PTHREAD_STACK_MIN > sz)
+ sz = PTHREAD_STACK_MIN;
+
+ version (CRuntime_Glibc)
+ {
+ // On glibc, TLS uses the top of the stack, so add its size to the requested size
+ version (GNU)
+ {
+ sz += externDFunc!("gcc.sections.elf_shared.sizeOfTLS",
+ size_t function() @nogc nothrow)();
+ }
+ else
+ {
+ sz += externDFunc!("rt.sections_elf_shared.sizeOfTLS",
+ size_t function() @nogc nothrow)();
+ }
+ }
+
+ // stack size must be a multiple of PAGESIZE
+ sz = ((sz + PAGESIZE - 1) & ~(PAGESIZE - 1));
+
+ return sz;
+}
--- /dev/null
+/**
+ * The thread module provides support for thread creation and management.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2012.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
+ * Source: $(DRUNTIMESRC core/thread/package.d)
+ */
+
+module core.thread;
+
+public import core.time;
+public import core.thread.fiber;
+public import core.thread.osthread;
+public import core.thread.threadbase;
+public import core.thread.threadgroup;
+public import core.thread.types;
+public import core.thread.context;
--- /dev/null
+/**
+ * The threadbase module provides OS-independent code
+ * for thread storage and management.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2012.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
+ * Source: $(DRUNTIMESRC core/thread/osthread.d)
+ */
+
+module core.thread.threadbase;
+
+import core.thread.context;
+import core.thread.types;
+import core.time;
+import core.sync.mutex;
+import core.stdc.stdlib : free, realloc;
+
+private
+{
+ import core.internal.traits : externDFunc;
+
+ // interface to rt.tlsgc
+ alias rt_tlsgc_init = externDFunc!("rt.tlsgc.init", void* function() nothrow @nogc);
+ alias rt_tlsgc_destroy = externDFunc!("rt.tlsgc.destroy", void function(void*) nothrow @nogc);
+
+ alias ScanDg = void delegate(void* pstart, void* pend) nothrow;
+ alias rt_tlsgc_scan =
+ externDFunc!("rt.tlsgc.scan", void function(void*, scope ScanDg) nothrow);
+
+ alias rt_tlsgc_processGCMarks =
+ externDFunc!("rt.tlsgc.processGCMarks", void function(void*, scope IsMarkedDg) nothrow);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread and Fiber Exceptions
+///////////////////////////////////////////////////////////////////////////////
+
+
+/**
+ * Base class for thread exceptions.
+ */
+class ThreadException : Exception
+{
+ @nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
+ {
+ super(msg, file, line, next);
+ }
+
+ @nogc @safe pure nothrow this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
+ {
+ super(msg, file, line, next);
+ }
+}
+
+
+/**
+* Base class for thread errors to be used for function inside GC when allocations are unavailable.
+*/
+class ThreadError : Error
+{
+ @nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
+ {
+ super(msg, file, line, next);
+ }
+
+ @nogc @safe pure nothrow this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
+ {
+ super(msg, file, line, next);
+ }
+}
+
+private
+{
+ // Handling unaligned mutexes are not supported on all platforms, so we must
+ // ensure that the address of all shared data are appropriately aligned.
+ import core.internal.traits : classInstanceAlignment;
+
+ enum mutexAlign = classInstanceAlignment!Mutex;
+ enum mutexClassInstanceSize = __traits(classInstanceSize, Mutex);
+
+ alias swapContext = externDFunc!("core.thread.osthread.swapContext", void* function(void*) nothrow @nogc);
+
+ alias getStackBottom = externDFunc!("core.thread.osthread.getStackBottom", void* function() nothrow @nogc);
+ alias getStackTop = externDFunc!("core.thread.osthread.getStackTop", void* function() nothrow @nogc);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread
+///////////////////////////////////////////////////////////////////////////////
+
+
+class ThreadBase
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Initialization
+ ///////////////////////////////////////////////////////////////////////////
+
+ this(void function() fn, size_t sz = 0) @safe pure nothrow @nogc
+ in(fn)
+ {
+ this(sz);
+ m_call = fn;
+ }
+
+ this(void delegate() dg, size_t sz = 0) @safe pure nothrow @nogc
+ in(dg)
+ {
+ this(sz);
+ m_call = dg;
+ }
+
+ /**
+ * Cleans up any remaining resources used by this object.
+ */
+ package bool destructBeforeDtor() nothrow @nogc
+ {
+ destroyDataStorageIfAvail();
+
+ bool no_context = m_addr == m_addr.init;
+ bool not_registered = !next && !prev && (sm_tbeg !is this);
+
+ return (no_context || not_registered);
+ }
+
+ package void tlsGCdataInit() nothrow @nogc
+ {
+ m_tlsgcdata = rt_tlsgc_init();
+ }
+
+ package void initDataStorage() nothrow
+ {
+ assert(m_curr is &m_main);
+
+ m_main.bstack = getStackBottom();
+ m_main.tstack = m_main.bstack;
+ tlsGCdataInit();
+ }
+
+ package void destroyDataStorage() nothrow @nogc
+ {
+ rt_tlsgc_destroy(m_tlsgcdata);
+ m_tlsgcdata = null;
+ }
+
+ package void destroyDataStorageIfAvail() nothrow @nogc
+ {
+ if (m_tlsgcdata)
+ destroyDataStorage();
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // General Actions
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Waits for this thread to complete. If the thread terminated as the
+ * result of an unhandled exception, this exception will be rethrown.
+ *
+ * Params:
+ * rethrow = Rethrow any unhandled exception which may have caused this
+ * thread to terminate.
+ *
+ * Throws:
+ * ThreadException if the operation fails.
+ * Any exception not handled by the joined thread.
+ *
+ * Returns:
+ * Any exception not handled by this thread if rethrow = false, null
+ * otherwise.
+ */
+ abstract Throwable join(bool rethrow = true);
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // General Properties
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * Gets the OS identifier for this thread.
+ *
+ * Returns:
+ * If the thread hasn't been started yet, returns $(LREF ThreadID)$(D.init).
+ * Otherwise, returns the result of $(D GetCurrentThreadId) on Windows,
+ * and $(D pthread_self) on POSIX.
+ *
+ * The value is unique for the current process.
+ */
+ final @property ThreadID id() @safe @nogc
+ {
+ synchronized(this)
+ {
+ return m_addr;
+ }
+ }
+
+
+ /**
+ * Gets the user-readable label for this thread.
+ *
+ * Returns:
+ * The name of this thread.
+ */
+ final @property string name() @safe @nogc
+ {
+ synchronized(this)
+ {
+ return m_name;
+ }
+ }
+
+
+ /**
+ * Sets the user-readable label for this thread.
+ *
+ * Params:
+ * val = The new name of this thread.
+ */
+ final @property void name(string val) @safe @nogc
+ {
+ synchronized(this)
+ {
+ m_name = val;
+ }
+ }
+
+
+ /**
+ * Gets the daemon status for this thread. While the runtime will wait for
+ * all normal threads to complete before tearing down the process, daemon
+ * threads are effectively ignored and thus will not prevent the process
+ * from terminating. In effect, daemon threads will be terminated
+ * automatically by the OS when the process exits.
+ *
+ * Returns:
+ * true if this is a daemon thread.
+ */
+ final @property bool isDaemon() @safe @nogc
+ {
+ synchronized(this)
+ {
+ return m_isDaemon;
+ }
+ }
+
+
+ /**
+ * Sets the daemon status for this thread. While the runtime will wait for
+ * all normal threads to complete before tearing down the process, daemon
+ * threads are effectively ignored and thus will not prevent the process
+ * from terminating. In effect, daemon threads will be terminated
+ * automatically by the OS when the process exits.
+ *
+ * Params:
+ * val = The new daemon status for this thread.
+ */
+ final @property void isDaemon(bool val) @safe @nogc
+ {
+ synchronized(this)
+ {
+ m_isDaemon = val;
+ }
+ }
+
+ /**
+ * Tests whether this thread is the main thread, i.e. the thread
+ * that initialized the runtime
+ *
+ * Returns:
+ * true if the thread is the main thread
+ */
+ final @property bool isMainThread() nothrow @nogc
+ {
+ return this is sm_main;
+ }
+
+ /**
+ * Tests whether this thread is running.
+ *
+ * Returns:
+ * true if the thread is running, false if not.
+ */
+ @property bool isRunning() nothrow @nogc
+ {
+ if (m_addr == m_addr.init)
+ return false;
+
+ return true;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Thread Accessors
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Provides a reference to the calling thread.
+ *
+ * Returns:
+ * The thread object representing the calling thread. The result of
+ * deleting this object is undefined. If the current thread is not
+ * attached to the runtime, a null reference is returned.
+ */
+ static ThreadBase getThis() @safe nothrow @nogc
+ {
+ // NOTE: This function may not be called until thread_init has
+ // completed. See thread_suspendAll for more information
+ // on why this might occur.
+ return sm_this;
+ }
+
+
+ /**
+ * Provides a list of all threads currently being tracked by the system.
+ * Note that threads in the returned array might no longer run (see
+ * $(D ThreadBase.)$(LREF isRunning)).
+ *
+ * Returns:
+ * An array containing references to all threads currently being
+ * tracked by the system. The result of deleting any contained
+ * objects is undefined.
+ */
+ static ThreadBase[] getAll()
+ {
+ static void resize(ref ThreadBase[] buf, size_t nlen)
+ {
+ buf.length = nlen;
+ }
+ return getAllImpl!resize();
+ }
+
+
+ /**
+ * Operates on all threads currently being tracked by the system. The
+ * result of deleting any Thread object is undefined.
+ * Note that threads passed to the callback might no longer run (see
+ * $(D ThreadBase.)$(LREF isRunning)).
+ *
+ * Params:
+ * dg = The supplied code as a delegate.
+ *
+ * Returns:
+ * Zero if all elemented are visited, nonzero if not.
+ */
+ static int opApply(scope int delegate(ref ThreadBase) dg)
+ {
+ static void resize(ref ThreadBase[] buf, size_t nlen)
+ {
+ import core.exception: onOutOfMemoryError;
+
+ auto newBuf = cast(ThreadBase*)realloc(buf.ptr, nlen * size_t.sizeof);
+ if (newBuf is null) onOutOfMemoryError();
+ buf = newBuf[0 .. nlen];
+ }
+ auto buf = getAllImpl!resize;
+ scope(exit) if (buf.ptr) free(buf.ptr);
+
+ foreach (t; buf)
+ {
+ if (auto res = dg(t))
+ return res;
+ }
+ return 0;
+ }
+
+ private static ThreadBase[] getAllImpl(alias resize)()
+ {
+ import core.atomic;
+
+ ThreadBase[] buf;
+ while (true)
+ {
+ immutable len = atomicLoad!(MemoryOrder.raw)(*cast(shared)&sm_tlen);
+ resize(buf, len);
+ assert(buf.length == len);
+ synchronized (slock)
+ {
+ if (len == sm_tlen)
+ {
+ size_t pos;
+ for (ThreadBase t = sm_tbeg; t; t = t.next)
+ buf[pos++] = t;
+ return buf;
+ }
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Actions on Calling Thread
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Forces a context switch to occur away from the calling thread.
+ */
+ private static void yield() @nogc nothrow
+ {
+ thread_yield();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Stuff That Should Go Away
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Initializes a thread object which has no associated executable function.
+ // This is used for the main thread initialized in thread_init().
+ //
+ package this(size_t sz = 0) @safe pure nothrow @nogc
+ {
+ m_sz = sz;
+ m_curr = &m_main;
+ }
+
+ //
+ // Thread entry point. Invokes the function or delegate passed on
+ // construction (if any).
+ //
+ package final void run()
+ {
+ m_call();
+ }
+
+package:
+
+ //
+ // Local storage
+ //
+ static ThreadBase sm_this;
+
+
+ //
+ // Main process thread
+ //
+ __gshared ThreadBase sm_main;
+
+
+ //
+ // Standard thread data
+ //
+ ThreadID m_addr;
+ Callable m_call;
+ string m_name;
+ size_t m_sz;
+ bool m_isDaemon;
+ bool m_isInCriticalRegion;
+ Throwable m_unhandled;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Storage of Active Thread
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Sets a thread-local reference to the current thread object.
+ //
+ package static void setThis(ThreadBase t) nothrow @nogc
+ {
+ sm_this = t;
+ }
+
+package(core.thread):
+
+ StackContext m_main;
+ StackContext* m_curr;
+ bool m_lock;
+ private void* m_tlsgcdata;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Thread Context and GC Scanning Support
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ final void pushContext(StackContext* c) nothrow @nogc
+ in
+ {
+ assert(!c.within);
+ }
+ do
+ {
+ m_curr.ehContext = swapContext(c.ehContext);
+ c.within = m_curr;
+ m_curr = c;
+ }
+
+
+ final void popContext() nothrow @nogc
+ in
+ {
+ assert(m_curr && m_curr.within);
+ }
+ do
+ {
+ StackContext* c = m_curr;
+ m_curr = c.within;
+ c.ehContext = swapContext(m_curr.ehContext);
+ c.within = null;
+ }
+
+ private final StackContext* topContext() nothrow @nogc
+ in(m_curr)
+ {
+ return m_curr;
+ }
+
+
+package(core.thread):
+ ///////////////////////////////////////////////////////////////////////////
+ // GC Scanning Support
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ // NOTE: The GC scanning process works like so:
+ //
+ // 1. Suspend all threads.
+ // 2. Scan the stacks of all suspended threads for roots.
+ // 3. Resume all threads.
+ //
+ // Step 1 and 3 require a list of all threads in the system, while
+ // step 2 requires a list of all thread stacks (each represented by
+ // a Context struct). Traditionally, there was one stack per thread
+ // and the Context structs were not necessary. However, Fibers have
+ // changed things so that each thread has its own 'main' stack plus
+ // an arbitrary number of nested stacks (normally referenced via
+ // m_curr). Also, there may be 'free-floating' stacks in the system,
+ // which are Fibers that are not currently executing on any specific
+ // thread but are still being processed and still contain valid
+ // roots.
+ //
+ // To support all of this, the Context struct has been created to
+ // represent a stack range, and a global list of Context structs has
+ // been added to enable scanning of these stack ranges. The lifetime
+ // (and presence in the Context list) of a thread's 'main' stack will
+ // be equivalent to the thread's lifetime. So the Ccontext will be
+ // added to the list on thread entry, and removed from the list on
+ // thread exit (which is essentially the same as the presence of a
+ // Thread object in its own global list). The lifetime of a Fiber's
+ // context, however, will be tied to the lifetime of the Fiber object
+ // itself, and Fibers are expected to add/remove their Context struct
+ // on construction/deletion.
+
+
+ //
+ // All use of the global thread lists/array should synchronize on this lock.
+ //
+ // Careful as the GC acquires this lock after the GC lock to suspend all
+ // threads any GC usage with slock held can result in a deadlock through
+ // lock order inversion.
+ @property static Mutex slock() nothrow @nogc
+ {
+ return cast(Mutex)_slock.ptr;
+ }
+
+ @property static Mutex criticalRegionLock() nothrow @nogc
+ {
+ return cast(Mutex)_criticalRegionLock.ptr;
+ }
+
+ __gshared align(mutexAlign) void[mutexClassInstanceSize] _slock;
+ __gshared align(mutexAlign) void[mutexClassInstanceSize] _criticalRegionLock;
+
+ static void initLocks() @nogc
+ {
+ _slock[] = typeid(Mutex).initializer[];
+ (cast(Mutex)_slock.ptr).__ctor();
+
+ _criticalRegionLock[] = typeid(Mutex).initializer[];
+ (cast(Mutex)_criticalRegionLock.ptr).__ctor();
+ }
+
+ static void termLocks() @nogc
+ {
+ (cast(Mutex)_slock.ptr).__dtor();
+ (cast(Mutex)_criticalRegionLock.ptr).__dtor();
+ }
+
+ __gshared StackContext* sm_cbeg;
+
+ __gshared ThreadBase sm_tbeg;
+ __gshared size_t sm_tlen;
+
+ // can't use core.internal.util.array in public code
+ __gshared ThreadBase* pAboutToStart;
+ __gshared size_t nAboutToStart;
+
+ //
+ // Used for ordering threads in the global thread list.
+ //
+ ThreadBase prev;
+ ThreadBase next;
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Global Context List Operations
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Add a context to the global context list.
+ //
+ static void add(StackContext* c) nothrow @nogc
+ in
+ {
+ assert(c);
+ assert(!c.next && !c.prev);
+ }
+ do
+ {
+ slock.lock_nothrow();
+ scope(exit) slock.unlock_nothrow();
+ assert(!suspendDepth); // must be 0 b/c it's only set with slock held
+
+ if (sm_cbeg)
+ {
+ c.next = sm_cbeg;
+ sm_cbeg.prev = c;
+ }
+ sm_cbeg = c;
+ }
+
+ //
+ // Remove a context from the global context list.
+ //
+ // This assumes slock being acquired. This isn't done here to
+ // avoid double locking when called from remove(Thread)
+ static void remove(StackContext* c) nothrow @nogc
+ in
+ {
+ assert(c);
+ assert(c.next || c.prev);
+ }
+ do
+ {
+ if (c.prev)
+ c.prev.next = c.next;
+ if (c.next)
+ c.next.prev = c.prev;
+ if (sm_cbeg == c)
+ sm_cbeg = c.next;
+ // NOTE: Don't null out c.next or c.prev because opApply currently
+ // follows c.next after removing a node. This could be easily
+ // addressed by simply returning the next node from this
+ // function, however, a context should never be re-added to the
+ // list anyway and having next and prev be non-null is a good way
+ // to ensure that.
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Global Thread List Operations
+ ///////////////////////////////////////////////////////////////////////////
+
+
+ //
+ // Add a thread to the global thread list.
+ //
+ static void add(ThreadBase t, bool rmAboutToStart = true) nothrow @nogc
+ in
+ {
+ assert(t);
+ assert(!t.next && !t.prev);
+ }
+ do
+ {
+ slock.lock_nothrow();
+ scope(exit) slock.unlock_nothrow();
+ assert(t.isRunning); // check this with slock to ensure pthread_create already returned
+ assert(!suspendDepth); // must be 0 b/c it's only set with slock held
+
+ if (rmAboutToStart)
+ {
+ size_t idx = -1;
+ foreach (i, thr; pAboutToStart[0 .. nAboutToStart])
+ {
+ if (thr is t)
+ {
+ idx = i;
+ break;
+ }
+ }
+ assert(idx != -1);
+ import core.stdc.string : memmove;
+ memmove(pAboutToStart + idx, pAboutToStart + idx + 1, size_t.sizeof * (nAboutToStart - idx - 1));
+ pAboutToStart =
+ cast(ThreadBase*)realloc(pAboutToStart, size_t.sizeof * --nAboutToStart);
+ }
+
+ if (sm_tbeg)
+ {
+ t.next = sm_tbeg;
+ sm_tbeg.prev = t;
+ }
+ sm_tbeg = t;
+ ++sm_tlen;
+ }
+
+
+ //
+ // Remove a thread from the global thread list.
+ //
+ static void remove(ThreadBase t) nothrow @nogc
+ in
+ {
+ assert(t);
+ }
+ do
+ {
+ // Thread was already removed earlier, might happen b/c of thread_detachInstance
+ if (!t.next && !t.prev && (sm_tbeg !is t))
+ return;
+
+ slock.lock_nothrow();
+ {
+ // NOTE: When a thread is removed from the global thread list its
+ // main context is invalid and should be removed as well.
+ // It is possible that t.m_curr could reference more
+ // than just the main context if the thread exited abnormally
+ // (if it was terminated), but we must assume that the user
+ // retains a reference to them and that they may be re-used
+ // elsewhere. Therefore, it is the responsibility of any
+ // object that creates contexts to clean them up properly
+ // when it is done with them.
+ remove(&t.m_main);
+
+ if (t.prev)
+ t.prev.next = t.next;
+ if (t.next)
+ t.next.prev = t.prev;
+ if (sm_tbeg is t)
+ sm_tbeg = t.next;
+ t.prev = t.next = null;
+ --sm_tlen;
+ }
+ // NOTE: Don't null out t.next or t.prev because opApply currently
+ // follows t.next after removing a node. This could be easily
+ // addressed by simply returning the next node from this
+ // function, however, a thread should never be re-added to the
+ // list anyway and having next and prev be non-null is a good way
+ // to ensure that.
+ slock.unlock_nothrow();
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// GC Support Routines
+///////////////////////////////////////////////////////////////////////////////
+
+private alias attachThread = externDFunc!("core.thread.osthread.attachThread", ThreadBase function(ThreadBase) @nogc nothrow);
+
+extern (C) void _d_monitordelete_nogc(Object h) @nogc;
+
+/**
+ * Terminates the thread module. No other thread routine may be called
+ * afterwards.
+ */
+package void thread_term_tpl(ThreadT, MainThreadStore)(ref MainThreadStore _mainThreadStore) @nogc
+{
+ assert(_mainThreadStore.ptr is cast(void*) ThreadBase.sm_main);
+
+ // destruct manually as object.destroy is not @nogc
+ (cast(ThreadT) cast(void*) ThreadBase.sm_main).__dtor();
+ _d_monitordelete_nogc(ThreadBase.sm_main);
+ if (typeid(ThreadT).initializer.ptr)
+ _mainThreadStore[] = typeid(ThreadT).initializer[];
+ else
+ (cast(ubyte[])_mainThreadStore)[] = 0;
+ ThreadBase.sm_main = null;
+
+ assert(ThreadBase.sm_tbeg && ThreadBase.sm_tlen == 1);
+ assert(!ThreadBase.nAboutToStart);
+ if (ThreadBase.pAboutToStart) // in case realloc(p, 0) doesn't return null
+ {
+ free(ThreadBase.pAboutToStart);
+ ThreadBase.pAboutToStart = null;
+ }
+ ThreadBase.termLocks();
+ termLowlevelThreads();
+}
+
+
+/**
+ *
+ */
+extern (C) bool thread_isMainThread() nothrow @nogc
+{
+ return ThreadBase.getThis() is ThreadBase.sm_main;
+}
+
+
+/**
+ * Registers the calling thread for use with the D Runtime. If this routine
+ * is called for a thread which is already registered, no action is performed.
+ *
+ * NOTE: This routine does not run thread-local static constructors when called.
+ * If full functionality as a D thread is desired, the following function
+ * must be called after thread_attachThis:
+ *
+ * extern (C) void rt_moduleTlsCtor();
+ */
+package ThreadT thread_attachThis_tpl(ThreadT)()
+{
+ if (auto t = ThreadT.getThis())
+ return t;
+
+ return cast(ThreadT) attachThread(new ThreadT());
+}
+
+
+/**
+ * Deregisters the calling thread from use with the runtime. If this routine
+ * is called for a thread which is not registered, the result is undefined.
+ *
+ * NOTE: This routine does not run thread-local static destructors when called.
+ * If full functionality as a D thread is desired, the following function
+ * must be called after thread_detachThis, particularly if the thread is
+ * being detached at some indeterminate time before program termination:
+ *
+ * $(D extern(C) void rt_moduleTlsDtor();)
+ */
+extern (C) void thread_detachThis() nothrow @nogc
+{
+ if (auto t = ThreadBase.getThis())
+ ThreadBase.remove(t);
+}
+
+
+/**
+ * Deregisters the given thread from use with the runtime. If this routine
+ * is called for a thread which is not registered, the result is undefined.
+ *
+ * NOTE: This routine does not run thread-local static destructors when called.
+ * If full functionality as a D thread is desired, the following function
+ * must be called by the detached thread, particularly if the thread is
+ * being detached at some indeterminate time before program termination:
+ *
+ * $(D extern(C) void rt_moduleTlsDtor();)
+ */
+extern (C) void thread_detachByAddr(ThreadID addr)
+{
+ if (auto t = thread_findByAddr(addr))
+ ThreadBase.remove(t);
+}
+
+
+/// ditto
+extern (C) void thread_detachInstance(ThreadBase t) nothrow @nogc
+{
+ ThreadBase.remove(t);
+}
+
+
+/**
+ * Search the list of all threads for a thread with the given thread identifier.
+ *
+ * Params:
+ * addr = The thread identifier to search for.
+ * Returns:
+ * The thread object associated with the thread identifier, null if not found.
+ */
+static ThreadBase thread_findByAddr(ThreadID addr)
+{
+ ThreadBase.slock.lock_nothrow();
+ scope(exit) ThreadBase.slock.unlock_nothrow();
+
+ // also return just spawned thread so that
+ // DLL_THREAD_ATTACH knows it's a D thread
+ foreach (t; ThreadBase.pAboutToStart[0 .. ThreadBase.nAboutToStart])
+ if (t.m_addr == addr)
+ return t;
+
+ foreach (t; ThreadBase)
+ if (t.m_addr == addr)
+ return t;
+
+ return null;
+}
+
+
+/**
+ * Sets the current thread to a specific reference. Only to be used
+ * when dealing with externally-created threads (in e.g. C code).
+ * The primary use of this function is when ThreadBase.getThis() must
+ * return a sensible value in, for example, TLS destructors. In
+ * other words, don't touch this unless you know what you're doing.
+ *
+ * Params:
+ * t = A reference to the current thread. May be null.
+ */
+extern (C) void thread_setThis(ThreadBase t) nothrow @nogc
+{
+ ThreadBase.setThis(t);
+}
+
+
+/**
+ * Joins all non-daemon threads that are currently running. This is done by
+ * performing successive scans through the thread list until a scan consists
+ * of only daemon threads.
+ */
+extern (C) void thread_joinAll()
+{
+ Lagain:
+ ThreadBase.slock.lock_nothrow();
+ // wait for just spawned threads
+ if (ThreadBase.nAboutToStart)
+ {
+ ThreadBase.slock.unlock_nothrow();
+ ThreadBase.yield();
+ goto Lagain;
+ }
+
+ // join all non-daemon threads, the main thread is also a daemon
+ auto t = ThreadBase.sm_tbeg;
+ while (t)
+ {
+ if (!t.isRunning)
+ {
+ auto tn = t.next;
+ ThreadBase.remove(t);
+ t = tn;
+ }
+ else if (t.isDaemon)
+ {
+ t = t.next;
+ }
+ else
+ {
+ ThreadBase.slock.unlock_nothrow();
+ t.join(); // might rethrow
+ goto Lagain; // must restart iteration b/c of unlock
+ }
+ }
+ ThreadBase.slock.unlock_nothrow();
+}
+
+
+/**
+ * Performs intermediate shutdown of the thread module.
+ */
+shared static ~this()
+{
+ // NOTE: The functionality related to garbage collection must be minimally
+ // operable after this dtor completes. Therefore, only minimal
+ // cleanup may occur.
+ auto t = ThreadBase.sm_tbeg;
+ while (t)
+ {
+ auto tn = t.next;
+ if (!t.isRunning)
+ ThreadBase.remove(t);
+ t = tn;
+ }
+}
+
+// Used for needLock below.
+package __gshared bool multiThreadedFlag = false;
+
+// Used for suspendAll/resumeAll below.
+package __gshared uint suspendDepth = 0;
+
+private alias resume = externDFunc!("core.thread.osthread.resume", void function(ThreadBase) nothrow @nogc);
+
+/**
+ * Resume all threads but the calling thread for "stop the world" garbage
+ * collection runs. This function must be called once for each preceding
+ * call to thread_suspendAll before the threads are actually resumed.
+ *
+ * In:
+ * This routine must be preceded by a call to thread_suspendAll.
+ *
+ * Throws:
+ * ThreadError if the resume operation fails for a running thread.
+ */
+extern (C) void thread_resumeAll() nothrow
+in
+{
+ assert(suspendDepth > 0);
+}
+do
+{
+ // NOTE: See thread_suspendAll for the logic behind this.
+ if (!multiThreadedFlag && ThreadBase.sm_tbeg)
+ {
+ if (--suspendDepth == 0)
+ resume(ThreadBase.getThis());
+ return;
+ }
+
+ scope(exit) ThreadBase.slock.unlock_nothrow();
+ {
+ if (--suspendDepth > 0)
+ return;
+
+ for (ThreadBase t = ThreadBase.sm_tbeg; t; t = t.next)
+ {
+ // NOTE: We do not need to care about critical regions at all
+ // here. thread_suspendAll takes care of everything.
+ resume(t);
+ }
+ }
+}
+
+/**
+ * Indicates the kind of scan being performed by $(D thread_scanAllType).
+ */
+enum ScanType
+{
+ stack, /// The stack and/or registers are being scanned.
+ tls, /// TLS data is being scanned.
+}
+
+alias ScanAllThreadsFn = void delegate(void*, void*) nothrow; /// The scanning function.
+alias ScanAllThreadsTypeFn = void delegate(ScanType, void*, void*) nothrow; /// ditto
+
+/**
+ * The main entry point for garbage collection. The supplied delegate
+ * will be passed ranges representing both stack and register values.
+ *
+ * Params:
+ * scan = The scanner function. It should scan from p1 through p2 - 1.
+ *
+ * In:
+ * This routine must be preceded by a call to thread_suspendAll.
+ */
+extern (C) void thread_scanAllType(scope ScanAllThreadsTypeFn scan) nothrow
+in
+{
+ assert(suspendDepth > 0);
+}
+do
+{
+ callWithStackShell(sp => scanAllTypeImpl(scan, sp));
+}
+
+package alias callWithStackShellDg = void delegate(void* sp) nothrow;
+private alias callWithStackShell = externDFunc!("core.thread.osthread.callWithStackShell", void function(scope callWithStackShellDg) nothrow);
+
+private void scanAllTypeImpl(scope ScanAllThreadsTypeFn scan, void* curStackTop) nothrow
+{
+ ThreadBase thisThread = null;
+ void* oldStackTop = null;
+
+ if (ThreadBase.sm_tbeg)
+ {
+ thisThread = ThreadBase.getThis();
+ if (!thisThread.m_lock)
+ {
+ oldStackTop = thisThread.m_curr.tstack;
+ thisThread.m_curr.tstack = curStackTop;
+ }
+ }
+
+ scope(exit)
+ {
+ if (ThreadBase.sm_tbeg)
+ {
+ if (!thisThread.m_lock)
+ {
+ thisThread.m_curr.tstack = oldStackTop;
+ }
+ }
+ }
+
+ // NOTE: Synchronizing on ThreadBase.slock is not needed because this
+ // function may only be called after all other threads have
+ // been suspended from within the same lock.
+ if (ThreadBase.nAboutToStart)
+ scan(ScanType.stack, ThreadBase.pAboutToStart, ThreadBase.pAboutToStart + ThreadBase.nAboutToStart);
+
+ for (StackContext* c = ThreadBase.sm_cbeg; c; c = c.next)
+ {
+ static if (isStackGrowingDown)
+ {
+ assert(c.tstack <= c.bstack, "stack bottom can't be less than top");
+
+ // NOTE: We can't index past the bottom of the stack
+ // so don't do the "+1" if isStackGrowingDown.
+ if (c.tstack && c.tstack < c.bstack)
+ scan(ScanType.stack, c.tstack, c.bstack);
+ }
+ else
+ {
+ assert(c.bstack <= c.tstack, "stack top can't be less than bottom");
+
+ if (c.bstack && c.bstack < c.tstack)
+ scan(ScanType.stack, c.bstack, c.tstack + 1);
+ }
+ }
+
+ for (ThreadBase t = ThreadBase.sm_tbeg; t; t = t.next)
+ {
+ version (Windows)
+ {
+ // Ideally, we'd pass ScanType.regs or something like that, but this
+ // would make portability annoying because it only makes sense on Windows.
+ scanWindowsOnly(scan, t);
+ }
+
+ if (t.m_tlsgcdata !is null)
+ rt_tlsgc_scan(t.m_tlsgcdata, (p1, p2) => scan(ScanType.tls, p1, p2));
+ }
+}
+
+version (Windows)
+{
+ // Currently scanWindowsOnly can't be handled properly by externDFunc
+ // https://github.com/dlang/druntime/pull/3135#issuecomment-643673218
+ pragma(mangle, "_D4core6thread8osthread15scanWindowsOnlyFNbMDFNbEQBvQBt10threadbase8ScanTypePvQcZvCQDdQDbQBi10ThreadBaseZv")
+ private extern (D) void scanWindowsOnly(scope ScanAllThreadsTypeFn scan, ThreadBase) nothrow;
+}
+
+/**
+ * The main entry point for garbage collection. The supplied delegate
+ * will be passed ranges representing both stack and register values.
+ *
+ * Params:
+ * scan = The scanner function. It should scan from p1 through p2 - 1.
+ *
+ * In:
+ * This routine must be preceded by a call to thread_suspendAll.
+ */
+extern (C) void thread_scanAll(scope ScanAllThreadsFn scan) nothrow
+{
+ thread_scanAllType((type, p1, p2) => scan(p1, p2));
+}
+
+private alias thread_yield = externDFunc!("core.thread.osthread.thread_yield", void function() @nogc nothrow);
+
+/**
+ * Signals that the code following this call is a critical region. Any code in
+ * this region must finish running before the calling thread can be suspended
+ * by a call to thread_suspendAll.
+ *
+ * This function is, in particular, meant to help maintain garbage collector
+ * invariants when a lock is not used.
+ *
+ * A critical region is exited with thread_exitCriticalRegion.
+ *
+ * $(RED Warning):
+ * Using critical regions is extremely error-prone. For instance, using locks
+ * inside a critical region can easily result in a deadlock when another thread
+ * holding the lock already got suspended.
+ *
+ * The term and concept of a 'critical region' comes from
+ * $(LINK2 https://github.com/mono/mono/blob/521f4a198e442573c400835ef19bbb36b60b0ebb/mono/metadata/sgen-gc.h#L925, Mono's SGen garbage collector).
+ *
+ * In:
+ * The calling thread must be attached to the runtime.
+ */
+extern (C) void thread_enterCriticalRegion() @nogc
+in
+{
+ assert(ThreadBase.getThis());
+}
+do
+{
+ synchronized (ThreadBase.criticalRegionLock)
+ ThreadBase.getThis().m_isInCriticalRegion = true;
+}
+
+
+/**
+ * Signals that the calling thread is no longer in a critical region. Following
+ * a call to this function, the thread can once again be suspended.
+ *
+ * In:
+ * The calling thread must be attached to the runtime.
+ */
+extern (C) void thread_exitCriticalRegion() @nogc
+in
+{
+ assert(ThreadBase.getThis());
+}
+do
+{
+ synchronized (ThreadBase.criticalRegionLock)
+ ThreadBase.getThis().m_isInCriticalRegion = false;
+}
+
+
+/**
+ * Returns true if the current thread is in a critical region; otherwise, false.
+ *
+ * In:
+ * The calling thread must be attached to the runtime.
+ */
+extern (C) bool thread_inCriticalRegion() @nogc
+in
+{
+ assert(ThreadBase.getThis());
+}
+do
+{
+ synchronized (ThreadBase.criticalRegionLock)
+ return ThreadBase.getThis().m_isInCriticalRegion;
+}
+
+
+/**
+* A callback for thread errors in D during collections. Since an allocation is not possible
+* a preallocated ThreadError will be used as the Error instance
+*
+* Returns:
+* never returns
+* Throws:
+* ThreadError.
+*/
+package void onThreadError(string msg) nothrow @nogc
+{
+ __gshared ThreadError error = new ThreadError(null);
+ error.msg = msg;
+ error.next = null;
+ import core.exception : SuppressTraceInfo;
+ error.info = SuppressTraceInfo.instance;
+ throw error;
+}
+
+unittest
+{
+ assert(!thread_inCriticalRegion());
+
+ {
+ thread_enterCriticalRegion();
+
+ scope (exit)
+ thread_exitCriticalRegion();
+
+ assert(thread_inCriticalRegion());
+ }
+
+ assert(!thread_inCriticalRegion());
+}
+
+
+/**
+ * Indicates whether an address has been marked by the GC.
+ */
+enum IsMarked : int
+{
+ no, /// Address is not marked.
+ yes, /// Address is marked.
+ unknown, /// Address is not managed by the GC.
+}
+
+alias IsMarkedDg = int delegate(void* addr) nothrow; /// The isMarked callback function.
+
+/**
+ * This routine allows the runtime to process any special per-thread handling
+ * for the GC. This is needed for taking into account any memory that is
+ * referenced by non-scanned pointers but is about to be freed. That currently
+ * means the array append cache.
+ *
+ * Params:
+ * isMarked = The function used to check if $(D addr) is marked.
+ *
+ * In:
+ * This routine must be called just prior to resuming all threads.
+ */
+extern(C) void thread_processGCMarks(scope IsMarkedDg isMarked) nothrow
+{
+ for (ThreadBase t = ThreadBase.sm_tbeg; t; t = t.next)
+ {
+ /* Can be null if collection was triggered between adding a
+ * thread and calling rt_tlsgc_init.
+ */
+ if (t.m_tlsgcdata !is null)
+ rt_tlsgc_processGCMarks(t.m_tlsgcdata, isMarked);
+ }
+}
+
+
+/**
+ * Returns the stack top of the currently active stack within the calling
+ * thread.
+ *
+ * In:
+ * The calling thread must be attached to the runtime.
+ *
+ * Returns:
+ * The address of the stack top.
+ */
+extern (C) void* thread_stackTop() nothrow @nogc
+in
+{
+ // Not strictly required, but it gives us more flexibility.
+ assert(ThreadBase.getThis());
+}
+do
+{
+ return getStackTop();
+}
+
+
+/**
+ * Returns the stack bottom of the currently active stack within the calling
+ * thread.
+ *
+ * In:
+ * The calling thread must be attached to the runtime.
+ *
+ * Returns:
+ * The address of the stack bottom.
+ */
+extern (C) void* thread_stackBottom() nothrow @nogc
+in (ThreadBase.getThis())
+{
+ return ThreadBase.getThis().topContext().bstack;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// lowlovel threading support
+///////////////////////////////////////////////////////////////////////////////
+package
+{
+ __gshared size_t ll_nThreads;
+ __gshared ll_ThreadData* ll_pThreads;
+
+ __gshared align(mutexAlign) void[mutexClassInstanceSize] ll_lock;
+
+ @property Mutex lowlevelLock() nothrow @nogc
+ {
+ return cast(Mutex)ll_lock.ptr;
+ }
+
+ void initLowlevelThreads() @nogc
+ {
+ ll_lock[] = typeid(Mutex).initializer[];
+ lowlevelLock.__ctor();
+ }
+
+ void termLowlevelThreads() @nogc
+ {
+ lowlevelLock.__dtor();
+ }
+
+ void ll_removeThread(ThreadID tid) nothrow @nogc
+ {
+ lowlevelLock.lock_nothrow();
+ scope(exit) lowlevelLock.unlock_nothrow();
+
+ foreach (i; 0 .. ll_nThreads)
+ {
+ if (tid is ll_pThreads[i].tid)
+ {
+ import core.stdc.string : memmove;
+ memmove(ll_pThreads + i, ll_pThreads + i + 1, ll_ThreadData.sizeof * (ll_nThreads - i - 1));
+ --ll_nThreads;
+ // no need to minimize, next add will do
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Check whether a thread was created by `createLowLevelThread`.
+ *
+ * Params:
+ * tid = the platform specific thread ID.
+ *
+ * Returns: `true` if the thread was created by `createLowLevelThread` and is still running.
+ */
+bool findLowLevelThread(ThreadID tid) nothrow @nogc
+{
+ lowlevelLock.lock_nothrow();
+ scope(exit) lowlevelLock.unlock_nothrow();
+
+ foreach (i; 0 .. ll_nThreads)
+ if (tid is ll_pThreads[i].tid)
+ return true;
+ return false;
+}
--- /dev/null
+/**
+ * The osthread module provides types used in threads modules.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2012.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
+ * Source: $(DRUNTIMESRC core/thread/osthread.d)
+ */
+
+module core.thread.threadgroup;
+
+import core.thread.osthread;
+
+
+/**
+ * This class is intended to simplify certain common programming techniques.
+ */
+class ThreadGroup
+{
+ /**
+ * Creates and starts a new Thread object that executes fn and adds it to
+ * the list of tracked threads.
+ *
+ * Params:
+ * fn = The thread function.
+ *
+ * Returns:
+ * A reference to the newly created thread.
+ */
+ final Thread create(void function() fn)
+ {
+ Thread t = new Thread(fn).start();
+
+ synchronized(this)
+ {
+ m_all[t] = t;
+ }
+ return t;
+ }
+
+
+ /**
+ * Creates and starts a new Thread object that executes dg and adds it to
+ * the list of tracked threads.
+ *
+ * Params:
+ * dg = The thread function.
+ *
+ * Returns:
+ * A reference to the newly created thread.
+ */
+ final Thread create(void delegate() dg)
+ {
+ Thread t = new Thread(dg).start();
+
+ synchronized(this)
+ {
+ m_all[t] = t;
+ }
+ return t;
+ }
+
+
+ /**
+ * Add t to the list of tracked threads if it is not already being tracked.
+ *
+ * Params:
+ * t = The thread to add.
+ *
+ * In:
+ * t must not be null.
+ */
+ final void add(Thread t)
+ in
+ {
+ assert(t);
+ }
+ do
+ {
+ synchronized(this)
+ {
+ m_all[t] = t;
+ }
+ }
+
+
+ /**
+ * Removes t from the list of tracked threads. No operation will be
+ * performed if t is not currently being tracked by this object.
+ *
+ * Params:
+ * t = The thread to remove.
+ *
+ * In:
+ * t must not be null.
+ */
+ final void remove(Thread t)
+ in
+ {
+ assert(t);
+ }
+ do
+ {
+ synchronized(this)
+ {
+ m_all.remove(t);
+ }
+ }
+
+
+ /**
+ * Operates on all threads currently tracked by this object.
+ */
+ final int opApply(scope int delegate(ref Thread) dg)
+ {
+ synchronized(this)
+ {
+ int ret = 0;
+
+ // NOTE: This loop relies on the knowledge that m_all uses the
+ // Thread object for both the key and the mapped value.
+ foreach (Thread t; m_all.keys)
+ {
+ ret = dg(t);
+ if (ret)
+ break;
+ }
+ return ret;
+ }
+ }
+
+
+ /**
+ * Iteratively joins all tracked threads. This function will block add,
+ * remove, and opApply until it completes.
+ *
+ * Params:
+ * rethrow = Rethrow any unhandled exception which may have caused the
+ * current thread to terminate.
+ *
+ * Throws:
+ * Any exception not handled by the joined threads.
+ */
+ final void joinAll(bool rethrow = true)
+ {
+ synchronized(this)
+ {
+ // NOTE: This loop relies on the knowledge that m_all uses the
+ // Thread object for both the key and the mapped value.
+ foreach (Thread t; m_all.keys)
+ {
+ t.join(rethrow);
+ }
+ }
+ }
+
+
+private:
+ Thread[Thread] m_all;
+}
--- /dev/null
+/**
+ * This module provides types and constants used in thread package.
+ *
+ * Copyright: Copyright Sean Kelly 2005 - 2012.
+ * License: Distributed under the
+ * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
+ * (See accompanying file LICENSE)
+ * Authors: Sean Kelly, Walter Bright, Alex Rønne Petersen, Martin Nowak
+ * Source: $(DRUNTIMESRC core/thread/osthread.d)
+ */
+
+module core.thread.types;
+
+/**
+ * Represents the ID of a thread, as returned by $(D Thread.)$(LREF id).
+ * The exact type varies from platform to platform.
+ */
+version (Windows)
+ alias ThreadID = uint;
+else
+version (Posix)
+{
+ import core.sys.posix.pthread;
+
+ alias ThreadID = pthread_t;
+}
+
+struct ll_ThreadData
+{
+ ThreadID tid;
+ version (Windows)
+ void delegate() nothrow cbDllUnload;
+}
+
+version (GNU)
+{
+ version (GNU_StackGrowsDown)
+ enum isStackGrowingDown = true;
+ else
+ enum isStackGrowingDown = false;
+}
+else
+{
+ // this should be true for most architectures
+ enum isStackGrowingDown = true;
+}
+
+package
+{
+ static immutable size_t PAGESIZE;
+ version (Posix) static immutable size_t PTHREAD_STACK_MIN;
+}
+
+shared static this()
+{
+ version (Windows)
+ {
+ import core.sys.windows.winbase;
+
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+
+ PAGESIZE = info.dwPageSize;
+ assert(PAGESIZE < int.max);
+ }
+ else version (Posix)
+ {
+ import core.sys.posix.unistd;
+
+ PAGESIZE = cast(size_t)sysconf(_SC_PAGESIZE);
+ PTHREAD_STACK_MIN = cast(size_t)sysconf(_SC_THREAD_STACK_MIN);
+ }
+ else
+ {
+ static assert(0, "unimplemented");
+ }
+}
}
}
+ size_t sizeOfTLS() nothrow @nogc
+ {
+ auto tdsos = initTLSRanges();
+ size_t sum;
+ foreach (ref tdso; *tdsos)
+ sum += tdso._tlsRange.length;
+ return sum;
+ }
+
// interface for core.thread to inherit loaded libraries
void* pinLoadedLibraries() nothrow @nogc
{
dg(rng.ptr, rng.ptr + rng.length);
}
}
+
+ size_t sizeOfTLS() nothrow @nogc
+ {
+ auto rngs = initTLSRanges();
+ size_t sum;
+ foreach (rng; *rngs)
+ sum += rng.length;
+ return sum;
+ }
}
private:
extern (C) void rt_finalize(void *data, bool det=true);
}
-// NOTE: For some reason, this declaration method doesn't work
-// in this particular file (and this file only). It must
-// be a DMD thing.
-//alias typeof(int.sizeof) size_t;
-//alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t;
-
-version (D_LP64)
-{
- alias size_t = ulong;
- alias ptrdiff_t = long;
-}
-else
-{
- alias size_t = uint;
- alias ptrdiff_t = int;
-}
+alias size_t = typeof(int.sizeof);
+alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0);
alias sizediff_t = ptrdiff_t; //For backwards compatibility only.
version (D_ObjectiveC) public import core.attribute : selector;
+// Some ABIs use a complex varargs implementation requiring TypeInfo.argTypes().
+version (GNU)
+{
+ // No TypeInfo-based core.vararg.va_arg().
+}
+else version (X86_64)
+{
+ version (DigitalMars) version = WithArgTypes;
+ else version (Windows) { /* no need for Win64 ABI */ }
+ else version = WithArgTypes;
+}
+version (AArch64)
+{
+ // Apple uses a trivial varargs implementation
+ version (OSX) {}
+ else version (iOS) {}
+ else version (TVOS) {}
+ else version (WatchOS) {}
+ else version = WithArgTypes;
+}
+
/**
* All D class objects inherit from Object.
*/
/** Return internal info on arguments fitting into 8byte.
* See X86-64 ABI 3.2.3
*/
- version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) @safe nothrow
+ version (WithArgTypes) int argTypes(out TypeInfo arg1, out TypeInfo arg2) @safe nothrow
{
arg1 = this;
return 0;
/** Return info used by the garbage collector to do precise collection.
*/
- @property immutable(void)* rtInfo() nothrow pure const @safe @nogc { return null; }
+ @property immutable(void)* rtInfo() nothrow pure const @safe @nogc { return rtinfoHasPointers; } // better safe than sorry
}
class TypeInfo_Enum : TypeInfo
override @property size_t talign() nothrow pure const { return base.talign; }
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
{
return base.argTypes(arg1, arg2);
}
return (void[]).alignof;
}
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
{
arg1 = typeid(size_t);
arg2 = typeid(void*);
return 0;
}
+
+ override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo!(void[]); }
}
class TypeInfo_StaticArray : TypeInfo
return value.talign;
}
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
{
arg1 = typeid(void*);
return 0;
}
+
+ // just return the rtInfo of the element, we have no generic type T to run RTInfo!T on
+ override @property immutable(void)* rtInfo() nothrow pure const @safe { return value.rtInfo(); }
}
class TypeInfo_AssociativeArray : TypeInfo
return (char[int]).alignof;
}
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
{
arg1 = typeid(void*);
return 0;
override @property size_t talign() nothrow pure const { return 16; }
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
{
return base.argTypes(arg1, arg2);
}
return null;
}
+ override @property immutable(void)* rtInfo() nothrow pure const @safe { return rtinfoNoPointers; }
+
TypeInfo next;
/**
return dg.alignof;
}
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
{
arg1 = typeid(void*);
arg2 = typeid(void*);
return 0;
}
+
+ override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo!(int delegate()); }
}
/**
uint m_align;
- override @property immutable(void)* rtInfo() const { return m_RTInfo; }
+ override @property immutable(void)* rtInfo() nothrow pure const @safe { return m_RTInfo; }
- version (X86_64)
+ version (WithArgTypes)
{
override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
{
assert(0);
}
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
{
assert(0);
}
override @property size_t talign() nothrow pure const { return base.talign; }
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
{
return base.argTypes(arg1, arg2);
}
* Create RTInfo for type T
*/
+template RTInfoImpl(size_t[] pointerBitmap)
+{
+ immutable size_t[pointerBitmap.length] RTInfoImpl = pointerBitmap[];
+}
+
+template NoPointersBitmapPayload(size_t N)
+{
+ enum size_t[N] NoPointersBitmapPayload = 0;
+}
+
template RTInfo(T)
{
- enum RTInfo = null;
+ enum pointerBitmap = __traits(getPointerBitmap, T);
+ static if (pointerBitmap[1 .. $] == NoPointersBitmapPayload!(pointerBitmap.length - 1))
+ enum RTInfo = rtinfoNoPointers;
+ else
+ enum RTInfo = RTInfoImpl!(pointerBitmap).ptr;
}
+/**
+* shortcuts for the precise GC, also generated by the compiler
+* used instead of the actual pointer bitmap
+*/
+enum immutable(void)* rtinfoNoPointers = null;
+enum immutable(void)* rtinfoHasPointers = cast(void*)1;
+
// lhs == rhs lowers to __equals(lhs, rhs) for dynamic arrays
bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
{
// we don't expect the Entry objects to be used outside of this module, so we have control
// over the non-usage of the callback methods and other entries and can keep these null
// xtoHash, xopEquals, xopCmp, xtoString and xpostblit
- ti.m_RTInfo = null;
+ ti.m_RTInfo = rtinfoNoPointers;
immutable entrySize = talign(kti.tsize, vti.talign) + vti.tsize;
ti.m_init = (cast(ubyte*) null)[0 .. entrySize]; // init length, but not ptr
extern (C) void _d_critical_term()
{
- for (auto p = head; p; p = p.next)
+ // This function is only ever called by the runtime shutdown code
+ // and therefore is single threaded so the following cast is fine.
+ auto h = cast()head;
+ for (auto p = h; p; p = p.next)
destroyMutex(cast(Mutex*)&p.mtx);
}
lockMutex(cast(Mutex*)&gcs.mtx);
if (atomicLoad!(MemoryOrder.raw)(*cast(shared) pcs) is null)
{
- auto cs = new shared(D_CRITICAL_SECTION);
+ auto cs = new shared D_CRITICAL_SECTION;
initMutex(cast(Mutex*)&cs.mtx);
atomicStore!(MemoryOrder.rel)(*cast(shared) pcs, cs);
}
body
{
auto m = ensureMonitor(cast(Object) owner);
- auto i = m.impl;
- if (i is null)
+ if (m.impl is null)
{
atomicOp!("+=")(m.refs, cast(size_t) 1);
- ownee.__monitor = owner.__monitor;
- return;
}
- // If m.impl is set (ie. if this is a user-created monitor), assume
- // the monitor is garbage collected and simply copy the reference.
+ // Assume the monitor is garbage collected and simply copy the reference.
ownee.__monitor = owner.__monitor;
}
}
}
+// does not call dispose events, for internal use only
+extern (C) void _d_monitordelete_nogc(Object h) @nogc
+{
+ auto m = getMonitor(h);
+ if (m is null)
+ return;
+
+ if (m.impl)
+ {
+ // let the GC collect the monitor
+ setMonitor(h, null);
+ }
+ else if (!atomicOp!("-=")(m.refs, cast(size_t) 1))
+ {
+ // refcount == 0 means unshared => no synchronization required
+ deleteMonitor(cast(Monitor*) m);
+ setMonitor(h, null);
+ }
+}
+
extern (C) void _d_monitorenter(Object h)
in
{
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Acdouble;
-
-private import rt.util.typeinfo;
-
-// cdouble[]
-
-class TypeInfo_Ar : TypeInfo_Array
-{
- alias F = cdouble;
-
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return (F[]).stringof; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- return Array!F.hashOf(*cast(F[]*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(F);
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Acfloat;
-
-private import rt.util.typeinfo;
-
-// cfloat[]
-
-class TypeInfo_Aq : TypeInfo_Array
-{
- alias F = cfloat;
-
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return (F[]).stringof; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- return Array!F.hashOf(*cast(F[]*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(F);
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Acreal;
-
-private import rt.util.typeinfo;
-
-// creal[]
-
-class TypeInfo_Ac : TypeInfo_Array
-{
- alias F = creal;
-
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return (F[]).stringof; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- return Array!F.hashOf(*cast(F[]*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(F);
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Adouble;
-
-private import rt.util.typeinfo;
-
-// double[]
-
-class TypeInfo_Ad : TypeInfo_Array
-{
- alias F = double;
-
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return (F[]).stringof; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- return Array!F.hashOf(*cast(F[]*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(F);
- }
-}
-
-// idouble[]
-
-class TypeInfo_Ap : TypeInfo_Ad
-{
- alias F = idouble;
-
- override string toString() const { return (F[]).stringof; }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(F);
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Afloat;
-
-private import rt.util.typeinfo;
-
-// float[]
-
-class TypeInfo_Af : TypeInfo_Array
-{
- alias F = float;
-
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return (F[]).stringof; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- return Array!F.hashOf(*cast(F[]*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(F);
- }
-}
-
-// ifloat[]
-
-class TypeInfo_Ao : TypeInfo_Af
-{
- alias F = ifloat;
-
- override string toString() const { return (F[]).stringof; }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(F);
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Ag;
-
-private import core.stdc.string;
-private import core.internal.string;
-
-// byte[]
-
-class TypeInfo_Ag : TypeInfo_Array
-{
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return "byte[]"; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- const s = *cast(const void[]*)p;
- return hashOf(s);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- byte[] s1 = *cast(byte[]*)p1;
- byte[] s2 = *cast(byte[]*)p2;
-
- return s1.length == s2.length &&
- memcmp(cast(byte *)s1, cast(byte *)s2, s1.length) == 0;
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- byte[] s1 = *cast(byte[]*)p1;
- byte[] s2 = *cast(byte[]*)p2;
- size_t len = s1.length;
-
- if (s2.length < len)
- len = s2.length;
- for (size_t u = 0; u < len; u++)
- {
- int result = s1[u] - s2[u];
- if (result)
- return result;
- }
- if (s1.length < s2.length)
- return -1;
- else if (s1.length > s2.length)
- return 1;
- return 0;
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(byte);
- }
-}
-
-
-// ubyte[]
-
-class TypeInfo_Ah : TypeInfo_Ag
-{
- override string toString() const { return "ubyte[]"; }
-
- override int compare(in void* p1, in void* p2) const
- {
- char[] s1 = *cast(char[]*)p1;
- char[] s2 = *cast(char[]*)p2;
-
- return dstrcmp(s1, s2);
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(ubyte);
- }
-}
-
-// void[]
-
-class TypeInfo_Av : TypeInfo_Ah
-{
- override string toString() const { return "void[]"; }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(void);
- }
-}
-
-// bool[]
-
-class TypeInfo_Ab : TypeInfo_Ah
-{
- override string toString() const { return "bool[]"; }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(bool);
- }
-}
-
-// char[]
-
-class TypeInfo_Aa : TypeInfo_Ah
-{
- override string toString() const { return "char[]"; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- char[] s = *cast(char[]*)p;
- return hashOf(s);
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(char);
- }
-}
-
-// string
-
-class TypeInfo_Aya : TypeInfo_Aa
-{
- override string toString() const { return "immutable(char)[]"; }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(immutable(char));
- }
-}
-
-// const(char)[]
-
-class TypeInfo_Axa : TypeInfo_Aa
-{
- override string toString() const { return "const(char)[]"; }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(const(char));
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Aint;
-
-private import core.stdc.string;
-
-extern (C) void[] _adSort(void[] a, TypeInfo ti);
-
-// int[]
-
-class TypeInfo_Ai : TypeInfo_Array
-{
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return "int[]"; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- // Hash as if unsigned.
- const s = *cast(const uint[]*)p;
- return hashOf(s);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- int[] s1 = *cast(int[]*)p1;
- int[] s2 = *cast(int[]*)p2;
-
- return s1.length == s2.length &&
- memcmp(cast(void *)s1, cast(void *)s2, s1.length * int.sizeof) == 0;
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- int[] s1 = *cast(int[]*)p1;
- int[] s2 = *cast(int[]*)p2;
- size_t len = s1.length;
-
- if (s2.length < len)
- len = s2.length;
- for (size_t u = 0; u < len; u++)
- {
- if (s1[u] < s2[u])
- return -1;
- else if (s1[u] > s2[u])
- return 1;
- }
- if (s1.length < s2.length)
- return -1;
- else if (s1.length > s2.length)
- return 1;
- return 0;
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(int);
- }
-}
-
-unittest
-{
- int[][] a = [[5,3,8,7], [2,5,3,8,7]];
- _adSort(*cast(void[]*)&a, typeid(a[0]));
- assert(a == [[2,5,3,8,7], [5,3,8,7]]);
-
- a = [[5,3,8,7], [5,3,8]];
- _adSort(*cast(void[]*)&a, typeid(a[0]));
- assert(a == [[5,3,8], [5,3,8,7]]);
-}
-
-unittest
-{
- // Issue 13073: original code uses int subtraction which is susceptible to
- // integer overflow, causing the following case to fail.
- int[] a = [int.max, int.max];
- int[] b = [int.min, int.min];
- assert(a > b);
- assert(b < a);
-}
-
-// uint[]
-
-class TypeInfo_Ak : TypeInfo_Ai
-{
- override string toString() const { return "uint[]"; }
-
- override int compare(in void* p1, in void* p2) const
- {
- uint[] s1 = *cast(uint[]*)p1;
- uint[] s2 = *cast(uint[]*)p2;
- size_t len = s1.length;
-
- if (s2.length < len)
- len = s2.length;
- for (size_t u = 0; u < len; u++)
- {
- if (s1[u] < s2[u])
- return -1;
- else if (s1[u] > s2[u])
- return 1;
- }
- if (s1.length < s2.length)
- return -1;
- else if (s1.length > s2.length)
- return 1;
- return 0;
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(uint);
- }
-}
-
-unittest
-{
- // Original test case from issue 13073
- uint x = 0x22_DF_FF_FF;
- uint y = 0xA2_DF_FF_FF;
- assert(!(x < y && y < x));
- uint[] a = [x];
- uint[] b = [y];
- assert(!(a < b && b < a)); // Original failing case
- uint[1] a1 = [x];
- uint[1] b1 = [y];
- assert(!(a1 < b1 && b1 < a1)); // Original failing case
-}
-
-// dchar[]
-
-class TypeInfo_Aw : TypeInfo_Ak
-{
- override string toString() const { return "dchar[]"; }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(dchar);
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Along;
-
-private import core.stdc.string;
-
-// long[]
-
-class TypeInfo_Al : TypeInfo_Array
-{
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return "long[]"; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- // Hash as if unsigned.
- const s = *cast(const ulong[]*)p;
- return hashOf(s);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- long[] s1 = *cast(long[]*)p1;
- long[] s2 = *cast(long[]*)p2;
-
- return s1.length == s2.length &&
- memcmp(cast(void *)s1, cast(void *)s2, s1.length * long.sizeof) == 0;
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- long[] s1 = *cast(long[]*)p1;
- long[] s2 = *cast(long[]*)p2;
- size_t len = s1.length;
-
- if (s2.length < len)
- len = s2.length;
- for (size_t u = 0; u < len; u++)
- {
- if (s1[u] < s2[u])
- return -1;
- else if (s1[u] > s2[u])
- return 1;
- }
- if (s1.length < s2.length)
- return -1;
- else if (s1.length > s2.length)
- return 1;
- return 0;
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(long);
- }
-}
-
-
-// ulong[]
-
-class TypeInfo_Am : TypeInfo_Al
-{
- override string toString() const { return "ulong[]"; }
-
- override int compare(in void* p1, in void* p2) const
- {
- ulong[] s1 = *cast(ulong[]*)p1;
- ulong[] s2 = *cast(ulong[]*)p2;
- size_t len = s1.length;
-
- if (s2.length < len)
- len = s2.length;
- for (size_t u = 0; u < len; u++)
- {
- if (s1[u] < s2[u])
- return -1;
- else if (s1[u] > s2[u])
- return 1;
- }
- if (s1.length < s2.length)
- return -1;
- else if (s1.length > s2.length)
- return 1;
- return 0;
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(ulong);
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Areal;
-
-private import rt.util.typeinfo;
-
-// real[]
-
-class TypeInfo_Ae : TypeInfo_Array
-{
- alias F = real;
-
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return (F[]).stringof; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- return Array!F.hashOf(*cast(F[]*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- return Array!F.equals(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- return Array!F.compare(*cast(F[]*)p1, *cast(F[]*)p2);
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(F);
- }
-}
-
-// ireal[]
-
-class TypeInfo_Aj : TypeInfo_Ae
-{
- alias F = ireal;
-
- override string toString() const { return (F[]).stringof; }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(F);
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_Ashort;
-
-private import core.stdc.string;
-
-// short[]
-
-class TypeInfo_As : TypeInfo_Array
-{
- override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
-
- override string toString() const { return "short[]"; }
-
- override size_t getHash(scope const void* p) @trusted const
- {
- // Hash as if unsigned.
- const s = *cast(const ushort[]*)p;
- return hashOf(s);
- }
-
- override bool equals(in void* p1, in void* p2) const
- {
- short[] s1 = *cast(short[]*)p1;
- short[] s2 = *cast(short[]*)p2;
-
- return s1.length == s2.length &&
- memcmp(cast(void *)s1, cast(void *)s2, s1.length * short.sizeof) == 0;
- }
-
- override int compare(in void* p1, in void* p2) const
- {
- short[] s1 = *cast(short[]*)p1;
- short[] s2 = *cast(short[]*)p2;
- size_t len = s1.length;
-
- if (s2.length < len)
- len = s2.length;
- for (size_t u = 0; u < len; u++)
- {
- int result = s1[u] - s2[u];
- if (result)
- return result;
- }
- if (s1.length < s2.length)
- return -1;
- else if (s1.length > s2.length)
- return 1;
- return 0;
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(short);
- }
-}
-
-
-// ushort[]
-
-class TypeInfo_At : TypeInfo_As
-{
- override string toString() const { return "ushort[]"; }
-
- override int compare(in void* p1, in void* p2) const
- {
- ushort[] s1 = *cast(ushort[]*)p1;
- ushort[] s2 = *cast(ushort[]*)p2;
- size_t len = s1.length;
-
- if (s2.length < len)
- len = s2.length;
- for (size_t u = 0; u < len; u++)
- {
- int result = s1[u] - s2[u];
- if (result)
- return result;
- }
- if (s1.length < s2.length)
- return -1;
- else if (s1.length > s2.length)
- return 1;
- return 0;
- }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(ushort);
- }
-}
-
-// wchar[]
-
-class TypeInfo_Au : TypeInfo_At
-{
- override string toString() const { return "wchar[]"; }
-
- override @property inout(TypeInfo) next() inout
- {
- return cast(inout)typeid(wchar);
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_C;
-
-// Object
-
-class TypeInfo_C : TypeInfo
-{
- @trusted:
- const:
- //pure:
- //nothrow:
-
- override size_t getHash(scope const void* p)
- {
- Object o = *cast(Object*)p;
- return o ? o.toHash() : 0;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- Object o1 = *cast(Object*)p1;
- Object o2 = *cast(Object*)p2;
-
- return o1 == o2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- Object o1 = *cast(Object*)p1;
- Object o2 = *cast(Object*)p2;
- int c = 0;
-
- // Regard null references as always being "less than"
- if (!(o1 is o2))
- {
- if (o1)
- {
- if (!o2)
- c = 1;
- else
- c = o1.opCmp(o2);
- }
- else
- c = -1;
- }
- return c;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return Object.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. Object.sizeof];
- }
-
- override @property uint flags() nothrow pure
- {
- return 1;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_byte;
-
-// byte
-
-class TypeInfo_g : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "byte"; }
-
- override size_t getHash(scope const void* p)
- {
- return *cast(const byte *)p;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(byte *)p1 == *cast(byte *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- return *cast(byte *)p1 - *cast(byte *)p2;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return byte.sizeof;
- }
-
- override const(void)[] initializer() @trusted
- {
- return (cast(void *)null)[0 .. byte.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- byte t;
-
- t = *cast(byte *)p1;
- *cast(byte *)p1 = *cast(byte *)p2;
- *cast(byte *)p2 = t;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_cdouble;
-
-private import rt.util.typeinfo;
-
-// cdouble
-
-class TypeInfo_r : TypeInfo
-{
- pure:
- nothrow:
- @safe:
-
- alias F = cdouble;
-
- override string toString() const { return F.stringof; }
-
- override size_t getHash(scope const void* p) const @trusted
- {
- return Floating!F.hashOf(*cast(F*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.equals(*cast(F*)p1, *cast(F*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.compare(*cast(F*)p1, *cast(F*)p2);
- }
-
- override @property size_t tsize() const
- {
- return F.sizeof;
- }
-
- override void swap(void *p1, void *p2) const @trusted
- {
- F t = *cast(F*)p1;
- *cast(F*)p1 = *cast(F*)p2;
- *cast(F*)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable F r;
- return (&r)[0 .. 1];
- }
-
- override @property size_t talign() const
- {
- return F.alignof;
- }
-
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
- {
- arg1 = typeid(double);
- arg2 = typeid(double);
- return 0;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2015.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2015.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_cent;
-
-static if (is(cent)):
-
-// cent
-
-class TypeInfo_zi : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "cent"; }
-
- override size_t getHash(scope const void* p)
- {
- // cent & ucent hash the same if ucent.sizeof >= size_t.sizeof.
- return hashOf(*cast(const ucent*) p);
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(cent *)p1 == *cast(cent *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- if (*cast(cent *)p1 < *cast(cent *)p2)
- return -1;
- else if (*cast(cent *)p1 > *cast(cent *)p2)
- return 1;
- return 0;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return cent.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. cent.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- cent t;
-
- t = *cast(cent *)p1;
- *cast(cent *)p1 = *cast(cent *)p2;
- *cast(cent *)p2 = t;
- }
-
- override @property size_t talign() nothrow pure
- {
- return cent.alignof;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_cfloat;
-
-private import rt.util.typeinfo;
-
-// cfloat
-
-class TypeInfo_q : TypeInfo
-{
- pure:
- nothrow:
- @safe:
-
- alias F = cfloat;
-
- override string toString() const { return F.stringof; }
-
- override size_t getHash(scope const void* p) const @trusted
- {
- return Floating!F.hashOf(*cast(F*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.equals(*cast(F*)p1, *cast(F*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.compare(*cast(F*)p1, *cast(F*)p2);
- }
-
- override @property size_t tsize() const
- {
- return F.sizeof;
- }
-
- override void swap(void *p1, void *p2) const @trusted
- {
- F t = *cast(F*)p1;
- *cast(F*)p1 = *cast(F*)p2;
- *cast(F*)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable F r;
- return (&r)[0 .. 1];
- }
-
- override @property size_t talign() const
- {
- return F.alignof;
- }
-
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
- {
- arg1 = typeid(double);
- return 0;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_char;
-
-// char
-
-class TypeInfo_a : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "char"; }
-
- override size_t getHash(scope const void* p)
- {
- return *cast(const char *)p;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(char *)p1 == *cast(char *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- return *cast(char *)p1 - *cast(char *)p2;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return char.sizeof;
- }
-
- override void swap(void *p1, void *p2)
- {
- char t;
-
- t = *cast(char *)p1;
- *cast(char *)p1 = *cast(char *)p2;
- *cast(char *)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable char c;
-
- return (&c)[0 .. 1];
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_creal;
-
-private import rt.util.typeinfo;
-
-// creal
-
-class TypeInfo_c : TypeInfo
-{
- pure:
- nothrow:
- @safe:
-
- alias F = creal;
-
- override string toString() const { return F.stringof; }
-
- override size_t getHash(scope const void* p) const @trusted
- {
- return Floating!F.hashOf(*cast(F*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.equals(*cast(F*)p1, *cast(F*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.compare(*cast(F*)p1, *cast(F*)p2);
- }
-
- override @property size_t tsize() const
- {
- return F.sizeof;
- }
-
- override void swap(void *p1, void *p2) const @trusted
- {
- F t = *cast(F*)p1;
- *cast(F*)p1 = *cast(F*)p2;
- *cast(F*)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable F r;
- return (&r)[0 .. 1];
- }
-
- override @property size_t talign() const
- {
- return F.alignof;
- }
-
- version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
- {
- arg1 = typeid(real);
- arg2 = typeid(real);
- return 0;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_dchar;
-
-// dchar
-
-class TypeInfo_w : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "dchar"; }
-
- override size_t getHash(scope const void* p)
- {
- return *cast(const dchar *)p;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(dchar *)p1 == *cast(dchar *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- return *cast(dchar *)p1 - *cast(dchar *)p2;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return dchar.sizeof;
- }
-
- override void swap(void *p1, void *p2)
- {
- dchar t;
-
- t = *cast(dchar *)p1;
- *cast(dchar *)p1 = *cast(dchar *)p2;
- *cast(dchar *)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable dchar c;
-
- return (&c)[0 .. 1];
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_delegate;
-
-
-// delegate
-
-alias void delegate(int) dg;
-
-class TypeInfo_D : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override size_t getHash(scope const void* p)
- {
- return hashOf(*cast(dg*)p);
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(dg *)p1 == *cast(dg *)p2;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return dg.sizeof;
- }
-
- override void swap(void *p1, void *p2)
- {
- dg t;
-
- t = *cast(dg *)p1;
- *cast(dg *)p1 = *cast(dg *)p2;
- *cast(dg *)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable dg d;
-
- return (cast(void *)null)[0 .. dg.sizeof];
- }
-
- override @property uint flags() nothrow pure
- {
- return 1;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_double;
-
-private import rt.util.typeinfo;
-
-// double
-
-class TypeInfo_d : TypeInfo
-{
- pure:
- nothrow:
- @safe:
-
- alias F = double;
-
- override string toString() const { return F.stringof; }
-
- override size_t getHash(scope const void* p) const @trusted
- {
- return Floating!F.hashOf(*cast(F*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.equals(*cast(F*)p1, *cast(F*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.compare(*cast(F*)p1, *cast(F*)p2);
- }
-
- override @property size_t tsize() const
- {
- return F.sizeof;
- }
-
- override void swap(void *p1, void *p2) const @trusted
- {
- F t = *cast(F*)p1;
- *cast(F*)p1 = *cast(F*)p2;
- *cast(F*)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable F r;
- return (&r)[0 .. 1];
- }
-
- override @property size_t talign() const
- {
- return F.alignof;
- }
-
- version (Windows)
- {
- }
- else version (X86_64)
- {
- // 2 means arg to function is passed in XMM registers
- override @property uint flags() const { return 2; }
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_float;
-
-private import rt.util.typeinfo;
-
-// float
-
-class TypeInfo_f : TypeInfo
-{
- pure:
- nothrow:
- @safe:
-
- alias F = float;
-
- override string toString() const { return F.stringof; }
-
- override size_t getHash(scope const void* p) const @trusted
- {
- return Floating!F.hashOf(*cast(F*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.equals(*cast(F*)p1, *cast(F*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.compare(*cast(F*)p1, *cast(F*)p2);
- }
-
- override @property size_t tsize() const
- {
- return F.sizeof;
- }
-
- override void swap(void *p1, void *p2) const @trusted
- {
- F t = *cast(F*)p1;
- *cast(F*)p1 = *cast(F*)p2;
- *cast(F*)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable F r;
- return (&r)[0 .. 1];
- }
-
- version (Windows)
- {
- }
- else version (X86_64)
- {
- // 2 means arg to function is passed in XMM registers
- override @property uint flags() const { return 2; }
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_idouble;
-
-private import rt.typeinfo.ti_double;
-
-// idouble
-
-class TypeInfo_p : TypeInfo_d
-{
- pure:
- nothrow:
- @safe:
-
- override string toString() const { return idouble.stringof; }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_ifloat;
-
-private import rt.typeinfo.ti_float;
-
-// ifloat
-
-class TypeInfo_o : TypeInfo_f
-{
- pure:
- nothrow:
- @safe:
-
- override string toString() const { return ifloat.stringof; }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_int;
-
-// int
-
-class TypeInfo_i : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "int"; }
-
- override size_t getHash(scope const void* p)
- {
- return *cast(const int *)p;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(uint *)p1 == *cast(uint *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- if (*cast(int*) p1 < *cast(int*) p2)
- return -1;
- else if (*cast(int*) p1 > *cast(int*) p2)
- return 1;
- return 0;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return int.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. int.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- int t;
-
- t = *cast(int *)p1;
- *cast(int *)p1 = *cast(int *)p2;
- *cast(int *)p2 = t;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_ireal;
-
-private import rt.typeinfo.ti_real;
-
-// ireal
-
-class TypeInfo_j : TypeInfo_e
-{
- pure:
- nothrow:
- @safe:
-
- override string toString() const { return ireal.stringof; }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_long;
-
-// long
-
-class TypeInfo_l : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "long"; }
-
- override size_t getHash(scope const void* p)
- {
- static if (ulong.sizeof <= size_t.sizeof)
- return *cast(const long*)p;
- else
- // long & ulong hash the same if ulong.sizeof > size_t.sizeof.
- return hashOf(*cast(const ulong*)p);
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(long *)p1 == *cast(long *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- if (*cast(long *)p1 < *cast(long *)p2)
- return -1;
- else if (*cast(long *)p1 > *cast(long *)p2)
- return 1;
- return 0;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return long.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. long.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- long t;
-
- t = *cast(long *)p1;
- *cast(long *)p1 = *cast(long *)p2;
- *cast(long *)p2 = t;
- }
-
- override @property size_t talign() nothrow pure
- {
- return long.alignof;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2016.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Kenji Hara
- */
-
-/* Copyright Digital Mars 2016.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_n;
-
-// typeof(null)
-
-class TypeInfo_n : TypeInfo
-{
- override string toString() const @safe { return "typeof(null)"; }
-
- override size_t getHash(scope const void* p) const
- {
- return 0;
- }
-
- override bool equals(in void* p1, in void* p2) const @trusted
- {
- //return *cast(typeof(null)*)p1 is *cast(typeof(null)*)p2;
- return true;
- }
-
- override int compare(in void* p1, in void* p2) const @trusted
- {
- //if (*cast(int*) p1 < *cast(int*) p2)
- // return -1;
- //else if (*cast(int*) p1 > *cast(int*) p2)
- // return 1;
- return 0;
- }
-
- override @property size_t tsize() const
- {
- return typeof(null).sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void*)null)[0 .. typeof(null).sizeof];
- }
-
- override void swap(void *p1, void *p2) const @trusted
- {
- //auto t = *cast(typeof(null)*)p1;
- //*cast(typeof(null)*)p1 = *cast(typeof(null)*)p2;
- //*cast(typeof(null)*)p2 = t;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_ptr;
-
-// internal typeinfo for any pointer type
-// please keep in sync with TypeInfo_Pointer
-
-class TypeInfo_P : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override size_t getHash(scope const void* p)
- {
- size_t addr = cast(size_t) *cast(const void**)p;
- return addr ^ (addr >> 4);
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(void**)p1 == *cast(void**)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- if (*cast(void**)p1 < *cast(void**)p2)
- return -1;
- else if (*cast(void**)p1 > *cast(void**)p2)
- return 1;
- else
- return 0;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return (void*).sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. (void*).sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- void* tmp = *cast(void**)p1;
- *cast(void**)p1 = *cast(void**)p2;
- *cast(void**)p2 = tmp;
- }
-
- override @property uint flags() nothrow pure const { return 1; }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_real;
-
-private import rt.util.typeinfo;
-
-// real
-
-class TypeInfo_e : TypeInfo
-{
- pure:
- nothrow:
- @safe:
-
- alias F = real;
-
- override string toString() const { return F.stringof; }
-
- override size_t getHash(scope const void* p) const @trusted
- {
- return Floating!F.hashOf(*cast(F*)p);
- }
-
- override bool equals(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.equals(*cast(F*)p1, *cast(F*)p2);
- }
-
- override int compare(in void* p1, in void* p2) const @trusted
- {
- return Floating!F.compare(*cast(F*)p1, *cast(F*)p2);
- }
-
- override @property size_t tsize() const
- {
- return F.sizeof;
- }
-
- override void swap(void *p1, void *p2) const @trusted
- {
- F t = *cast(F*)p1;
- *cast(F*)p1 = *cast(F*)p2;
- *cast(F*)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable F r;
- return (&r)[0 .. 1];
- }
-
- override @property size_t talign() const
- {
- return F.alignof;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_short;
-
-// short
-
-class TypeInfo_s : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "short"; }
-
- override size_t getHash(scope const void* p)
- {
- return *cast(const short *)p;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(short *)p1 == *cast(short *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- return *cast(short *)p1 - *cast(short *)p2;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return short.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. short.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- short t;
-
- t = *cast(short *)p1;
- *cast(short *)p1 = *cast(short *)p2;
- *cast(short *)p2 = t;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_ubyte;
-
-// ubyte
-
-class TypeInfo_h : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "ubyte"; }
-
- override size_t getHash(scope const void* p)
- {
- return *cast(const ubyte *)p;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(ubyte *)p1 == *cast(ubyte *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- return *cast(ubyte *)p1 - *cast(ubyte *)p2;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return ubyte.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. ubyte.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- ubyte t;
-
- t = *cast(ubyte *)p1;
- *cast(ubyte *)p1 = *cast(ubyte *)p2;
- *cast(ubyte *)p2 = t;
- }
-}
-
-class TypeInfo_b : TypeInfo_h
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "bool"; }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2015.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2015.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_ucent;
-
-static if (is(ucent)):
-
-// ucent
-
-class TypeInfo_zk : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "ucent"; }
-
- override size_t getHash(scope const void* p)
- {
- return hashOf(*cast(const ucent*) p);
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(ucent *)p1 == *cast(ucent *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- if (*cast(ucent *)p1 < *cast(ucent *)p2)
- return -1;
- else if (*cast(ucent *)p1 > *cast(ucent *)p2)
- return 1;
- return 0;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return ucent.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. ucent.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- ucent t;
-
- t = *cast(ucent *)p1;
- *cast(ucent *)p1 = *cast(ucent *)p2;
- *cast(ucent *)p2 = t;
- }
-
- override @property size_t talign() nothrow pure
- {
- return ucent.alignof;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_uint;
-
-// uint
-
-class TypeInfo_k : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "uint"; }
-
- override size_t getHash(scope const void* p)
- {
- return *cast(const uint *)p;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(uint *)p1 == *cast(uint *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- if (*cast(uint*) p1 < *cast(uint*) p2)
- return -1;
- else if (*cast(uint*) p1 > *cast(uint*) p2)
- return 1;
- return 0;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return uint.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. uint.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- int t;
-
- t = *cast(uint *)p1;
- *cast(uint *)p1 = *cast(uint *)p2;
- *cast(uint *)p2 = t;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_ulong;
-
-
-// ulong
-
-class TypeInfo_m : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "ulong"; }
-
- override size_t getHash(scope const void* p)
- {
- static if (ulong.sizeof <= size_t.sizeof)
- return *cast(const ulong*)p;
- else
- return hashOf(*cast(const ulong*)p);
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(ulong *)p1 == *cast(ulong *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- if (*cast(ulong *)p1 < *cast(ulong *)p2)
- return -1;
- else if (*cast(ulong *)p1 > *cast(ulong *)p2)
- return 1;
- return 0;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return ulong.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. ulong.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- ulong t;
-
- t = *cast(ulong *)p1;
- *cast(ulong *)p1 = *cast(ulong *)p2;
- *cast(ulong *)p2 = t;
- }
-
- override @property size_t talign() nothrow pure
- {
- return ulong.alignof;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_ushort;
-
-// ushort
-
-class TypeInfo_t : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "ushort"; }
-
- override size_t getHash(scope const void* p)
- {
- return *cast(const ushort *)p;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(ushort *)p1 == *cast(ushort *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- return *cast(ushort *)p1 - *cast(ushort *)p2;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return ushort.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. ushort.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- ushort t;
-
- t = *cast(ushort *)p1;
- *cast(ushort *)p1 = *cast(ushort *)p2;
- *cast(ushort *)p2 = t;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_void;
-
-// void
-
-class TypeInfo_v : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() const pure nothrow @safe { return "void"; }
-
- override size_t getHash(scope const void* p)
- {
- assert(0);
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(byte *)p1 == *cast(byte *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- return *cast(byte *)p1 - *cast(byte *)p2;
- }
-
- override @property size_t tsize() nothrow pure
- {
- return void.sizeof;
- }
-
- override const(void)[] initializer() const @trusted
- {
- return (cast(void *)null)[0 .. void.sizeof];
- }
-
- override void swap(void *p1, void *p2)
- {
- byte t;
-
- t = *cast(byte *)p1;
- *cast(byte *)p1 = *cast(byte *)p2;
- *cast(byte *)p2 = t;
- }
-
- override @property uint flags() nothrow pure
- {
- return 1;
- }
-}
+++ /dev/null
-/**
- * TypeInfo support code.
- *
- * Copyright: Copyright Digital Mars 2004 - 2009.
- * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
- * Authors: Walter Bright
- */
-
-/* Copyright Digital Mars 2004 - 2009.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- */
-module rt.typeinfo.ti_wchar;
-
-// wchar
-
-class TypeInfo_u : TypeInfo
-{
- @trusted:
- const:
- pure:
- nothrow:
-
- override string toString() { return "wchar"; }
-
- override size_t getHash(scope const void* p)
- {
- return *cast(const wchar *)p;
- }
-
- override bool equals(in void* p1, in void* p2)
- {
- return *cast(wchar *)p1 == *cast(wchar *)p2;
- }
-
- override int compare(in void* p1, in void* p2)
- {
- return *cast(wchar *)p1 - *cast(wchar *)p2;
- }
-
- override @property size_t tsize()
- {
- return wchar.sizeof;
- }
-
- override void swap(void *p1, void *p2)
- {
- wchar t;
-
- t = *cast(wchar *)p1;
- *cast(wchar *)p1 = *cast(wchar *)p2;
- *cast(wchar *)p2 = t;
- }
-
- override const(void)[] initializer() const @trusted
- {
- static immutable wchar c;
-
- return (&c)[0 .. 1];
- }
-}
}
}();
}
+
+// Reduces to `T` if `cond` is `true` or `U` otherwise.
+private template Select(bool cond, T, U)
+{
+ static if (cond) alias Select = T;
+ else alias Select = U;
+}
+
+/*
+TypeInfo information for built-in types.
+
+A `Base` type may be specified, which must be a type with the same layout, alignment, hashing, and
+equality comparison as type `T`. This saves on code size because parts of `Base` will be reused. Example:
+`float` and `ifloat` or `char` and `ubyte`. The implementation assumes `Base` and `T` hash the same, swap
+the same, have the same ABI flags, and compare the same for equality. For ordering comparisons, we detect
+during compilation whether they have different signedness and override appropriately. For initializer, we
+detect if we need to override. The overriding initializer should be nonzero.
+*/
+private class TypeInfoGeneric(T, Base = T) : Select!(is(T == Base), TypeInfo, TypeInfoGeneric!Base)
+if (T.sizeof == Base.sizeof && T.alignof == Base.alignof)
+{
+ const: nothrow: pure: @trusted:
+
+ // Returns the type name.
+ override string toString() const pure nothrow @safe { return T.stringof; }
+
+ // `getHash` is the same for `Base` and `T`, introduce it just once.
+ static if (is(T == Base))
+ override size_t getHash(scope const void* p)
+ {
+ static if (__traits(isFloating, T))
+ return Floating!T.hashOf(*cast(T*)p);
+ else
+ return hashOf(*cast(const T *)p);
+ }
+
+ // `equals` is the same for `Base` and `T`, introduce it just once.
+ static if (is(T == Base))
+ override bool equals(in void* p1, in void* p2)
+ {
+ static if (__traits(isFloating, T))
+ return Floating!T.equals(*cast(T*)p1, *cast(T*)p2);
+ else
+ return *cast(T *)p1 == *cast(T *)p2;
+ }
+
+ // `T` and `Base` may have different signedness, so this function is introduced conditionally.
+ static if (is(T == Base) || (__traits(isIntegral, T) && T.max != Base.max))
+ override int compare(in void* p1, in void* p2)
+ {
+ static if (__traits(isFloating, T))
+ {
+ return Floating!T.compare(*cast(T*)p1, *cast(T*)p2);
+ }
+ else static if (T.sizeof < int.sizeof)
+ {
+ // Taking the difference will always fit in an int.
+ return int(*cast(T *) p1) - int(*cast(T *) p2);
+ }
+ else
+ {
+ auto lhs = *cast(T *) p1, rhs = *cast(T *) p2;
+ return (lhs > rhs) - (lhs < rhs);
+ }
+ }
+
+ static if (is(T == Base))
+ override @property size_t tsize() nothrow pure
+ {
+ return T.sizeof;
+ }
+
+ static if (is(T == Base))
+ override @property size_t talign() nothrow pure
+ {
+ return T.alignof;
+ }
+
+ // Override initializer only if necessary.
+ static if (is(T == Base) || T.init != Base.init)
+ override const(void)[] initializer() @trusted
+ {
+ static if (__traits(isZeroInit, T))
+ {
+ return (cast(void *)null)[0 .. T.sizeof];
+ }
+ else
+ {
+ static immutable T[1] c;
+ return c;
+ }
+ }
+
+ // `swap` is the same for `Base` and `T`, so introduce only once.
+ static if (is(T == Base))
+ override void swap(void *p1, void *p2)
+ {
+ auto t = *cast(T *) p1;
+ *cast(T *)p1 = *cast(T *)p2;
+ *cast(T *)p2 = t;
+ }
+
+ static if (is(T == Base) || RTInfo!T != RTInfo!Base)
+ override @property immutable(void)* rtInfo() nothrow pure const @safe
+ {
+ return RTInfo!T;
+ }
+
+ static if (is(T == Base))
+ static if (__traits(isFloating, T) && T.mant_dig != 64)
+ // FP types except 80-bit X87 are passed in SIMD register.
+ override @property uint flags() const { return 2; }
+}
+
+unittest
+{
+ assert(typeid(int).toString == "int");
+
+ with (typeid(double))
+ {
+ double a = 42, b = 43;
+ assert(equals(&a, &a));
+ assert(!equals(&a, &b));
+ assert(compare(&a, &a) == 0);
+ assert(compare(&a, &b) == -1);
+ assert(compare(&b, &a) == 1);
+ }
+
+ with (typeid(short))
+ {
+ short c = 42, d = 43;
+ assert(equals(&c, &c));
+ assert(!equals(&c, &d));
+ assert(compare(&c, &c) == 0);
+ assert(compare(&c, &d) == -1);
+ assert(compare(&d, &c) == 1);
+ assert(initializer.ptr is null);
+ assert(initializer.length == short.sizeof);
+ swap(&d, &c);
+ assert(c == 43 && d == 42);
+ }
+}
+
+/*
+TypeInfo information for arrays of built-in types.
+
+A `Base` type may be specified, which must be a type with the same layout, alignment, hashing, and
+equality comparison as type `T`. This saves on code size because parts of `Base` will be reused. Example:
+`float` and `ifloat` or `char` and `ubyte`. The implementation assumes `Base` and `T` hash the same, swap
+the same, have the same ABI flags, and compare the same for equality. For ordering comparisons, we detect
+during compilation whether they have different signedness and override appropriately. For initializer, we
+detect if we need to override. The overriding initializer should be nonzero.
+*/
+private class TypeInfoArrayGeneric(T, Base = T) : Select!(is(T == Base), TypeInfo_Array, TypeInfoArrayGeneric!Base)
+{
+ static if (is(T == Base))
+ override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
+
+ override string toString() const { return (T[]).stringof; }
+
+ static if (is(T == Base))
+ override size_t getHash(scope const void* p) @trusted const
+ {
+ static if (__traits(isFloating, T))
+ return Array!T.hashOf(*cast(T[]*)p);
+ else
+ return hashOf(*cast(const T[]*) p);
+ }
+
+ static if (is(T == Base))
+ override bool equals(in void* p1, in void* p2) const
+ {
+ static if (__traits(isFloating, T))
+ {
+ return Array!T.equals(*cast(T[]*)p1, *cast(T[]*)p2);
+ }
+ else
+ {
+ import core.stdc.string;
+ auto s1 = *cast(T[]*)p1;
+ auto s2 = *cast(T[]*)p2;
+ return s1.length == s2.length &&
+ memcmp(s1.ptr, s2.ptr, s1.length) == 0;
+ }
+ }
+
+ static if (is(T == Base) || (__traits(isIntegral, T) && T.max != Base.max))
+ override int compare(in void* p1, in void* p2) const
+ {
+ static if (__traits(isFloating, T))
+ {
+ return Array!T.compare(*cast(T[]*)p1, *cast(T[]*)p2);
+ }
+ else
+ {
+ auto s1 = *cast(T[]*)p1;
+ auto s2 = *cast(T[]*)p2;
+ auto len = s1.length;
+
+ if (s2.length < len)
+ len = s2.length;
+ for (size_t u = 0; u < len; u++)
+ {
+ if (int result = (s1[u] > s2[u]) - (s1[u] < s2[u]))
+ return result;
+ }
+ return (s1.length > s2.length) - (s1.length < s2.length);
+ }
+ }
+
+ override @property inout(TypeInfo) next() inout
+ {
+ return cast(inout) typeid(T);
+ }
+}
+
+unittest
+{
+ assert(typeid(int[]) == typeid(int[]));
+ assert(typeid(int[]) != typeid(uint[]));
+ assert(typeid(int[]).toString == "int[]");
+
+ with (typeid(double[]))
+ {
+ double[] a = [ 1, 2, 3 ], b = [ 2, 3 ];
+ assert(equals(&a, &a));
+ assert(!equals(&a, &b));
+ assert(compare(&a, &a) == 0);
+ assert(compare(&a, &b) == -1);
+ assert(compare(&b, &a) == 1);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Predefined TypeInfos
+////////////////////////////////////////////////////////////////////////////////
+
+// void
+class TypeInfo_v : TypeInfoGeneric!ubyte
+{
+ const: nothrow: pure: @trusted:
+
+ override string toString() const pure nothrow @safe { return "void"; }
+
+ override size_t getHash(scope const void* p)
+ {
+ assert(0);
+ }
+
+ override @property uint flags() nothrow pure
+ {
+ return 1;
+ }
+
+ unittest
+ {
+ assert(typeid(void).toString == "void");
+ assert(typeid(void).flags == 1);
+ }
+}
+
+// All integrals.
+class TypeInfo_h : TypeInfoGeneric!ubyte {}
+class TypeInfo_b : TypeInfoGeneric!(bool, ubyte) {}
+class TypeInfo_g : TypeInfoGeneric!(byte, ubyte) {}
+class TypeInfo_a : TypeInfoGeneric!(char, ubyte) {}
+class TypeInfo_t : TypeInfoGeneric!ushort {}
+class TypeInfo_s : TypeInfoGeneric!(short, ushort) {}
+class TypeInfo_u : TypeInfoGeneric!(wchar, ushort) {}
+class TypeInfo_w : TypeInfoGeneric!(dchar, uint) {}
+class TypeInfo_k : TypeInfoGeneric!uint {}
+class TypeInfo_i : TypeInfoGeneric!(int, uint) {}
+class TypeInfo_m : TypeInfoGeneric!ulong {}
+class TypeInfo_l : TypeInfoGeneric!(long, ulong) {}
+static if (is(cent)) class TypeInfo_zi : TypeInfoGeneric!cent {}
+static if (is(ucent)) class TypeInfo_zk : TypeInfoGeneric!ucent {}
+
+// All simple floating-point types.
+class TypeInfo_f : TypeInfoGeneric!float {}
+class TypeInfo_o : TypeInfoGeneric!(ifloat, float) {}
+class TypeInfo_d : TypeInfoGeneric!double {}
+class TypeInfo_p : TypeInfoGeneric!(idouble, double) {}
+class TypeInfo_e : TypeInfoGeneric!real {}
+class TypeInfo_j : TypeInfoGeneric!(ireal, real) {}
+
+// All complex floating-point types.
+
+// cfloat
+class TypeInfo_q : TypeInfoGeneric!cfloat
+{
+ const: nothrow: pure: @trusted:
+ static if (__traits(hasMember, TypeInfo, "argTypes"))
+ override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ {
+ arg1 = typeid(double);
+ return 0;
+ }
+}
+
+// cdouble
+class TypeInfo_r : TypeInfoGeneric!cdouble
+{
+ const: nothrow: pure: @trusted:
+ static if (__traits(hasMember, TypeInfo, "argTypes"))
+ override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ {
+ arg1 = typeid(double);
+ arg2 = typeid(double);
+ return 0;
+ }
+}
+
+// creal
+class TypeInfo_c : TypeInfoGeneric!creal
+{
+ const: nothrow: pure: @trusted:
+ static if (__traits(hasMember, TypeInfo, "argTypes"))
+ override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
+ {
+ arg1 = typeid(real);
+ arg2 = typeid(real);
+ return 0;
+ }
+}
+
+static if (__traits(hasMember, TypeInfo, "argTypes"))
+ unittest
+ {
+ TypeInfo t1, t2;
+ assert(typeid(cfloat).argTypes(t1, t2) == 0 && t1 == typeid(double) &&
+ t2 is null);
+ assert(typeid(cdouble).argTypes(t1, t2) == 0 && t1 == typeid(double) &&
+ t2 == typeid(double));
+ assert(typeid(creal).argTypes(t1, t2) == 0 && t1 == typeid(real) &&
+ t2 == typeid(real));
+ }
+
+// Arrays of all integrals.
+class TypeInfo_Ah : TypeInfoArrayGeneric!ubyte {}
+class TypeInfo_Ab : TypeInfoArrayGeneric!(bool, ubyte) {}
+class TypeInfo_Ag : TypeInfoArrayGeneric!(byte, ubyte) {}
+class TypeInfo_Aa : TypeInfoArrayGeneric!(char, ubyte) {}
+class TypeInfo_Axa : TypeInfoArrayGeneric!(const char) {}
+class TypeInfo_Aya : TypeInfoArrayGeneric!(immutable char)
+{
+ // Must override this, otherwise "string" is returned.
+ override string toString() const { return "immutable(char)[]"; }
+}
+class TypeInfo_At : TypeInfoArrayGeneric!ushort {}
+class TypeInfo_As : TypeInfoArrayGeneric!(short, ushort) {}
+class TypeInfo_Au : TypeInfoArrayGeneric!(wchar, ushort) {}
+class TypeInfo_Ak : TypeInfoArrayGeneric!uint {}
+class TypeInfo_Ai : TypeInfoArrayGeneric!(int, uint) {}
+class TypeInfo_Aw : TypeInfoArrayGeneric!(dchar, uint) {}
+class TypeInfo_Am : TypeInfoArrayGeneric!ulong {}
+class TypeInfo_Al : TypeInfoArrayGeneric!(long, ulong) {}
+
+version (unittest)
+ private extern (C) void[] _adSort(void[] a, TypeInfo ti);
+
+unittest
+{
+ assert(typeid(string).toString() == "immutable(char)[]");
+ int[][] a = [[5,3,8,7], [2,5,3,8,7]];
+ _adSort(*cast(void[]*)&a, typeid(a[0]));
+ assert(a == [[2,5,3,8,7], [5,3,8,7]]);
+
+ a = [[5,3,8,7], [5,3,8]];
+ _adSort(*cast(void[]*)&a, typeid(a[0]));
+ assert(a == [[5,3,8], [5,3,8,7]]);
+}
+
+unittest
+{
+ // https://issues.dlang.org/show_bug.cgi?id=13073: original code uses int subtraction which is susceptible to
+ // integer overflow, causing the following case to fail.
+ int[] a = [int.max, int.max];
+ int[] b = [int.min, int.min];
+ assert(a > b);
+ assert(b < a);
+}
+
+unittest
+{
+ // Original test case from issue 13073
+ uint x = 0x22_DF_FF_FF;
+ uint y = 0xA2_DF_FF_FF;
+ assert(!(x < y && y < x));
+ uint[] a = [x];
+ uint[] b = [y];
+ assert(!(a < b && b < a)); // Original failing case
+ uint[1] a1 = [x];
+ uint[1] b1 = [y];
+ assert(!(a1 < b1 && b1 < a1)); // Original failing case
+}
+
+// Arrays of all floating point types.
+class TypeInfo_Af : TypeInfoArrayGeneric!float {}
+class TypeInfo_Ao : TypeInfoArrayGeneric!(ifloat, float) {}
+class TypeInfo_Ad : TypeInfoArrayGeneric!double {}
+class TypeInfo_Ap : TypeInfoArrayGeneric!(idouble, double) {}
+class TypeInfo_Ae : TypeInfoArrayGeneric!real {}
+class TypeInfo_Aj : TypeInfoArrayGeneric!(ireal, real) {}
+class TypeInfo_Aq : TypeInfoArrayGeneric!cfloat {}
+class TypeInfo_Ar : TypeInfoArrayGeneric!cdouble {}
+class TypeInfo_Ac : TypeInfoArrayGeneric!creal {}
+
+// void[] is a bit different, behaves like ubyte[] for comparison purposes.
+class TypeInfo_Av : TypeInfo_Ah
+{
+ override string toString() const { return "void[]"; }
+
+ override @property inout(TypeInfo) next() inout
+ {
+ return cast(inout) typeid(void);
+ }
+
+ unittest
+ {
+ assert(typeid(void[]).toString == "void[]");
+ assert(typeid(void[]).next == typeid(void));
+ }
+}
+
+// all delegates
+unittest
+{
+ assert(typeid(void delegate(int)).flags == 1);
+}
+
+// typeof(null)
+class TypeInfo_n : TypeInfo
+{
+ override string toString() const @safe { return "typeof(null)"; }
+
+ override size_t getHash(scope const void* p) const
+ {
+ return 0;
+ }
+
+ override bool equals(in void* p1, in void* p2) const @trusted
+ {
+ return true;
+ }
+
+ override int compare(in void* p1, in void* p2) const @trusted
+ {
+ return 0;
+ }
+
+ override @property size_t tsize() const
+ {
+ return typeof(null).sizeof;
+ }
+
+ override const(void)[] initializer() const @trusted
+ {
+ __gshared immutable void[typeof(null).sizeof] init;
+ return init;
+ }
+
+ override void swap(void *p1, void *p2) const @trusted
+ {
+ }
+
+ override @property immutable(void)* rtInfo() nothrow pure const @safe { return rtinfoNoPointers; }
+
+ unittest
+ {
+ with (typeid(typeof(null)))
+ {
+ assert(toString == "typeof(null)");
+ assert(getHash(null) == 0);
+ assert(equals(null, null));
+ assert(compare(null, null) == 0);
+ assert(tsize == typeof(null).sizeof);
+ assert(initializer == new ubyte[(void*).sizeof]);
+ assert(rtInfo == rtinfoNoPointers);
+ }
+ }
+}
+
+// Test typeinfo for classes.
+unittest
+{
+ static class Bacon
+ {
+ int sizzle = 1;
+ override int opCmp(Object rhs) const
+ {
+ if (auto rhsb = cast(Bacon) rhs)
+ return (sizzle > rhsb.sizzle) - (sizzle < rhsb.sizzle);
+ return 0;
+ }
+ }
+ Object obj = new Bacon;
+ Bacon obj2 = new Bacon;
+ obj2.sizzle = 2;
+ auto dummy = new Object;
+ with (typeid(obj))
+ {
+ assert(toString[$ - 6 .. $] == ".Bacon");
+ assert(getHash(&obj) != 0);
+ assert(equals(&obj, &obj));
+ assert(!equals(&obj, &obj2));
+ assert(compare(&obj, &dummy) == 0);
+ assert(compare(&obj, &obj) == 0);
+ assert(compare(&obj, &obj2) == -1);
+ assert(compare(&obj2, &obj) == 1);
+ assert(tsize == Object.sizeof);
+ assert(rtInfo == RTInfo!Bacon);
+ assert(tsize == Object.sizeof);
+ assert(initializer.ptr !is null);
+ assert(initializer.length == __traits(classInstanceSize, Bacon));
+ assert(flags == 1);
+ }
+}
// allocate a page below (above) the fiber's stack to make stack overflows possible (w/o segfaulting)
version (StackGrowsDown)
{
- static assert(__traits(identifier, test_fiber.tupleof[8]) == "m_pmem");
- auto stackBottom = test_fiber.tupleof[8];
+ auto stackBottom = __traits(getMember, test_fiber, "m_pmem");
auto p = mmap(stackBottom - 8 * stackSize, 8 * stackSize,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
assert(p !is null, "failed to allocate page");
}
else
{
- auto m_sz = test_fiber.tupleof[7];
- auto m_pmem = test_fiber.tupleof[8];
- static assert(__traits(identifier, test_fiber.tupleof[7]) == "m_size");
- static assert(__traits(identifier, test_fiber.tupleof[8]) == "m_pmem");
+ auto m_sz = __traits(getMember, test_fiber, "m_sz");
+ auto m_pmem = __traits(getMember, test_fiber, "m_pmem");
auto stackTop = m_pmem + m_sz;
auto p = mmap(stackTop, 8 * stackSize,