-
-
Notifications
You must be signed in to change notification settings - Fork 421
Add attributes to core.thread #1726
Add attributes to core.thread #1726
Conversation
This commit adds attributes to those functions in `core.thread` that don't require changes outside of the module. Not much of this has profound effect to the users but makes adding a templated `Thread`/`Fiber` classes on the user's callback much easier later on, which should help address the need for `@nogc` and `nothrow` threading primitives.
f4fab63 to
a1cb7b8
Compare
ad96e37 to
1a0f2ac
Compare
This commit fixes `Thread.~this()`, `thread_attachThis`
and partially `thread_entryPoint` and `thread_attachByAddrB`.
`thread_entryPoint` can't be made `@nogc` because it calls
`Thread.run`, `rt_moduleTlsCtor` and `rt_moduleTlsDtor`,
which can execute arbitrary user code.
`thread_attachByAddrB` can't be made `@nogc` because
it calls `thread_findByAddr`, which calls `Thread.opApply`,
which can't be `@nogc` because it calls a non-`@nogc`
delegate.
This change is a bit large because many call-sites needed
to be fixed in one go:
* On posix, `thread_entryPoint` calls `inheritLoadedLibraries`
and `cleanupLoadedLibraries`, and `Thread.start` calls
`rt.sections.pinLoadedLibraries` and `unpinLoadedLibraries`.
* `Thread.~this()` calls `rt.tlsgc.destroy`, which in turn
calls `rt.sections.finiTLSRanges`, which is implemented
in `rt.secions_{platform}`.
* Similarly, `thread_attachThis` calls `rt.tlsgc.init`, which in
turn calls `rt.sections.initTLSRanges`, which is implemented
in `rt.secions_{platform}`. On some platforms
`rt.sections.initTLSRanges` calls `rt.minfo.ModuleGroup.this`,
so I made it `nothrow` and `@nogc` too.
* Additionally, `rt.sections.initSections` and `finiSections` were
easy to fix, so I added appropriate attributes to them, even
though they are called only from `rt.dmain2.rt_init`.
Finally, some function from `rt.sections_elf_shared` was accessing
`ModuleInfo.name` which wasn't marked as `@nogc`, so I went
through `object.ModuleInfo` and made all of its members
`@nogc` (they were already `nothrow`).
This commit adds attributes to Fiber.callImpl.
The call chain looks like this:
-> core.thread.Fiber.callImpl
-> core.Fiber.switchIn
-> core.Thread.pushContext/core.Thread.popContext
-> core.thread.swapContext
-> depending on the platform:
-> rt.deh_win32/deh_win64_posix._d_eh_swapContext (On Windows and sometimes on Posix)
-> rt.dwarfeh._d_eh_swapContextDwarf (on Posix)
1a0f2ac to
f533e93
Compare
|
@jmdavis @schveiguy @rainers @MartinNowak please take a look. The diff is a bit large but otherwise all of the changes should be easy to review. @joakim-noah is there an easy way (preferably without messing with LDC) to test my change for |
|
No, I'll try it and let you know. |
|
Thanks @joakim-noah, much appreciated! |
FYI there would have been a different way: letting Anyways this is great work! |
Yeah, that's probably a better approach, but I wanted to finish my PR, which fortunately led me to this one and #1728.
Thanks, though IMO #1728 is much interesting and important, because it makes |
|
Regarding Android compatibility, I tried modifying this PR to apply against druntime from ldc master, which is from the 2.071 branch. However, it crapped out when compiling with a bunch of attribute errors in |
|
Ping @klickverbot @ibuclaw @MartinNowak I'd like to move forward with this PR. Is there anything else I need to do? |
|
Good stuff! |
|
Thanks! |
|
You gotta hate attributes. Hope we get to that 2017H2, Mitigating the attribute proliferation - attribute inference for functions - D Programming Language Discussion Forum. |
|
This broke at least vibe.d and dependents, we need to be really careful with API's of non-final classes. Unfortunately the current project tester didn't cover this b/c ZombineDev wasn't yet whitelisted (ci2 won't need whitelists ¹). Related to class compatibility and deprecations. |
|
@MartinNowak how do Java and C# (of which standard and other libraries rely heavily on non-final classes) deal with such breakages? |
|
Guess they don't have such an attribute craze like us. |
|
They do have related issues, hence the addition of default interface function implementations to Java. |
|
@MartinNowak Do you know of any other issues than the one reported in https://issues.dlang.org/show_bug.cgi?id=17130. Or is it just PR #1728 the culprit? |
|
@MartinNowak how do I get myself whitelisted and how can I join dlang.slack.com? |
While working on adding attributes to
std.random(and in particularunpredictableSeed) in PR dlang/phobos#4136, I noticed that much of the functions incore.threaddon't have appropriate attributes (in particularThread.getThis), so I added them where possible.As a result, after going through the whole module, here's what's left before the
core.threadcan befully
@nogcandnothrow:thread_entryPoint-> calls
Thread.run, which is not@nogcandnothrowthread_suspendHandler
-> calls
callWithStackShellwhich takes a non-@nogcdelegateThread.start-> calls
onThreadErrorwhich is not@nogcThread.id/name/isDeamon-> synchronized is not
nothrowThread.priority-> throws
new ThreadExceptionThread.run-> User's callback has no attributes
thread_init-> calls
Thread.initLocksthread_term-> calls
Thread.termLocksThread.initLocks/termLocks-> calls
Mutex.this/~thiswhich are not@nogcandnothrowthread_attachThis/thread_attachByAddr/thread_attachByAddrB-> Create a new
Threadinstance with the GCthread_detachByAddr->
thread_findByAddris not@nogcandnothrowthread_findByAddr->
Thread.opApplyis not@nogcandnothrowThread.getAll/opApply/getAllImpl-> calls a non-
@nogcnon-nothrowdelegate->
Thread.getAllreturns a GC-ed arraythread_joinAll-> calls
Thread.joinwhich is not@nogcandnothrow-> calls
Thread.isDeamonnotnothrowThread.join-> throws
new ThreadExceptionthread_suspendAll-> calls
Thread.suspendwhich not@nogc-> calls
onThreadErrorwhich is not@nogcThread.suspend-> calls
onThreadErrorwhich is not@nogcthread_resumeAll-> calls
Thread.resumewhich is not@nogcThread.resume-> calls
onThreadErrorwhich is not@nogcthread_scanAll/thread_scanAllType/scanAllTypeImpl-> take a non-
@nogcdelegate-> call
rt_tlsgc_scanwhich also takes a non-@nogcdelegatethread_enterCriticalRegion/thread_exitCriticalRegion/thread_inCriticalRegion-> uses
synchronizedwhich is notnothrowthread_processGCMarks-> calls a non-@
nogcdelegateThreadGroup.*-> uses associative array under
synchronizedFiber.this-> calls
allocStackwhich is not@nogcallocStack-> allocates a new
Thread.Contextfrom with the GCFiber.call-> calls
fiber_entryPointfiber_entryPoint-> calls
Fiber.runwhich is not@nogcFiber.run-> calls arbitrary user callback
In summary, most of these fall into several categories:
calls
onThreadErrorwhich is not@nogc->onThreadError, to not use the GC, probably stepping on Make AssertError a singleton #1710throws
new ThreadException->onThreadErrorcalls
Mutex.this/~thiswhich are not@nogcandnothrow->core.sync.*- done in Makes core.sync.mutex.Mutex usable in modern code #1728synchronized is not
nothrow->_d_monitorenterand_d_monitorexitreturns GC allocated memory to the user (e.g.
thread_attachThis,Thread.getAll) ->Internally allocates GC memory (e.g.
Fiber'sallocStack) ->Internal function calls an internal non-
@nogccallback ->@nogcCalls a user provided callback.That's probably the trickiest. ->
DerivedThread(std.traits.FunctionAttribute Attr) and DerivedFiber(std.traits.FunctionAttribute Attr) templates, so thatThread.runandFiber.call` would propagate the attributes.ThreadGroupis notnothrow @nogc->@nogc nothrowmutex (see Makes core.sync.mutex.Mutex usable in modern code #1728)