utmutex.c revision 217365
1151937Sjkim/*******************************************************************************
2151937Sjkim *
3151937Sjkim * Module Name: utmutex - local mutex support
4151937Sjkim *
5151937Sjkim ******************************************************************************/
6151937Sjkim
7217365Sjkim/*
8217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp.
9151937Sjkim * All rights reserved.
10151937Sjkim *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
25151937Sjkim *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
29151937Sjkim *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
43151937Sjkim
44151937Sjkim
45151937Sjkim#define __UTMUTEX_C__
46151937Sjkim
47193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
48193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
49151937Sjkim
50151937Sjkim#define _COMPONENT          ACPI_UTILITIES
51151937Sjkim        ACPI_MODULE_NAME    ("utmutex")
52151937Sjkim
53151937Sjkim/* Local prototypes */
54151937Sjkim
55151937Sjkimstatic ACPI_STATUS
56151937SjkimAcpiUtCreateMutex (
57151937Sjkim    ACPI_MUTEX_HANDLE       MutexId);
58151937Sjkim
59202771Sjkimstatic void
60151937SjkimAcpiUtDeleteMutex (
61151937Sjkim    ACPI_MUTEX_HANDLE       MutexId);
62151937Sjkim
63151937Sjkim
64151937Sjkim/*******************************************************************************
65151937Sjkim *
66151937Sjkim * FUNCTION:    AcpiUtMutexInitialize
67151937Sjkim *
68151937Sjkim * PARAMETERS:  None.
69151937Sjkim *
70151937Sjkim * RETURN:      Status
71151937Sjkim *
72193267Sjkim * DESCRIPTION: Create the system mutex objects. This includes mutexes,
73193267Sjkim *              spin locks, and reader/writer locks.
74151937Sjkim *
75151937Sjkim ******************************************************************************/
76151937Sjkim
77151937SjkimACPI_STATUS
78151937SjkimAcpiUtMutexInitialize (
79151937Sjkim    void)
80151937Sjkim{
81151937Sjkim    UINT32                  i;
82151937Sjkim    ACPI_STATUS             Status;
83151937Sjkim
84151937Sjkim
85167802Sjkim    ACPI_FUNCTION_TRACE (UtMutexInitialize);
86151937Sjkim
87151937Sjkim
88193267Sjkim    /* Create each of the predefined mutex objects */
89193267Sjkim
90167802Sjkim    for (i = 0; i < ACPI_NUM_MUTEX; i++)
91151937Sjkim    {
92151937Sjkim        Status = AcpiUtCreateMutex (i);
93151937Sjkim        if (ACPI_FAILURE (Status))
94151937Sjkim        {
95151937Sjkim            return_ACPI_STATUS (Status);
96151937Sjkim        }
97151937Sjkim    }
98151937Sjkim
99167802Sjkim    /* Create the spinlocks for use at interrupt level */
100167802Sjkim
101151937Sjkim    Status = AcpiOsCreateLock (&AcpiGbl_GpeLock);
102167802Sjkim    if (ACPI_FAILURE (Status))
103167802Sjkim    {
104167802Sjkim        return_ACPI_STATUS (Status);
105167802Sjkim    }
106167802Sjkim
107167802Sjkim    Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock);
108193267Sjkim    if (ACPI_FAILURE (Status))
109193267Sjkim    {
110193267Sjkim        return_ACPI_STATUS (Status);
111193267Sjkim    }
112193267Sjkim
113210976Sjkim    /* Mutex for _OSI support */
114210976Sjkim    Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex);
115210976Sjkim    if (ACPI_FAILURE (Status))
116210976Sjkim    {
117210976Sjkim        return_ACPI_STATUS (Status);
118210976Sjkim    }
119210976Sjkim
120193267Sjkim    /* Create the reader/writer lock for namespace access */
121193267Sjkim
122193267Sjkim    Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock);
123151937Sjkim    return_ACPI_STATUS (Status);
124151937Sjkim}
125151937Sjkim
126151937Sjkim
127151937Sjkim/*******************************************************************************
128151937Sjkim *
129151937Sjkim * FUNCTION:    AcpiUtMutexTerminate
130151937Sjkim *
131151937Sjkim * PARAMETERS:  None.
132151937Sjkim *
133151937Sjkim * RETURN:      None.
134151937Sjkim *
135193267Sjkim * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
136193267Sjkim *              spin locks, and reader/writer locks.
137151937Sjkim *
138151937Sjkim ******************************************************************************/
139151937Sjkim
140151937Sjkimvoid
141151937SjkimAcpiUtMutexTerminate (
142151937Sjkim    void)
143151937Sjkim{
144151937Sjkim    UINT32                  i;
145151937Sjkim
146151937Sjkim
147167802Sjkim    ACPI_FUNCTION_TRACE (UtMutexTerminate);
148151937Sjkim
149151937Sjkim
150193267Sjkim    /* Delete each predefined mutex object */
151193267Sjkim
152167802Sjkim    for (i = 0; i < ACPI_NUM_MUTEX; i++)
153151937Sjkim    {
154202771Sjkim        AcpiUtDeleteMutex (i);
155151937Sjkim    }
156151937Sjkim
157210976Sjkim    AcpiOsDeleteMutex (AcpiGbl_OsiMutex);
158210976Sjkim
159167802Sjkim    /* Delete the spinlocks */
160167802Sjkim
161151937Sjkim    AcpiOsDeleteLock (AcpiGbl_GpeLock);
162167802Sjkim    AcpiOsDeleteLock (AcpiGbl_HardwareLock);
163193267Sjkim
164193267Sjkim    /* Delete the reader/writer lock */
165193267Sjkim
166193267Sjkim    AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock);
167151937Sjkim    return_VOID;
168151937Sjkim}
169151937Sjkim
170151937Sjkim
171151937Sjkim/*******************************************************************************
172151937Sjkim *
173151937Sjkim * FUNCTION:    AcpiUtCreateMutex
174151937Sjkim *
175151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be created
176151937Sjkim *
177151937Sjkim * RETURN:      Status
178151937Sjkim *
179151937Sjkim * DESCRIPTION: Create a mutex object.
180151937Sjkim *
181151937Sjkim ******************************************************************************/
182151937Sjkim
183151937Sjkimstatic ACPI_STATUS
184151937SjkimAcpiUtCreateMutex (
185151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
186151937Sjkim{
187151937Sjkim    ACPI_STATUS             Status = AE_OK;
188151937Sjkim
189151937Sjkim
190167802Sjkim    ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId);
191151937Sjkim
192151937Sjkim
193151937Sjkim    if (!AcpiGbl_MutexInfo[MutexId].Mutex)
194151937Sjkim    {
195167802Sjkim        Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex);
196151937Sjkim        AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
197151937Sjkim        AcpiGbl_MutexInfo[MutexId].UseCount = 0;
198151937Sjkim    }
199151937Sjkim
200151937Sjkim    return_ACPI_STATUS (Status);
201151937Sjkim}
202151937Sjkim
203151937Sjkim
204151937Sjkim/*******************************************************************************
205151937Sjkim *
206151937Sjkim * FUNCTION:    AcpiUtDeleteMutex
207151937Sjkim *
208151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be deleted
209151937Sjkim *
210151937Sjkim * RETURN:      Status
211151937Sjkim *
212151937Sjkim * DESCRIPTION: Delete a mutex object.
213151937Sjkim *
214151937Sjkim ******************************************************************************/
215151937Sjkim
216202771Sjkimstatic void
217151937SjkimAcpiUtDeleteMutex (
218151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
219151937Sjkim{
220151937Sjkim
221167802Sjkim    ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId);
222151937Sjkim
223151937Sjkim
224167802Sjkim    AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex);
225151937Sjkim
226151937Sjkim    AcpiGbl_MutexInfo[MutexId].Mutex = NULL;
227151937Sjkim    AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
228151937Sjkim}
229151937Sjkim
230151937Sjkim
231151937Sjkim/*******************************************************************************
232151937Sjkim *
233151937Sjkim * FUNCTION:    AcpiUtAcquireMutex
234151937Sjkim *
235151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be acquired
236151937Sjkim *
237151937Sjkim * RETURN:      Status
238151937Sjkim *
239151937Sjkim * DESCRIPTION: Acquire a mutex object.
240151937Sjkim *
241151937Sjkim ******************************************************************************/
242151937Sjkim
243151937SjkimACPI_STATUS
244151937SjkimAcpiUtAcquireMutex (
245151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
246151937Sjkim{
247151937Sjkim    ACPI_STATUS             Status;
248167802Sjkim    ACPI_THREAD_ID          ThisThreadId;
249151937Sjkim
250151937Sjkim
251167802Sjkim    ACPI_FUNCTION_NAME (UtAcquireMutex);
252151937Sjkim
253151937Sjkim
254167802Sjkim    if (MutexId > ACPI_MAX_MUTEX)
255151937Sjkim    {
256151937Sjkim        return (AE_BAD_PARAMETER);
257151937Sjkim    }
258151937Sjkim
259151937Sjkim    ThisThreadId = AcpiOsGetThreadId ();
260151937Sjkim
261151937Sjkim#ifdef ACPI_MUTEX_DEBUG
262151937Sjkim    {
263151937Sjkim        UINT32                  i;
264151937Sjkim        /*
265151937Sjkim         * Mutex debug code, for internal debugging only.
266151937Sjkim         *
267151937Sjkim         * Deadlock prevention.  Check if this thread owns any mutexes of value
268151937Sjkim         * greater than or equal to this one.  If so, the thread has violated
269151937Sjkim         * the mutex ordering rule.  This indicates a coding error somewhere in
270151937Sjkim         * the ACPI subsystem code.
271151937Sjkim         */
272193267Sjkim        for (i = MutexId; i < ACPI_NUM_MUTEX; i++)
273151937Sjkim        {
274151937Sjkim            if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId)
275151937Sjkim            {
276151937Sjkim                if (i == MutexId)
277151937Sjkim                {
278167802Sjkim                    ACPI_ERROR ((AE_INFO,
279212761Sjkim                        "Mutex [%s] already acquired by this thread [%u]",
280193267Sjkim                        AcpiUtGetMutexName (MutexId),
281212761Sjkim                        (UINT32) ThisThreadId));
282151937Sjkim
283151937Sjkim                    return (AE_ALREADY_ACQUIRED);
284151937Sjkim                }
285151937Sjkim
286167802Sjkim                ACPI_ERROR ((AE_INFO,
287212761Sjkim                    "Invalid acquire order: Thread %u owns [%s], wants [%s]",
288212761Sjkim                    (UINT32) ThisThreadId, AcpiUtGetMutexName (i),
289151937Sjkim                    AcpiUtGetMutexName (MutexId)));
290151937Sjkim
291151937Sjkim                return (AE_ACQUIRE_DEADLOCK);
292151937Sjkim            }
293151937Sjkim        }
294151937Sjkim    }
295151937Sjkim#endif
296151937Sjkim
297151937Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
298212761Sjkim        "Thread %u attempting to acquire Mutex [%s]\n",
299212761Sjkim        (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId)));
300151937Sjkim
301167802Sjkim    Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex,
302167802Sjkim                ACPI_WAIT_FOREVER);
303151937Sjkim    if (ACPI_SUCCESS (Status))
304151937Sjkim    {
305212761Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n",
306212761Sjkim            (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId)));
307151937Sjkim
308151937Sjkim        AcpiGbl_MutexInfo[MutexId].UseCount++;
309151937Sjkim        AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId;
310151937Sjkim    }
311151937Sjkim    else
312151937Sjkim    {
313167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
314212761Sjkim            "Thread %u could not acquire Mutex [0x%X]",
315212761Sjkim            (UINT32) ThisThreadId, MutexId));
316151937Sjkim    }
317151937Sjkim
318151937Sjkim    return (Status);
319151937Sjkim}
320151937Sjkim
321151937Sjkim
322151937Sjkim/*******************************************************************************
323151937Sjkim *
324151937Sjkim * FUNCTION:    AcpiUtReleaseMutex
325151937Sjkim *
326151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be released
327151937Sjkim *
328151937Sjkim * RETURN:      Status
329151937Sjkim *
330151937Sjkim * DESCRIPTION: Release a mutex object.
331151937Sjkim *
332151937Sjkim ******************************************************************************/
333151937Sjkim
334151937SjkimACPI_STATUS
335151937SjkimAcpiUtReleaseMutex (
336151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
337151937Sjkim{
338167802Sjkim    ACPI_THREAD_ID          ThisThreadId;
339151937Sjkim
340151937Sjkim
341167802Sjkim    ACPI_FUNCTION_NAME (UtReleaseMutex);
342151937Sjkim
343151937Sjkim
344151937Sjkim    ThisThreadId = AcpiOsGetThreadId ();
345212761Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
346212761Sjkim        (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId)));
347151937Sjkim
348167802Sjkim    if (MutexId > ACPI_MAX_MUTEX)
349151937Sjkim    {
350151937Sjkim        return (AE_BAD_PARAMETER);
351151937Sjkim    }
352151937Sjkim
353151937Sjkim    /*
354151937Sjkim     * Mutex must be acquired in order to release it!
355151937Sjkim     */
356151937Sjkim    if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED)
357151937Sjkim    {
358167802Sjkim        ACPI_ERROR ((AE_INFO,
359204773Sjkim            "Mutex [0x%X] is not acquired, cannot release", MutexId));
360151937Sjkim
361151937Sjkim        return (AE_NOT_ACQUIRED);
362151937Sjkim    }
363151937Sjkim
364151937Sjkim#ifdef ACPI_MUTEX_DEBUG
365151937Sjkim    {
366151937Sjkim        UINT32                  i;
367151937Sjkim        /*
368151937Sjkim         * Mutex debug code, for internal debugging only.
369151937Sjkim         *
370151937Sjkim         * Deadlock prevention.  Check if this thread owns any mutexes of value
371151937Sjkim         * greater than this one.  If so, the thread has violated the mutex
372151937Sjkim         * ordering rule.  This indicates a coding error somewhere in
373151937Sjkim         * the ACPI subsystem code.
374151937Sjkim         */
375193267Sjkim        for (i = MutexId; i < ACPI_NUM_MUTEX; i++)
376151937Sjkim        {
377151937Sjkim            if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId)
378151937Sjkim            {
379151937Sjkim                if (i == MutexId)
380151937Sjkim                {
381151937Sjkim                    continue;
382151937Sjkim                }
383151937Sjkim
384167802Sjkim                ACPI_ERROR ((AE_INFO,
385167802Sjkim                    "Invalid release order: owns [%s], releasing [%s]",
386151937Sjkim                    AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId)));
387151937Sjkim
388151937Sjkim                return (AE_RELEASE_DEADLOCK);
389151937Sjkim            }
390151937Sjkim        }
391151937Sjkim    }
392151937Sjkim#endif
393151937Sjkim
394151937Sjkim    /* Mark unlocked FIRST */
395151937Sjkim
396151937Sjkim    AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
397151937Sjkim
398167802Sjkim    AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex);
399167802Sjkim    return (AE_OK);
400151937Sjkim}
401151937Sjkim
402151937Sjkim
403