Annotation of XNU/osfmk/default_pager/default_pager_internal.h, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 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  [email protected]
        !            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:  *             General definitions.
        !            54:  */
        !            55: 
        !            56: #ifndef        _DEFAULT_PAGER_INTERNAL_H_
        !            57: #define _DEFAULT_PAGER_INTERNAL_H_
        !            58: 
        !            59: #include <default_pager/diag.h>
        !            60: #include <default_pager/default_pager_types.h>
        !            61: #include <mach/mach_types.h>
        !            62: #include <ipc/ipc_port.h>
        !            63: #include <ipc/ipc_types.h>
        !            64: #include <ipc/ipc_space.h>
        !            65: #include <kern/lock.h>
        !            66: #include <kern/kalloc.h>
        !            67: #include <kern/thread.h>
        !            68: #include <vm/vm_kern.h>
        !            69: #include <device/device_types.h>
        !            70: 
        !            71: /*
        !            72:  * Default option settings.
        !            73:  */
        !            74: #ifndef        PARALLEL
        !            75: #define        PARALLEL        1
        !            76: #endif
        !            77: 
        !            78: #ifndef        CHECKSUM
        !            79: #define        CHECKSUM        0
        !            80: #endif
        !            81: 
        !            82: #define MACH_PORT_FACE mach_port_t
        !            83: 
        !            84: #ifndef        USE_PRECIOUS
        !            85: #define        USE_PRECIOUS    TRUE
        !            86: #endif
        !            87: 
        !            88: #ifdef USER_PAGER
        !            89: #define UP(stuff)      stuff
        !            90: #else  /* USER_PAGER */
        !            91: #define UP(stuff)
        !            92: #endif /* USER_PAGER */
        !            93: 
        !            94: extern int norma_mk;           /* is the kernel configured with NORMA ? */
        !            95: 
        !            96: #ifndef MACH_KERNEL
        !            97: extern struct mutex dprintf_lock;
        !            98: #define PRINTF_LOCK_INIT()     mutex_init(&dprintf_lock)
        !            99: #define PRINTF_LOCK()          mutex_lock(&dprintf_lock)
        !           100: #define PRINTF_UNLOCK()                mutex_unlock(&dprintf_lock)
        !           101: #endif
        !           102: 
        !           103: #ifndef MACH_KERNEL
        !           104: #define dprintf(args)                                                  \
        !           105:        do {                                                            \
        !           106:                PRINTF_LOCK();                                          \
        !           107:                printf("%s[%d]%s: ", my_name, dp_thread_id(), here);    \
        !           108:                printf args;                                            \
        !           109:                PRINTF_UNLOCK();                                        \
        !           110:        } while (0)
        !           111: #else
        !           112: #define dprintf(args)                                          \
        !           113:        do {                                                    \
        !           114:                printf("%s[KERNEL:]%s: ", my_name, here);               \
        !           115:                printf args;                                    \
        !           116:        } while (0)
        !           117: #endif
        !           118: 
        !           119: /*
        !           120:  * Debug.
        !           121:  */
        !           122: extern char    my_name[];
        !           123: 
        !           124: #define DEFAULT_PAGER_DEBUG    0
        !           125: 
        !           126: #if    DEFAULT_PAGER_DEBUG
        !           127: 
        !           128: extern int     debug_mask;
        !           129: #define        DEBUG_MSG_EXTERNAL      0x00000001
        !           130: #define DEBUG_MSG_INTERNAL     0x00000002
        !           131: #define DEBUG_MO_EXTERNAL      0x00000100
        !           132: #define DEBUG_MO_INTERNAL      0x00000200
        !           133: #define DEBUG_VS_EXTERNAL      0x00010000
        !           134: #define DEBUG_VS_INTERNAL      0x00020000
        !           135: #define DEBUG_BS_EXTERNAL      0x01000000
        !           136: #define DEBUG_BS_INTERNAL      0x02000000
        !           137: 
        !           138: #define DEBUG(level, args)                                             \
        !           139:        do {                                                            \
        !           140:                if (debug_mask & (level))                               \
        !           141:                        dprintf(args);                                  \
        !           142:        } while (0)
        !           143: 
        !           144: #define ASSERT(expr)                                                   \
        !           145:        do {                                                            \
        !           146:                if (!(expr))                                            \
        !           147: #ifndef MACH_KERNEL
        !           148:                        panic("%s[%d]%s: assertion failed in %s line %d: %s",\
        !           149:                              my_name, dp_thread_id(), here,            \
        !           150:                              __FILE__, __LINE__, # expr);              \
        !           151: #else
        !           152:                  panic("%s[KERNEL]%s: assertion failed in %s line %d: %s",\
        !           153:                              my_name, here, __FILE__, __LINE__, # expr); \
        !           154: #endif
        !           155:        } while (0)
        !           156: 
        !           157: #else  /* DEFAULT_PAGER_DEBUG */
        !           158: 
        !           159: #define DEBUG(level, args)     here[0] = here[0]
        !           160: #define ASSERT(clause)         here[0] = here[0]
        !           161: 
        !           162: #endif /* DEFAULT_PAGER_DEBUG */
        !           163: 
        !           164: #ifndef MACH_KERNEL
        !           165: extern char *mach_error_string(kern_return_t);
        !           166: #endif
        !           167: 
        !           168: #define MIN(a,b)       (((a) < (b)) ? (a) : (b))
        !           169: 
        !           170: #define        PAGER_SUCCESS   0
        !           171: #define        PAGER_FULL      1
        !           172: #define        PAGER_ERROR     2
        !           173: 
        !           174: /*
        !           175:  * VM and IPC globals.
        !           176:  */
        !           177: #ifdef MACH_KERNEL
        !           178: #define vm_page_size page_size
        !           179: extern vm_size_t       page_size;
        !           180: #else
        !           181: extern vm_size_t       vm_page_size;
        !           182: #endif
        !           183: extern int             vm_page_mask;
        !           184: extern int             vm_page_shift;
        !           185: 
        !           186: #ifndef MACH_KERNEL
        !           187: #define        ptoa(p) ((p)*vm_page_size)
        !           188: #define        atop(a) ((a)/vm_page_size)
        !           189: #endif
        !           190: #define        howmany(a,b)    (((a) + (b) - 1)/(b))
        !           191: 
        !           192: #ifdef MACH_KERNEL
        !           193: extern mutex_t         dpt_lock;       /* Lock for the dpt array */
        !           194: extern unsigned int    default_pager_internal_count;
        !           195: extern MACH_PORT_FACE  default_pager_host_port;
        !           196: /* extern task_t               default_pager_self; */  /* dont need or want */
        !           197: extern MACH_PORT_FACE  default_pager_internal_set;
        !           198: extern MACH_PORT_FACE  default_pager_external_set;
        !           199: extern MACH_PORT_FACE  default_pager_default_port;
        !           200: extern MACH_PORT_FACE  default_pager_default_set;
        !           201: #else
        !           202: extern mach_port_t     default_pager_host_port;
        !           203: extern task_port_t     default_pager_self;
        !           204: extern mach_port_t     default_pager_internal_set;
        !           205: extern mach_port_t     default_pager_external_set;
        !           206: extern mach_port_t     default_pager_default_port;
        !           207: extern mach_port_t     default_pager_default_set;
        !           208: #endif
        !           209: 
        !           210: typedef struct default_pager_thread {
        !           211: #ifndef MACH_KERNEL
        !           212:        cthread_t       dpt_thread;     /* Server thread. */
        !           213: #endif
        !           214:        vm_offset_t     dpt_buffer;     /* Read buffer. */
        !           215:        boolean_t       dpt_internal;   /* Do we handle internal objects? */
        !           216: #ifndef MACH_KERNEL
        !           217:        int             dpt_id;         /* thread id for printf */
        !           218: #else
        !           219:        int             checked_out;    
        !           220: #endif
        !           221:        boolean_t       dpt_initialized_p; /* Thread is ready for requests.  */
        !           222: } default_pager_thread_t;
        !           223: 
        !           224: #ifdef MACH_KERNEL
        !           225: extern default_pager_thread_t  **dpt_array;
        !           226: #endif
        !           227: 
        !           228: /*
        !           229:  * Global statistics.
        !           230:  */
        !           231: struct {
        !           232:        unsigned int    gs_pageout_calls;       /* # pageout calls */
        !           233:        unsigned int    gs_pagein_calls;        /* # pagein calls */
        !           234:        unsigned int    gs_pages_in;            /* # pages paged in (total) */
        !           235:        unsigned int    gs_pages_out;           /* # pages paged out (total) */
        !           236:        unsigned int    gs_pages_unavail;       /* # zero-fill pages */
        !           237:        unsigned int    gs_pages_init;          /* # page init requests */
        !           238:        unsigned int    gs_pages_init_writes;   /* # page init writes */
        !           239:        VSTATS_LOCK_DECL(gs_lock)
        !           240: } global_stats;
        !           241: #define GSTAT(clause)  VSTATS_ACTION(&global_stats.gs_lock, (clause))
        !           242: 
        !           243: /*
        !           244:  * Cluster related definitions.
        !           245:  * Clusters are sized in number of pages per cluster.
        !           246:  * Cluster sizes must be powers of two.
        !           247:  *
        !           248:  * These numbers are related to the struct vs_map,
        !           249:  * defined below.
        !           250:  */
        !           251: #define MAX_CLUSTER_SIZE 8
        !           252: #define MAX_CLUSTER_SHIFT 3
        !           253: #define NO_CLSIZE 0
        !           254: 
        !           255: /*
        !           256:  * bit map related macros
        !           257:  */
        !           258: #define        NBBY            8       /* bits per byte XXX */
        !           259: #define BYTEMASK       0xff
        !           260: #define setbit(a,i)    (*(((char *)(a)) + ((i)/NBBY)) |= 1<<((i)%NBBY))
        !           261: #define clrbit(a,i)    (*(((char *)(a)) + ((i)/NBBY)) &= ~(1<<((i)%NBBY)))
        !           262: #define isset(a,i)     (*(((char *)(a)) + ((i)/NBBY)) & (1<<((i)%NBBY)))
        !           263: #define isclr(a,i)     ((*(((char *)(a)) + ((i)/NBBY)) & (1<<((i)%NBBY))) == 0)
        !           264: 
        !           265: /*
        !           266:  *     Default Pager.
        !           267:  *             Backing Store Management.
        !           268:  */
        !           269: 
        !           270: #define BS_MAXPRI      4
        !           271: #define BS_MINPRI      0
        !           272: #define BS_NOPRI       -1
        !           273: #define BS_FULLPRI     -2
        !           274: 
        !           275: /*
        !           276:  * Mapping between backing store port and backing store object.
        !           277:  */
        !           278: struct backing_store {
        !           279:        queue_chain_t   bs_links;       /* link in backing_store_list */
        !           280: #ifdef MACH_KERNEL
        !           281:        mutex_t         bs_lock;        /* lock for the structure */
        !           282: #else
        !           283:        struct mutex    bs_lock;        /* lock for the structure */
        !           284: #endif
        !           285:        MACH_PORT_FACE  bs_port;        /* backing store port */
        !           286:        int             bs_priority;
        !           287:        int             bs_clsize;      /* cluster size in pages */
        !           288: 
        !           289:        /* statistics */
        !           290:        unsigned int    bs_pages_free;          /* # unallocated pages */
        !           291:        unsigned int    bs_pages_total;         /* # pages (total) */
        !           292:        unsigned int    bs_pages_in;            /* # page read requests */
        !           293:        unsigned int    bs_pages_in_fail;       /* # page read errors */
        !           294:        unsigned int    bs_pages_out;           /* # page write requests */
        !           295:        unsigned int    bs_pages_out_fail;      /* # page write errors */
        !           296: };
        !           297: typedef struct backing_store   *backing_store_t;
        !           298: #define        BACKING_STORE_NULL      ((backing_store_t) 0)
        !           299: #define BS_STAT(bs, clause)    VSTATS_ACTION(&(bs)->bs_lock, (clause))
        !           300: 
        !           301: #ifdef MACH_KERNEL
        !           302: #define BS_LOCK_INIT(bs)       mutex_init(&(bs)->bs_lock, ETAP_DPAGE_BS)
        !           303: #else
        !           304: #define BS_LOCK_INIT(bs)       mutex_init(&(bs)->bs_lock)
        !           305: #endif
        !           306: #define BS_LOCK(bs)            mutex_lock(&(bs)->bs_lock)
        !           307: #define BS_UNLOCK(bs)          mutex_unlock(&(bs)->bs_lock)
        !           308: 
        !           309: struct backing_store_list_head {
        !           310:        queue_head_t    bsl_queue;
        !           311: #ifdef MACH_KERNEL
        !           312:        mutex_t         bsl_lock;
        !           313: #else
        !           314:        struct mutex    bsl_lock;
        !           315: #endif
        !           316: };
        !           317: extern struct backing_store_list_head  backing_store_list;
        !           318: 
        !           319: #ifdef MACH_KERNEL
        !           320: #define        BSL_LOCK_INIT() mutex_init(&backing_store_list.bsl_lock, ETAP_DPAGE_BSL)
        !           321: #else
        !           322: #define        BSL_LOCK_INIT() mutex_init(&backing_store_list.bsl_lock)
        !           323: #endif
        !           324: #define BSL_LOCK()     mutex_lock(&backing_store_list.bsl_lock)
        !           325: #define BSL_UNLOCK()   mutex_unlock(&backing_store_list.bsl_lock)
        !           326: 
        !           327: /*
        !           328:  *     Paging segment management.
        !           329:  *     Controls allocation of blocks within paging area.
        !           330:  */
        !           331: struct paging_segment {
        !           332:        /* device management */
        !           333:        union {
        !           334:                MACH_PORT_FACE  dev;            /* Port to device */
        !           335:                struct vnode    *vnode;         /* vnode for bs file */
        !           336:        } storage_type;
        !           337:        unsigned int    ps_segtype;     /* file type or partition */
        !           338:        MACH_PORT_FACE  ps_device;      /* Port to device */
        !           339:        vm_offset_t     ps_offset;      /* Offset of segment within device */
        !           340:        vm_offset_t     ps_recnum;      /* Number of device records in segment*/
        !           341:        unsigned int    ps_pgnum;       /* Number of pages in segment */
        !           342:        unsigned int    ps_record_shift;/* Bit shift: pages to device records */
        !           343: 
        !           344:        /* clusters and pages */
        !           345:        unsigned int    ps_clshift;     /* Bit shift: clusters to pages */
        !           346:        unsigned int    ps_ncls;        /* Number of clusters in segment */
        !           347:        unsigned int    ps_clcount;     /* Number of free clusters */
        !           348:        unsigned int    ps_pgcount;     /* Number of free pages */
        !           349:        long            ps_hint;        /* Hint of where to look next. */
        !           350: 
        !           351:        /* bitmap */
        !           352: #ifdef MACH_KERNEL
        !           353:        mutex_t         ps_lock;        /* Lock for contents of struct */
        !           354: #else
        !           355:        struct mutex    ps_lock;        /* Lock for contents of struct */
        !           356: #endif
        !           357:        unsigned char   *ps_bmap;       /* Map of used clusters */
        !           358:        
        !           359:        /* backing store */
        !           360:        backing_store_t ps_bs;          /* Backing store segment belongs to */
        !           361: 
        !           362:        boolean_t       ps_going_away;  /* Destroy attempt in progress */
        !           363: };
        !           364: 
        !           365: #define ps_vnode       storage_type.vnode
        !           366: #define ps_device      storage_type.dev
        !           367: #define PS_PARTITION 1
        !           368: #define PS_FILE        2
        !           369: 
        !           370: typedef struct paging_segment *paging_segment_t;
        !           371: 
        !           372: #define PAGING_SEGMENT_NULL    ((paging_segment_t) 0)
        !           373: 
        !           374: #ifdef MACH_KERNEL
        !           375: #define PS_LOCK_INIT(ps)       mutex_init(&(ps)->ps_lock, ETAP_DPAGE_SEGMENT)
        !           376: #else
        !           377: #define PS_LOCK_INIT(ps)       mutex_init(&(ps)->ps_lock)
        !           378: #endif
        !           379: #define PS_LOCK(ps)            mutex_lock(&(ps)->ps_lock)
        !           380: #define PS_UNLOCK(ps)          mutex_unlock(&(ps)->ps_lock)
        !           381: 
        !           382: typedef unsigned int   pseg_index_t;
        !           383: 
        !           384: #define        INVALID_PSEG_INDEX      ((pseg_index_t)-1)
        !           385: #define NULL_PSEG_INDEX                ((pseg_index_t) 0)
        !           386: /*
        !           387:  * MAX_PSEG_INDEX value is related to struct vs_map below.
        !           388:  * "0" is reserved for empty map entries (no segment).
        !           389:  */
        !           390: #define MAX_PSEG_INDEX 31      /* 0 is reserved for empty map */
        !           391: #define MAX_NUM_PAGING_SEGMENTS MAX_PSEG_INDEX
        !           392: 
        !           393: /* paging segments array */
        !           394: extern paging_segment_t        paging_segments[MAX_NUM_PAGING_SEGMENTS];
        !           395: #ifdef MACH_KERNEL
        !           396: extern mutex_t paging_segments_lock;
        !           397: #else
        !           398: extern struct mutex paging_segments_lock;
        !           399: #endif
        !           400: extern int     paging_segment_count;   /* number of active paging segments */
        !           401: extern int     paging_segment_max;     /* highest used paging segment index */
        !           402: extern int ps_select_array[DEFAULT_PAGER_BACKING_STORE_MAXPRI+1];
        !           403: 
        !           404: #ifdef MACH_KERNEL
        !           405: #define        PSL_LOCK_INIT() mutex_init(&paging_segments_lock, ETAP_DPAGE_SEGLIST)
        !           406: #else
        !           407: #define        PSL_LOCK_INIT() mutex_init(&paging_segments_lock)
        !           408: #endif
        !           409: #define PSL_LOCK()     mutex_lock(&paging_segments_lock)
        !           410: #define PSL_UNLOCK()   mutex_unlock(&paging_segments_lock)
        !           411: 
        !           412: /*
        !           413:  * Vstruct manipulation.  The vstruct is the pager's internal
        !           414:  * representation of vm objects it manages.  There is one vstruct allocated
        !           415:  * per vm object.
        !           416:  *
        !           417:  * The following data structures are defined for vstruct and vm object
        !           418:  * management.
        !           419:  */
        !           420: 
        !           421: /*
        !           422:  * vs_map
        !           423:  * A structure used only for temporary objects.  It is the element
        !           424:  * contained in the vs_clmap structure, which contains information
        !           425:  * about which clusters and pages in an object are present on backing
        !           426:  * store (a paging file).
        !           427:  * Note that this structure and its associated constants may change
        !           428:  * with minimal impact on code.  The only function which knows the
        !           429:  * internals of this structure is ps_clmap().
        !           430:  *
        !           431:  * If it is necessary to change the maximum number of paging segments
        !           432:  * or pages in a cluster, then this structure is the one most
        !           433:  * affected.   The constants and structures which *may* change are:
        !           434:  *     MAX_CLUSTER_SIZE
        !           435:  *     MAX_CLUSTER_SHIFT
        !           436:  *     MAX_NUM_PAGING_SEGMENTS
        !           437:  *     VSTRUCT_DEF_CLSHIFT
        !           438:  *     struct vs_map and associated macros and constants (VSM_*)
        !           439:  *       (only the macro definitions need change, the exported (inside the
        !           440:  *        pager only) interfaces remain the same; the constants are for
        !           441:  *        internal vs_map manipulation only).
        !           442:  *     struct clbmap (below).
        !           443:  */
        !           444: struct vs_map {
        !           445:        unsigned int    vsmap_entry:23,         /* offset in paging segment */
        !           446:                        vsmap_psindex:8,        /* paging segment */
        !           447:                        vsmap_error:1,
        !           448:                        vsmap_bmap:16,
        !           449:                        vsmap_alloc:16;
        !           450: };
        !           451: 
        !           452: typedef struct vs_map *vs_map_t;
        !           453: 
        !           454: 
        !           455: #define        VSM_ENTRY_NULL  0x7fffff
        !           456: 
        !           457: /*
        !           458:  * Exported macros for manipulating the vs_map structure --
        !           459:  * checking status, getting and setting bits.
        !           460:  */
        !           461: #define        VSCLSIZE(vs)            (1 << (vs)->vs_clshift)
        !           462: #define        VSM_ISCLR(vsm)          (((vsm).vsmap_entry == VSM_ENTRY_NULL) &&   \
        !           463:                                        ((vsm).vsmap_error == 0))
        !           464: #define        VSM_ISERR(vsm)          ((vsm).vsmap_error)
        !           465: #define        VSM_SETCLOFF(vsm, val)  ((vsm).vsmap_entry = (val))
        !           466: #define        VSM_SETERR(vsm, err)    ((vsm).vsmap_error = 1,   \
        !           467:                                        (vsm).vsmap_entry = (err))
        !           468: #define        VSM_GETERR(vsm)         ((vsm).vsmap_entry)
        !           469: #define        VSM_SETPG(vsm, page)    ((vsm).vsmap_bmap |= (1 << (page)))
        !           470: #define        VSM_CLRPG(vsm, page)    ((vsm).vsmap_bmap &= ~(1 << (page)))
        !           471: #define        VSM_SETPS(vsm, psindx)  ((vsm).vsmap_psindex = (psindx))
        !           472: #define        VSM_PSINDEX(vsm)        ((vsm).vsmap_psindex)
        !           473: #define        VSM_PS(vsm)             paging_segments[(vsm).vsmap_psindex]
        !           474: #define        VSM_BMAP(vsm)           ((vsm).vsmap_bmap)
        !           475: #define        VSM_CLOFF(vsm)          ((vsm).vsmap_entry)
        !           476: #define        VSM_CLR(vsm)            ((vsm).vsmap_entry = VSM_ENTRY_NULL,   \
        !           477:                                        (vsm).vsmap_psindex = 0,   \
        !           478:                                        (vsm).vsmap_error = 0,     \
        !           479:                                        (vsm).vsmap_bmap = 0,      \
        !           480:                                        (vsm).vsmap_alloc = 0)
        !           481: #define        VSM_ALLOC(vsm)          ((vsm).vsmap_alloc)
        !           482: #define        VSM_SETALLOC(vsm, page) ((vsm).vsmap_alloc |= (1 << (page)))
        !           483: #define        VSM_CLRALLOC(vsm, page) ((vsm).vsmap_alloc &= ~(1 << (page)))
        !           484: 
        !           485: /*
        !           486:  * Constants and macros for dealing with vstruct maps,
        !           487:  * which comprise vs_map structures, which
        !           488:  * map vm objects to backing storage (paging files and clusters).
        !           489:  */
        !           490: #define CLMAP_THRESHOLD        512     /* bytes */
        !           491: #define        CLMAP_ENTRIES           (CLMAP_THRESHOLD/sizeof(struct vs_map))
        !           492: #define        CLMAP_SIZE(ncls)        (ncls*sizeof(struct vs_map))
        !           493: 
        !           494: #define        INDIRECT_CLMAP_ENTRIES(ncls) (((ncls-1)/CLMAP_ENTRIES) + 1)
        !           495: #define INDIRECT_CLMAP_SIZE(ncls) (INDIRECT_CLMAP_ENTRIES(ncls) * sizeof(struct vs_map *))
        !           496: #define INDIRECT_CLMAP(size)   (CLMAP_SIZE(size) > CLMAP_THRESHOLD)
        !           497: 
        !           498: #define RMAPSIZE(blocks)       (howmany(blocks,NBBY))
        !           499: 
        !           500: #define CL_FIND 1
        !           501: #define CL_ALLOC 2
        !           502: 
        !           503: /*
        !           504:  * clmap
        !           505:  *
        !           506:  * A cluster map returned by ps_clmap.  It is an abstracted cluster of
        !           507:  * pages.  It gives the caller information about the cluster
        !           508:  * desired.  On read it tells the caller if a cluster is mapped, and if so,
        !           509:  * which of its pages are valid.  It should not be referenced directly,
        !           510:  * except by  ps_clmap; macros should be used.  If the number of pages
        !           511:  * in a cluster needs to be more than 32, then the struct clbmap must
        !           512:  * become larger.
        !           513:  */
        !           514: struct clbmap {
        !           515:        unsigned int    clb_map;
        !           516: };
        !           517: 
        !           518: struct clmap {
        !           519:        paging_segment_t cl_ps;         /* paging segment backing cluster */
        !           520:        int             cl_numpages;    /* number of valid pages */
        !           521:        struct clbmap   cl_bmap;        /* map of pages in cluster */
        !           522:        int             cl_error;       /* cluster error value */
        !           523:        struct clbmap   cl_alloc;       /* map of allocated pages in cluster */
        !           524: };
        !           525: 
        !           526: #define  CLMAP_ERROR(clm)      (clm).cl_error
        !           527: #define  CLMAP_PS(clm)         (clm).cl_ps
        !           528: #define  CLMAP_NPGS(clm)       (clm).cl_numpages
        !           529: #define         CLMAP_ISSET(clm,i)     ((1<<(i))&((clm).cl_bmap.clb_map))
        !           530: #define  CLMAP_ALLOC(clm)      (clm).cl_alloc.clb_map
        !           531: /*
        !           532:  * Shift off unused bits in a partial cluster
        !           533:  */
        !           534: #define  CLMAP_SHIFT(clm,vs)   \
        !           535:        (clm)->cl_bmap.clb_map >>= (VSCLSIZE(vs) - (clm)->cl_numpages)
        !           536: #define  CLMAP_SHIFTALLOC(clm,vs)      \
        !           537:        (clm)->cl_alloc.clb_map >>= (VSCLSIZE(vs) - (clm)->cl_numpages)
        !           538: 
        !           539: typedef struct vstruct_alias {
        !           540:        vm_offset_t name;
        !           541:        struct vstruct *vs;
        !           542: } vstruct_alias_t;
        !           543: 
        !           544: /*
        !           545:  * VM Object Structure:  This is the structure used to manage pagers associated
        !           546:  * to VM objects.Mapping between pager port and paging object.
        !           547:  */
        !           548: 
        !           549: typedef struct vstruct {
        !           550:        queue_chain_t   vs_links;       /* Link in pager-port list */
        !           551: #ifdef MACH_KERNEL
        !           552:        hw_lock_data_t  vs_lock;        /* Lock for the structure */
        !           553: #else
        !           554:        struct mutex    vs_lock;        /* Lock for the structure */
        !           555: #endif
        !           556:        MACH_PORT_FACE  vs_mem_obj_port; /* Memory object port */
        !           557:        mach_port_seqno_t vs_next_seqno; /* next sequence number to issue */
        !           558:        mach_port_seqno_t vs_seqno;     /* Pager port sequence number */
        !           559:        MACH_PORT_FACE  vs_control_port;/* Memory object's control port */
        !           560:        mach_port_urefs_t vs_control_refs; /* Mem object's control port refs */
        !           561:        MACH_PORT_FACE  vs_object_name; /* Name port */
        !           562:        mach_port_urefs_t vs_name_refs; /* Name port user-refs */
        !           563: 
        !           564: #ifdef MACH_KERNEL
        !           565:        boolean_t vs_waiting_seqno;/* to wait on seqno */
        !           566:        boolean_t vs_waiting_read; /* to wait on readers */
        !           567:        boolean_t vs_waiting_write;/* to wait on writers */
        !           568:        boolean_t vs_waiting_refs; /* to wait on refs */
        !           569:        boolean_t vs_waiting_async;/* to wait on async_pending */
        !           570: #else
        !           571:        event_t vs_waiting_seqno;/* to wait on seqno */
        !           572:        event_t vs_waiting_read; /* to wait on readers */
        !           573:        event_t vs_waiting_write;/* to wait on writers */
        !           574:        event_t vs_waiting_refs; /* to wait on refs */
        !           575:        event_t vs_waiting_async;/* to wait on async_pending */
        !           576: #endif
        !           577:        unsigned int    vs_readers;     /* Reads in progress */
        !           578:        unsigned int    vs_writers;     /* Writes in progress */
        !           579: 
        !           580:        unsigned int    vs_errors;      /* Pageout error count */
        !           581: 
        !           582:        int             vs_clshift;     /* Bit shift: clusters to pages */
        !           583:        int             vs_size;        /* Object size in clusters */
        !           584:        int             vs_indirect:1,  /* Is the map indirect ? */
        !           585:                        vs_xfer_pending:1; /* xfering out of a seg ? */
        !           586:        int             vs_async_pending; /* Count of pending async writes */
        !           587: #ifdef MACH_KERNEL
        !           588:        mutex_t         vs_map_lock;    /* to protect map below */
        !           589: #else
        !           590:        struct mutex    vs_map_lock;    /* to protect map below */
        !           591: #endif
        !           592:        union {
        !           593:                struct vs_map   *vsu_dmap;      /* Direct map of clusters */
        !           594:                struct vs_map   **vsu_imap;     /* Indirect map of clusters */
        !           595:        } vs_un;
        !           596: } *vstruct_t;
        !           597: 
        !           598: #define vs_dmap vs_un.vsu_dmap
        !           599: #define vs_imap vs_un.vsu_imap
        !           600: #define MEM_OBJ_CTL(vs)        ((vs)->vs_control_port)
        !           601: 
        !           602: #define VSTRUCT_NULL   ((vstruct_t) 0)
        !           603: 
        !           604: #ifdef MACH_KERNEL
        !           605: #define DPT_LOCK_INIT(lock)    mutex_init(&(lock), ETAP_DPAGE_VSTRUCT)
        !           606: #define DPT_LOCK(lock)         mutex_lock(&(lock))
        !           607: #define DPT_UNLOCK(lock)       mutex_unlock(&(lock))
        !           608: #define VS_LOCK_INIT(vs)       hw_lock_init(&(vs)->vs_lock)
        !           609: #define VS_TRY_LOCK(vs)                (VS_LOCK(vs),TRUE)
        !           610: #define VS_LOCK(vs)            hw_lock_lock(&(vs)->vs_lock)
        !           611: #define VS_UNLOCK(vs)          hw_lock_unlock(&(vs)->vs_lock)
        !           612: #else
        !           613: #define VS_LOCK_INIT(vs)       mutex_init(&(vs)->vs_lock, ETAP_DPAGE_VSTRUCT)
        !           614: #define VS_TRY_LOCK(vs)                mutex_try_lock(&(vs)->vs_lock)
        !           615: #define VS_LOCK(vs)            mutex_lock(&(vs)->vs_lock)
        !           616: #define VS_UNLOCK(vs)          mutex_unlock(&(vs)->vs_lock)
        !           617: #endif
        !           618: 
        !           619: #ifdef MACH_KERNEL
        !           620: #define VS_MAP_LOCK_INIT(vs)   mutex_init(&(vs)->vs_map_lock, ETAP_DPAGE_VSMAP)
        !           621: #else
        !           622: #define VS_MAP_LOCK_INIT(vs)   mutex_init(&(vs)->vs_map_lock)
        !           623: #endif
        !           624: #define VS_MAP_LOCK(vs)                mutex_lock(&(vs)->vs_map_lock)
        !           625: #ifndef MACH_KERNEL
        !           626: #define VS_MAP_TRY_LOCK(vs)    mutex_try_lock(&(vs)->vs_map_lock)
        !           627: #else
        !           628: #define VS_MAP_TRY_LOCK(vs)    mutex_try(&(vs)->vs_map_lock)
        !           629: #endif
        !           630: #define VS_MAP_UNLOCK(vs)      mutex_unlock(&(vs)->vs_map_lock)
        !           631: 
        !           632: /*
        !           633:  * Data structures and variables dealing with asynchronous
        !           634:  * completion of paging operations.
        !           635:  */
        !           636: /*
        !           637:  * vs_async
        !           638:  *     A structure passed to ps_write_device for asynchronous completions.
        !           639:  *     It contains enough information to complete the write and
        !           640:  *     inform the VM of its completion.
        !           641:  */
        !           642: struct vs_async {
        !           643:        struct vs_async *vsa_next;      /* pointer to next structure */
        !           644:        vstruct_t       vsa_vs;         /* the vstruct for the object */
        !           645:        vm_offset_t     vsa_addr;       /* the vaddr of the data moved */
        !           646:        vm_offset_t     vsa_offset;     /* the object offset of the data */
        !           647:        vm_size_t       vsa_size;       /* the number of bytes moved */
        !           648:        paging_segment_t vsa_ps;        /* the paging segment used */
        !           649:        int             vsa_flags;      /* flags */
        !           650:        int             vsa_error;      /* error, if there is one */
        !           651:        mutex_t         vsa_lock;
        !           652:        MACH_PORT_FACE  reply_port;     /* associated reply port */
        !           653: };
        !           654: 
        !           655: /*
        !           656:  * flags values.
        !           657:  */
        !           658: #define VSA_READ       0x0001
        !           659: #define VSA_WRITE      0x0002
        !           660: #define VSA_TRANSFER   0x0004
        !           661: 
        !           662: /*
        !           663:  * List of all vstructs.  A specific vstruct is
        !           664:  * found directly via its port, this list is
        !           665:  * only used for monitoring purposes by the
        !           666:  * default_pager_object* calls
        !           667:  */
        !           668: struct vstruct_list_head {
        !           669:        queue_head_t    vsl_queue;
        !           670: #ifdef MACH_KERNEL
        !           671:        mutex_t         vsl_lock;
        !           672: #else
        !           673:        struct mutex    vsl_lock;
        !           674: #endif
        !           675:        int             vsl_count;      /* saves code */
        !           676:        queue_head_t    vsl_leak_queue;
        !           677: };
        !           678: extern struct vstruct_list_head        vstruct_list;
        !           679: 
        !           680: #ifdef MACH_KERNEL
        !           681: #define VSL_LOCK_INIT()        mutex_init(&vstruct_list.vsl_lock, ETAP_DPAGE_VSLIST)
        !           682: #else
        !           683: #define VSL_LOCK_INIT()        mutex_init(&vstruct_list.vsl_lock)
        !           684: #endif
        !           685: #define VSL_LOCK()     mutex_lock(&vstruct_list.vsl_lock)
        !           686: #define VSL_LOCK_TRY() mutex_try(&vstruct_list.vsl_lock)
        !           687: #define VSL_UNLOCK()   mutex_unlock(&vstruct_list.vsl_lock)
        !           688: 
        !           689: /*
        !           690:  * Create port alias for vstruct address.
        !           691:  *
        !           692:  * We assume that the last two bits of a vstruct address will be zero due to
        !           693:  * memory allocation restrictions, hence are available for use as a sanity
        !           694:  * check.
        !           695:  */
        !           696: #ifdef MACH_KERNEL
        !           697: #define ISVS 123456
        !           698: #define port_is_vs(_port_)                                             \
        !           699:        ((((struct vstruct_alias *)((_port_)->alias)) != NULL) &&       \
        !           700:                (((struct vstruct_alias *)(_port_)->alias)->name==ISVS))
        !           701: #define port_to_vs(_port_)                                             \
        !           702:        ((struct vstruct_alias *)(_port_)->alias)->vs
        !           703: #define vs_to_port(_vs_) (_vs_->vs_mem_obj_port)
        !           704: #define vs_lookup(_port_, _vs_)                                                \
        !           705:        do {                                                            \
        !           706:        if ((((struct vstruct_alias *)(_port_)->alias) == NULL) ||      \
        !           707:                (((struct vstruct_alias *)(_port_)->alias)->name!=ISVS)) \
        !           708:                panic("bad pager port");                                \
        !           709:        _vs_ = port_to_vs(_port_);                                      \
        !           710:        } while (0)
        !           711: #else
        !           712: #define        vs_to_port(_vs_)        (((vm_offset_t)(_vs_))+1)
        !           713: #define        port_to_vs(_port_)      ((vstruct_t)(((vm_offset_t)(_port_))&~3))
        !           714: #define port_is_vs(_port_)     ((((vm_offset_t)(_port_))&3) == 1)
        !           715: 
        !           716: #define vs_lookup(_port_, _vs_)                                                \
        !           717:        do {                                                            \
        !           718:                if (!MACH_PORT_VALID(_port_) || !port_is_vs(_port_)     \
        !           719:                    || port_to_vs(_port_)->vs_mem_obj_port != (_port_)) \
        !           720:                        Panic("bad pager port");                        \
        !           721:                _vs_ = port_to_vs(_port_);                              \
        !           722:        } while (0)
        !           723: #endif
        !           724: 
        !           725: /*
        !           726:  * Cross-module routines declaration.
        !           727:  */
        !           728: #ifndef MACH_KERNEL
        !           729: extern int             dp_thread_id(void);
        !           730: #endif
        !           731: extern boolean_t       device_reply_server(mach_msg_header_t *,
        !           732:                                            mach_msg_header_t *);
        !           733: #ifdef MACH_KERNEL
        !           734: extern void            default_pager_no_senders(MACH_PORT_FACE,
        !           735:                                                 mach_port_seqno_t,
        !           736:                                                 mach_port_mscount_t);
        !           737: #else
        !           738: extern void            default_pager_no_senders(memory_object_t,
        !           739:                                                 mach_port_seqno_t,
        !           740:                                                 mach_port_mscount_t);
        !           741: #endif
        !           742: extern int             local_log2(unsigned int);
        !           743: extern void            bs_initialize(void);
        !           744: extern void            bs_global_info(vm_size_t *,
        !           745:                                       vm_size_t *);
        !           746: extern boolean_t       bs_add_device(char *,
        !           747:                                      MACH_PORT_FACE);
        !           748: extern vstruct_t       ps_vstruct_create(vm_size_t);
        !           749: extern void            ps_vstruct_dealloc(vstruct_t);
        !           750: extern kern_return_t   pvs_cluster_read(vstruct_t,
        !           751:                                        vm_offset_t,
        !           752:                                        vm_size_t);
        !           753: extern kern_return_t   vs_cluster_write(vstruct_t,
        !           754:                                         vm_offset_t,
        !           755:                                         vm_offset_t,
        !           756:                                         vm_size_t,
        !           757:                                         boolean_t);
        !           758: extern vm_offset_t     ps_clmap(vstruct_t,
        !           759:                                 vm_offset_t,
        !           760:                                 struct clmap *,
        !           761:                                 int,
        !           762:                                 vm_size_t,
        !           763:                                 int);
        !           764: extern vm_size_t       ps_vstruct_allocated_size(vstruct_t);
        !           765: extern size_t          ps_vstruct_allocated_pages(vstruct_t,
        !           766:                                                   default_pager_page_t *,
        !           767:                                                   size_t);
        !           768: extern boolean_t       bs_set_default_clsize(unsigned int);
        !           769: 
        !           770: extern boolean_t       verbose;
        !           771: 
        !           772: #endif /* _DEFAULT_PAGER_INTERNAL_H_ */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.