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