]> git.saurik.com Git - apple/xnu.git/blob - osfmk/default_pager/default_pager.c
xnu-344.34.tar.gz
[apple/xnu.git] / osfmk / default_pager / default_pager.c
1 /*
2 * Copyright (c) 2001, 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 * Mach Operating System
27 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
35 *
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50
51 /*
52 * Default pager.
53 * Threads management.
54 * Requests handling.
55 */
56
57 #include "default_pager_internal.h"
58 #include <kern/host.h>
59 #include <kern/ledger.h>
60 #include <mach/host_info.h>
61 #include <ipc/ipc_space.h>
62 #include <vm/vm_kern.h>
63
64 char my_name[] = "(default pager): ";
65
66 #if DEFAULT_PAGER_DEBUG
67 int debug_mask = 0;
68 #endif /* DEFAULT_PAGER_DEBUG */
69
70 /*
71 * Use 16 Kbyte stacks instead of the default 64K.
72 * Use 4 Kbyte waiting stacks instead of the default 8K.
73 */
74
75 vm_size_t cthread_stack_size = 16 *1024;
76 extern vm_size_t cthread_wait_stack_size;
77
78 unsigned long long vm_page_mask;
79 int vm_page_shift;
80
81 int norma_mk;
82
83 boolean_t verbose;
84
85 /* task_t default_pager_self; */ /* Our task port. */
86 mutex_t dpt_lock; /* lock for the dpt array struct */
87 default_pager_thread_t **dpt_array;
88
89 memory_object_default_t default_pager_object; /* for memory_object_create. */
90
91 MACH_PORT_FACE default_pager_default_set; /* Port set for "default" thread. */
92 MACH_PORT_FACE default_pager_internal_set; /* Port set for internal objects. */
93 MACH_PORT_FACE default_pager_external_set; /* Port set for external objects. */
94
95 #define DEFAULT_PAGER_INTERNAL_COUNT (4)
96
97
98 /* Memory created by default_pager_object_create should mostly be resident. */
99 #define DEFAULT_PAGER_EXTERNAL_COUNT (2)
100
101 unsigned int default_pager_internal_count = DEFAULT_PAGER_INTERNAL_COUNT;
102 /* Number of "internal" threads. */
103 unsigned int default_pager_external_count = DEFAULT_PAGER_EXTERNAL_COUNT;
104 /* Number of "external" threads. */
105
106 /*
107 * Forward declarations.
108 */
109 boolean_t default_pager_notify_server(mach_msg_header_t *,
110 mach_msg_header_t *);
111 boolean_t default_pager_demux_object(mach_msg_header_t *,
112 mach_msg_header_t *);
113 boolean_t default_pager_demux_default(mach_msg_header_t *,
114 mach_msg_header_t *);
115 default_pager_thread_t *start_default_pager_thread(int, boolean_t);
116 void default_pager(void);
117 void default_pager_thread(void *);
118 void default_pager_initialize(void);
119 void default_pager_set_policy(MACH_PORT_FACE);
120 boolean_t dp_parse_argument(char *); /* forward; */
121 unsigned int d_to_i(char *); /* forward; */
122
123
124 extern int vstruct_def_clshift;
125
126
127 /*
128 * Initialize and Run the default pager
129 */
130 void
131 default_pager(void)
132 {
133 int i, id;
134 static char here[] = "default_pager";
135 mach_msg_options_t server_options;
136 default_pager_thread_t dpt;
137 kern_return_t kr;
138
139
140
141 /*
142 * Give me space for the thread array and zero it.
143 */
144 i = default_pager_internal_count + default_pager_external_count + 1;
145 dpt_array = (default_pager_thread_t **)
146 kalloc(i * sizeof(default_pager_thread_t *));
147 memset(dpt_array, 0, i * sizeof(default_pager_thread_t *));
148
149 /* Setup my thread structure. */
150 id = 0;
151 dpt.dpt_buffer = 0;
152 dpt.dpt_internal = FALSE;
153 dpt.dpt_initialized_p = TRUE;
154 dpt_array[0] = &dpt;
155
156 /*
157 * Now we create the threads that will actually
158 * manage objects.
159 */
160
161 for (i = 0; i < default_pager_internal_count; i++) {
162 dpt_array[id] = (default_pager_thread_t *)
163 kalloc(sizeof (default_pager_thread_t));
164 if (dpt_array[id] == NULL)
165 Panic("alloc pager thread");
166 kr = vm_allocate(kernel_map, &((dpt_array[id])->dpt_buffer),
167 vm_page_size << vstruct_def_clshift, TRUE);
168 if (kr != KERN_SUCCESS)
169 Panic("alloc thread buffer");
170 kr = vm_map_wire(kernel_map, (dpt_array[id])->dpt_buffer,
171 ((dpt_array[id])->dpt_buffer)
172 +(vm_page_size << vstruct_def_clshift),
173 VM_PROT_DEFAULT,
174 FALSE);
175 if (kr != KERN_SUCCESS)
176 Panic("wire thread buffer");
177 (dpt_array[id])->dpt_internal = TRUE;
178 (dpt_array[id])->dpt_initialized_p = TRUE;
179 (dpt_array[id])->checked_out = FALSE;
180 id++;
181 }
182 DPT_LOCK_INIT(dpt_lock);
183 }
184
185
186
187
188
189
190 /* simple utility: only works for 2^n */
191 int
192 local_log2(
193 unsigned int n)
194 {
195 register int i = 0;
196
197 if(n == 0) return 0;
198
199 while ((n & 1) == 0) {
200 i++;
201 n >>= 1;
202 }
203 return i;
204 }
205
206
207
208
209 /* another simple utility, d_to_i(char*) supporting only decimal
210 * and devoid of range checking; obscure name chosen deliberately
211 * to avoid confusion with semantic-rich POSIX routines */
212 unsigned int
213 d_to_i(char * arg)
214 {
215 unsigned int rval = 0;
216 char ch;
217
218 while ((ch = *arg++) && ch >= '0' && ch <= '9') {
219 rval *= 10;
220 rval += ch - '0';
221 }
222 return(rval);
223 }
224
225
226
227
228 /*
229 * Check for non-disk-partition arguments of the form
230 * attribute=argument
231 * returning TRUE if one if found
232 */
233 boolean_t dp_parse_argument(char *av)
234 {
235 char *rhs = av;
236 static char here[] = "dp_parse_argument";
237
238 /* Check for '-v' flag */
239
240 if (av[0] == '-' && av[1] == 'v' && av[2] == 0) {
241 verbose = TRUE ;
242 return TRUE;
243 }
244
245 /*
246 * If we find a '=' followed by an argument in the string,
247 * check for known arguments
248 */
249 while (*rhs && *rhs != '=')
250 rhs++;
251 if (*rhs && *++rhs) {
252 /* clsize=N pages */
253 if (strprefix(av,"cl")) {
254 if (!bs_set_default_clsize(d_to_i(rhs)))
255 dprintf(("Bad argument (%s) - ignored\n", av));
256 return(TRUE);
257 }
258 /* else if strprefix(av,"another_argument")) {
259 handle_another_argument(av);
260 return(TRUE);
261 } */
262 }
263 return(FALSE);
264 }
265
266 int
267 start_def_pager(char *bs_device)
268 {
269 int my_node;
270 /*
271 MACH_PORT_FACE master_device_port;
272 */
273 MACH_PORT_FACE security_port;
274 /*
275 MACH_PORT_FACE root_ledger_wired;
276 MACH_PORT_FACE root_ledger_paged;
277 */
278 static char here[] = "main";
279 int need_dp_init = 1;
280
281
282
283 /*
284 default_pager_host_port = ipc_port_make_send(realhost.host_priv_self);
285 master_device_port = ipc_port_make_send(master_device_port);
286 root_ledger_wired = ipc_port_make_send(root_wired_ledger_port);
287 root_ledger_paged = ipc_port_make_send(root_paged_ledger_port);
288 */
289 security_port = ipc_port_make_send(realhost.host_security_self);
290
291
292 #if NORMA_VM
293 norma_mk = 1;
294 #else
295 norma_mk = 0;
296 #endif
297
298
299 /* setup read buffers, etc */
300 default_pager_initialize();
301 default_pager();
302 }
303
304 /*
305 * Return TRUE if string 2 is a prefix of string 1.
306 */
307 boolean_t
308 strprefix(register const char *s1, register const char *s2)
309 {
310 register int c;
311
312 while ((c = *s2++) != '\0') {
313 if (c != *s1++)
314 return (FALSE);
315 }
316 return (TRUE);
317 }
318
319
320 kern_return_t
321 default_pager_info(
322 memory_object_default_t pager,
323 default_pager_info_t *infop)
324 {
325 vm_size_t pages_total, pages_free;
326
327 if (pager != default_pager_object)
328 return KERN_INVALID_ARGUMENT;
329
330 bs_global_info(&pages_total, &pages_free);
331
332 infop->dpi_total_space = ptoa(pages_total);
333 infop->dpi_free_space = ptoa(pages_free);
334 infop->dpi_page_size = vm_page_size;
335
336 return KERN_SUCCESS;
337 }
338
339
340 void
341 default_pager_initialize()
342 {
343 kern_return_t kr;
344 static char here[] = "default_pager_initialize";
345
346
347 /*
348 * Vm variables.
349 */
350 vm_page_mask = vm_page_size - 1;
351 vm_page_shift = local_log2(vm_page_size);
352
353 /*
354 * List of all vstructs.
355 */
356 vstruct_zone = zinit(sizeof(struct vstruct),
357 10000 * sizeof(struct vstruct),
358 8192, "vstruct zone");
359 VSL_LOCK_INIT();
360 queue_init(&vstruct_list.vsl_queue);
361 vstruct_list.vsl_count = 0;
362
363 VSTATS_LOCK_INIT(&global_stats.gs_lock);
364
365 bs_initialize();
366
367 /*
368 * Exported DMM port.
369 */
370 default_pager_object = ipc_port_alloc_kernel();
371
372
373 /*
374 * Export pager interfaces.
375 */
376 #ifdef USER_PAGER
377 if ((kr = netname_check_in(name_server_port, "UserPager",
378 default_pager_self,
379 default_pager_object))
380 != KERN_SUCCESS) {
381 dprintf(("netname_check_in returned 0x%x\n", kr));
382 exit(1);
383 }
384 #else /* USER_PAGER */
385 {
386 int clsize;
387 memory_object_default_t dmm;
388
389 dmm = default_pager_object;
390 clsize = (vm_page_size << vstruct_def_clshift);
391 kr = host_default_memory_manager(host_priv_self(), &dmm, clsize);
392 if ((kr != KERN_SUCCESS) ||
393 (dmm != MEMORY_OBJECT_DEFAULT_NULL))
394 Panic("default memory manager");
395
396 }
397 #endif /* USER_PAGER */
398
399
400 }
401