15db2f26eSSascha Wildner /*
25db2f26eSSascha Wildner * Copyright (c) 2006 Jeffrey M. Hsu. All rights reserved.
35db2f26eSSascha Wildner *
45db2f26eSSascha Wildner * This code is derived from software contributed to The DragonFly Project
55db2f26eSSascha Wildner * by Jeffrey M. Hsu.
65db2f26eSSascha Wildner *
75db2f26eSSascha Wildner * Redistribution and use in source and binary forms, with or without
85db2f26eSSascha Wildner * modification, are permitted provided that the following conditions
95db2f26eSSascha Wildner * are met:
105db2f26eSSascha Wildner * 1. Redistributions of source code must retain the above copyright
115db2f26eSSascha Wildner * notice, this list of conditions and the following disclaimer.
125db2f26eSSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
135db2f26eSSascha Wildner * notice, this list of conditions and the following disclaimer in the
145db2f26eSSascha Wildner * documentation and/or other materials provided with the distribution.
155db2f26eSSascha Wildner * 3. Neither the name of The DragonFly Project nor the names of its
165db2f26eSSascha Wildner * contributors may be used to endorse or promote products derived
175db2f26eSSascha Wildner * from this software without specific, prior written permission.
185db2f26eSSascha Wildner *
195db2f26eSSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205db2f26eSSascha Wildner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215db2f26eSSascha Wildner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
225db2f26eSSascha Wildner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
235db2f26eSSascha Wildner * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
245db2f26eSSascha Wildner * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
255db2f26eSSascha Wildner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
265db2f26eSSascha Wildner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
275db2f26eSSascha Wildner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
285db2f26eSSascha Wildner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
295db2f26eSSascha Wildner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
305db2f26eSSascha Wildner * SUCH DAMAGE.
315db2f26eSSascha Wildner */
325db2f26eSSascha Wildner
336354fc0fSzrj #include <sys/types.h>
346354fc0fSzrj #include <sys/malloc.h>
355db2f26eSSascha Wildner #include <sys/objcache.h>
365db2f26eSSascha Wildner
375db2f26eSSascha Wildner struct acpicache {
385db2f26eSSascha Wildner struct objcache *cache;
395db2f26eSSascha Wildner struct objcache_malloc_args args;
405db2f26eSSascha Wildner };
415db2f26eSSascha Wildner
425db2f26eSSascha Wildner /*
435db2f26eSSascha Wildner * Add some magic numbers to catch double-frees earlier rather
445db2f26eSSascha Wildner * then later.
455db2f26eSSascha Wildner */
465db2f26eSSascha Wildner struct acpiobjhead {
475db2f26eSSascha Wildner int state;
485db2f26eSSascha Wildner void *cache;
495db2f26eSSascha Wildner const char *func;
505db2f26eSSascha Wildner int line;
515db2f26eSSascha Wildner int unused;
525db2f26eSSascha Wildner };
535db2f26eSSascha Wildner
545db2f26eSSascha Wildner #define TRACK_ALLOCATED 0x7AF45533
555db2f26eSSascha Wildner #define TRACK_FREED 0x7B056644
565db2f26eSSascha Wildner
575db2f26eSSascha Wildner #define OBJHEADSIZE sizeof(struct acpiobjhead)
585db2f26eSSascha Wildner
595db2f26eSSascha Wildner #include "acpi.h"
605db2f26eSSascha Wildner
615db2f26eSSascha Wildner ACPI_STATUS
AcpiOsCreateCache(char * CacheName,UINT16 ObjectSize,UINT16 MaxDepth,ACPI_CACHE_T ** ReturnCache)625db2f26eSSascha Wildner AcpiOsCreateCache(char *CacheName, UINT16 ObjectSize, UINT16 MaxDepth,
635db2f26eSSascha Wildner ACPI_CACHE_T **ReturnCache)
645db2f26eSSascha Wildner {
655db2f26eSSascha Wildner ACPI_CACHE_T *cache;
665db2f26eSSascha Wildner
675db2f26eSSascha Wildner cache = kmalloc(sizeof(*cache), M_TEMP, M_WAITOK);
685db2f26eSSascha Wildner cache->args.objsize = OBJHEADSIZE + ObjectSize;
695db2f26eSSascha Wildner cache->args.mtype = M_CACHE;
705db2f26eSSascha Wildner cache->cache = objcache_create(CacheName, 0, 0, NULL, NULL,
715db2f26eSSascha Wildner NULL, objcache_malloc_alloc, objcache_malloc_free, &cache->args);
725db2f26eSSascha Wildner *ReturnCache = cache;
735db2f26eSSascha Wildner return AE_OK;
745db2f26eSSascha Wildner }
755db2f26eSSascha Wildner
765db2f26eSSascha Wildner ACPI_STATUS
AcpiOsDeleteCache(ACPI_CACHE_T * Cache)775db2f26eSSascha Wildner AcpiOsDeleteCache(ACPI_CACHE_T *Cache)
785db2f26eSSascha Wildner {
795db2f26eSSascha Wildner objcache_destroy(Cache->cache);
805db2f26eSSascha Wildner kfree(Cache, M_TEMP);
815db2f26eSSascha Wildner return AE_OK;
825db2f26eSSascha Wildner }
835db2f26eSSascha Wildner
845db2f26eSSascha Wildner
855db2f26eSSascha Wildner ACPI_STATUS
AcpiOsPurgeCache(ACPI_CACHE_T * Cache)865db2f26eSSascha Wildner AcpiOsPurgeCache(ACPI_CACHE_T *Cache)
875db2f26eSSascha Wildner {
885db2f26eSSascha Wildner struct objcache *reclaimlist[] = { Cache->cache };
895db2f26eSSascha Wildner
90*8a7a7510SAaron LI objcache_reclaimlist(reclaimlist, 1);
915db2f26eSSascha Wildner return AE_OK;
925db2f26eSSascha Wildner }
935db2f26eSSascha Wildner
945db2f26eSSascha Wildner void *
AcpiOsAcquireObject(ACPI_CACHE_T * Cache)955db2f26eSSascha Wildner AcpiOsAcquireObject(ACPI_CACHE_T *Cache)
965db2f26eSSascha Wildner {
975db2f26eSSascha Wildner struct acpiobjhead *head;
985db2f26eSSascha Wildner
995db2f26eSSascha Wildner head = objcache_get(Cache->cache, M_WAITOK);
1005db2f26eSSascha Wildner bzero(head, Cache->args.objsize);
1015db2f26eSSascha Wildner head->state = TRACK_ALLOCATED;
1026af96acdSSascha Wildner #ifdef ACPI_DEBUG_CACHE
1035db2f26eSSascha Wildner head->cache = Cache;
1045db2f26eSSascha Wildner head->func = "nowhere";
1055db2f26eSSascha Wildner head->line = 0;
1065db2f26eSSascha Wildner #endif
1075db2f26eSSascha Wildner return (head + 1);
1085db2f26eSSascha Wildner }
1095db2f26eSSascha Wildner
1105db2f26eSSascha Wildner ACPI_STATUS
1116af96acdSSascha Wildner #ifdef ACPI_DEBUG_CACHE
_AcpiOsReleaseObject(ACPI_CACHE_T * Cache,void * Object,const char * func,int line)1125db2f26eSSascha Wildner _AcpiOsReleaseObject(ACPI_CACHE_T *Cache, void *Object,
1135db2f26eSSascha Wildner const char *func, int line)
1145db2f26eSSascha Wildner #else
1155db2f26eSSascha Wildner AcpiOsReleaseObject(ACPI_CACHE_T *Cache, void *Object)
1165db2f26eSSascha Wildner #endif
1175db2f26eSSascha Wildner {
1185db2f26eSSascha Wildner struct acpiobjhead *head = (void *)((char *)Object - OBJHEADSIZE);
1195db2f26eSSascha Wildner
1206af96acdSSascha Wildner #ifdef ACPI_DEBUG_CACHE
1215db2f26eSSascha Wildner if (head->cache != Cache) {
1225db2f26eSSascha Wildner kprintf("%s: object %p belongs to %p, not %p\n",
1235db2f26eSSascha Wildner __func__, Object, head->cache, Cache);
1245db2f26eSSascha Wildner }
1255db2f26eSSascha Wildner #endif
1265db2f26eSSascha Wildner if (head->state != TRACK_ALLOCATED) {
1275db2f26eSSascha Wildner if (head->state == TRACK_FREED) {
1286af96acdSSascha Wildner #ifdef ACPI_DEBUG_CACHE
1295db2f26eSSascha Wildner kprintf("%s: Double Free %p, %s:%d, first %s:%d\n",
1305db2f26eSSascha Wildner __func__, Object, func, line, head->func,
1315db2f26eSSascha Wildner head->line);
1325db2f26eSSascha Wildner #else
1335db2f26eSSascha Wildner kprintf("%s: Double Free %p\n", __func__, Object);
1345db2f26eSSascha Wildner #endif
1355db2f26eSSascha Wildner } else
1365db2f26eSSascha Wildner kprintf("AcpiOsReleaseObject: Bad object %p (%08x)\n",
1375db2f26eSSascha Wildner Object, head->state);
1385db2f26eSSascha Wildner return AE_OK;
1395db2f26eSSascha Wildner }
1405db2f26eSSascha Wildner head->state = TRACK_FREED;
1416af96acdSSascha Wildner #ifdef ACPI_DEBUG_CACHE
1425db2f26eSSascha Wildner head->func = func;
1435db2f26eSSascha Wildner head->line = line;
1445db2f26eSSascha Wildner #endif
1455db2f26eSSascha Wildner objcache_put(Cache->cache, head);
1465db2f26eSSascha Wildner return AE_OK;
1475db2f26eSSascha Wildner }
148