Source to osfmk/kern/etap_pool.c
/*
* 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((void (*)(void)) 0);
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 */