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