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