2 * Copyright (c) 2000-2010 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
63 #include "default_pager_internal.h"
64 #include <default_pager/default_pager_object_server.h>
65 #include <kern/host.h>
66 #include <mach/host_info.h>
67 #include <mach/host_priv.h>
68 #include <mach/vm_map.h>
69 #include <ipc/ipc_space.h>
70 #include <vm/vm_kern.h>
71 #include <vm/vm_map.h>
72 #include <vm/vm_protos.h>
73 #include <vm/vm_pageout.h>
75 char my_name
[] = "(default pager): ";
77 #if DEFAULT_PAGER_DEBUG
79 #endif /* DEFAULT_PAGER_DEBUG */
82 * Use 16 Kbyte stacks instead of the default 64K.
83 * Use 4 Kbyte waiting stacks instead of the default 8K.
86 vm_size_t cthread_stack_size
= 16 *1024;
87 extern vm_size_t cthread_wait_stack_size
;
90 unsigned long long vm_page_mask
;
96 /* task_t default_pager_self; */ /* Our task port. */
97 lck_mtx_t dpt_lock
; /* lock for the dpt array struct */
98 default_pager_thread_t
**dpt_array
;
100 memory_object_default_t default_pager_object
; /* for memory_object_create. */
102 MACH_PORT_FACE default_pager_default_set
; /* Port set for "default" thread. */
103 MACH_PORT_FACE default_pager_internal_set
; /* Port set for internal objects. */
104 MACH_PORT_FACE default_pager_external_set
; /* Port set for external objects. */
106 #define DEFAULT_PAGER_INTERNAL_COUNT (4)
109 /* Memory created by default_pager_object_create should mostly be resident. */
110 #define DEFAULT_PAGER_EXTERNAL_COUNT (2)
112 int default_pager_internal_count
= DEFAULT_PAGER_INTERNAL_COUNT
;
113 /* Number of "internal" threads. */
114 int default_pager_external_count
= DEFAULT_PAGER_EXTERNAL_COUNT
;
115 /* Number of "external" threads. */
118 * Forward declarations.
120 boolean_t
default_pager_notify_server(mach_msg_header_t
*,
121 mach_msg_header_t
*);
122 boolean_t
default_pager_demux_object(mach_msg_header_t
*,
123 mach_msg_header_t
*);
124 boolean_t
default_pager_demux_default(mach_msg_header_t
*,
125 mach_msg_header_t
*);
126 default_pager_thread_t
*start_default_pager_thread(int, boolean_t
);
127 void default_pager(void);
128 void default_pager_thread(void *);
129 void default_pager_initialize(void);
130 boolean_t
dp_parse_argument(char *); /* forward; */
131 unsigned int d_to_i(char *); /* forward; */
133 extern int vstruct_def_clshift
;
135 struct global_stats global_stats
;
138 * Initialize and Run the default pager
144 __unused
static char here
[] = "default_pager";
145 default_pager_thread_t dpt
;
151 * Give me space for the thread array and zero it.
153 i
= default_pager_internal_count
+ default_pager_external_count
+ 1;
154 dpt_array
= (default_pager_thread_t
**)
155 kalloc(i
* sizeof(default_pager_thread_t
*));
156 memset(dpt_array
, 0, i
* sizeof(default_pager_thread_t
*));
158 /* Setup my thread structure. */
161 dpt
.dpt_internal
= FALSE
;
162 dpt
.dpt_initialized_p
= TRUE
;
166 * Now we create the threads that will actually
170 for (i
= 0; i
< default_pager_internal_count
; i
++) {
171 dpt_array
[id
] = (default_pager_thread_t
*)
172 kalloc(sizeof (default_pager_thread_t
));
173 if (dpt_array
[id
] == NULL
)
174 Panic("alloc pager thread");
175 kr
= vm_allocate(kernel_map
, &((dpt_array
[id
])->dpt_buffer
),
176 vm_page_size
<< vstruct_def_clshift
, VM_FLAGS_ANYWHERE
| VM_MAKE_TAG(VM_KERN_MEMORY_OSFMK
));
177 if (kr
!= KERN_SUCCESS
)
178 Panic("alloc thread buffer");
179 kr
= vm_map_wire(kernel_map
, (dpt_array
[id
])->dpt_buffer
,
180 ((dpt_array
[id
])->dpt_buffer
)
181 +(vm_page_size
<< vstruct_def_clshift
),
182 VM_PROT_DEFAULT
| VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_OSFMK
),
184 if (kr
!= KERN_SUCCESS
)
185 Panic("wire thread buffer");
186 (dpt_array
[id
])->dpt_internal
= TRUE
;
187 (dpt_array
[id
])->dpt_initialized_p
= TRUE
;
188 (dpt_array
[id
])->checked_out
= FALSE
;
191 DPT_LOCK_INIT(dpt_lock
);
199 /* simple utility: only works for 2^n */
208 while ((n
& 1) == 0) {
218 /* another simple utility, d_to_i(char*) supporting only decimal
219 * and devoid of range checking; obscure name chosen deliberately
220 * to avoid confusion with semantic-rich POSIX routines */
224 unsigned int rval
= 0;
227 while ((ch
= *arg
++) && ch
>= '0' && ch
<= '9') {
238 * Check for non-disk-partition arguments of the form
240 * returning TRUE if one if found
242 boolean_t
dp_parse_argument(char *av
)
245 __unused
static char here
[] = "dp_parse_argument";
247 /* Check for '-v' flag */
249 if (av
[0] == '-' && av
[1] == 'v' && av
[2] == 0) {
255 * If we find a '=' followed by an argument in the string,
256 * check for known arguments
258 while (*rhs
&& *rhs
!= '=')
260 if (*rhs
&& *++rhs
) {
262 if (strprefix(av
,"cl")) {
263 if (!bs_set_default_clsize(d_to_i(rhs
)))
264 dprintf(("Bad argument (%s) - ignored\n", av
));
267 /* else if strprefix(av,"another_argument")) {
268 handle_another_argument(av);
276 start_def_pager( __unused
char *bs_device
)
279 MACH_PORT_FACE master_device_port;
282 MACH_PORT_FACE security_port;
284 __unused
static char here
[] = "main";
289 /* setup read buffers, etc */
290 default_pager_initialize();
296 if (DEFAULT_PAGER_IS_ACTIVE
) {
297 /* start the backing store monitor, it runs on a callout thread */
298 default_pager_backing_store_monitor_callout
=
299 thread_call_allocate(default_pager_backing_store_monitor
, NULL
);
300 if (!default_pager_backing_store_monitor_callout
)
301 panic("can't start backing store monitor thread");
302 thread_call_enter(default_pager_backing_store_monitor_callout
);
310 memory_object_default_t pager
,
311 default_pager_info_t
*infop
)
313 uint64_t pages_total
, pages_free
;
315 if (pager
!= default_pager_object
)
316 return KERN_INVALID_ARGUMENT
;
318 bs_global_info(&pages_total
, &pages_free
);
320 infop
->dpi_total_space
= (vm_size_t
) ptoa_64(pages_total
);
321 infop
->dpi_free_space
= (vm_size_t
) ptoa_64(pages_free
);
322 infop
->dpi_page_size
= vm_page_size
;
329 default_pager_info_64(
330 memory_object_default_t pager
,
331 default_pager_info_64_t
*infop
)
333 uint64_t pages_total
, pages_free
;
335 if (pager
!= default_pager_object
)
336 return KERN_INVALID_ARGUMENT
;
338 bs_global_info(&pages_total
, &pages_free
);
340 infop
->dpi_total_space
= ptoa_64(pages_total
);
341 infop
->dpi_free_space
= ptoa_64(pages_free
);
342 infop
->dpi_page_size
= vm_page_size
;
343 infop
->dpi_flags
= 0;
344 if (dp_encryption_inited
&& dp_encryption
== TRUE
) {
345 infop
->dpi_flags
|= DPI_ENCRYPTED
;
351 lck_grp_t default_pager_lck_grp
;
352 lck_grp_attr_t default_pager_lck_grp_attr
;
353 lck_attr_t default_pager_lck_attr
;
358 default_pager_initialize(void)
361 __unused
static char here
[] = "default_pager_initialize";
363 lck_grp_attr_setdefault(&default_pager_lck_grp_attr
);
364 lck_grp_init(&default_pager_lck_grp
, "default_pager", &default_pager_lck_grp_attr
);
365 lck_attr_setdefault(&default_pager_lck_attr
);
371 vm_page_mask
= vm_page_size
- 1;
372 assert((unsigned int) vm_page_size
== vm_page_size
);
373 vm_page_shift
= local_log2((unsigned int) vm_page_size
);
377 * List of all vstructs.
379 vstruct_zone
= zinit(sizeof(struct vstruct
),
380 10000 * sizeof(struct vstruct
),
381 8192, "vstruct zone");
382 zone_change(vstruct_zone
, Z_CALLERACCT
, FALSE
);
383 zone_change(vstruct_zone
, Z_NOENCRYPT
, TRUE
);
386 queue_init(&vstruct_list
.vsl_queue
);
387 vstruct_list
.vsl_count
= 0;
389 VSTATS_LOCK_INIT(&global_stats
.gs_lock
);
396 default_pager_object
= ipc_port_alloc_kernel();
400 * Export pager interfaces.
403 if ((kr
= netname_check_in(name_server_port
, "UserPager",
405 default_pager_object
))
407 dprintf(("netname_check_in returned 0x%x\n", kr
));
410 #else /* USER_PAGER */
413 memory_object_default_t dmm
;
415 dmm
= default_pager_object
;
416 assert((unsigned int) vm_page_size
== vm_page_size
);
417 clsize
= ((unsigned int) vm_page_size
<< vstruct_def_clshift
);
418 kr
= host_default_memory_manager(host_priv_self(), &dmm
, clsize
);
419 if ((kr
!= KERN_SUCCESS
) ||
420 (dmm
!= MEMORY_OBJECT_DEFAULT_NULL
))
421 Panic("default memory manager");
424 #endif /* USER_PAGER */