1// GNU D Compiler thread support for emulated TLS routines. 2// Copyright (C) 2019-2020 Free Software Foundation, Inc. 3 4// GCC is free software; you can redistribute it and/or modify it under 5// the terms of the GNU General Public License as published by the Free 6// Software Foundation; either version 3, or (at your option) any later 7// version. 8 9// GCC is distributed in the hope that it will be useful, but WITHOUT ANY 10// WARRANTY; without even the implied warranty of MERCHANTABILITY or 11// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12// for more details. 13 14// Under Section 7 of GPL version 3, you are granted additional 15// permissions described in the GCC Runtime Library Exception, version 16// 3.1, as published by the Free Software Foundation. 17 18// You should have received a copy of the GNU General Public License and 19// a copy of the GCC Runtime Library Exception along with this program; 20// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 21// <http://www.gnu.org/licenses/>. 22 23module gcc.gthread; 24import gcc.config; 25 26extern (C) nothrow @nogc: 27 28alias GthreadDestroyFn = extern (C) void function(void*); 29alias GthreadOnceFn = extern (C) void function(); 30 31static if (GNU_Thread_Model == ThreadModel.Posix) 32{ 33 import core.sys.posix.pthread; 34 35 alias __gthread_key_create = pthread_key_create; 36 alias __gthread_key_delete = pthread_key_delete; 37 alias __gthread_getspecific = pthread_getspecific; 38 alias __gthread_setspecific = pthread_setspecific; 39 alias __gthread_once = pthread_once; 40 alias __gthread_key_t = pthread_key_t; 41 alias __gthread_once_t = pthread_once_t; 42 enum GTHREAD_ONCE_INIT = PTHREAD_ONCE_INIT; 43 44 // TODO: FreeBSD and Solaris exposes a dummy POSIX threads 45 // interface that will need to be handled here. 46 extern (D) int __gthread_active_p() 47 { 48 return 1; 49 } 50} 51else static if (GNU_Thread_Model == ThreadModel.Single) 52{ 53 alias __gthread_key_t = int; 54 alias __gthread_once_t = int; 55 enum GTHREAD_ONCE_INIT = 0; 56 57 extern (D) int __gthread_key_create(__gthread_key_t*, GthreadDestroyFn) 58 { 59 return 0; 60 } 61 62 extern (D) int __gthread_key_delete(__gthread_key_t) 63 { 64 return 0; 65 } 66 67 extern (D) void* __gthread_getspecific(__gthread_key_t) 68 { 69 return null; 70 } 71 72 extern (D) int __gthread_setspecific(__gthread_key_t, void*) 73 { 74 return 0; 75 } 76 77 extern (D) int __gthread_once(__gthread_once_t*, GthreadOnceFn) 78 { 79 return 0; 80 } 81 82 extern (D) int __gthread_active_p() 83 { 84 return 0; 85 } 86} 87else static if (GNU_Thread_Model == ThreadModel.Win32) 88{ 89 struct __gthread_once_t 90 { 91 INT done; 92 LONG started; 93 } 94 95 int __gthr_win32_key_create(__gthread_key_t* keyp, GthreadDestroyFn dtor); 96 int __gthr_win32_key_delete(__gthread_key_t key); 97 void* __gthr_win32_getspecific(__gthread_key_t key); 98 int __gthr_win32_setspecific(__gthread_key_t key, const void* ptr); 99 int __gthr_win32_once(__gthread_once_t* once, GthreadOnceFn); 100 101 alias __gthread_key_create = __gthr_win32_key_create; 102 alias __gthread_key_delete = __gthr_win32_key_delete; 103 alias __gthread_getspecific = __gthr_win32_getspecific; 104 alias __gthread_setspecific = __gthr_win32_setspecific; 105 alias __gthread_once = __gthr_win32_once; 106 enum GTHREAD_ONCE_INIT = __gthread_once_t(0, -1); 107 alias __gthread_key_t = c_ulong; 108 109 version (MinGW) 110 { 111 // Mingw runtime >= v0.3 provides a magic variable that is set to nonzero 112 // if -mthreads option was specified, or 0 otherwise. 113 extern __gshared int _CRT_MT; 114 } 115 116 extern (D) int __gthread_active_p() 117 { 118 version (MinGW) 119 return _CRT_MT; 120 else 121 return 1; 122 } 123} 124else 125{ 126 static assert(false, "Not implemented"); 127} 128