[threading] Add a coop backend. This paves the way to introduce cooperativeness into...
commitb4d03818772e0be45f1bd09da1818b99b44e9ae5
authorRodrigo Kumpera <kumpera@gmail.com>
Mon, 2 Feb 2015 16:04:37 +0000 (2 11:04 -0500)
committerRodrigo Kumpera <kumpera@gmail.com>
Thu, 26 Mar 2015 23:44:17 +0000 (26 19:44 -0400)
treeb82800018e822fc11962a716bb566f57b2d5fbd7
parent084cb4d103acfe0342af0eed6b47952d9c7805a3
[threading] Add a coop backend. This paves the way to introduce cooperativeness into the runtime.

Coop requires the following set of rules:

-blocking code must be wrapped with MONO_PREPARE_BLOCKING / MONO_FINISH_BLOCKING
Must not read managed refs read/writes inside the block
Managed memory (i.e. inside a byte[]) must be previously pinned[1]

-state escaping transitions (lazy thunks and others sneaky n2m transitions) must be wrapped with MONO_PREPARE_RESET_BLOCKING / MONO_FINISH_RESET_BLOCKING
This lands the thread in runnable state, so be careful to keep it suspendable by following the target environment rules.

The set of rules for what runtime code can/can't are still in flux, but here's the tentative list:

== On Wrapping syscall/waits

- Wrap it on the callee. We can't necessarily know in which context the syscall will be called. This will reduce reentrancy issues as blocking is not reentrant.

- Don't go blocking while holding locks as this will certainly deadlock.

- Avoid allocating memory while holding locks.

- Annotate blocking restrictions in the comments in the same way we do it for locking.

== On aborting blocking

- Avoid it as much as possible as it might lead to unbound pauses.

- Make sure you can always restore back to blocking.

[1] Since we conservatively scan the native stack, acquiring the ref outside of the block is enough for now.
mono/utils/Makefile.am
mono/utils/mono-threads-coop.c [new file with mode: 0644]
mono/utils/mono-threads-coop.h [new file with mode: 0644]