utlock.c revision 298714
1255570Strasz/******************************************************************************
2255570Strasz *
3255570Strasz * Module Name: utlock - Reader/Writer lock interfaces
4255570Strasz *
5255570Strasz *****************************************************************************/
6255570Strasz
7255570Strasz/*
8255570Strasz * Copyright (C) 2000 - 2016, Intel Corp.
9255570Strasz * All rights reserved.
10255570Strasz *
11255570Strasz * Redistribution and use in source and binary forms, with or without
12255570Strasz * modification, are permitted provided that the following conditions
13255570Strasz * are met:
14255570Strasz * 1. Redistributions of source code must retain the above copyright
15255570Strasz *    notice, this list of conditions, and the following disclaimer,
16255570Strasz *    without modification.
17255570Strasz * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18255570Strasz *    substantially similar to the "NO WARRANTY" disclaimer below
19255570Strasz *    ("Disclaimer") and any redistribution must be conditioned upon
20255570Strasz *    including a substantially similar Disclaimer requirement for further
21255570Strasz *    binary redistribution.
22255570Strasz * 3. Neither the names of the above-listed copyright holders nor the names
23255570Strasz *    of any contributors may be used to endorse or promote products derived
24255570Strasz *    from this software without specific prior written permission.
25255570Strasz *
26255570Strasz * Alternatively, this software may be distributed under the terms of the
27255570Strasz * GNU General Public License ("GPL") version 2 as published by the Free
28255570Strasz * Software Foundation.
29255570Strasz *
30255570Strasz * NO WARRANTY
31255570Strasz * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32255570Strasz * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33255570Strasz * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34255570Strasz * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35255570Strasz * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36255570Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37255570Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38255570Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39255570Strasz * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40255570Strasz * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41255570Strasz * POSSIBILITY OF SUCH DAMAGES.
42255570Strasz */
43255570Strasz
44255570Strasz#include <contrib/dev/acpica/include/acpi.h>
45255570Strasz#include <contrib/dev/acpica/include/accommon.h>
46255570Strasz
47255570Strasz
48255570Strasz#define _COMPONENT          ACPI_UTILITIES
49255570Strasz        ACPI_MODULE_NAME    ("utlock")
50255570Strasz
51255570Strasz
52255570Strasz/*******************************************************************************
53255570Strasz *
54255570Strasz * FUNCTION:    AcpiUtCreateRwLock
55255570Strasz *              AcpiUtDeleteRwLock
56255570Strasz *
57255570Strasz * PARAMETERS:  Lock                - Pointer to a valid RW lock
58255570Strasz *
59255570Strasz * RETURN:      Status
60255570Strasz *
61255570Strasz * DESCRIPTION: Reader/writer lock creation and deletion interfaces.
62255570Strasz *
63255570Strasz ******************************************************************************/
64255570Strasz
65255570StraszACPI_STATUS
66255570StraszAcpiUtCreateRwLock (
67255570Strasz    ACPI_RW_LOCK            *Lock)
68265507Strasz{
69265507Strasz    ACPI_STATUS             Status;
70255570Strasz
71255570Strasz
72255570Strasz    Lock->NumReaders = 0;
73255570Strasz    Status = AcpiOsCreateMutex (&Lock->ReaderMutex);
74265507Strasz    if (ACPI_FAILURE (Status))
75255570Strasz    {
76255570Strasz        return (Status);
77255570Strasz    }
78255570Strasz
79255570Strasz    Status = AcpiOsCreateMutex (&Lock->WriterMutex);
80255570Strasz    return (Status);
81255570Strasz}
82255570Strasz
83255570Strasz
84255665Straszvoid
85255570StraszAcpiUtDeleteRwLock (
86255570Strasz    ACPI_RW_LOCK            *Lock)
87255570Strasz{
88255570Strasz
89255570Strasz    AcpiOsDeleteMutex (Lock->ReaderMutex);
90255570Strasz    AcpiOsDeleteMutex (Lock->WriterMutex);
91255570Strasz
92255570Strasz    Lock->NumReaders = 0;
93255570Strasz    Lock->ReaderMutex = NULL;
94255570Strasz    Lock->WriterMutex = NULL;
95255570Strasz}
96255570Strasz
97255570Strasz
98255570Strasz/*******************************************************************************
99255570Strasz *
100255570Strasz * FUNCTION:    AcpiUtAcquireReadLock
101255570Strasz *              AcpiUtReleaseReadLock
102255570Strasz *
103255570Strasz * PARAMETERS:  Lock                - Pointer to a valid RW lock
104255570Strasz *
105255570Strasz * RETURN:      Status
106255570Strasz *
107255570Strasz * DESCRIPTION: Reader interfaces for reader/writer locks. On acquisition,
108255570Strasz *              only the first reader acquires the write mutex. On release,
109255570Strasz *              only the last reader releases the write mutex. Although this
110255570Strasz *              algorithm can in theory starve writers, this should not be a
111255570Strasz *              problem with ACPICA since the subsystem is infrequently used
112255570Strasz *              in comparison to (for example) an I/O system.
113255570Strasz *
114255570Strasz ******************************************************************************/
115255570Strasz
116255570StraszACPI_STATUS
117255570StraszAcpiUtAcquireReadLock (
118255570Strasz    ACPI_RW_LOCK            *Lock)
119255570Strasz{
120255570Strasz    ACPI_STATUS             Status;
121255570Strasz
122255570Strasz
123255570Strasz    Status = AcpiOsAcquireMutex (Lock->ReaderMutex, ACPI_WAIT_FOREVER);
124255570Strasz    if (ACPI_FAILURE (Status))
125255570Strasz    {
126255570Strasz        return (Status);
127255570Strasz    }
128255570Strasz
129255570Strasz    /* Acquire the write lock only for the first reader */
130255570Strasz
131255570Strasz    Lock->NumReaders++;
132255570Strasz    if (Lock->NumReaders == 1)
133255570Strasz    {
134255570Strasz        Status = AcpiOsAcquireMutex (Lock->WriterMutex, ACPI_WAIT_FOREVER);
135255570Strasz    }
136255570Strasz
137255570Strasz    AcpiOsReleaseMutex (Lock->ReaderMutex);
138255570Strasz    return (Status);
139255570Strasz}
140256189Strasz
141255570Strasz
142255570StraszACPI_STATUS
143255570StraszAcpiUtReleaseReadLock (
144255570Strasz    ACPI_RW_LOCK            *Lock)
145255570Strasz{
146255570Strasz    ACPI_STATUS             Status;
147255570Strasz
148255570Strasz
149255570Strasz    Status = AcpiOsAcquireMutex (Lock->ReaderMutex, ACPI_WAIT_FOREVER);
150255570Strasz    if (ACPI_FAILURE (Status))
151255570Strasz    {
152255570Strasz        return (Status);
153255570Strasz    }
154255570Strasz
155255570Strasz    /* Release the write lock only for the very last reader */
156255570Strasz
157255570Strasz    Lock->NumReaders--;
158255570Strasz    if (Lock->NumReaders == 0)
159255570Strasz    {
160255570Strasz        AcpiOsReleaseMutex (Lock->WriterMutex);
161255570Strasz    }
162255570Strasz
163255570Strasz    AcpiOsReleaseMutex (Lock->ReaderMutex);
164255570Strasz    return (Status);
165255570Strasz}
166255570Strasz
167255570Strasz
168255570Strasz/*******************************************************************************
169255570Strasz *
170255570Strasz * FUNCTION:    AcpiUtAcquireWriteLock
171255570Strasz *              AcpiUtReleaseWriteLock
172255570Strasz *
173255570Strasz * PARAMETERS:  Lock                - Pointer to a valid RW lock
174255570Strasz *
175255570Strasz * RETURN:      Status
176255570Strasz *
177255570Strasz * DESCRIPTION: Writer interfaces for reader/writer locks. Simply acquire or
178255570Strasz *              release the writer mutex associated with the lock. Acquisition
179255570Strasz *              of the lock is fully exclusive and will block all readers and
180255570Strasz *              writers until it is released.
181255570Strasz *
182255570Strasz ******************************************************************************/
183255570Strasz
184255570StraszACPI_STATUS
185255570StraszAcpiUtAcquireWriteLock (
186255570Strasz    ACPI_RW_LOCK            *Lock)
187255570Strasz{
188255570Strasz    ACPI_STATUS             Status;
189255570Strasz
190255570Strasz
191255570Strasz    Status = AcpiOsAcquireMutex (Lock->WriterMutex, ACPI_WAIT_FOREVER);
192255570Strasz    return (Status);
193255570Strasz}
194255570Strasz
195255570Strasz
196255570Straszvoid
197255570StraszAcpiUtReleaseWriteLock (
198255570Strasz    ACPI_RW_LOCK            *Lock)
199255570Strasz{
200255570Strasz
201255570Strasz    AcpiOsReleaseMutex (Lock->WriterMutex);
202255570Strasz}
203255570Strasz