Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wish: Sys.critical #5457

Closed
vicuna opened this issue Dec 30, 2011 · 4 comments
Closed

Wish: Sys.critical #5457

vicuna opened this issue Dec 30, 2011 · 4 comments

Comments

@vicuna
Copy link

vicuna commented Dec 30, 2011

Original bug ID: 5457
Reporter: gerd
Assigned to: @lefessan
Status: closed (set by @xavierleroy on 2013-08-31T10:44:19Z)
Resolution: won't fix
Priority: normal
Severity: feature
Version: 3.12.1
Category: ~DO NOT USE (was: OCaml general)
Monitored by: meyer @protz @ygrek @dbuenzli

Bug description

"Sys.critical : unit -> unit" would run a function with the additional guarantee of the runtime that no asynchronous actions occur that lead to the execution of other Ocaml code.

Asynchronous actions would be: Thread switches, Signals, GC finalisers, GC hooks. Events that would lead to the execution of such actions are delayed until the critical section ends. Sections can be nested.

Asynchronous events are characterized by the fact that they cannot be controlled by the programmer in any way. The plan is to add a basic way of control.

Additional information

What I have in mind is a counter that is increased at the beginning of the section, and is decreased at its end (regular or via exception). Delaying thread switches and signals is probably trivial (just don't do when the counter is > 0, and check again when the counter is decreased). The GC callbacks need probably a bit of work as the actions need to be saved, so they can be run when the counter is zero again.

There are two motivations: (1) It would give the programmers a very light-weight way of protecting shared resources. (2) It solves problems of the interaction between GC hooks and other asynchronous events. For example, in a multi-threaded program it is currently almost impossible to mutate a global variable from a GC hook in a safe way (other than trivial cases), because you cannot protect the variable with a mutex. If the GC hook wants to get the mutex, it might already been locked (leading to deadlock).

This might also serve as clean solution for #5436

@vicuna
Copy link
Author

vicuna commented Dec 31, 2011

Comment author: gerd

Another use cases: The Random module could become thread-safe

There are also (rare) occasions where you are changing the global properties of a process temporarily, and you don't want that other threads see this (e.g. chdir, umask)

@vicuna
Copy link
Author

vicuna commented Jan 14, 2012

Comment author: @xavierleroy

Preventing preemption between threads is easy -- the bytecode threads implementation (otherlibs/threads) does it to implement mutex. Preventing other forms of context switches between threads (e.g. a thread blocks on a Unix.read) feels weird to me. I'm a bit unsure about signals, and very unsure about GC-related actions. Queuing finalizers to be run later sounds painful to implement.

@vicuna
Copy link
Author

vicuna commented Jan 17, 2012

Comment author: gerd

Interesting reaction. I was prepared to hear more fundamental objections, e.g. that this change makes all other approaches to integrating multi-threading more difficult or impossible (especially those targeting multicore). Or that programmers could use the feature in the wrong way, and especially keep the lock for too long.

My intention is that it becomes easier to program signal handlers and GC hooks in Ocaml. I've more than once moved such code, especially finalizers to the C level, because I get there implicitly the described effect. If you stick to Ocaml, you often cannot do more than setting some flag, and do the real finalization later. As an example look at the memory pool implementation in Ocamlnet: https://godirepo.camlcity.org/svn/lib-ocamlnet2/trunk/code/src/netsys/netsys_mem.ml (at the end of the file, look for type memory_pool). A memory pool is a manager for page-aligned bigarrays of char. The finalizer cannot here do much, because in a multi-thread program it is impossible to lock the data structure from the finalizer (deadlock danger). In this case, it was possible to just delay finalization, but I can imagine other cases where one does not want this, because the resources to free are more valuable than just memory.

If Sys.critical would only prevent preemption and maybe signal handlers, it would already make a lot of such things easier (especially in a finalizer, because the execution of finalizers is serialized anyway). The idea to also include GC hooks in general is just for completeness of the concept.

@vicuna
Copy link
Author

vicuna commented Jan 17, 2012

Comment author: @lefessan

Your assumption was correct, we discussed the issue, and "fundamental objections" were raised, by those ones who would like to have a multicore runtime soon...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants