10 lines
16 KiB
HTML
10 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Proper maintenance and care of multi-threading locks · The Julia Language</title><script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
|
|
|
ga('create', 'UA-28835595-6', 'auto');
|
|
ga('send', 'pageview');
|
|
</script><link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css" rel="stylesheet" type="text/css"/><link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL=".."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js" data-main="../assets/documenter.js"></script><script src="../siteinfo.js"></script><script src="../../versions.js"></script><link href="../assets/documenter.css" rel="stylesheet" type="text/css"/><link href="../assets/julia-manual.css" rel="stylesheet" type="text/css"/></head><body><nav class="toc"><a href="../index.html"><img class="logo" src="../assets/logo.png" alt="The Julia Language logo"/></a><h1>The Julia Language</h1><select id="version-selector" onChange="window.location.href=this.value" style="visibility: hidden"></select><form class="search" id="search-form" action="../search.html"><input id="search-query" name="q" type="text" placeholder="Search docs"/></form><ul><li><a class="toctext" href="../index.html">Home</a></li><li><span class="toctext">Manual</span><ul><li><a class="toctext" href="../manual/introduction.html">Introduction</a></li><li><a class="toctext" href="../manual/getting-started.html">Getting Started</a></li><li><a class="toctext" href="../manual/variables.html">Variables</a></li><li><a class="toctext" href="../manual/integers-and-floating-point-numbers.html">Integers and Floating-Point Numbers</a></li><li><a class="toctext" href="../manual/mathematical-operations.html">Mathematical Operations and Elementary Functions</a></li><li><a class="toctext" href="../manual/complex-and-rational-numbers.html">Complex and Rational Numbers</a></li><li><a class="toctext" href="../manual/strings.html">Strings</a></li><li><a class="toctext" href="../manual/functions.html">Functions</a></li><li><a class="toctext" href="../manual/control-flow.html">Control Flow</a></li><li><a class="toctext" href="../manual/variables-and-scoping.html">Scope of Variables</a></li><li><a class="toctext" href="../manual/types.html">Types</a></li><li><a class="toctext" href="../manual/methods.html">Methods</a></li><li><a class="toctext" href="../manual/constructors.html">Constructors</a></li><li><a class="toctext" href="../manual/conversion-and-promotion.html">Conversion and Promotion</a></li><li><a class="toctext" href="../manual/interfaces.html">Interfaces</a></li><li><a class="toctext" href="../manual/modules.html">Modules</a></li><li><a class="toctext" href="../manual/documentation.html">Documentation</a></li><li><a class="toctext" href="../manual/metaprogramming.html">Metaprogramming</a></li><li><a class="toctext" href="../manual/arrays.html">Multi-dimensional Arrays</a></li><li><a class="toctext" href="../manual/linear-algebra.html">Linear algebra</a></li><li><a class="toctext" href="../manual/networking-and-streams.html">Networking and Streams</a></li><li><a class="toctext" href="../manual/parallel-computing.html">Parallel Computing</a></li><li><a class="toctext" href="../manual/dates.html">Date and DateTime</a></li><li><a class="toctext" href="../manual/interacting-with-julia.html">Interacting With Julia</a></li><li><a class="toctext" href="../manual/running-external-programs.html">Running External Programs</a></li><li><a class="toctext" href="../manual/calling-c-and-fortran-code.html">Calling C and Fortran Code</a></li><li><a class="toctext" href="../manual/handling-operating-system-variation.html">Handling Operating System Variation</a></li><li><a class="toctext" href="../manual/environment-variables.html">Environment Variables</a></li><li><a class="toctext" href="../manual/embedding.html">Embedding Julia</a></li><li><a class="toctext" href="../manual/packages.html">Packages</a></li><li><a class="toctext" href="../manual/profile.html">Profiling</a></li><li><a class="toctext" href="../manual/stacktraces.html">Stack Traces</a></li><li><a class="toctext" href="../manual/performance-tips.html">Performance Tips</a></li><li><a class="toctext" href="../manual/workflow-tips.html">Workflow Tips</a></li><li><a class="toctext" href="../manual/style-guide.html">Style Guide</a></li><li><a class="toctext" href="../manual/faq.html">Frequently Asked Questions</a></li><li><a class="toctext" href="../manual/noteworthy-differences.html">Noteworthy Differences from other Languages</a></li><li><a class="toctext" href="../manual/unicode-input.html">Unicode Input</a></li></ul></li><li><span class="toctext">Standard Library</span><ul><li><a class="toctext" href="../stdlib/base.html">Essentials</a></li><li><a class="toctext" href="../stdlib/collections.html">Collections and Data Structures</a></li><li><a class="toctext" href="../stdlib/math.html">Mathematics</a></li><li><a class="toctext" href="../stdlib/numbers.html">Numbers</a></li><li><a class="toctext" href="../stdlib/strings.html">Strings</a></li><li><a class="toctext" href="../stdlib/arrays.html">Arrays</a></li><li><a class="toctext" href="../stdlib/parallel.html">Tasks and Parallel Computing</a></li><li><a class="toctext" href="../stdlib/linalg.html">Linear Algebra</a></li><li><a class="toctext" href="../stdlib/constants.html">Constants</a></li><li><a class="toctext" href="../stdlib/file.html">Filesystem</a></li><li><a class="toctext" href="../stdlib/io-network.html">I/O and Network</a></li><li><a class="toctext" href="../stdlib/punctuation.html">Punctuation</a></li><li><a class="toctext" href="../stdlib/sort.html">Sorting and Related Functions</a></li><li><a class="toctext" href="../stdlib/pkg.html">Package Manager Functions</a></li><li><a class="toctext" href="../stdlib/dates.html">Dates and Time</a></li><li><a class="toctext" href="../stdlib/iterators.html">Iteration utilities</a></li><li><a class="toctext" href="../stdlib/test.html">Unit Testing</a></li><li><a class="toctext" href="../stdlib/c.html">C Interface</a></li><li><a class="toctext" href="../stdlib/libc.html">C Standard Library</a></li><li><a class="toctext" href="../stdlib/libdl.html">Dynamic Linker</a></li><li><a class="toctext" href="../stdlib/profile.html">Profiling</a></li><li><a class="toctext" href="../stdlib/stacktraces.html">StackTraces</a></li><li><a class="toctext" href="../stdlib/simd-types.html">SIMD Support</a></li></ul></li><li><span class="toctext">Developer Documentation</span><ul><li><a class="toctext" href="reflection.html">Reflection and introspection</a></li><li><span class="toctext">Documentation of Julia's Internals</span><ul><li><a class="toctext" href="init.html">Initialization of the Julia runtime</a></li><li><a class="toctext" href="ast.html">Julia ASTs</a></li><li><a class="toctext" href="types.html">More about types</a></li><li><a class="toctext" href="object.html">Memory layout of Julia Objects</a></li><li><a class="toctext" href="eval.html">Eval of Julia code</a></li><li><a class="toctext" href="callconv.html">Calling Conventions</a></li><li><a class="toctext" href="compiler.html">High-level Overview of the Native-Code Generation Process</a></li><li><a class="toctext" href="functions.html">Julia Functions</a></li><li><a class="toctext" href="cartesian.html">Base.Cartesian</a></li><li><a class="toctext" href="meta.html">Talking to the compiler (the <code>:meta</code> mechanism)</a></li><li><a class="toctext" href="subarrays.html">SubArrays</a></li><li><a class="toctext" href="sysimg.html">System Image Building</a></li><li><a class="toctext" href="llvm.html">Working with LLVM</a></li><li><a class="toctext" href="stdio.html">printf() and stdio in the Julia runtime</a></li><li><a class="toctext" href="boundscheck.html">Bounds checking</a></li><li class="current"><a class="toctext" href="locks.html">Proper maintenance and care of multi-threading locks</a><ul class="internal"><li><a class="toctext" href="#Locks-1">Locks</a></li><li><a class="toctext" href="#Broken-Locks-1">Broken Locks</a></li><li><a class="toctext" href="#Shared-Global-Data-Structures-1">Shared Global Data Structures</a></li></ul></li><li><a class="toctext" href="offset-arrays.html">Arrays with custom indices</a></li><li><a class="toctext" href="libgit2.html">Base.LibGit2</a></li><li><a class="toctext" href="require.html">Module loading</a></li></ul></li><li><span class="toctext">Developing/debugging Julia's C code</span><ul><li><a class="toctext" href="backtraces.html">Reporting and analyzing crashes (segfaults)</a></li><li><a class="toctext" href="debuggingtips.html">gdb debugging tips</a></li><li><a class="toctext" href="valgrind.html">Using Valgrind with Julia</a></li><li><a class="toctext" href="sanitizers.html">Sanitizer support</a></li></ul></li></ul></li></ul></nav><article id="docs"><header><nav><ul><li>Developer Documentation</li><li>Documentation of Julia's Internals</li><li><a href="locks.html">Proper maintenance and care of multi-threading locks</a></li></ul><a class="edit-page" href="https://github.com/JuliaLang/julia/blob/master/doc/src/devdocs/locks.md"><span class="fa"></span> Edit on GitHub</a></nav><hr/><div id="topbar"><span>Proper maintenance and care of multi-threading locks</span><a class="fa fa-bars" href="#"></a></div></header><h1><a class="nav-anchor" id="Proper-maintenance-and-care-of-multi-threading-locks-1" href="#Proper-maintenance-and-care-of-multi-threading-locks-1">Proper maintenance and care of multi-threading locks</a></h1><p>The following strategies are used to ensure that the code is dead-lock free (generally by addressing the 4th Coffman condition: circular wait).</p><blockquote><ol><li><p>structure code such that only one lock will need to be acquired at a time</p></li><li><p>always acquire shared locks in the same order, as given by the table below</p></li><li><p>avoid constructs that expect to need unrestricted recursion</p></li></ol></blockquote><h2><a class="nav-anchor" id="Locks-1" href="#Locks-1">Locks</a></h2><p>Below are all of the locks that exist in the system and the mechanisms for using them that avoid the potential for deadlocks (no Ostrich algorithm allowed here):</p><p>The following are definitely leaf locks (level 1), and must not try to acquire any other lock:</p><blockquote><ul><li><p>safepoint</p><blockquote><p>Note that this lock is acquired implicitly by <code>JL_LOCK</code> and <code>JL_UNLOCK</code>. use the <code>_NOGC</code> variants to avoid that for level 1 locks.</p><p>While holding this lock, the code must not do any allocation or hit any safepoints. Note that there are safepoints when doing allocation, enabling / disabling GC, entering / restoring exception frames, and taking / releasing locks.</p></blockquote></li><li><p>shared_map</p></li><li><p>finalizers</p></li><li><p>pagealloc</p></li><li><p>gc_perm_lock</p></li><li><p>flisp</p><blockquote><p>flisp itself is already threadsafe, this lock only protects the <code>jl_ast_context_list_t</code> pool</p></blockquote></li></ul></blockquote><p>The following is a leaf lock (level 2), and only acquires level 1 locks (safepoint) internally:</p><blockquote><ul><li><p>typecache</p></li></ul></blockquote><p>The following is a level 3 lock, which can only acquire level 1 or level 2 locks internally:</p><blockquote><ul><li><p>Method->writelock</p></li></ul></blockquote><p>The following is a level 4 lock, which can only recurse to acquire level 1, 2, or 3 locks:</p><blockquote><ul><li><p>MethodTable->writelock</p></li></ul></blockquote><p>No Julia code may be called while holding a lock above this point.</p><p>The following is a level 6 lock, which can only recurse to acquire locks at lower levels:</p><blockquote><ul><li><p>codegen</p></li></ul></blockquote><p>The following is an almost root lock (level end-1), meaning only the root look may be held when trying to acquire it:</p><blockquote><ul><li><p>typeinf</p><blockquote><p>this one is perhaps one of the most tricky ones, since type-inference can be invoked from many points</p><p>currently the lock is merged with the codegen lock, since they call each other recursively</p></blockquote></li></ul></blockquote><p>The following is the root lock, meaning no other lock shall be held when trying to acquire it:</p><blockquote><ul><li><p>toplevel</p><blockquote><p>this should be held while attempting a top-level action (such as making a new type or defining a new method): trying to obtain this lock inside a staged function will cause a deadlock condition!</p><p>additionally, it's unclear if <em>any</em> code can safely run in parallel with an arbitrary toplevel expression, so it may require all threads to get to a safepoint first</p></blockquote></li></ul></blockquote><h2><a class="nav-anchor" id="Broken-Locks-1" href="#Broken-Locks-1">Broken Locks</a></h2><p>The following locks are broken:</p><ul><li><p>toplevel</p><blockquote><p>doesn't exist right now</p><p>fix: create it</p></blockquote></li></ul><h2><a class="nav-anchor" id="Shared-Global-Data-Structures-1" href="#Shared-Global-Data-Structures-1">Shared Global Data Structures</a></h2><p>These data structures each need locks due to being shared mutable global state. It is the inverse list for the above lock priority list. This list does not include level 1 leaf resources due to their simplicity.</p><p>MethodTable modifications (def, cache, kwsorter type) : MethodTable->writelock</p><p>Type declarations : toplevel lock</p><p>Type application : typecache lock</p><p>Module serializer : toplevel lock</p><p>JIT & type-inference : codegen lock</p><p>MethodInstance updates : codegen lock</p><blockquote><ul><li><p>These fields are generally lazy initialized, using the test-and-test-and-set pattern.</p></li><li><p>These are set at construction and immutable:</p><ul><li><p>specTypes</p></li><li><p>sparam_vals</p></li><li><p>def</p></li></ul></li><li><p>These are set by <code>jl_type_infer</code> (while holding codegen lock):</p><ul><li><p>rettype</p></li><li><p>inferred</p></li><li><p>these can also be reset, see <code>jl_set_lambda_rettype</code> for that logic as it needs to keep <code>functionObjectsDecls</code> in sync</p></li></ul></li><li><p><code>inInference</code> flag:</p><ul><li><p>optimization to quickly avoid recurring into <code>jl_type_infer</code> while it is already running</p></li><li><p>actual state (of setting <code>inferred</code>, then <code>fptr</code>) is protected by codegen lock</p></li></ul></li><li><p>Function pointers (<code>jlcall_api</code> and <code>fptr</code>, <code>unspecialized_ducttape</code>):</p><ul><li><p>these transition once, from <code>NULL</code> to a value, while the codegen lock is held</p></li></ul></li><li><p>Code-generator cache (the contents of <code>functionObjectsDecls</code>):</p><ul><li><p>these can transition multiple times, but only while the codegen lock is held</p></li><li><p>it is valid to use old version of this, or block for new versions of this, so races are benign, as long as the code is careful not to reference other data in the method instance (such as <code>rettype</code>) and assume it is coordinated, unless also holding the codegen lock</p></li></ul></li><li><p><code>compile_traced</code> flag:</p><ul><li><p>unknown</p></li></ul></li></ul></blockquote><p>LLVMContext : codegen lock</p><p>Method : Method->writelock</p><ul><li><p>roots array (serializer and codegen)</p></li><li><p>invoke / specializations / tfunc modifications</p></li></ul><footer><hr/><a class="previous" href="boundscheck.html"><span class="direction">Previous</span><span class="title">Bounds checking</span></a><a class="next" href="offset-arrays.html"><span class="direction">Next</span><span class="title">Arrays with custom indices</span></a></footer></article></body></html>
|