]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/dev/acpica/utilities/utcache.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / dev / acpica / utilities / utcache.c
1 /******************************************************************************
2  *
3  * Module Name: utcache - local cache allocation routines
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2011, 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->LinkOffset = 8;
99     Cache->ListName   = CacheName;
100     Cache->ObjectSize = ObjectSize;
101     Cache->MaxDepth   = MaxDepth;
102
103     *ReturnCache = Cache;
104     return (AE_OK);
105 }
106
107
108 /*******************************************************************************
109  *
110  * FUNCTION:    AcpiOsPurgeCache
111  *
112  * PARAMETERS:  Cache           - Handle to cache object
113  *
114  * RETURN:      Status
115  *
116  * DESCRIPTION: Free all objects within the requested cache.
117  *
118  ******************************************************************************/
119
120 ACPI_STATUS
121 AcpiOsPurgeCache (
122     ACPI_MEMORY_LIST        *Cache)
123 {
124     char                    *Next;
125     ACPI_STATUS             Status;
126
127
128     ACPI_FUNCTION_ENTRY ();
129
130
131     if (!Cache)
132     {
133         return (AE_BAD_PARAMETER);
134     }
135
136     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
137     if (ACPI_FAILURE (Status))
138     {
139         return (Status);
140     }
141
142     /* Walk the list of objects in this cache */
143
144     while (Cache->ListHead)
145     {
146         /* Delete and unlink one cached state object */
147
148         Next = *(ACPI_CAST_INDIRECT_PTR (char,
149                     &(((char *) Cache->ListHead)[Cache->LinkOffset])));
150         ACPI_FREE (Cache->ListHead);
151
152         Cache->ListHead = Next;
153         Cache->CurrentDepth--;
154     }
155
156     (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
157     return (AE_OK);
158 }
159
160
161 /*******************************************************************************
162  *
163  * FUNCTION:    AcpiOsDeleteCache
164  *
165  * PARAMETERS:  Cache           - Handle to cache object
166  *
167  * RETURN:      Status
168  *
169  * DESCRIPTION: Free all objects within the requested cache and delete the
170  *              cache object.
171  *
172  ******************************************************************************/
173
174 ACPI_STATUS
175 AcpiOsDeleteCache (
176     ACPI_MEMORY_LIST        *Cache)
177 {
178     ACPI_STATUS             Status;
179
180
181     ACPI_FUNCTION_ENTRY ();
182
183
184    /* Purge all objects in the cache */
185
186     Status = AcpiOsPurgeCache (Cache);
187     if (ACPI_FAILURE (Status))
188     {
189         return (Status);
190     }
191
192     /* Now we can delete the cache object */
193
194     AcpiOsFree (Cache);
195     return (AE_OK);
196 }
197
198
199 /*******************************************************************************
200  *
201  * FUNCTION:    AcpiOsReleaseObject
202  *
203  * PARAMETERS:  Cache       - Handle to cache object
204  *              Object      - The object to be released
205  *
206  * RETURN:      None
207  *
208  * DESCRIPTION: Release an object to the specified cache.  If cache is full,
209  *              the object is deleted.
210  *
211  ******************************************************************************/
212
213 ACPI_STATUS
214 AcpiOsReleaseObject (
215     ACPI_MEMORY_LIST        *Cache,
216     void                    *Object)
217 {
218     ACPI_STATUS             Status;
219
220
221     ACPI_FUNCTION_ENTRY ();
222
223
224     if (!Cache || !Object)
225     {
226         return (AE_BAD_PARAMETER);
227     }
228
229     /* If cache is full, just free this object */
230
231     if (Cache->CurrentDepth >= Cache->MaxDepth)
232     {
233         ACPI_FREE (Object);
234         ACPI_MEM_TRACKING (Cache->TotalFreed++);
235     }
236
237     /* Otherwise put this object back into the cache */
238
239     else
240     {
241         Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
242         if (ACPI_FAILURE (Status))
243         {
244             return (Status);
245         }
246
247         /* Mark the object as cached */
248
249         ACPI_MEMSET (Object, 0xCA, Cache->ObjectSize);
250         ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_CACHED);
251
252         /* Put the object at the head of the cache list */
253
254         * (ACPI_CAST_INDIRECT_PTR (char,
255             &(((char *) Object)[Cache->LinkOffset]))) = Cache->ListHead;
256         Cache->ListHead = Object;
257         Cache->CurrentDepth++;
258
259         (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES);
260     }
261
262     return (AE_OK);
263 }
264
265
266 /*******************************************************************************
267  *
268  * FUNCTION:    AcpiOsAcquireObject
269  *
270  * PARAMETERS:  Cache           - Handle to cache object
271  *
272  * RETURN:      the acquired object.  NULL on error
273  *
274  * DESCRIPTION: Get an object from the specified cache.  If cache is empty,
275  *              the object is allocated.
276  *
277  ******************************************************************************/
278
279 void *
280 AcpiOsAcquireObject (
281     ACPI_MEMORY_LIST        *Cache)
282 {
283     ACPI_STATUS             Status;
284     void                    *Object;
285
286
287     ACPI_FUNCTION_NAME (OsAcquireObject);
288
289
290     if (!Cache)
291     {
292         return (NULL);
293     }
294
295     Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES);
296     if (ACPI_FAILURE (Status))
297     {
298         return (NULL);
299     }
300
301     ACPI_MEM_TRACKING (Cache->Requests++);
302
303     /* Check the cache first */
304
305     if (Cache->ListHead)
306     {
307         /* There is an object available, use it */
308
309         Object = Cache->ListHead;
310         Cache->ListHead = *(ACPI_CAST_INDIRECT_PTR (char,
311                                 &(((char *) Object)[Cache->LinkOffset])));
312
313         Cache->CurrentDepth--;
314
315         ACPI_MEM_TRACKING (Cache->Hits++);
316         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
317             "Object %p from %s cache\n", Object, Cache->ListName));
318
319         Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES);
320         if (ACPI_FAILURE (Status))
321         {
322             return (NULL);
323         }
324
325         /* Clear (zero) the previously used Object */
326
327         ACPI_MEMSET (Object, 0, Cache->ObjectSize);
328     }
329     else
330     {
331         /* The cache is empty, create a new object */
332
333         ACPI_MEM_TRACKING (Cache->TotalAllocated++);
334
335 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
336         if ((Cache->TotalAllocated - Cache->TotalFreed) > Cache->MaxOccupied)
337         {
338             Cache->MaxOccupied = Cache->TotalAllocated - Cache->TotalFreed;
339         }
340 #endif
341
342         /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
343
344         Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES);
345         if (ACPI_FAILURE (Status))
346         {
347             return (NULL);
348         }
349
350         Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize);
351         if (!Object)
352         {
353             return (NULL);
354         }
355     }
356
357     return (Object);
358 }
359 #endif /* ACPI_USE_LOCAL_CACHE */
360
361