📄 pthread_mutex_init.html
字号:
<p>Defining symbols for the maximum number of mutexes and condition variables was considered but rejected because the number ofthese objects may change dynamically. Furthermore, many implementations place these objects into application memory; thus, there isno explicit maximum.</p><h5><a name="tag_03_537_08_04"></a>Static Initializers for Mutexes and Condition Variables</h5><p>Providing for static initialization of statically allocated synchronization objects allows modules with private staticsynchronization variables to avoid runtime initialization tests and overhead. Furthermore, it simplifies the coding ofself-initializing modules. Such modules are common in C libraries, where for various reasons the design calls forself-initialization instead of requiring an explicit module initialization function to be called. An example use of staticinitialization follows.</p><p>Without static initialization, a self-initializing routine <i>foo</i>() might look as follows:</p><pre><tt>static pthread_once_t foo_once = PTHREAD_ONCE_INIT;static pthread_mutex_t foo_mutex;<br>void foo_init(){ pthread_mutex_init(&foo_mutex, NULL);}<br>void foo(){ pthread_once(&foo_once, foo_init); pthread_mutex_lock(&foo_mutex); /* Do work. */ pthread_mutex_unlock(&foo_mutex);}</tt></pre><p>With static initialization, the same routine could be coded as follows:</p><pre><tt>static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;<br>void foo(){ pthread_mutex_lock(&foo_mutex); /* Do work. */ pthread_mutex_unlock(&foo_mutex);}</tt></pre><p>Note that the static initialization both eliminates the need for the initialization test inside <a href="../functions/pthread_once.html"><i>pthread_once</i>()</a> and the fetch of &<i>foo_mutex</i> to learn the address to be passedto <a href="../functions/pthread_mutex_lock.html"><i>pthread_mutex_lock</i>()</a> or <a href="../functions/pthread_mutex_unlock.html"><i>pthread_mutex_unlock</i>()</a>.</p><p>Thus, the C code written to initialize static objects is simpler on all systems and is also faster on a large class of systems;those where the (entire) synchronization object can be stored in application memory.</p><p>Yet the locking performance question is likely to be raised for machines that require mutexes to be allocated out of specialmemory. Such machines actually have to have mutexes and possibly condition variables contain pointers to the actual hardware locks.For static initialization to work on such machines, <a href="../functions/pthread_mutex_lock.html"><i>pthread_mutex_lock</i>()</a>also has to test whether or not the pointer to the actual lock has been allocated. If it has not, <a href="../functions/pthread_mutex_lock.html"><i>pthread_mutex_lock</i>()</a> has to initialize it before use. The reservation of suchresources can be made when the program is loaded, and hence return codes have not been added to mutex locking and conditionvariable waiting to indicate failure to complete initialization.</p><p>This runtime test in <a href="../functions/pthread_mutex_lock.html"><i>pthread_mutex_lock</i>()</a> would at first seem to beextra work; an extra test is required to see whether the pointer has been initialized. On most machines this would actually beimplemented as a fetch of the pointer, testing the pointer against zero, and then using the pointer if it has already beeninitialized. While the test might seem to add extra work, the extra effort of testing a register is usually negligible since noextra memory references are actually done. As more and more machines provide caches, the real expenses are memory references, notinstructions executed.</p><p>Alternatively, depending on the machine architecture, there are often ways to eliminate <i>all</i> overhead in the mostimportant case: on the lock operations that occur <i>after</i> the lock has been initialized. This can be done by shifting moreoverhead to the less frequent operation: initialization. Since out-of-line mutex allocation also means that an address has to bedereferenced to find the actual lock, one technique that is widely applicable is to have static initialization store a bogus valuefor that address; in particular, an address that causes a machine fault to occur. When such a fault occurs upon the first attemptto lock such a mutex, validity checks can be done, and then the correct address for the actual lock can be filled in. Subsequentlock operations incur no extra overhead since they do not "fault". This is merely one technique that can be used to supportstatic initialization, while not adversely affecting the performance of lock acquisition. No doubt there are other techniques thatare highly machine-dependent.</p><p>The locking overhead for machines doing out-of-line mutex allocation is thus similar for modules being implicitly initialized,where it is improved for those doing mutex allocation entirely inline. The inline case is thus made much faster, and theout-of-line case is not significantly worse.</p><p>Besides the issue of locking performance for such machines, a concern is raised that it is possible that threads would serializecontending for initialization locks when attempting to finish initializing statically allocated mutexes. (Such finishing wouldtypically involve taking an internal lock, allocating a structure, storing a pointer to the structure in the mutex, and releasingthe internal lock.) First, many implementations would reduce such serialization by hashing on the mutex address. Second, suchserialization can only occur a bounded number of times. In particular, it can happen at most as many times as there are staticallyallocated synchronization objects. Dynamically allocated objects would still be initialized via <i>pthread_mutex_init</i>() or <ahref="../functions/pthread_cond_init.html"><i>pthread_cond_init</i>()</a>.</p><p>Finally, if none of the above optimization techniques for out-of-line allocation yields sufficient performance for anapplication on some implementation, the application can avoid static initialization altogether by explicitly initializing allsynchronization objects with the corresponding <i>pthread_*_init</i>() functions,which are supported by all implementations. An implementation can also document the tradeoffs and advise which initializationtechnique is more efficient for that particular implementation.</p><h5><a name="tag_03_537_08_05"></a>Destroying Mutexes</h5><p>A mutex can be destroyed immediately after it is unlocked. For example, consider the following code:</p><pre><tt>struct obj {pthread_mutex_t om; int refcnt; ...};<br>obj_done(struct obj *op){ pthread_mutex_lock(&op->om); if (--op->refcnt == 0) { pthread_mutex_unlock(&op->om);(A) pthread_mutex_destroy(&op->om);(B) free(op); } else(C) pthread_mutex_unlock(&op->om);}</tt></pre><p>In this case <i>obj</i> is reference counted and <i>obj_done</i>() is called whenever a reference to the object is dropped.Implementations are required to allow an object to be destroyed and freed and potentially unmapped (for example, lines A and B)immediately after the object is unlocked (line C).</p></blockquote><h4><a name="tag_03_537_09"></a>FUTURE DIRECTIONS</h4><blockquote><p>None.</p></blockquote><h4><a name="tag_03_537_10"></a>SEE ALSO</h4><blockquote><p><a href="pthread_mutex_getprioceiling.html"><i>pthread_mutex_getprioceiling</i>()</a> , <a href="pthread_mutex_lock.html"><i>pthread_mutex_lock</i>()</a> , <a href="pthread_mutex_timedlock.html"><i>pthread_mutex_timedlock</i>()</a> , <a href="pthread_mutexattr_getpshared.html"><i>pthread_mutexattr_getpshared</i>()</a> , the Base Definitions volume ofIEEE Std 1003.1-2001, <a href="../basedefs/pthread.h.html"><i><pthread.h></i></a></p></blockquote><h4><a name="tag_03_537_11"></a>CHANGE HISTORY</h4><blockquote><p>First released in Issue 5. Included for alignment with the POSIX Threads Extension.</p></blockquote><h4><a name="tag_03_537_12"></a>Issue 6</h4><blockquote><p>The <i>pthread_mutex_destroy</i>() and <i>pthread_mutex_init</i>() functions are marked as part of the Threads option.</p><p>The <a href="../functions/pthread_mutex_timedlock.html"><i>pthread_mutex_timedlock</i>()</a> function is added to the SEE ALSOsection for alignment with IEEE Std 1003.1d-1999.</p><p>IEEE PASC Interpretation 1003.1c #34 is applied, updating the DESCRIPTION.</p><p>The <b>restrict</b> keyword is added to the <i>pthread_mutex_init</i>() prototype for alignment with the ISO/IEC 9899:1999standard.</p></blockquote><div class="box"><em>End of informative text.</em></div><hr><hr size="2" noshade><center><font size="2"><!--footer start-->UNIX ® is a registered Trademark of The Open Group.<br>POSIX ® is a registered Trademark of The IEEE.<br>[ <a href="../mindex.html">Main Index</a> | <a href="../basedefs/contents.html">XBD</a> | <a href="../utilities/contents.html">XCU</a> | <a href="../functions/contents.html">XSH</a> | <a href="../xrat/contents.html">XRAT</a>]</font></center><!--footer end--><hr size="2" noshade></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -