utmutex.c revision 249112
1151937Sjkim/*******************************************************************************
2151937Sjkim *
3151937Sjkim * Module Name: utmutex - local mutex support
4151937Sjkim *
5151937Sjkim ******************************************************************************/
6151937Sjkim
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, 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
99249112Sjkim    /* Create the spinlocks for use at interrupt level or for speed */
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
113249112Sjkim    Status = AcpiOsCreateLock (&AcpiGbl_ReferenceCountLock);
114249112Sjkim    if (ACPI_FAILURE (Status))
115249112Sjkim    {
116249112Sjkim        return_ACPI_STATUS (Status);
117249112Sjkim    }
118249112Sjkim
119210976Sjkim    /* Mutex for _OSI support */
120249112Sjkim
121210976Sjkim    Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex);
122210976Sjkim    if (ACPI_FAILURE (Status))
123210976Sjkim    {
124210976Sjkim        return_ACPI_STATUS (Status);
125210976Sjkim    }
126210976Sjkim
127193267Sjkim    /* Create the reader/writer lock for namespace access */
128193267Sjkim
129193267Sjkim    Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock);
130151937Sjkim    return_ACPI_STATUS (Status);
131151937Sjkim}
132151937Sjkim
133151937Sjkim
134151937Sjkim/*******************************************************************************
135151937Sjkim *
136151937Sjkim * FUNCTION:    AcpiUtMutexTerminate
137151937Sjkim *
138151937Sjkim * PARAMETERS:  None.
139151937Sjkim *
140151937Sjkim * RETURN:      None.
141151937Sjkim *
142193267Sjkim * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes,
143193267Sjkim *              spin locks, and reader/writer locks.
144151937Sjkim *
145151937Sjkim ******************************************************************************/
146151937Sjkim
147151937Sjkimvoid
148151937SjkimAcpiUtMutexTerminate (
149151937Sjkim    void)
150151937Sjkim{
151151937Sjkim    UINT32                  i;
152151937Sjkim
153151937Sjkim
154167802Sjkim    ACPI_FUNCTION_TRACE (UtMutexTerminate);
155151937Sjkim
156151937Sjkim
157193267Sjkim    /* Delete each predefined mutex object */
158193267Sjkim
159167802Sjkim    for (i = 0; i < ACPI_NUM_MUTEX; i++)
160151937Sjkim    {
161202771Sjkim        AcpiUtDeleteMutex (i);
162151937Sjkim    }
163151937Sjkim
164210976Sjkim    AcpiOsDeleteMutex (AcpiGbl_OsiMutex);
165210976Sjkim
166167802Sjkim    /* Delete the spinlocks */
167167802Sjkim
168151937Sjkim    AcpiOsDeleteLock (AcpiGbl_GpeLock);
169167802Sjkim    AcpiOsDeleteLock (AcpiGbl_HardwareLock);
170249112Sjkim    AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock);
171193267Sjkim
172193267Sjkim    /* Delete the reader/writer lock */
173193267Sjkim
174193267Sjkim    AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock);
175151937Sjkim    return_VOID;
176151937Sjkim}
177151937Sjkim
178151937Sjkim
179151937Sjkim/*******************************************************************************
180151937Sjkim *
181151937Sjkim * FUNCTION:    AcpiUtCreateMutex
182151937Sjkim *
183151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be created
184151937Sjkim *
185151937Sjkim * RETURN:      Status
186151937Sjkim *
187151937Sjkim * DESCRIPTION: Create a mutex object.
188151937Sjkim *
189151937Sjkim ******************************************************************************/
190151937Sjkim
191151937Sjkimstatic ACPI_STATUS
192151937SjkimAcpiUtCreateMutex (
193151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
194151937Sjkim{
195151937Sjkim    ACPI_STATUS             Status = AE_OK;
196151937Sjkim
197151937Sjkim
198167802Sjkim    ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId);
199151937Sjkim
200151937Sjkim
201151937Sjkim    if (!AcpiGbl_MutexInfo[MutexId].Mutex)
202151937Sjkim    {
203167802Sjkim        Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex);
204151937Sjkim        AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
205151937Sjkim        AcpiGbl_MutexInfo[MutexId].UseCount = 0;
206151937Sjkim    }
207151937Sjkim
208151937Sjkim    return_ACPI_STATUS (Status);
209151937Sjkim}
210151937Sjkim
211151937Sjkim
212151937Sjkim/*******************************************************************************
213151937Sjkim *
214151937Sjkim * FUNCTION:    AcpiUtDeleteMutex
215151937Sjkim *
216151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be deleted
217151937Sjkim *
218151937Sjkim * RETURN:      Status
219151937Sjkim *
220151937Sjkim * DESCRIPTION: Delete a mutex object.
221151937Sjkim *
222151937Sjkim ******************************************************************************/
223151937Sjkim
224202771Sjkimstatic void
225151937SjkimAcpiUtDeleteMutex (
226151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
227151937Sjkim{
228151937Sjkim
229167802Sjkim    ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId);
230151937Sjkim
231151937Sjkim
232167802Sjkim    AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex);
233151937Sjkim
234151937Sjkim    AcpiGbl_MutexInfo[MutexId].Mutex = NULL;
235151937Sjkim    AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
236241973Sjkim
237241973Sjkim    return_VOID;
238151937Sjkim}
239151937Sjkim
240151937Sjkim
241151937Sjkim/*******************************************************************************
242151937Sjkim *
243151937Sjkim * FUNCTION:    AcpiUtAcquireMutex
244151937Sjkim *
245151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be acquired
246151937Sjkim *
247151937Sjkim * RETURN:      Status
248151937Sjkim *
249151937Sjkim * DESCRIPTION: Acquire a mutex object.
250151937Sjkim *
251151937Sjkim ******************************************************************************/
252151937Sjkim
253151937SjkimACPI_STATUS
254151937SjkimAcpiUtAcquireMutex (
255151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
256151937Sjkim{
257151937Sjkim    ACPI_STATUS             Status;
258167802Sjkim    ACPI_THREAD_ID          ThisThreadId;
259151937Sjkim
260151937Sjkim
261167802Sjkim    ACPI_FUNCTION_NAME (UtAcquireMutex);
262151937Sjkim
263151937Sjkim
264167802Sjkim    if (MutexId > ACPI_MAX_MUTEX)
265151937Sjkim    {
266151937Sjkim        return (AE_BAD_PARAMETER);
267151937Sjkim    }
268151937Sjkim
269151937Sjkim    ThisThreadId = AcpiOsGetThreadId ();
270151937Sjkim
271151937Sjkim#ifdef ACPI_MUTEX_DEBUG
272151937Sjkim    {
273151937Sjkim        UINT32                  i;
274151937Sjkim        /*
275151937Sjkim         * Mutex debug code, for internal debugging only.
276151937Sjkim         *
277241973Sjkim         * Deadlock prevention. Check if this thread owns any mutexes of value
278241973Sjkim         * greater than or equal to this one. If so, the thread has violated
279241973Sjkim         * the mutex ordering rule. This indicates a coding error somewhere in
280151937Sjkim         * the ACPI subsystem code.
281151937Sjkim         */
282193267Sjkim        for (i = MutexId; i < ACPI_NUM_MUTEX; i++)
283151937Sjkim        {
284151937Sjkim            if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId)
285151937Sjkim            {
286151937Sjkim                if (i == MutexId)
287151937Sjkim                {
288167802Sjkim                    ACPI_ERROR ((AE_INFO,
289212761Sjkim                        "Mutex [%s] already acquired by this thread [%u]",
290193267Sjkim                        AcpiUtGetMutexName (MutexId),
291212761Sjkim                        (UINT32) ThisThreadId));
292151937Sjkim
293151937Sjkim                    return (AE_ALREADY_ACQUIRED);
294151937Sjkim                }
295151937Sjkim
296167802Sjkim                ACPI_ERROR ((AE_INFO,
297212761Sjkim                    "Invalid acquire order: Thread %u owns [%s], wants [%s]",
298212761Sjkim                    (UINT32) ThisThreadId, AcpiUtGetMutexName (i),
299151937Sjkim                    AcpiUtGetMutexName (MutexId)));
300151937Sjkim
301151937Sjkim                return (AE_ACQUIRE_DEADLOCK);
302151937Sjkim            }
303151937Sjkim        }
304151937Sjkim    }
305151937Sjkim#endif
306151937Sjkim
307151937Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
308212761Sjkim        "Thread %u attempting to acquire Mutex [%s]\n",
309212761Sjkim        (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId)));
310151937Sjkim
311167802Sjkim    Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex,
312167802Sjkim                ACPI_WAIT_FOREVER);
313151937Sjkim    if (ACPI_SUCCESS (Status))
314151937Sjkim    {
315212761Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n",
316212761Sjkim            (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId)));
317151937Sjkim
318151937Sjkim        AcpiGbl_MutexInfo[MutexId].UseCount++;
319151937Sjkim        AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId;
320151937Sjkim    }
321151937Sjkim    else
322151937Sjkim    {
323167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
324212761Sjkim            "Thread %u could not acquire Mutex [0x%X]",
325212761Sjkim            (UINT32) ThisThreadId, MutexId));
326151937Sjkim    }
327151937Sjkim
328151937Sjkim    return (Status);
329151937Sjkim}
330151937Sjkim
331151937Sjkim
332151937Sjkim/*******************************************************************************
333151937Sjkim *
334151937Sjkim * FUNCTION:    AcpiUtReleaseMutex
335151937Sjkim *
336151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be released
337151937Sjkim *
338151937Sjkim * RETURN:      Status
339151937Sjkim *
340151937Sjkim * DESCRIPTION: Release a mutex object.
341151937Sjkim *
342151937Sjkim ******************************************************************************/
343151937Sjkim
344151937SjkimACPI_STATUS
345151937SjkimAcpiUtReleaseMutex (
346151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
347151937Sjkim{
348167802Sjkim    ACPI_FUNCTION_NAME (UtReleaseMutex);
349151937Sjkim
350241973Sjkim
351212761Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
352228110Sjkim        (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId)));
353151937Sjkim
354167802Sjkim    if (MutexId > ACPI_MAX_MUTEX)
355151937Sjkim    {
356151937Sjkim        return (AE_BAD_PARAMETER);
357151937Sjkim    }
358151937Sjkim
359151937Sjkim    /*
360151937Sjkim     * Mutex must be acquired in order to release it!
361151937Sjkim     */
362151937Sjkim    if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED)
363151937Sjkim    {
364167802Sjkim        ACPI_ERROR ((AE_INFO,
365204773Sjkim            "Mutex [0x%X] is not acquired, cannot release", MutexId));
366151937Sjkim
367151937Sjkim        return (AE_NOT_ACQUIRED);
368151937Sjkim    }
369151937Sjkim
370151937Sjkim#ifdef ACPI_MUTEX_DEBUG
371151937Sjkim    {
372151937Sjkim        UINT32                  i;
373151937Sjkim        /*
374151937Sjkim         * Mutex debug code, for internal debugging only.
375151937Sjkim         *
376241973Sjkim         * Deadlock prevention. Check if this thread owns any mutexes of value
377241973Sjkim         * greater than this one. If so, the thread has violated the mutex
378241973Sjkim         * ordering rule. This indicates a coding error somewhere in
379151937Sjkim         * the ACPI subsystem code.
380151937Sjkim         */
381193267Sjkim        for (i = MutexId; i < ACPI_NUM_MUTEX; i++)
382151937Sjkim        {
383228110Sjkim            if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ())
384151937Sjkim            {
385151937Sjkim                if (i == MutexId)
386151937Sjkim                {
387151937Sjkim                    continue;
388151937Sjkim                }
389151937Sjkim
390167802Sjkim                ACPI_ERROR ((AE_INFO,
391167802Sjkim                    "Invalid release order: owns [%s], releasing [%s]",
392151937Sjkim                    AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId)));
393151937Sjkim
394151937Sjkim                return (AE_RELEASE_DEADLOCK);
395151937Sjkim            }
396151937Sjkim        }
397151937Sjkim    }
398151937Sjkim#endif
399151937Sjkim
400151937Sjkim    /* Mark unlocked FIRST */
401151937Sjkim
402151937Sjkim    AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
403151937Sjkim
404167802Sjkim    AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex);
405167802Sjkim    return (AE_OK);
406151937Sjkim}
407