| // GNU D Compiler thread support for emulated TLS routines. | |
| // Copyright (C) 2019-2020 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 the Free | |
| // Software Foundation; either version 3, or (at your option) any later | |
| // version. | |
| // GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
| // WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| // for more details. | |
| // Under Section 7 of GPL version 3, you are granted additional | |
| // permissions described in the GCC Runtime Library Exception, version | |
| // 3.1, as published by the Free Software Foundation. | |
| // You should have received a copy of the GNU General Public License and | |
| // a copy of the GCC Runtime Library Exception along with this program; | |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
| // <http://www.gnu.org/licenses/>. | |
| module gcc.gthread; | |
| import gcc.config; | |
| extern (C) nothrow @nogc: | |
| alias GthreadDestroyFn = extern (C) void function(void*); | |
| alias GthreadOnceFn = extern (C) void function(); | |
| static if (GNU_Thread_Model == ThreadModel.Posix) | |
| { | |
| import core.sys.posix.pthread; | |
| alias __gthread_key_create = pthread_key_create; | |
| alias __gthread_key_delete = pthread_key_delete; | |
| alias __gthread_getspecific = pthread_getspecific; | |
| alias __gthread_setspecific = pthread_setspecific; | |
| alias __gthread_once = pthread_once; | |
| alias __gthread_key_t = pthread_key_t; | |
| alias __gthread_once_t = pthread_once_t; | |
| enum GTHREAD_ONCE_INIT = PTHREAD_ONCE_INIT; | |
| // TODO: FreeBSD and Solaris exposes a dummy POSIX threads | |
| // interface that will need to be handled here. | |
| extern (D) int __gthread_active_p() | |
| { | |
| return 1; | |
| } | |
| } | |
| else static if (GNU_Thread_Model == ThreadModel.Single) | |
| { | |
| alias __gthread_key_t = int; | |
| alias __gthread_once_t = int; | |
| enum GTHREAD_ONCE_INIT = 0; | |
| extern (D) int __gthread_key_create(__gthread_key_t*, GthreadDestroyFn) | |
| { | |
| return 0; | |
| } | |
| extern (D) int __gthread_key_delete(__gthread_key_t) | |
| { | |
| return 0; | |
| } | |
| extern (D) void* __gthread_getspecific(__gthread_key_t) | |
| { | |
| return null; | |
| } | |
| extern (D) int __gthread_setspecific(__gthread_key_t, void*) | |
| { | |
| return 0; | |
| } | |
| extern (D) int __gthread_once(__gthread_once_t*, GthreadOnceFn) | |
| { | |
| return 0; | |
| } | |
| extern (D) int __gthread_active_p() | |
| { | |
| return 0; | |
| } | |
| } | |
| else static if (GNU_Thread_Model == ThreadModel.Win32) | |
| { | |
| struct __gthread_once_t | |
| { | |
| INT done; | |
| LONG started; | |
| } | |
| int __gthr_win32_key_create(__gthread_key_t* keyp, GthreadDestroyFn dtor); | |
| int __gthr_win32_key_delete(__gthread_key_t key); | |
| void* __gthr_win32_getspecific(__gthread_key_t key); | |
| int __gthr_win32_setspecific(__gthread_key_t key, const void* ptr); | |
| int __gthr_win32_once(__gthread_once_t* once, GthreadOnceFn); | |
| alias __gthread_key_create = __gthr_win32_key_create; | |
| alias __gthread_key_delete = __gthr_win32_key_delete; | |
| alias __gthread_getspecific = __gthr_win32_getspecific; | |
| alias __gthread_setspecific = __gthr_win32_setspecific; | |
| alias __gthread_once = __gthr_win32_once; | |
| enum GTHREAD_ONCE_INIT = __gthread_once_t(0, -1); | |
| alias __gthread_key_t = c_ulong; | |
| version (MinGW) | |
| { | |
| // Mingw runtime >= v0.3 provides a magic variable that is set to nonzero | |
| // if -mthreads option was specified, or 0 otherwise. | |
| extern __gshared int _CRT_MT; | |
| } | |
| extern (D) int __gthread_active_p() | |
| { | |
| version (MinGW) | |
| return _CRT_MT; | |
| else | |
| return 1; | |
| } | |
| } | |
| else | |
| { | |
| static assert(false, "Not implemented"); | |
| } |