]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/dev/acpica/components/utilities/utcache.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / dev / acpica / components / utilities / utcache.c
1 /******************************************************************************
2  *
3  * Module Name: utcache - local cache allocation routines
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2013, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #define __UTCACHE_C__
45
46 #include <contrib/dev/acpica/include/acpi.h>
47 #include <contrib/dev/acpica/include/accommon.h>
48
49 #define _COMPONENT          ACPI_UTILITIES
50         ACPI_MODULE_NAME    ("utcache")
51
52
53 #ifdef ACPI_USE_LOCAL_CACHE
54 /*******************************************************************************
55  *
56  * FUNCTION:    AcpiOsCreateCache
57  *
58  * PARAMETERS:  CacheName       - Ascii name for the cache
59  *              ObjectSize      - Size of each cached object
60  *              MaxDepth        - Maximum depth of the cache (in objects)
61  *              ReturnCache     - Where the new cache object is returned
62  *
63  * RETURN:      Status
64  *
65  * DESCRIPTION: Create a cache object
66  *
67  ******************************************************************************/
68
69 ACPI_STATUS
70 AcpiOsCreateCache (
71     char                    *CacheName,
72     UINT16                  ObjectSize,
73     UINT16                  MaxDepth,
74     ACPI_MEMORY_LIST        **ReturnCache)
75 {
76     ACPI_MEMORY_LIST        *Cache;
77
78
79     ACPI_FUNCTION_ENTRY ();
80
81
82     if (!CacheName || !ReturnCache || (ObjectSize < 16))
83     {
84         return (AE_BAD_PARAMETER);
85     }
86
87     /* Create the cache object */
88
89     Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST));
90     if (!Cache)
91     {
92         return (AE_NO_MEMORY);
93     }
94
95     /* Populate the cache object and return it */
96
97     ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST));
98     Cache->ListName   = CacheName;
99     Cache->ObjectSize = ObjectSize;
100     Cache->MaxDepth   = MaxDepth;
101
102     *ReturnCache = Cache;
103     return (AE_OK);
104 }
105
106
107 /*******************************************************************************
108  *
109  * FUNCTION:    AcpiOsPurgeCache
110  *
111  * PARAMETERS:  Cache           - Handle to cache object
112  *
113  * RETURN:      Status
114  *
115  * DESCRIPTION: Free all objects within the requested cache.
116  *
117  ******************************************************************************/
118
119 ACPI_STATUS
120 AcpiOsPurgeCache (
121     ACPI_MEMORY_LIST        *Cache)
122 {
123     void                    *Next;
124     ACPI_STATUS             Status;
125
126
127     ACPI_FUNCTION_ENTRY ();
128
129
130     if (!Cache)
131     {
132         return (AE_BAD_PARAMETER);
133     }
134
135     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
136     if (ACPI_FAILURE (Status))
137     {
138         return (Status);
139     }
140
141     /* Walk the list of objects in this cache */
142
143     while (Cache->ListHead)
144     {
145         /* Delete and unlink one cached state object */
146
147         Next = ACPI_GET_DESCRIPTOR_PTR (Cache->ListHead);
148         ACPI_FREE (Cache->ListHead);
149
150         Cache->ListHead = Next;
151         Cache->CurrentDepth--;
152     }
153
154     (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
155     return (AE_OK);
156 }
157
158
159 /*******************************************************************************
160  *
161  * FUNCTION:    AcpiOsDeleteCache
162  *
163  * PARAMETERS:  Cache           - Handle to cache object
164  *
165  * RETURN:      Status
166  *
167  * DESCRIPTION: Free all objects within the requested cache and delete the
168  *              cache object.
169  *
170  ******************************************************************************/
171
172 ACPI_STATUS
173 AcpiOsDeleteCache (
174     ACPI_MEMORY_LIST        *Cache)
175 {
176     ACPI_STATUS             Status;
177
178
179     ACPI_FUNCTION_ENTRY ();
180
181
182    /* Purge all objects in the cache */
183
184     Status = AcpiOsPurgeCache (Cache);
185     if (ACPI_FAILURE (Status))
186     {
187         return (Status);
188     }
189
190     /* Now we can delete the cache object */
191
192     AcpiOsFree (Cache);
193     return (AE_OK);
194 }
195
196
197 /*******************************************************************************
198  *
199  * FUNCTION:    AcpiOsReleaseObject
200  *
201  * PARAMETERS:  Cache       - Handle to cache object
202  *              Object      - The object to be released
203  *
204  * RETURN:      None
205  *
206  * DESCRIPTION: Release an object to the specified cache. If cache is full,
207  *              the object is deleted.
208  *
209  ******************************************************************************/
210
211 ACPI_STATUS
212 AcpiOsReleaseObject (
213     ACPI_MEMORY_LIST        *Cache,
214     void                    *Object)
215 {
216     ACPI_STATUS             Status;
217
218
219     ACPI_FUNCTION_ENTRY ();
220
221
222     if (!Cache || !Object)
223     {
224         return (AE_BAD_PARAMETER);
225     }
226
227     /* If cache is full, just free this object */
228
229     if (Cache->CurrentDepth >= Cache->MaxDepth)
230     {
231         ACPI_FREE (Object);
232         ACPI_MEM_TRACKING (Cache->TotalFreed++);
233     }
234
235     /* Otherwise put this object back into the cache */
236
237     else
238     {
239         Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
240         if (ACPI_FAILURE (Status))
241         {
242             return (Status);
243         }
244
245         /* Mark the object as cached */
246
247         ACPI_MEMSET (Object, 0xCA, Cache->ObjectSize);
248         ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_CACHED);
249
250         /* Put the object at the head of the cache list */
251
252         ACPI_SET_DESCRIPTOR_PTR (Object, Cache->ListHead);
253         Cache->ListHead = Object;
254         Cache->CurrentDepth++;
255
256         (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
257     }
258
259     return (AE_OK);
260 }
261
262
263 /*******************************************************************************
264  *
265  * FUNCTION:    AcpiOsAcquireObject
266  *
267  * PARAMETERS:  Cache           - Handle to cache object
268  *
269  * RETURN:      the acquired object. NULL on error
270  *
271  * DESCRIPTION: Get an object from the specified cache. If cache is empty,
272  *              the object is allocated.
273  *
274  ******************************************************************************/
275
276 void *
277 AcpiOsAcquireObject (
278     ACPI_MEMORY_LIST        *Cache)
279 {
280     ACPI_STATUS             Status;
281     void                    *Object;
282
283
284     ACPI_FUNCTION_NAME (OsAcquireObject);
285
286
287     if (!Cache)
288     {
289         return (NULL);
290     }
291
292     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
293     if (ACPI_FAILURE (Status))
294     {
295         return (NULL);
296     }
297
298     ACPI_MEM_TRACKING (Cache->Requests++);
299
300     /* Check the cache first */
301
302     if (Cache->ListHead)
303     {
304         /* There is an object available, use it */
305
306         Object = Cache->ListHead;
307         Cache->ListHead = ACPI_GET_DESCRIPTOR_PTR (Object);
308
309         Cache->CurrentDepth--;
310
311         ACPI_MEM_TRACKING (Cache->Hits++);
312         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
313             "Object %p from %s cache\n", Object, Cache->ListName));
314
315         Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES);
316         if (ACPI_FAILURE (Status))
317         {
318             return (NULL);
319         }
320
321         /* Clear (zero) the previously used Object */
322
323         ACPI_MEMSET (Object, 0, Cache->ObjectSize);
324     }
325     else
326     {
327         /* The cache is empty, create a new object */
328
329         ACPI_MEM_TRACKING (Cache->TotalAllocated++);
330
331 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
332         if ((Cache->TotalAllocated - Cache->TotalFreed) > Cache->MaxOccupied)
333         {
334             Cache->MaxOccupied = Cache->TotalAllocated - Cache->TotalFreed;
335         }
336 #endif
337
338         /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
339
340         Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES);
341         if (ACPI_FAILURE (Status))
342         {
343             return (NULL);
344         }
345
346         Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize);
347         if (!Object)
348         {
349             return (NULL);
350         }
351     }
352
353     return (Object);
354 }
355 #endif /* ACPI_USE_LOCAL_CACHE */