1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 2<HTML> 3<HEAD> 4<META http-equiv="Content-Type" content="text/html; charset=windows-1252"> 5<META name="GENERATOR" content="IBM WebSphere Studio Homepage Builder Version 7.0.1.0 for Windows"> 6<META http-equiv="Content-Style-Type" content="text/css"> 7<TITLE>Exclusion Control (Mutex): Overview </TITLE> 8<LINK rel="stylesheet" href="../../css/nitro.css" type="text/css"> 9</HEAD> 10<BODY> 11<H1 align="left">Exclusion Control (Mutex): Overview</H1> 12<P>Mutex (<I>mutual exclusion</I> service) is a mechanism to control thread execution. This is a mechanism that can be used to prevent multiple threads from executing simultaneously in particular places in the program and from simultaneously accessing data, registers and other resources.</P> 13<H2>Initializing Mutex</H2> 14<P>Mutex is initialized with <nobr><code><a href="OS_InitMutex.html">OS_InitMutex()</a></code></nobr>. One mutex can be configured for each OSMutex structure object.</P> 15<H2>The Mutex Structure</H2> 16<P>The OSMutex structure is as follows:</P> 17<TABLE border="1"> 18 <TBODY> 19 <TR> 20 <TD> 21<pre>struct OSMutex 22{ 23 OSThreadQueue queue; 24 OSThread* thread; // the current owner 25 s32 count; // lock count (notice: use upper 1byte as mutex type) 26 27 OSMutex* prev; // link for OSThread.queueMutex 28 OSMutex* next; // link for OSThread.queueMutex 29};</pre> 30 </TD> 31 </TR> 32 </TBODY> 33</TABLE> 34<P><BR> The members <CODE>prev</CODE> and <CODE>next</CODE> manage mutex lists. The actual synchronous mutex functionality is done using the <CODE>queue</CODE>, <CODE>thread</CODE>, and <CODE>count</CODE> members.</P> 35<P><code><em><strong>queue</strong></em></code> is the thread queue where the thread that is being made to wait by mutex is registered.</P> 36<P><code><em><strong>thread</strong></em></code> is the member which registers the current thread that is locking other threads with this mutex.</P> 37<P><code><em><strong>count</strong></em></code> is the member that manages the lock nest for this mutex. It counts the number of times the lock has been set. However, the upper 1 byte is used to indicate the mutex type. The remaining 24 bits are used for the count value. The type is included in <CODE>count</CODE> instead of setting it to a separate member in order to retain compatibility with previous versions of mutex. (Note: Because the emphasis is on speed, the upper limit of the count value is not checked. One mutex can use 24 bits, which is equal to roughly 1.667 million nested levels. That limit will probably never be reached.)</P> 38<P>The following section explains mutex types.</P> 39<H2>Mutex Types</H2> 40<P>The mutex types are <I>STD</I>, <I>R</I>, and <I>W</I>. (These are defined in the header as OS_MUTEX_TYPE_STD and so forth. In the following explanation they are referred to as <I>STD</I>, <I>R</I>, and <I>W</I>.) If no type is specified, <I>NONE</I> is used.</P> 41<P>For normal thread synchronization, a STD mutex is used. With this type of mutex, other threads are not permitted unconditional entry. </P> 42<P>The R and W types are called <CODE>read lock</CODE> and <CODE>write lock</CODE> mutexes.</P> 43<P>The <CODE>read lock</CODE> mutex does not allow other threads to perform write or standard mutex locks. This type can be used when data is read. Multiple threads can simultaneously read the data without problem, but a data-writing process at this point could compromise the data consistency.</P> 44<P>The <CODE>write lock</CODE> mutex can be used when a thread is writing data. The data to be written cannot come from multiple threads. The W mutex does not permit another thread to read the data during the writing process. A W mutex has lock policy similar to that of a STD mutex. They are not exactly the same, because there are functions to change between <CODE>read lock</CODE> and <CODE>write lock</CODE> mutexes.</P> 45<P>An R mutex can change to a W type, and a W mutex can change an R type, provided there is only one level of locking by the thread with the mutex. In the following example, after data is written the process immediately changes to reading without releasing the lock (thus permitting reading by another thread).</P> 46<BLOCKQUOTE style="background-color:#ffffcc"><CODE>OSMutex mutex;<BR> OS_InitMutex( &mutex );<BR> <BR> <B>void write_and_read()</B><BR> {<BR> OS_LockMutexW( &mutex ); <FONT color="#ff0000"> write lock</FONT> <BR> writeData();<BR> OS_LockMutexFromWToR( &mutex ); <FONT color="#ff0000">Change from write lock to read lock</FONT><BR> readData();<BR> OS_UnlockMutexR(); <FONT color="#ff0000">Unlock as a read lock</FONT><BR> }<BR> <BR> <B>void read()</B><BR> {<BR> OS_LockMutexR( &mutex );<BR> readData();<BR> OS_UnlockMutexR( &mutex );<BR> }<BR> <BR> <BR> <B>thread1()</B><BR> {<BR> write_and_read();<BR> }<BR> <BR> <B>thread2()</B><BR> {<BR> read();<BR> }<BR> <BR></CODE></BLOCKQUOTE> 47<H2>Mutex Operations</H2> 48<P>The following operations can be performed on a mutex after it has been initialized.</P> 49<P> - Lock the mutex (<CODE>Lock</CODE> functions):<BR> <CODE><A href="OS_LockMutex.html">OS_LockMutex</A></CODE>, <CODE><A href="OS_LockMutexRW.html">OS_LockMutexR</A></CODE>, <CODE><A href="OS_LockMutexRW.html">OS_LockMutexW</A></CODE></P> 50<P> - Unlock the mutex (<CODE>Unlock</CODE> functions):<BR> <CODE><A href="OS_UnlockMutex.html">OS_UnlockMutex</A></CODE>, <CODE><A href="OS_UnlockMutexRW.html">OS_UnlockMutexR</A></CODE>, <CODE><A href="OS_UnlockMutexRW.html">OS_UnlockMutexW</A></CODE>, <CODE><A href="OS_UnlockMutexRW.html">OS_UnlockMutexRW</A></CODE></P> 51<P> - Attempt to lock the mutex (<CODE>TryLock</CODE> functions):<BR><CODE><A href="OS_TryLockMutex.html">OS_TryLockMutex</A></CODE>, <CODE><A href="OS_TryLockMutexRW.html">OS_TryLockMutexR</A></CODE>, <CODE><A href="OS_TryLockMutexRW.html">OS_TryLockMutexW</A></CODE></P> 52<P> </P> 53<P>When you lock a mutex, other threads are blocked from locking that mutex. However, <CODE>read lock</CODE> mutexes do not block each other. A blocked thread waits for the mutex to be unlocked.</P> 54<P>Lock functions wait until the lock is completed, but the <CODE>TryLock</CODE> functions return immediately, regardless of whether the mutex can be locked. You can determine from the returned value whether the lock was successful.</P> 55<P>The following operations are available for <CODE>read lock</CODE> and <CODE>write lock</CODE> mutexes.</P> 56<P> - Change the mutex type: <BR> <CODE><A href="OS_LockMutexFromToRW.html">OS_LockMutexFromRToW</A></CODE>, <CODE><A href="OS_LockMutexFromToRW.html">OS_LockMutexFromWToR</A></CODE></P> 57<P> - Attempt to change the mutex type: <BR> <CODE><A href="OS_TryLockMutexFromToRW.html">OS_TryLockMutexFromRToW</A></CODE>, <CODE><A href="OS_TryLockMutexFromToRW.html">OS_TryLockMutexFromWToR</A></CODE></P> 58<P> </P> 59<H2>Internal Operations: Locking A Mutex</H2> 60<P>This section explains the internal operations when a mutex is locked.</P> 61<P>When the mutex is initialized by the <CODE><A href="OS_InitMutex.html">OS_InitMutex</A></CODE> function, the owner of the <CODE>OSMutex</CODE> thread, the count value, the thread type, and the thread queue have the values shown in the following table. (The <CODE>count</CODE> member of <CODE>OSMutex</CODE> contains two pieces of information: the count value and the mutex type. This information is shown as <I>count </I>and <I>type</I>.)</P> 62<BLOCKQUOTE><IMG src="image_initial_member.gif" border="0"></BLOCKQUOTE> 63<P>This section explains locking with a standard mutex, not with a <CODE>read lock/write lock</CODE> mutex.</P> 64<P>If <code><a href="OS_LockMutex.html">OS_LockMutex()</a></code> is called in a program and the designated mutex is not being used in a lock at that point in time, <code>OS_LockMutex</code> records and locks the current thread.</P> 65<P>If a <nobr><code><a href="OS_LockMutex.html">OS_LockMutex()</a></code></nobr> call occurs for an already locked mutex, the mutex count is incremented and the mutex is bypassed if it is being locked by the same thread as the current thread. If the thread is not the same, it will go into a pause state until the lock is released. Thread re-scheduling occurs at this time.</P> 66<P>For example, consider the figure below when there is a <code>Mutex1</code> and a program which uses it for locking.</P> 67<BLOCKQUOTE><IMG src="image_mutex_l1.gif" border="0"></BLOCKQUOTE> 68<P>Suppose <code>thread1</code> attempts to execute this program. <CODE>thread1</CODE> executes the mutex lock function <CODE><A href="OS_LockMutex.html">OS_LockMutex( &Mutex1 )</A></CODE>. Because <CODE>Mutex1</CODE> is not in use, <CODE>thread 1</CODE> is recorded as the <CODE>Mutex1</CODE> owner thread, the count is set to <CODE>1</CODE>, and the program returns from the lock function. (The determination of whether <CODE>Mutex1</CODE> is in use is based on whether the <CODE>Mutex1</CODE> owner thread is <CODE>NULL</CODE>.) </P> 69<BLOCKQUOTE><IMG src="image_mutex_l2.gif" border="0"></BLOCKQUOTE> 70<P>Next, consider what happens when a separate thread, <code>thread2</code>, attempts to execute the same program. <code>thread2</code> runs <nobr><code>OS_LockMutex ( &Mutex1 )</code></nobr>, but <code>mutex1</code> is already being used in a lock. Since <code>thread2</code> is not the <code>mutex1</code> owner thread, <code>thread2</code> cannot proceed any further. As a result, <code>thread2</code> goes into a pause state. At this point, <code>thread2</code> is registered inside the <code>mutex1</code> thread queue as waiting for this lock to be released.<BLOCKQUOTE><IMG src="image_mutex_l3.gif" border="0"></BLOCKQUOTE> 71<P>Now consider a case where <code>thread1</code> once again runs <nobr><code>OS_LockMutex ( &Mutex1 )</code></nobr> (whether it is on the same line or a different line). <code>mutex1</code> is already being used in a lock, but the <code>mutex1</code> owner thread is the same as the current thread (<code>thread1</code>), so it can be bypassed. When this happens, the <code>mutex1</code> count increments.<BLOCKQUOTE><IMG src="image_mutex_l4.gif" border="0"></BLOCKQUOTE> 72<P>There are also times when multiple threads are registered in a single mutex thread queue. These threads are all locked by that mutex. However, it is not necessarily the case that all threads are in a pause state on the same line. If the mutex is unlocked, all registered threads will go into an executable state.<BLOCKQUOTE><IMG src="image_mutex_l5.gif" border="0"></BLOCKQUOTE> 73<H2>Internal Operations: Unlocking A Mutex</H2> 74<P>This section explains the internal operations when a mutex lock is unlocked. The explanation explains unlocking a standard mutex, not a <CODE>read lock/write lock</CODE> mutex.</P> 75<P>The function used to unlocking a mutex is <nobr><code><a href="OS_UnlockMutex.html">OS_UnlockMutex</a></code>. However, calling this function does not always unlock the mutex. Only when the <CODE>count</CODE> value inside the mutex has decremented to 0 will the lock be released. If the value is not zero, <CODE>count</CODE> will only be decremented and control will return from the function.</P> 76<P>For example, consider the following figure, where <code>thread1</code> runs <nobr><code>OS_LockMutex ( &Mutex1 )</code></nobr> while using <code>mutex1</code> to block <code>thread2</code>. 77<BLOCKQUOTE><IMG src="image_mutex_u1.gif" border="0"></BLOCKQUOTE> 78<P>At this point, the count has been decremented to zero, so the thread registered in the thread queue is put into an executable state and is re-scheduled. In this example, <code>thread2</code> goes into an executable state.</P> 79<BLOCKQUOTE><IMG src="image_mutex_u2.gif" border="0"></BLOCKQUOTE> 80<P>If <code>thread2</code> has higher priority than <code>thread1</code>, the threads will be switched. In other words, <code>thread1</code> will pause and <code>thread2</code> will execute. In its previous attempt to execute <CODE><A href="OS_LockMutex.html">OS_LockMutex( &Mutex1 )</A></CODE>, <code>thread2</code> was blocked by <code>thread1</code>. This time, however, because <code>Mutex1</code> has been released and initialized, <code>thread2</code> uses <code>Mutex1</code> to block the other threads.<BLOCKQUOTE><IMG src="image_mutex_u3.gif" border="0"><BR> 81</BLOCKQUOTE> 82<P>When <code>thread1</code> runs <nobr><code><a href="OS_UnlockMutex.html">OS_UnlockMutex</a></code></nobr> and the count value is not zero after being decremented, <CODE>thread1</CODE> can still continue. If this is the case, no thread re-scheduling occurs. In this way, mutex locks can take on a nested structure.<BLOCKQUOTE><IMG src="image_mutex_u4.gif" border="0"></BLOCKQUOTE> 83<H2>Attempting to Lock a Mutex</H2> 84<P>Until there is a lock, the <nobr><code><a href="OS_LockMutex.html">OS_LockMutex</a></code></nobr> function does not return. Conversely, the <nobr><code><a href="OS_TryLockMutex.html">OS_TryLockMutex</a></code></nobr> function locks if it can, but returns immediately if it can't. 85 86 87 88 89<P>Use the <nobr><code><a href="OS_TryLockMutex.html">OS_TryLockMutex</a></code></nobr> function to determine if a mutex was successfully locked. 90 91 92 93 94<P>The following <I>Try</I> functions perform similarly. <P>- The <CODE><A href="OS_TryLockMutexRW.html">OS_TryLockMutexR</A></CODE> function corresponds with <CODE><A href="OS_LockMutexRW.html">OS_LockMutexR</A></CODE>. 95<P> - The <CODE><A href="OS_TryLockMutexRW.html">OS_TryLockMutexW</A></CODE> function corresponds with <CODE><A href="OS_LockMutexRW.html">OS_LockMutexW</A></CODE>. 96<P> - The <CODE><A href="OS_TryLockMutexFromToRW.html">OS_TryLockMutexFromRToW</A></CODE> function corresponds with <CODE><A href="OS_LockMutexFromToRW.html">OS_LockMutexFromRToW</A></CODE>. 97 98<P> - The <CODE><A href="OS_TryLockMutexFromToRW.html">OS_TryLockMutexFromWToR</A></CODE> function corresponds with <CODE><A href="OS_LockMutexFromToRW.html">OS_LockMutexFromWToR</A></CODE>. 99 100<H2>When the Thread Ends</H2> 101<P>When the thread ends, every mutex locked by that thread is unlocked. This is true not only for a standard mutex, but also for <CODE>read lock/write lock</CODE> mutexes.</P> 102<H2>Warning Messages</H2> 103<P>When a function specifies a pointer to a mutex that is NULL or the call is clearly unusual in some other way, the DEBUG build will catch on the <CODE><A href="../debug/SDK_ASSERT.html">SDK_ASSERT</A></CODE> function. If an unlock function is called for a mutex that has not been locked, '<FONT color="#ff0000">Illegal unlock mutex</FONT>' is displayed. If this message is displayed, verify that the lock and unlock levels accurately correspond. Note that this message is output by the <CODE><A href="../debug/OS_TWarning.html">SDK_TWarning</A></CODE> function, so the program will not stop.</P> 104<H2>See Also</H2> 105<P><CODE><A href="../list_os.html#Mutex">Overview of OS Functions (Exclusion Control)<BR></A></CODE></P> 106<H2>Revision History</H2> 107<P>2008/12/17 Revised contents to reflect <CODE>read/write lock</CODE>.<BR>2004/12/14 Revised terminology and word endings.<BR>2004/11/11 Initial version.</P> 108<hr><p>CONFIDENTIAL</p></body> 109</HTML>