Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions src/core/thread.d
Original file line number Diff line number Diff line change
Expand Up @@ -1727,7 +1727,7 @@ private:

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

static void initLocks()
static void initLocks() @nogc
{
foreach (ref lock; _locks)
{
Expand All @@ -1736,7 +1736,7 @@ private:
}
}

static void termLocks()
static void termLocks() @nogc
{
foreach (ref lock; _locks)
(cast(Mutex)lock.ptr).__dtor();
Expand Down Expand Up @@ -2020,7 +2020,7 @@ version( Posix )
* garbage collector on startup and before any other thread routines
* are called.
*/
extern (C) void thread_init()
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
Expand Down Expand Up @@ -2090,17 +2090,28 @@ extern (C) void thread_init()
status = sem_init( &suspendCount, 0, 0 );
assert( status == 0 );
}
Thread.sm_main = thread_attachThis();
if (typeid(Thread).initializer.ptr)
_mainThreadStore[] = typeid(Thread).initializer[];
Thread.sm_main = attachThread((cast(Thread)_mainThreadStore.ptr).__ctor());
}

private __gshared align(Thread.alignof) void[__traits(classInstanceSize, Thread)] _mainThreadStore;

extern (C) void _d_monitordelete_nogc(Object h) @nogc;

/**
* Terminates the thread module. No other thread routine may be called
* afterwards.
*/
extern (C) void thread_term()
extern (C) void thread_term() @nogc
{
destroy(Thread.sm_main);
assert(_mainThreadStore.ptr is cast(void*) Thread.sm_main);

// destruct manually as object.destroy is not @nogc
Thread.sm_main.__dtor();
_d_monitordelete_nogc(Thread.sm_main);
if (typeid(Thread).initializer.ptr)
_mainThreadStore[] = typeid(Thread).initializer[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple comments here:

My coverage analysis is saying this code is never run.

The normal destroy will nullify the vtable, and also if the initializer.ptr is null, it means you should zero the data. But I don't actually think you need to check if it's null, as it should always have a vtable in the initializer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage messurement fails here because this is run outside of the main loop, i.e. after coverage is collected and reported.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, you can easily fixup or edit PRs. Much less hassle than asking for single-line changes.

Thread.sm_main = null;

assert(Thread.sm_tbeg && Thread.sm_tlen == 1);
Expand Down Expand Up @@ -2135,12 +2146,14 @@ extern (C) bool thread_isMainThread() nothrow @nogc
*/
extern (C) Thread thread_attachThis()
{
GC.disable(); scope(exit) GC.enable();

if (auto t = Thread.getThis())
return t;

Thread thisThread = new Thread();
return attachThread(new Thread());
}

private Thread attachThread(Thread thisThread) @nogc
{
Thread.Context* thisContext = &thisThread.m_main;
assert( thisContext == thisThread.m_curr );

Expand Down
9 changes: 0 additions & 9 deletions src/gc/proxy.d
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ private
static import core.memory;
alias BlkInfo = core.memory.GC.BlkInfo;

extern (C) void thread_init();
extern (C) void thread_term();

__gshared GC instance;
__gshared GC proxiedGC; // used to iterate roots of Windows DLLs

Expand All @@ -50,10 +47,6 @@ extern (C)
fprintf(stderr, "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr);
exit(1);
}

// NOTE: The GC must initialize the thread library
// before its first collection.
thread_init();
}

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

thread_term();

ManualGC.finalize(instance);
ConservativeGC.finalize(instance);
}
Expand Down
4 changes: 4 additions & 0 deletions src/rt/dmain2.d
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ extern (C) void _d_critical_init();
extern (C) void _d_critical_term();
extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void thread_init() @nogc;
extern (C) void thread_term() @nogc;
extern (C) void lifetime_init();
extern (C) void rt_moduleCtor();
extern (C) void rt_moduleTlsCtor();
Expand Down Expand Up @@ -190,6 +192,7 @@ extern (C) int rt_init()
// this initializes mono time before anything else to allow usage
// in other druntime systems.
_d_initMonoTime();
thread_init();
gc_init();
initStaticDataGC();
lifetime_init();
Expand Down Expand Up @@ -221,6 +224,7 @@ extern (C) int rt_term()
thread_joinAll();
rt_moduleDtor();
gc_term();
thread_term();
return 1;
}
catch (Throwable t)
Expand Down
29 changes: 25 additions & 4 deletions src/rt/monitor_.d
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,26 @@ extern (C) void _d_monitordelete(Object h, bool det)
}
}

// 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
{
Expand Down Expand Up @@ -173,6 +193,7 @@ else version (Posix)
{
import core.sys.posix.pthread;

@nogc:
alias Mutex = pthread_mutex_t;
__gshared pthread_mutexattr_t gattr;

Expand Down Expand Up @@ -211,17 +232,17 @@ struct Monitor

private:

@property ref shared(Monitor*) monitor(Object h) pure nothrow
@property ref shared(Monitor*) monitor(Object h) pure nothrow @nogc
{
return *cast(shared Monitor**)&h.__monitor;
}

private shared(Monitor)* getMonitor(Object h) pure
private shared(Monitor)* getMonitor(Object h) pure @nogc
{
return atomicLoad!(MemoryOrder.acq)(h.monitor);
}

void setMonitor(Object h, shared(Monitor)* m) pure
void setMonitor(Object h, shared(Monitor)* m) pure @nogc
{
atomicStore!(MemoryOrder.rel)(h.monitor, m);
}
Expand Down Expand Up @@ -263,7 +284,7 @@ shared(Monitor)* ensureMonitor(Object h)
}
}

void deleteMonitor(Monitor* m)
void deleteMonitor(Monitor* m) @nogc
{
destroyMutex(&m.mtx);
free(m);
Expand Down