]> git.saurik.com Git - apple/xnu.git/blame - osfmk/default_pager/default_pager.c
xnu-792.10.96.tar.gz
[apple/xnu.git] / osfmk / default_pager / default_pager.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
37839358
A
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.
1c79356b 11 *
37839358
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
37839358
A
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.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_COPYRIGHT@
24 */
1c79356b
A
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"
91447636 58#include <default_pager/default_pager_object_server.h>
1c79356b
A
59#include <kern/host.h>
60#include <kern/ledger.h>
61#include <mach/host_info.h>
91447636
A
62#include <mach/host_priv.h>
63#include <mach/vm_map.h>
1c79356b
A
64#include <ipc/ipc_space.h>
65#include <vm/vm_kern.h>
91447636
A
66#include <vm/vm_map.h>
67#include <vm/vm_protos.h>
1c79356b
A
68
69char my_name[] = "(default pager): ";
70
71#if DEFAULT_PAGER_DEBUG
72int debug_mask = 0;
73#endif /* DEFAULT_PAGER_DEBUG */
74
75/*
76 * Use 16 Kbyte stacks instead of the default 64K.
77 * Use 4 Kbyte waiting stacks instead of the default 8K.
78 */
79
80vm_size_t cthread_stack_size = 16 *1024;
81extern vm_size_t cthread_wait_stack_size;
82
83unsigned long long vm_page_mask;
84int vm_page_shift;
85
86int norma_mk;
87
88boolean_t verbose;
89
90/* task_t default_pager_self; */ /* Our task port. */
91mutex_t dpt_lock; /* lock for the dpt array struct */
92default_pager_thread_t **dpt_array;
93
0b4e3aa0
A
94memory_object_default_t default_pager_object; /* for memory_object_create. */
95
1c79356b 96MACH_PORT_FACE default_pager_default_set; /* Port set for "default" thread. */
1c79356b
A
97MACH_PORT_FACE default_pager_internal_set; /* Port set for internal objects. */
98MACH_PORT_FACE default_pager_external_set; /* Port set for external objects. */
99
100#define DEFAULT_PAGER_INTERNAL_COUNT (4)
101
102
103/* Memory created by default_pager_object_create should mostly be resident. */
104#define DEFAULT_PAGER_EXTERNAL_COUNT (2)
105
91447636 106int default_pager_internal_count = DEFAULT_PAGER_INTERNAL_COUNT;
1c79356b 107/* Number of "internal" threads. */
91447636 108int default_pager_external_count = DEFAULT_PAGER_EXTERNAL_COUNT;
1c79356b
A
109/* Number of "external" threads. */
110
111/*
112 * Forward declarations.
113 */
114boolean_t default_pager_notify_server(mach_msg_header_t *,
115 mach_msg_header_t *);
116boolean_t default_pager_demux_object(mach_msg_header_t *,
117 mach_msg_header_t *);
118boolean_t default_pager_demux_default(mach_msg_header_t *,
119 mach_msg_header_t *);
120default_pager_thread_t *start_default_pager_thread(int, boolean_t);
121void default_pager(void);
122void default_pager_thread(void *);
123void default_pager_initialize(void);
1c79356b
A
124boolean_t dp_parse_argument(char *); /* forward; */
125unsigned int d_to_i(char *); /* forward; */
91447636 126boolean_t strprefix(register const char *s1, register const char *s2);
1c79356b
A
127
128
129extern int vstruct_def_clshift;
130
131
132/*
133 * Initialize and Run the default pager
134 */
135void
136default_pager(void)
137{
138 int i, id;
91447636 139 __unused static char here[] = "default_pager";
1c79356b
A
140 default_pager_thread_t dpt;
141 kern_return_t kr;
142
143
144
145 /*
146 * Give me space for the thread array and zero it.
147 */
148 i = default_pager_internal_count + default_pager_external_count + 1;
149 dpt_array = (default_pager_thread_t **)
150 kalloc(i * sizeof(default_pager_thread_t *));
151 memset(dpt_array, 0, i * sizeof(default_pager_thread_t *));
152
153 /* Setup my thread structure. */
154 id = 0;
155 dpt.dpt_buffer = 0;
156 dpt.dpt_internal = FALSE;
157 dpt.dpt_initialized_p = TRUE;
158 dpt_array[0] = &dpt;
159
160 /*
161 * Now we create the threads that will actually
162 * manage objects.
163 */
164
165 for (i = 0; i < default_pager_internal_count; i++) {
166 dpt_array[id] = (default_pager_thread_t *)
167 kalloc(sizeof (default_pager_thread_t));
168 if (dpt_array[id] == NULL)
169 Panic("alloc pager thread");
170 kr = vm_allocate(kernel_map, &((dpt_array[id])->dpt_buffer),
91447636 171 vm_page_size << vstruct_def_clshift, VM_FLAGS_ANYWHERE);
1c79356b
A
172 if (kr != KERN_SUCCESS)
173 Panic("alloc thread buffer");
174 kr = vm_map_wire(kernel_map, (dpt_array[id])->dpt_buffer,
175 ((dpt_array[id])->dpt_buffer)
176 +(vm_page_size << vstruct_def_clshift),
177 VM_PROT_DEFAULT,
178 FALSE);
179 if (kr != KERN_SUCCESS)
180 Panic("wire thread buffer");
181 (dpt_array[id])->dpt_internal = TRUE;
182 (dpt_array[id])->dpt_initialized_p = TRUE;
183 (dpt_array[id])->checked_out = FALSE;
184 id++;
185 }
186 DPT_LOCK_INIT(dpt_lock);
187}
188
189
190
191
192
193
194/* simple utility: only works for 2^n */
195int
196local_log2(
197 unsigned int n)
198{
199 register int i = 0;
200
201 if(n == 0) return 0;
202
203 while ((n & 1) == 0) {
204 i++;
205 n >>= 1;
206 }
207 return i;
208}
209
210
211
212
213/* another simple utility, d_to_i(char*) supporting only decimal
214 * and devoid of range checking; obscure name chosen deliberately
215 * to avoid confusion with semantic-rich POSIX routines */
216unsigned int
217d_to_i(char * arg)
218{
219 unsigned int rval = 0;
220 char ch;
221
222 while ((ch = *arg++) && ch >= '0' && ch <= '9') {
223 rval *= 10;
224 rval += ch - '0';
225 }
226 return(rval);
227}
228
229
230
231
232/*
233 * Check for non-disk-partition arguments of the form
234 * attribute=argument
235 * returning TRUE if one if found
236 */
237boolean_t dp_parse_argument(char *av)
238{
239 char *rhs = av;
91447636 240 __unused static char here[] = "dp_parse_argument";
1c79356b
A
241
242 /* Check for '-v' flag */
243
244 if (av[0] == '-' && av[1] == 'v' && av[2] == 0) {
245 verbose = TRUE ;
246 return TRUE;
247 }
248
249 /*
250 * If we find a '=' followed by an argument in the string,
251 * check for known arguments
252 */
253 while (*rhs && *rhs != '=')
254 rhs++;
255 if (*rhs && *++rhs) {
256 /* clsize=N pages */
257 if (strprefix(av,"cl")) {
258 if (!bs_set_default_clsize(d_to_i(rhs)))
259 dprintf(("Bad argument (%s) - ignored\n", av));
260 return(TRUE);
261 }
262 /* else if strprefix(av,"another_argument")) {
263 handle_another_argument(av);
264 return(TRUE);
265 } */
266 }
267 return(FALSE);
268}
269
270int
91447636 271start_def_pager( __unused char *bs_device )
1c79356b 272{
1c79356b
A
273/*
274 MACH_PORT_FACE master_device_port;
275*/
1c79356b 276/*
55e303ae 277 MACH_PORT_FACE security_port;
1c79356b
A
278 MACH_PORT_FACE root_ledger_wired;
279 MACH_PORT_FACE root_ledger_paged;
280*/
91447636 281 __unused static char here[] = "main";
1c79356b
A
282
283
284
285/*
286 default_pager_host_port = ipc_port_make_send(realhost.host_priv_self);
287 master_device_port = ipc_port_make_send(master_device_port);
288 root_ledger_wired = ipc_port_make_send(root_wired_ledger_port);
289 root_ledger_paged = ipc_port_make_send(root_paged_ledger_port);
1c79356b 290 security_port = ipc_port_make_send(realhost.host_security_self);
55e303ae 291*/
1c79356b
A
292
293
294#if NORMA_VM
295 norma_mk = 1;
296#else
297 norma_mk = 0;
298#endif
299
300
301 /* setup read buffers, etc */
302 default_pager_initialize();
303 default_pager();
55e303ae
A
304
305 /* start the backing store monitor, it runs on a callout thread */
91447636
A
306 default_pager_backing_store_monitor_callout =
307 thread_call_allocate(default_pager_backing_store_monitor, NULL);
308 if (!default_pager_backing_store_monitor_callout)
309 panic("can't start backing store monitor thread");
310 thread_call_enter(default_pager_backing_store_monitor_callout);
c0fea474
A
311
312 return (0);
1c79356b
A
313}
314
315/*
316 * Return TRUE if string 2 is a prefix of string 1.
317 */
318boolean_t
319strprefix(register const char *s1, register const char *s2)
320{
321 register int c;
322
323 while ((c = *s2++) != '\0') {
324 if (c != *s1++)
325 return (FALSE);
326 }
327 return (TRUE);
328}
329
330
331kern_return_t
332default_pager_info(
0b4e3aa0 333 memory_object_default_t pager,
1c79356b
A
334 default_pager_info_t *infop)
335{
336 vm_size_t pages_total, pages_free;
337
0b4e3aa0 338 if (pager != default_pager_object)
1c79356b
A
339 return KERN_INVALID_ARGUMENT;
340
341 bs_global_info(&pages_total, &pages_free);
342
55e303ae
A
343 infop->dpi_total_space = ptoa_32(pages_total);
344 infop->dpi_free_space = ptoa_32(pages_free);
1c79356b
A
345 infop->dpi_page_size = vm_page_size;
346
347 return KERN_SUCCESS;
348}
349
350
91447636
A
351kern_return_t
352default_pager_info_64(
353 memory_object_default_t pager,
354 default_pager_info_64_t *infop)
355{
356 vm_size_t pages_total, pages_free;
357
358 if (pager != default_pager_object)
359 return KERN_INVALID_ARGUMENT;
360
361 bs_global_info(&pages_total, &pages_free);
362
363 infop->dpi_total_space = ptoa_64(pages_total);
364 infop->dpi_free_space = ptoa_64(pages_free);
365 infop->dpi_page_size = vm_page_size;
366 infop->dpi_flags = 0;
367 if (dp_encryption_inited && dp_encryption == TRUE) {
368 infop->dpi_flags |= DPI_ENCRYPTED;
369 }
370
371 return KERN_SUCCESS;
372}
373
374
1c79356b
A
375void
376default_pager_initialize()
377{
378 kern_return_t kr;
91447636 379 __unused static char here[] = "default_pager_initialize";
1c79356b
A
380
381
0b4e3aa0
A
382 /*
383 * Vm variables.
384 */
385 vm_page_mask = vm_page_size - 1;
386 vm_page_shift = local_log2(vm_page_size);
387
388 /*
389 * List of all vstructs.
390 */
391 vstruct_zone = zinit(sizeof(struct vstruct),
392 10000 * sizeof(struct vstruct),
393 8192, "vstruct zone");
394 VSL_LOCK_INIT();
395 queue_init(&vstruct_list.vsl_queue);
396 vstruct_list.vsl_count = 0;
397
398 VSTATS_LOCK_INIT(&global_stats.gs_lock);
399
400 bs_initialize();
401
1c79356b
A
402 /*
403 * Exported DMM port.
404 */
0b4e3aa0 405 default_pager_object = ipc_port_alloc_kernel();
1c79356b
A
406
407
408 /*
409 * Export pager interfaces.
410 */
411#ifdef USER_PAGER
412 if ((kr = netname_check_in(name_server_port, "UserPager",
413 default_pager_self,
0b4e3aa0 414 default_pager_object))
1c79356b
A
415 != KERN_SUCCESS) {
416 dprintf(("netname_check_in returned 0x%x\n", kr));
417 exit(1);
418 }
419#else /* USER_PAGER */
420 {
421 int clsize;
0b4e3aa0 422 memory_object_default_t dmm;
1c79356b 423
0b4e3aa0 424 dmm = default_pager_object;
1c79356b 425 clsize = (vm_page_size << vstruct_def_clshift);
0b4e3aa0
A
426 kr = host_default_memory_manager(host_priv_self(), &dmm, clsize);
427 if ((kr != KERN_SUCCESS) ||
428 (dmm != MEMORY_OBJECT_DEFAULT_NULL))
1c79356b
A
429 Panic("default memory manager");
430
431 }
432#endif /* USER_PAGER */
433
434
1c79356b
A
435}
436