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