utmutex.c revision 151937
155714Skris/*******************************************************************************
2280304Sjkim *
3280304Sjkim * Module Name: utmutex - local mutex support
4280304Sjkim *              $Revision: 1.3 $
555714Skris *
655714Skris ******************************************************************************/
755714Skris
855714Skris/******************************************************************************
955714Skris *
1055714Skris * 1. Copyright Notice
1155714Skris *
1255714Skris * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
1355714Skris * All rights reserved.
14280304Sjkim *
1555714Skris * 2. License
1655714Skris *
1755714Skris * 2.1. This is your license from Intel Corp. under its intellectual property
1855714Skris * rights.  You may have additional license terms from the party that provided
1955714Skris * you this software, covering your right to use that party's intellectual
2055714Skris * property rights.
2155714Skris *
2255714Skris * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2355714Skris * copy of the source code appearing in this file ("Covered Code") an
2455714Skris * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2555714Skris * base code distributed originally by Intel ("Original Intel Code") to copy,
2655714Skris * make derivatives, distribute, use and display any portion of the Covered
2755714Skris * Code in any form, with the right to sublicense such rights; and
2855714Skris *
2955714Skris * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3055714Skris * license (with the right to sublicense), under only those claims of Intel
3155714Skris * patents that are infringed by the Original Intel Code, to make, use, sell,
3255714Skris * offer to sell, and import the Covered Code and derivative works thereof
3355714Skris * solely to the minimum extent necessary to exercise the above copyright
3455714Skris * license, and in no event shall the patent license extend to any additions
3555714Skris * to or modifications of the Original Intel Code.  No other license or right
3655714Skris * is granted directly or by implication, estoppel or otherwise;
3755714Skris *
3855714Skris * The above copyright and patent license is granted only if the following
3955714Skris * conditions are met:
4055714Skris *
4155714Skris * 3. Conditions
4255714Skris *
4355714Skris * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4455714Skris * Redistribution of source code of any substantial portion of the Covered
4555714Skris * Code or modification with rights to further distribute source must include
4655714Skris * the above Copyright Notice, the above License, this list of Conditions,
4755714Skris * and the following Disclaimer and Export Compliance provision.  In addition,
4855714Skris * Licensee must cause all Covered Code to which Licensee contributes to
4955714Skris * contain a file documenting the changes Licensee made to create that Covered
5055714Skris * Code and the date of any change.  Licensee must include in that file the
5155714Skris * documentation of any changes made by any predecessor Licensee.  Licensee
5255714Skris * must include a prominent statement that the modification is derived,
5355714Skris * directly or indirectly, from Original Intel Code.
5455714Skris *
5555714Skris * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5655714Skris * Redistribution of source code of any substantial portion of the Covered
5755714Skris * Code or modification without rights to further distribute source must
5855714Skris * include the following Disclaimer and Export Compliance provision in the
5955714Skris * documentation and/or other materials provided with distribution.  In
6055714Skris * addition, Licensee may not authorize further sublicense of source of any
6155714Skris * portion of the Covered Code, and must include terms to the effect that the
6255714Skris * license from Licensee to its licensee is limited to the intellectual
6355714Skris * property embodied in the software Licensee provides to its licensee, and
6455714Skris * not to intellectual property embodied in modifications its licensee may
6555714Skris * make.
66280304Sjkim *
67280304Sjkim * 3.3. Redistribution of Executable. Redistribution in executable form of any
68280304Sjkim * substantial portion of the Covered Code or modification must reproduce the
69280304Sjkim * above Copyright Notice, and the following Disclaimer and Export Compliance
70280304Sjkim * provision in the documentation and/or other materials provided with the
71280304Sjkim * distribution.
72280304Sjkim *
73280304Sjkim * 3.4. Intel retains all right, title, and interest in and to the Original
74280304Sjkim * Intel Code.
7555714Skris *
7655714Skris * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7755714Skris * Intel shall be used in advertising or otherwise to promote the sale, use or
78280304Sjkim * other dealings in products derived from or relating to the Covered Code
79280304Sjkim * without prior written authorization from Intel.
80280304Sjkim *
81280304Sjkim * 4. Disclaimer and Export Compliance
82280304Sjkim *
83280304Sjkim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84280304Sjkim * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85280304Sjkim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86280304Sjkim * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87280304Sjkim * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8855714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
8955714Skris * PARTICULAR PURPOSE.
90280304Sjkim *
91280304Sjkim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92280304Sjkim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93280304Sjkim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9455714Skris * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95160814Ssimon * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96280304Sjkim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97280304Sjkim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9855714Skris * LIMITED REMEDY.
99280304Sjkim *
100280304Sjkim * 4.3. Licensee shall not export, either directly or indirectly, any of this
101280304Sjkim * software or system incorporating such software without first obtaining any
102280304Sjkim * required license or other approval from the U. S. Department of Commerce or
103280304Sjkim * any other agency or department of the United States Government.  In the
104280304Sjkim * event Licensee exports any such software from the United States or
10555714Skris * re-exports any such software from a foreign destination, Licensee shall
106280304Sjkim * ensure that the distribution and export/re-export of the software is in
107160814Ssimon * compliance with all laws, regulations, orders, or other restrictions of the
108280304Sjkim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109280304Sjkim * any of its subsidiaries will export/re-export any technical data, process,
11055714Skris * software, or service, directly or indirectly, to any country for which the
111280304Sjkim * United States government or any agency thereof requires an export license,
112280304Sjkim * other governmental approval, or letter of assurance, without first obtaining
113280304Sjkim * such license, approval or letter.
114280304Sjkim *
115280304Sjkim *****************************************************************************/
116280304Sjkim
117280304Sjkim
118280304Sjkim#define __UTMUTEX_C__
119280304Sjkim
120280304Sjkim#include <contrib/dev/acpica/acpi.h>
121280304Sjkim
122280304Sjkim#define _COMPONENT          ACPI_UTILITIES
123280304Sjkim        ACPI_MODULE_NAME    ("utmutex")
124280304Sjkim
125280304Sjkim/* Local prototypes */
126280304Sjkim
127280304Sjkimstatic ACPI_STATUS
128280304SjkimAcpiUtCreateMutex (
129280304Sjkim    ACPI_MUTEX_HANDLE       MutexId);
130280304Sjkim
131280304Sjkimstatic ACPI_STATUS
132280304SjkimAcpiUtDeleteMutex (
133280304Sjkim    ACPI_MUTEX_HANDLE       MutexId);
134280304Sjkim
135280304Sjkim
136280304Sjkim/*******************************************************************************
137280304Sjkim *
138280304Sjkim * FUNCTION:    AcpiUtMutexInitialize
139280304Sjkim *
140280304Sjkim * PARAMETERS:  None.
141280304Sjkim *
14255714Skris * RETURN:      Status
143 *
144 * DESCRIPTION: Create the system mutex objects.
145 *
146 ******************************************************************************/
147
148ACPI_STATUS
149AcpiUtMutexInitialize (
150    void)
151{
152    UINT32                  i;
153    ACPI_STATUS             Status;
154
155
156    ACPI_FUNCTION_TRACE ("UtMutexInitialize");
157
158
159    /*
160     * Create each of the predefined mutex objects
161     */
162    for (i = 0; i < NUM_MUTEX; i++)
163    {
164        Status = AcpiUtCreateMutex (i);
165        if (ACPI_FAILURE (Status))
166        {
167            return_ACPI_STATUS (Status);
168        }
169    }
170
171    Status = AcpiOsCreateLock (&AcpiGbl_GpeLock);
172    return_ACPI_STATUS (Status);
173}
174
175
176/*******************************************************************************
177 *
178 * FUNCTION:    AcpiUtMutexTerminate
179 *
180 * PARAMETERS:  None.
181 *
182 * RETURN:      None.
183 *
184 * DESCRIPTION: Delete all of the system mutex objects.
185 *
186 ******************************************************************************/
187
188void
189AcpiUtMutexTerminate (
190    void)
191{
192    UINT32                  i;
193
194
195    ACPI_FUNCTION_TRACE ("UtMutexTerminate");
196
197
198    /*
199     * Delete each predefined mutex object
200     */
201    for (i = 0; i < NUM_MUTEX; i++)
202    {
203        (void) AcpiUtDeleteMutex (i);
204    }
205
206    AcpiOsDeleteLock (AcpiGbl_GpeLock);
207    return_VOID;
208}
209
210
211/*******************************************************************************
212 *
213 * FUNCTION:    AcpiUtCreateMutex
214 *
215 * PARAMETERS:  MutexID         - ID of the mutex to be created
216 *
217 * RETURN:      Status
218 *
219 * DESCRIPTION: Create a mutex object.
220 *
221 ******************************************************************************/
222
223static ACPI_STATUS
224AcpiUtCreateMutex (
225    ACPI_MUTEX_HANDLE       MutexId)
226{
227    ACPI_STATUS             Status = AE_OK;
228
229
230    ACPI_FUNCTION_TRACE_U32 ("UtCreateMutex", MutexId);
231
232
233    if (MutexId > MAX_MUTEX)
234    {
235        return_ACPI_STATUS (AE_BAD_PARAMETER);
236    }
237
238    if (!AcpiGbl_MutexInfo[MutexId].Mutex)
239    {
240        Status = AcpiOsCreateSemaphore (1, 1,
241                        &AcpiGbl_MutexInfo[MutexId].Mutex);
242        AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
243        AcpiGbl_MutexInfo[MutexId].UseCount = 0;
244    }
245
246    return_ACPI_STATUS (Status);
247}
248
249
250/*******************************************************************************
251 *
252 * FUNCTION:    AcpiUtDeleteMutex
253 *
254 * PARAMETERS:  MutexID         - ID of the mutex to be deleted
255 *
256 * RETURN:      Status
257 *
258 * DESCRIPTION: Delete a mutex object.
259 *
260 ******************************************************************************/
261
262static ACPI_STATUS
263AcpiUtDeleteMutex (
264    ACPI_MUTEX_HANDLE       MutexId)
265{
266    ACPI_STATUS             Status;
267
268
269    ACPI_FUNCTION_TRACE_U32 ("UtDeleteMutex", MutexId);
270
271
272    if (MutexId > MAX_MUTEX)
273    {
274        return_ACPI_STATUS (AE_BAD_PARAMETER);
275    }
276
277    Status = AcpiOsDeleteSemaphore (AcpiGbl_MutexInfo[MutexId].Mutex);
278
279    AcpiGbl_MutexInfo[MutexId].Mutex = NULL;
280    AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
281
282    return_ACPI_STATUS (Status);
283}
284
285
286/*******************************************************************************
287 *
288 * FUNCTION:    AcpiUtAcquireMutex
289 *
290 * PARAMETERS:  MutexID         - ID of the mutex to be acquired
291 *
292 * RETURN:      Status
293 *
294 * DESCRIPTION: Acquire a mutex object.
295 *
296 ******************************************************************************/
297
298ACPI_STATUS
299AcpiUtAcquireMutex (
300    ACPI_MUTEX_HANDLE       MutexId)
301{
302    ACPI_STATUS             Status;
303    UINT32                  ThisThreadId;
304
305
306    ACPI_FUNCTION_NAME ("UtAcquireMutex");
307
308
309    if (MutexId > MAX_MUTEX)
310    {
311        return (AE_BAD_PARAMETER);
312    }
313
314    ThisThreadId = AcpiOsGetThreadId ();
315
316#ifdef ACPI_MUTEX_DEBUG
317    {
318        UINT32                  i;
319        /*
320         * Mutex debug code, for internal debugging only.
321         *
322         * Deadlock prevention.  Check if this thread owns any mutexes of value
323         * greater than or equal to this one.  If so, the thread has violated
324         * the mutex ordering rule.  This indicates a coding error somewhere in
325         * the ACPI subsystem code.
326         */
327        for (i = MutexId; i < MAX_MUTEX; i++)
328        {
329            if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId)
330            {
331                if (i == MutexId)
332                {
333                    ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
334                        "Mutex [%s] already acquired by this thread [%X]\n",
335                        AcpiUtGetMutexName (MutexId), ThisThreadId));
336
337                    return (AE_ALREADY_ACQUIRED);
338                }
339
340                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
341                    "Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
342                    ThisThreadId, AcpiUtGetMutexName (i),
343                    AcpiUtGetMutexName (MutexId)));
344
345                return (AE_ACQUIRE_DEADLOCK);
346            }
347        }
348    }
349#endif
350
351    ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
352        "Thread %X attempting to acquire Mutex [%s]\n",
353        ThisThreadId, AcpiUtGetMutexName (MutexId)));
354
355    Status = AcpiOsWaitSemaphore (AcpiGbl_MutexInfo[MutexId].Mutex,
356                                    1, ACPI_WAIT_FOREVER);
357    if (ACPI_SUCCESS (Status))
358    {
359        ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n",
360            ThisThreadId, AcpiUtGetMutexName (MutexId)));
361
362        AcpiGbl_MutexInfo[MutexId].UseCount++;
363        AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId;
364    }
365    else
366    {
367        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
368            "Thread %X could not acquire Mutex [%s] %s\n",
369                ThisThreadId, AcpiUtGetMutexName (MutexId),
370                AcpiFormatException (Status)));
371    }
372
373    return (Status);
374}
375
376
377/*******************************************************************************
378 *
379 * FUNCTION:    AcpiUtReleaseMutex
380 *
381 * PARAMETERS:  MutexID         - ID of the mutex to be released
382 *
383 * RETURN:      Status
384 *
385 * DESCRIPTION: Release a mutex object.
386 *
387 ******************************************************************************/
388
389ACPI_STATUS
390AcpiUtReleaseMutex (
391    ACPI_MUTEX_HANDLE       MutexId)
392{
393    ACPI_STATUS             Status;
394    UINT32                  ThisThreadId;
395
396
397    ACPI_FUNCTION_NAME ("UtReleaseMutex");
398
399
400    ThisThreadId = AcpiOsGetThreadId ();
401    ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
402        "Thread %X releasing Mutex [%s]\n", ThisThreadId,
403        AcpiUtGetMutexName (MutexId)));
404
405    if (MutexId > MAX_MUTEX)
406    {
407        return (AE_BAD_PARAMETER);
408    }
409
410    /*
411     * Mutex must be acquired in order to release it!
412     */
413    if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED)
414    {
415        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
416            "Mutex [%s] is not acquired, cannot release\n",
417            AcpiUtGetMutexName (MutexId)));
418
419        return (AE_NOT_ACQUIRED);
420    }
421
422#ifdef ACPI_MUTEX_DEBUG
423    {
424        UINT32                  i;
425        /*
426         * Mutex debug code, for internal debugging only.
427         *
428         * Deadlock prevention.  Check if this thread owns any mutexes of value
429         * greater than this one.  If so, the thread has violated the mutex
430         * ordering rule.  This indicates a coding error somewhere in
431         * the ACPI subsystem code.
432         */
433        for (i = MutexId; i < MAX_MUTEX; i++)
434        {
435            if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId)
436            {
437                if (i == MutexId)
438                {
439                    continue;
440                }
441
442                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
443                    "Invalid release order: owns [%s], releasing [%s]\n",
444                    AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId)));
445
446                return (AE_RELEASE_DEADLOCK);
447            }
448        }
449    }
450#endif
451
452    /* Mark unlocked FIRST */
453
454    AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
455
456    Status = AcpiOsSignalSemaphore (AcpiGbl_MutexInfo[MutexId].Mutex, 1);
457
458    if (ACPI_FAILURE (Status))
459    {
460        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
461            "Thread %X could not release Mutex [%s] %s\n",
462            ThisThreadId, AcpiUtGetMutexName (MutexId),
463            AcpiFormatException (Status)));
464    }
465    else
466    {
467        ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n",
468            ThisThreadId, AcpiUtGetMutexName (MutexId)));
469    }
470
471    return (Status);
472}
473
474
475