]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/etap_pool.c
xnu-517.tar.gz
[apple/xnu.git] / osfmk / kern / etap_pool.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * @OSF_COPYRIGHT@
27 */
28 /*
29 * HISTORY
30 *
31 * Revision 1.1.1.1 1998/09/22 21:05:34 wsanchez
32 * Import of Mac OS X kernel (~semeria)
33 *
34 * Revision 1.1.1.1 1998/03/07 02:25:54 wsanchez
35 * Import of OSF Mach kernel (~mburg)
36 *
37 * Revision 1.1.12.1 1996/09/17 16:27:00 bruel
38 * fixed bzero prototype.
39 * [96/09/17 bruel]
40 *
41 * Revision 1.1.2.4 1995/10/09 17:13:51 devrcs
42 * Merged in RT3_SHARED ETAP code.
43 * [1995/09/13 18:34:15 joe]
44 *
45 * Revision 1.1.2.3 1995/09/18 19:13:37 devrcs
46 * Merged in RT3_SHARED ETAP code.
47 * [1995/09/13 18:34:15 joe]
48 *
49 * Revision 1.1.2.2 1995/01/10 05:11:15 devrcs
50 * mk6 CR801 - merge up from nmk18b4 to nmk18b7
51 * patch up spinlock references ==> simplelock
52 * [1994/12/09 20:54:30 dwm]
53 *
54 * mk6 CR801 - new file for mk6_shared from cnmk_shared.
55 * [1994/12/01 21:11:49 dwm]
56 *
57 * Revision 1.1.2.1 1994/10/21 18:28:50 joe
58 * Initial ETAP submission
59 * [1994/10/20 19:31:33 joe]
60 *
61 * $EndLog$
62 */
63 /*
64 * File: etap_pool.c
65 *
66 * etap_pool.c contains the functions for maintenance
67 * of the start_data_pool. The start_data_pool is
68 * used by the ETAP package. Its primary
69 * objective is to provide start_data_nodes to complex
70 * locks so they can hold start information for read
71 * locks (since multiple readers can acquire a read
72 * lock). Each complex lock will maintain a linked
73 * list of these nodes.
74 *
75 * NOTES: The start_data_pool is used instead of zalloc to
76 * eliminate complex lock dependancies. If zalloc was used,
77 * then no complex locks could be used in zalloc code paths.
78 * This is both difficult and unrealistic, since zalloc
79 * allocates memory dynamically. Hence, this dependancy is
80 * eliminated with the use of the statically allocated
81 * start_data_pool.
82 *
83 */
84
85 #include <kern/lock.h>
86 #include <kern/spl.h>
87 #include <kern/etap_pool.h>
88 #include <kern/sched_prim.h>
89 #include <kern/macro_help.h>
90
91 #if ETAP_LOCK_TRACE
92
93 /*
94 * Statically allocate the start data pool,
95 * header and lock.
96 */
97
98 struct start_data_node sd_pool [SD_POOL_ENTRIES]; /* static buffer */
99 start_data_node_t sd_free_list; /* pointer to free node list */
100 int sd_sleepers; /* number of blocked threads */
101
102 simple_lock_data_t sd_pool_lock;
103
104
105 /*
106 * Interrupts must be disabled while the
107 * sd_pool_lock is taken.
108 */
109
110 #define pool_lock(s) \
111 MACRO_BEGIN \
112 s = splhigh(); \
113 simple_lock(&sd_pool_lock); \
114 MACRO_END
115
116 #define pool_unlock(s) \
117 MACRO_BEGIN \
118 simple_unlock(&sd_pool_lock); \
119 splx(s); \
120 MACRO_END
121
122
123 /*
124 * ROUTINE: init_start_data_pool
125 *
126 * FUNCTION: Initialize the start_data_pool:
127 * - create the free list chain for the max
128 * number of entries.
129 * - initialize the sd_pool_lock
130 */
131
132 void
133 init_start_data_pool(void)
134 {
135 int x;
136
137 simple_lock_init(&sd_pool_lock, ETAP_MISC_SD_POOL);
138
139 /*
140 * Establish free list pointer chain
141 */
142
143 for (x=0; x < SD_POOL_ENTRIES-1; x++)
144 sd_pool[x].next = &sd_pool[x+1];
145
146 sd_pool[SD_POOL_ENTRIES-1].next = SD_ENTRY_NULL;
147 sd_free_list = &sd_pool[0];
148 sd_sleepers = 0;
149 }
150
151 /*
152 * ROUTINE: get_start_data_node
153 *
154 * FUNCTION: Returns a free node from the start data pool
155 * to the caller. If none are available, the
156 * call will block, then try again.
157 */
158
159 start_data_node_t
160 get_start_data_node(void)
161 {
162 start_data_node_t avail_node;
163 spl_t s;
164
165 pool_lock(s);
166
167 /*
168 * If the pool does not have any nodes available,
169 * block until one becomes free.
170 */
171
172 while (sd_free_list == SD_ENTRY_NULL) {
173
174 sd_sleepers++;
175 assert_wait((event_t) &sd_pool[0], THREAD_UNINT);
176 pool_unlock(s);
177
178 printf ("DEBUG-KERNEL: empty start_data_pool\n");
179 thread_block(THREAD_CONTINUE_NULL);
180
181 pool_lock(s);
182 sd_sleepers--;
183 }
184
185 avail_node = sd_free_list;
186 sd_free_list = sd_free_list->next;
187
188 pool_unlock(s);
189
190 bzero ((char *) avail_node, sizeof(struct start_data_node));
191 avail_node->next = SD_ENTRY_NULL;
192
193 return (avail_node);
194 }
195
196 /*
197 * ROUTINE: free_start_data_node
198 *
199 * FUNCTION: Releases start data node back to the sd_pool,
200 * so that it can be used again.
201 */
202
203 void
204 free_start_data_node (
205 start_data_node_t node)
206 {
207 boolean_t wakeup = FALSE;
208 spl_t s;
209
210 if (node == SD_ENTRY_NULL)
211 return;
212
213 pool_lock(s);
214
215 node->next = sd_free_list;
216 sd_free_list = node;
217
218 if (sd_sleepers)
219 wakeup = TRUE;
220
221 pool_unlock(s);
222
223 if (wakeup)
224 thread_wakeup((event_t) &sd_pool[0]);
225 }
226
227 #endif /* ETAP_LOCK_TRACE */