2  * Copyright (c) 2001, 2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved. 
   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 
  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 
  17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  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. 
  23  * @APPLE_LICENSE_HEADER_END@ 
  29  * Mach Operating System 
  30  * Copyright (c) 1991,1990,1989 Carnegie Mellon University 
  31  * All Rights Reserved. 
  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. 
  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. 
  43  * Carnegie Mellon requests users of this software to return to 
  45  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU 
  46  *  School of Computer Science 
  47  *  Carnegie Mellon University 
  48  *  Pittsburgh PA 15213-3890 
  50  * any improvements or extensions that they make and grant Carnegie Mellon 
  51  * the rights to redistribute these changes. 
  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> 
  67 char    my_name
[] = "(default pager): "; 
  69 #if     DEFAULT_PAGER_DEBUG 
  71 #endif  /* DEFAULT_PAGER_DEBUG */ 
  74  * Use 16 Kbyte stacks instead of the default 64K. 
  75  * Use 4 Kbyte waiting stacks instead of the default 8K. 
  78 vm_size_t       cthread_stack_size 
= 16 *1024; 
  79 extern vm_size_t cthread_wait_stack_size
; 
  81 unsigned long long      vm_page_mask
; 
  88 /* task_t default_pager_self; */        /* Our task port. */ 
  89 mutex_t                 dpt_lock
;       /* lock for the dpt array struct */ 
  90 default_pager_thread_t  
**dpt_array
; 
  92 memory_object_default_t default_pager_object
; /* for memory_object_create. */ 
  94 MACH_PORT_FACE default_pager_default_set
; /* Port set for "default" thread. */ 
  95 MACH_PORT_FACE default_pager_internal_set
; /* Port set for internal objects. */ 
  96 MACH_PORT_FACE default_pager_external_set
; /* Port set for external objects. */ 
  98 #define DEFAULT_PAGER_INTERNAL_COUNT    (4) 
 101 /* Memory created by default_pager_object_create should mostly be resident. */ 
 102 #define DEFAULT_PAGER_EXTERNAL_COUNT    (2) 
 104 unsigned int    default_pager_internal_count 
= DEFAULT_PAGER_INTERNAL_COUNT
; 
 105 /* Number of "internal" threads. */ 
 106 unsigned int    default_pager_external_count 
= DEFAULT_PAGER_EXTERNAL_COUNT
; 
 107 /* Number of "external" threads. */ 
 110  * Forward declarations. 
 112 boolean_t 
default_pager_notify_server(mach_msg_header_t 
*, 
 113                                       mach_msg_header_t 
*); 
 114 boolean_t 
default_pager_demux_object(mach_msg_header_t 
*, 
 115                                      mach_msg_header_t 
*); 
 116 boolean_t 
default_pager_demux_default(mach_msg_header_t 
*, 
 117                                       mach_msg_header_t 
*); 
 118 default_pager_thread_t 
*start_default_pager_thread(int, boolean_t
); 
 119 void    default_pager(void); 
 120 void    default_pager_thread(void *); 
 121 void    default_pager_initialize(void); 
 122 void    default_pager_set_policy(MACH_PORT_FACE
); 
 123 boolean_t       
dp_parse_argument(char *);      /* forward; */ 
 124 unsigned int    d_to_i(char *);                 /* forward; */ 
 127 extern int vstruct_def_clshift
; 
 131  * Initialize and Run the default pager 
 137         static char             here
[] = "default_pager"; 
 138         mach_msg_options_t      server_options
; 
 139         default_pager_thread_t  dpt
; 
 145          * Give me space for the thread array and zero it. 
 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 
*)); 
 152         /* Setup my thread structure.  */ 
 155         dpt
.dpt_internal 
= FALSE
; 
 156         dpt
.dpt_initialized_p 
= TRUE
; 
 160          * Now we create the threads that will actually 
 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
),  
 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
