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