xref: /titanic_52/usr/src/uts/intel/io/acpica/utilities/utcache.c (revision ba91f08b676cdb873326906656bad68790a01301)
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 "acpi.h"
47 #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 
362