Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 32409f5

Browse files
authored
Merge pull request #2079 from MartinNowak/nogc_thread_init
separate thread_init/term from gc_init/term
2 parents 1b5d296 + 00e1945 commit 32409f5

File tree

4 files changed

+51
-22
lines changed

4 files changed

+51
-22
lines changed

src/core/thread.d

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,7 +1727,7 @@ private:
17271727

17281728
__gshared align(Mutex.alignof) void[__traits(classInstanceSize, Mutex)][2] _locks;
17291729

1730-
static void initLocks()
1730+
static void initLocks() @nogc
17311731
{
17321732
foreach (ref lock; _locks)
17331733
{
@@ -1736,7 +1736,7 @@ private:
17361736
}
17371737
}
17381738

1739-
static void termLocks()
1739+
static void termLocks() @nogc
17401740
{
17411741
foreach (ref lock; _locks)
17421742
(cast(Mutex)lock.ptr).__dtor();
@@ -2020,7 +2020,7 @@ version( Posix )
20202020
* garbage collector on startup and before any other thread routines
20212021
* are called.
20222022
*/
2023-
extern (C) void thread_init()
2023+
extern (C) void thread_init() @nogc
20242024
{
20252025
// NOTE: If thread_init itself performs any allocations then the thread
20262026
// routines reserved for garbage collector use may be called while
@@ -2090,17 +2090,28 @@ extern (C) void thread_init()
20902090
status = sem_init( &suspendCount, 0, 0 );
20912091
assert( status == 0 );
20922092
}
2093-
Thread.sm_main = thread_attachThis();
2093+
if (typeid(Thread).initializer.ptr)
2094+
_mainThreadStore[] = typeid(Thread).initializer[];
2095+
Thread.sm_main = attachThread((cast(Thread)_mainThreadStore.ptr).__ctor());
20942096
}
20952097

2098+
private __gshared align(Thread.alignof) void[__traits(classInstanceSize, Thread)] _mainThreadStore;
2099+
2100+
extern (C) void _d_monitordelete_nogc(Object h) @nogc;
20962101

20972102
/**
20982103
* Terminates the thread module. No other thread routine may be called
20992104
* afterwards.
21002105
*/
2101-
extern (C) void thread_term()
2106+
extern (C) void thread_term() @nogc
21022107
{
2103-
destroy(Thread.sm_main);
2108+
assert(_mainThreadStore.ptr is cast(void*) Thread.sm_main);
2109+
2110+
// destruct manually as object.destroy is not @nogc
2111+
Thread.sm_main.__dtor();
2112+
_d_monitordelete_nogc(Thread.sm_main);
2113+
if (typeid(Thread).initializer.ptr)
2114+
_mainThreadStore[] = typeid(Thread).initializer[];
21042115
Thread.sm_main = null;
21052116

21062117
assert(Thread.sm_tbeg && Thread.sm_tlen == 1);
@@ -2135,12 +2146,14 @@ extern (C) bool thread_isMainThread() nothrow @nogc
21352146
*/
21362147
extern (C) Thread thread_attachThis()
21372148
{
2138-
GC.disable(); scope(exit) GC.enable();
2139-
21402149
if (auto t = Thread.getThis())
21412150
return t;
21422151

2143-
Thread thisThread = new Thread();
2152+
return attachThread(new Thread());
2153+
}
2154+
2155+
private Thread attachThread(Thread thisThread) @nogc
2156+
{
21442157
Thread.Context* thisContext = &thisThread.m_main;
21452158
assert( thisContext == thisThread.m_curr );
21462159

src/gc/proxy.d

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ private
2525
static import core.memory;
2626
alias BlkInfo = core.memory.GC.BlkInfo;
2727

28-
extern (C) void thread_init();
29-
extern (C) void thread_term();
30-
3128
__gshared GC instance;
3229
__gshared GC proxiedGC; // used to iterate roots of Windows DLLs
3330

@@ -50,10 +47,6 @@ extern (C)
5047
fprintf(stderr, "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr);
5148
exit(1);
5249
}
53-
54-
// NOTE: The GC must initialize the thread library
55-
// before its first collection.
56-
thread_init();
5750
}
5851

5952
void gc_term()
@@ -71,8 +64,6 @@ extern (C)
7164
instance.collectNoStack(); // not really a 'collect all' -- still scans
7265
// static data area, roots, and ranges.
7366

74-
thread_term();
75-
7667
ManualGC.finalize(instance);
7768
ConservativeGC.finalize(instance);
7869
}

src/rt/dmain2.d

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ extern (C) void _d_critical_init();
6060
extern (C) void _d_critical_term();
6161
extern (C) void gc_init();
6262
extern (C) void gc_term();
63+
extern (C) void thread_init() @nogc;
64+
extern (C) void thread_term() @nogc;
6365
extern (C) void lifetime_init();
6466
extern (C) void rt_moduleCtor();
6567
extern (C) void rt_moduleTlsCtor();
@@ -194,6 +196,7 @@ extern (C) int rt_init()
194196
// this initializes mono time before anything else to allow usage
195197
// in other druntime systems.
196198
_d_initMonoTime();
199+
thread_init();
197200
gc_init();
198201
initStaticDataGC();
199202
lifetime_init();
@@ -225,6 +228,7 @@ extern (C) int rt_term()
225228
thread_joinAll();
226229
rt_moduleDtor();
227230
gc_term();
231+
thread_term();
228232
return 1;
229233
}
230234
catch (Throwable t)

src/rt/monitor_.d

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,26 @@ extern (C) void _d_monitordelete(Object h, bool det)
5656
}
5757
}
5858

59+
// does not call dispose events, for internal use only
60+
extern (C) void _d_monitordelete_nogc(Object h) @nogc
61+
{
62+
auto m = getMonitor(h);
63+
if (m is null)
64+
return;
65+
66+
if (m.impl)
67+
{
68+
// let the GC collect the monitor
69+
setMonitor(h, null);
70+
}
71+
else if (!atomicOp!("-=")(m.refs, cast(size_t) 1))
72+
{
73+
// refcount == 0 means unshared => no synchronization required
74+
deleteMonitor(cast(Monitor*) m);
75+
setMonitor(h, null);
76+
}
77+
}
78+
5979
extern (C) void _d_monitorenter(Object h)
6080
in
6181
{
@@ -173,6 +193,7 @@ else version (Posix)
173193
{
174194
import core.sys.posix.pthread;
175195

196+
@nogc:
176197
alias Mutex = pthread_mutex_t;
177198
__gshared pthread_mutexattr_t gattr;
178199

@@ -211,17 +232,17 @@ struct Monitor
211232

212233
private:
213234

214-
@property ref shared(Monitor*) monitor(Object h) pure nothrow
235+
@property ref shared(Monitor*) monitor(Object h) pure nothrow @nogc
215236
{
216237
return *cast(shared Monitor**)&h.__monitor;
217238
}
218239

219-
private shared(Monitor)* getMonitor(Object h) pure
240+
private shared(Monitor)* getMonitor(Object h) pure @nogc
220241
{
221242
return atomicLoad!(MemoryOrder.acq)(h.monitor);
222243
}
223244

224-
void setMonitor(Object h, shared(Monitor)* m) pure
245+
void setMonitor(Object h, shared(Monitor)* m) pure @nogc
225246
{
226247
atomicStore!(MemoryOrder.rel)(h.monitor, m);
227248
}
@@ -263,7 +284,7 @@ shared(Monitor)* ensureMonitor(Object h)
263284
}
264285
}
265286

266-
void deleteMonitor(Monitor* m)
287+
void deleteMonitor(Monitor* m) @nogc
267288
{
268289
destroyMutex(&m.mtx);
269290
free(m);

0 commit comments

Comments
 (0)