/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ */ /* * HISTORY * * Revision 1.1.1.1 1998/09/22 21:05:34 wsanchez * Import of Mac OS X kernel (~semeria) * * Revision 1.1.1.1 1998/03/07 02:25:54 wsanchez * Import of OSF Mach kernel (~mburg) * * Revision 1.1.12.1 1996/09/17 16:27:00 bruel * fixed bzero prototype. * [96/09/17 bruel] * * Revision 1.1.2.4 1995/10/09 17:13:51 devrcs * Merged in RT3_SHARED ETAP code. * [1995/09/13 18:34:15 joe] * * Revision 1.1.2.3 1995/09/18 19:13:37 devrcs * Merged in RT3_SHARED ETAP code. * [1995/09/13 18:34:15 joe] * * Revision 1.1.2.2 1995/01/10 05:11:15 devrcs * mk6 CR801 - merge up from nmk18b4 to nmk18b7 * patch up spinlock references ==> simplelock * [1994/12/09 20:54:30 dwm] * * mk6 CR801 - new file for mk6_shared from cnmk_shared. * [1994/12/01 21:11:49 dwm] * * Revision 1.1.2.1 1994/10/21 18:28:50 joe * Initial ETAP submission * [1994/10/20 19:31:33 joe] * * $EndLog$ */ /* * File: etap_pool.c * * etap_pool.c contains the functions for maintenance * of the start_data_pool. The start_data_pool is * used by the ETAP package. Its primary * objective is to provide start_data_nodes to complex * locks so they can hold start information for read * locks (since multiple readers can acquire a read * lock). Each complex lock will maintain a linked * list of these nodes. * * NOTES: The start_data_pool is used instead of zalloc to * eliminate complex lock dependancies. If zalloc was used, * then no complex locks could be used in zalloc code paths. * This is both difficult and unrealistic, since zalloc * allocates memory dynamically. Hence, this dependancy is * eliminated with the use of the statically allocated * start_data_pool. * */ #include <kern/lock.h> #include <kern/spl.h> #include <kern/etap_pool.h> #include <kern/sched_prim.h> #include <kern/macro_help.h> #if ETAP_LOCK_TRACE /* * Statically allocate the start data pool, * header and lock. */ struct start_data_node sd_pool [SD_POOL_ENTRIES]; /* static buffer */ start_data_node_t sd_free_list; /* pointer to free node list */ int sd_sleepers; /* number of blocked threads */ simple_lock_data_t sd_pool_lock; /* * Interrupts must be disabled while the * sd_pool_lock is taken. */ #define pool_lock(s) \ MACRO_BEGIN \ s = splhigh(); \ simple_lock(&sd_pool_lock); \ MACRO_END #define pool_unlock(s) \ MACRO_BEGIN \ simple_unlock(&sd_pool_lock); \ splx(s); \ MACRO_END /* * ROUTINE: init_start_data_pool * * FUNCTION: Initialize the start_data_pool: * - create the free list chain for the max * number of entries. * - initialize the sd_pool_lock */ void init_start_data_pool(void) { int x; simple_lock_init(&sd_pool_lock, ETAP_MISC_SD_POOL); /* * Establish free list pointer chain */ for (x=0; x < SD_POOL_ENTRIES-1; x++) sd_pool[x].next = &sd_pool[x+1]; sd_pool[SD_POOL_ENTRIES-1].next = SD_ENTRY_NULL; sd_free_list = &sd_pool[0]; sd_sleepers = 0; } /* * ROUTINE: get_start_data_node * * FUNCTION: Returns a free node from the start data pool * to the caller. If none are available, the * call will block, then try again. */ start_data_node_t get_start_data_node(void) { start_data_node_t avail_node; spl_t s; pool_lock(s); /* * If the pool does not have any nodes available, * block until one becomes free. */ while (sd_free_list == SD_ENTRY_NULL) { sd_sleepers++; assert_wait((event_t) &sd_pool[0], THREAD_UNINT); pool_unlock(s); printf ("DEBUG-KERNEL: empty start_data_pool\n"); thread_block(THREAD_CONTINUE_NULL); pool_lock(s); sd_sleepers--; } avail_node = sd_free_list; sd_free_list = sd_free_list->next; pool_unlock(s); bzero ((char *) avail_node, sizeof(struct start_data_node)); avail_node->next = SD_ENTRY_NULL; return (avail_node); } /* * ROUTINE: free_start_data_node * * FUNCTION: Releases start data node back to the sd_pool, * so that it can be used again. */ void free_start_data_node ( start_data_node_t node) { boolean_t wakeup = FALSE; spl_t s; if (node == SD_ENTRY_NULL) return; pool_lock(s); node->next = sd_free_list; sd_free_list = node; if (sd_sleepers) wakeup = TRUE; pool_unlock(s); if (wakeup) thread_wakeup((event_t) &sd_pool[0]); } #endif /* ETAP_LOCK_TRACE */