2 * Copyright (c) 2001, 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28 * All Rights Reserved.
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.
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.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
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>
64 char my_name
[] = "(default pager): ";
66 #if DEFAULT_PAGER_DEBUG
68 #endif /* DEFAULT_PAGER_DEBUG */
71 * Use 16 Kbyte stacks instead of the default 64K.
72 * Use 4 Kbyte waiting stacks instead of the default 8K.
75 vm_size_t cthread_stack_size
= 16 *1024;
76 extern vm_size_t cthread_wait_stack_size
;
78 unsigned long long vm_page_mask
;
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
;
89 memory_object_default_t default_pager_object
; /* for memory_object_create. */
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. */
95 #define DEFAULT_PAGER_INTERNAL_COUNT (4)
98 /* Memory created by default_pager_object_create should mostly be resident. */
99 #define DEFAULT_PAGER_EXTERNAL_COUNT (2)
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. */
107 * Forward declarations.
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; */
124 extern int vstruct_def_clshift
;
128 * Initialize and Run the default pager
134 static char here
[] = "default_pager";
135 mach_msg_options_t server_options
;
136 default_pager_thread_t dpt
;
142 * Give me space for the thread array and zero it.
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
*));
149 /* Setup my thread structure. */
152 dpt
.dpt_internal
= FALSE
;
153 dpt
.dpt_initialized_p
= TRUE
;
157 * Now we create the threads that will actually
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
),
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
;
182 DPT_LOCK_INIT(dpt_lock
);
190 /* simple utility: only works for 2^n */
199 while ((n
& 1) == 0) {
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 */
215 unsigned int rval
= 0;
218 while ((ch
= *arg
++) && ch
>= '0' && ch
<= '9') {
229 * Check for non-disk-partition arguments of the form
231 * returning TRUE if one if found
233 boolean_t
dp_parse_argument(char *av
)
236 static char here
[] = "dp_parse_argument";
238 /* Check for '-v' flag */
240 if (av
[0] == '-' && av
[1] == 'v' && av
[2] == 0) {
246 * If we find a '=' followed by an argument in the string,
247 * check for known arguments
249 while (*rhs
&& *rhs
!= '=')
251 if (*rhs
&& *++rhs
) {
253 if (strprefix(av
,"cl")) {
254 if (!bs_set_default_clsize(d_to_i(rhs
)))
255 dprintf(("Bad argument (%s) - ignored\n", av
));
258 /* else if strprefix(av,"another_argument")) {
259 handle_another_argument(av);
267 start_def_pager(char *bs_device
)
271 MACH_PORT_FACE master_device_port;
273 MACH_PORT_FACE security_port
;
275 MACH_PORT_FACE root_ledger_wired;
276 MACH_PORT_FACE root_ledger_paged;
278 static char here
[] = "main";
279 int need_dp_init
= 1;
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);
289 security_port
= ipc_port_make_send(realhost
.host_security_self
);
299 /* setup read buffers, etc */
300 default_pager_initialize();
305 * Return TRUE if string 2 is a prefix of string 1.
308 strprefix(register const char *s1
, register const char *s2
)
312 while ((c
= *s2
++) != '\0') {
322 memory_object_default_t pager
,
323 default_pager_info_t
*infop
)
325 vm_size_t pages_total
, pages_free
;
327 if (pager
!= default_pager_object
)
328 return KERN_INVALID_ARGUMENT
;
330 bs_global_info(&pages_total
, &pages_free
);
332 infop
->dpi_total_space
= ptoa(pages_total
);
333 infop
->dpi_free_space
= ptoa(pages_free
);
334 infop
->dpi_page_size
= vm_page_size
;
341 default_pager_initialize()
344 static char here
[] = "default_pager_initialize";
350 vm_page_mask
= vm_page_size
- 1;
351 vm_page_shift
= local_log2(vm_page_size
);
354 * List of all vstructs.
356 vstruct_zone
= zinit(sizeof(struct vstruct
),
357 10000 * sizeof(struct vstruct
),
358 8192, "vstruct zone");
360 queue_init(&vstruct_list
.vsl_queue
);
361 vstruct_list
.vsl_count
= 0;
363 VSTATS_LOCK_INIT(&global_stats
.gs_lock
);
370 default_pager_object
= ipc_port_alloc_kernel();
374 * Export pager interfaces.
377 if ((kr
= netname_check_in(name_server_port
, "UserPager",
379 default_pager_object
))
381 dprintf(("netname_check_in returned 0x%x\n", kr
));
384 #else /* USER_PAGER */
387 memory_object_default_t dmm
;
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");
397 #endif /* USER_PAGER */