utmutex.c revision 245582
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
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;
228241973Sjkim
229241973Sjkim    return_VOID;
230151937Sjkim}
231151937Sjkim
232151937Sjkim
233151937Sjkim/*******************************************************************************
234151937Sjkim *
235151937Sjkim * FUNCTION:    AcpiUtAcquireMutex
236151937Sjkim *
237151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be acquired
238151937Sjkim *
239151937Sjkim * RETURN:      Status
240151937Sjkim *
241151937Sjkim * DESCRIPTION: Acquire a mutex object.
242151937Sjkim *
243151937Sjkim ******************************************************************************/
244151937Sjkim
245151937SjkimACPI_STATUS
246151937SjkimAcpiUtAcquireMutex (
247151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
248151937Sjkim{
249151937Sjkim    ACPI_STATUS             Status;
250167802Sjkim    ACPI_THREAD_ID          ThisThreadId;
251151937Sjkim
252151937Sjkim
253167802Sjkim    ACPI_FUNCTION_NAME (UtAcquireMutex);
254151937Sjkim
255151937Sjkim
256167802Sjkim    if (MutexId > ACPI_MAX_MUTEX)
257151937Sjkim    {
258151937Sjkim        return (AE_BAD_PARAMETER);
259151937Sjkim    }
260151937Sjkim
261151937Sjkim    ThisThreadId = AcpiOsGetThreadId ();
262151937Sjkim
263151937Sjkim#ifdef ACPI_MUTEX_DEBUG
264151937Sjkim    {
265151937Sjkim        UINT32                  i;
266151937Sjkim        /*
267151937Sjkim         * Mutex debug code, for internal debugging only.
268151937Sjkim         *
269241973Sjkim         * Deadlock prevention. Check if this thread owns any mutexes of value
270241973Sjkim         * greater than or equal to this one. If so, the thread has violated
271241973Sjkim         * the mutex ordering rule. This indicates a coding error somewhere in
272151937Sjkim         * the ACPI subsystem code.
273151937Sjkim         */
274193267Sjkim        for (i = MutexId; i < ACPI_NUM_MUTEX; i++)
275151937Sjkim        {
276151937Sjkim            if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId)
277151937Sjkim            {
278151937Sjkim                if (i == MutexId)
279151937Sjkim                {
280167802Sjkim                    ACPI_ERROR ((AE_INFO,
281212761Sjkim                        "Mutex [%s] already acquired by this thread [%u]",
282193267Sjkim                        AcpiUtGetMutexName (MutexId),
283212761Sjkim                        (UINT32) ThisThreadId));
284151937Sjkim
285151937Sjkim                    return (AE_ALREADY_ACQUIRED);
286151937Sjkim                }
287151937Sjkim
288167802Sjkim                ACPI_ERROR ((AE_INFO,
289212761Sjkim                    "Invalid acquire order: Thread %u owns [%s], wants [%s]",
290212761Sjkim                    (UINT32) ThisThreadId, AcpiUtGetMutexName (i),
291151937Sjkim                    AcpiUtGetMutexName (MutexId)));
292151937Sjkim
293151937Sjkim                return (AE_ACQUIRE_DEADLOCK);
294151937Sjkim            }
295151937Sjkim        }
296151937Sjkim    }
297151937Sjkim#endif
298151937Sjkim
299151937Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX,
300212761Sjkim        "Thread %u attempting to acquire Mutex [%s]\n",
301212761Sjkim        (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId)));
302151937Sjkim
303167802Sjkim    Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex,
304167802Sjkim                ACPI_WAIT_FOREVER);
305151937Sjkim    if (ACPI_SUCCESS (Status))
306151937Sjkim    {
307212761Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n",
308212761Sjkim            (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId)));
309151937Sjkim
310151937Sjkim        AcpiGbl_MutexInfo[MutexId].UseCount++;
311151937Sjkim        AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId;
312151937Sjkim    }
313151937Sjkim    else
314151937Sjkim    {
315167802Sjkim        ACPI_EXCEPTION ((AE_INFO, Status,
316212761Sjkim            "Thread %u could not acquire Mutex [0x%X]",
317212761Sjkim            (UINT32) ThisThreadId, MutexId));
318151937Sjkim    }
319151937Sjkim
320151937Sjkim    return (Status);
321151937Sjkim}
322151937Sjkim
323151937Sjkim
324151937Sjkim/*******************************************************************************
325151937Sjkim *
326151937Sjkim * FUNCTION:    AcpiUtReleaseMutex
327151937Sjkim *
328151937Sjkim * PARAMETERS:  MutexID         - ID of the mutex to be released
329151937Sjkim *
330151937Sjkim * RETURN:      Status
331151937Sjkim *
332151937Sjkim * DESCRIPTION: Release a mutex object.
333151937Sjkim *
334151937Sjkim ******************************************************************************/
335151937Sjkim
336151937SjkimACPI_STATUS
337151937SjkimAcpiUtReleaseMutex (
338151937Sjkim    ACPI_MUTEX_HANDLE       MutexId)
339151937Sjkim{
340167802Sjkim    ACPI_FUNCTION_NAME (UtReleaseMutex);
341151937Sjkim
342241973Sjkim
343212761Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
344228110Sjkim        (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId)));
345151937Sjkim
346167802Sjkim    if (MutexId > ACPI_MAX_MUTEX)
347151937Sjkim    {
348151937Sjkim        return (AE_BAD_PARAMETER);
349151937Sjkim    }
350151937Sjkim
351151937Sjkim    /*
352151937Sjkim     * Mutex must be acquired in order to release it!
353151937Sjkim     */
354151937Sjkim    if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED)
355151937Sjkim    {
356167802Sjkim        ACPI_ERROR ((AE_INFO,
357204773Sjkim            "Mutex [0x%X] is not acquired, cannot release", MutexId));
358151937Sjkim
359151937Sjkim        return (AE_NOT_ACQUIRED);
360151937Sjkim    }
361151937Sjkim
362151937Sjkim#ifdef ACPI_MUTEX_DEBUG
363151937Sjkim    {
364151937Sjkim        UINT32                  i;
365151937Sjkim        /*
366151937Sjkim         * Mutex debug code, for internal debugging only.
367151937Sjkim         *
368241973Sjkim         * Deadlock prevention. Check if this thread owns any mutexes of value
369241973Sjkim         * greater than this one. If so, the thread has violated the mutex
370241973Sjkim         * ordering rule. This indicates a coding error somewhere in
371151937Sjkim         * the ACPI subsystem code.
372151937Sjkim         */
373193267Sjkim        for (i = MutexId; i < ACPI_NUM_MUTEX; i++)
374151937Sjkim        {
375228110Sjkim            if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ())
376151937Sjkim            {
377151937Sjkim                if (i == MutexId)
378151937Sjkim                {
379151937Sjkim                    continue;
380151937Sjkim                }
381151937Sjkim
382167802Sjkim                ACPI_ERROR ((AE_INFO,
383167802Sjkim                    "Invalid release order: owns [%s], releasing [%s]",
384151937Sjkim                    AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId)));
385151937Sjkim
386151937Sjkim                return (AE_RELEASE_DEADLOCK);
387151937Sjkim            }
388151937Sjkim        }
389151937Sjkim    }
390151937Sjkim#endif
391151937Sjkim
392151937Sjkim    /* Mark unlocked FIRST */
393151937Sjkim
394151937Sjkim    AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED;
395151937Sjkim
396167802Sjkim    AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex);
397167802Sjkim    return (AE_OK);
398151937Sjkim}
399