; 
 185         DPT_LOCK_INIT(dpt_lock
); 
 193 /* simple utility: only works for 2^n */ 
 202         while ((n 
& 1) == 0) { 
 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 */ 
 218     unsigned int rval 
= 0; 
 221     while ((ch 
= *arg
++) && ch 
>= '0' && ch 
<= '9') { 
 232  * Check for non-disk-partition arguments of the form 
 234  * returning TRUE if one if found 
 236 boolean_t 
dp_parse_argument(char *av
) 
 239         static char     here
[] = "dp_parse_argument"; 
 241         /* Check for '-v' flag */ 
 243         if (av
[0] == '-' && av
[1] == 'v' && av
[2] == 0) { 
 249          * If we find a '=' followed by an argument in the string, 
 250          * check for known arguments 
 252         while (*rhs 
&& *rhs 
!= '=') 
 254         if (*rhs 
&& *++rhs
) { 
 256                 if (strprefix(av
,"cl")) { 
 257                         if (!bs_set_default_clsize(d_to_i(rhs
))) 
 258                                 dprintf(("Bad argument (%s) - ignored\n", av
)); 
 261                 /* else if strprefix(av,"another_argument")) { 
 262                         handle_another_argument(av); 
 270 start_def_pager(char *bs_device
) 
 274         MACH_PORT_FACE          master_device_port; 
 276         MACH_PORT_FACE          security_port
; 
 278         MACH_PORT_FACE          root_ledger_wired; 
 279         MACH_PORT_FACE          root_ledger_paged; 
 281         static char             here
[] = "main"; 
 282         int                     need_dp_init 
= 1; 
 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); 
 292         security_port 
= ipc_port_make_send(realhost
.host_security_self
); 
 302         /* setup read buffers, etc */ 
 303         default_pager_initialize(); 
 308  * Return TRUE if string 2 is a prefix of string 1. 
 311 strprefix(register const char *s1
, register const char *s2
) 
 315         while ((c 
= *s2
++) != '\0') { 
 325         memory_object_default_t pager
, 
 326         default_pager_info_t    
*infop
) 
 328         vm_size_t       pages_total
, pages_free
; 
 330         if (pager 
!= default_pager_object
) 
 331                 return KERN_INVALID_ARGUMENT
;  
 333         bs_global_info(&pages_total
, &pages_free
); 
 335         infop
->dpi_total_space 
= ptoa_32(pages_total
); 
 336         infop
->dpi_free_space 
= ptoa_32(pages_free
); 
 337         infop
->dpi_page_size 
= vm_page_size
; 
 344 default_pager_initialize() 
 347         static char             here
[] = "default_pager_initialize"; 
 353         vm_page_mask 
= vm_page_size 
- 1; 
 354         vm_page_shift 
= local_log2(vm_page_size
); 
 357          * List of all vstructs. 
 359         vstruct_zone 
= zinit(sizeof(struct vstruct
), 
 360                              10000 * sizeof(struct vstruct
), 
 361                              8192, "vstruct zone"); 
 363         queue_init(&vstruct_list
.vsl_queue
); 
 364         vstruct_list
.vsl_count 
= 0; 
 366         VSTATS_LOCK_INIT(&global_stats
.gs_lock
); 
 373         default_pager_object 
= ipc_port_alloc_kernel(); 
 377          * Export pager interfaces. 
 380         if ((kr 
= netname_check_in(name_server_port
, "UserPager", 
 382                                    default_pager_object
)) 
 384                 dprintf(("netname_check_in returned 0x%x\n", kr
)); 
 387 #else   /* USER_PAGER */ 
 390                 memory_object_default_t dmm
; 
 392                 dmm 
= default_pager_object
; 
 393                 clsize 
= (vm_page_size 
<< vstruct_def_clshift
); 
 394                 kr 
= host_default_memory_manager(host_priv_self(), &dmm
, clsize
); 
 395                 if ((kr 
!= KERN_SUCCESS
) || 
 396                     (dmm 
!= MEMORY_OBJECT_DEFAULT_NULL
)) 
 397                         Panic("default memory manager"); 
 400 #endif  /* USER_PAGER */