Annotation of XNU/osfmk/default_pager/dp_memory_object.c, revision 1.1.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:  *             Memory Object Management.
                     54:  */
                     55: 
                     56: #include "default_pager_internal.h"
                     57: #include <mach/memory_object_server.h>
                     58: #include <vm/vm_pageout.h> /* include for upl_t */
                     59: 
                     60: 
                     61: /*
                     62:  * List of all vstructs.  A specific vstruct is
                     63:  * found directly via its port, this list is
                     64:  * only used for monitoring purposes by the
                     65:  * default_pager_object* calls and by ps_delete
                     66:  * when abstract memory objects must be scanned
                     67:  * to remove any live storage on a segment which
                     68:  * is to be removed.
                     69:  */
                     70: struct vstruct_list_head       vstruct_list;
                     71: 
                     72: void vstruct_list_insert(vstruct_t vs);        /* forward */
                     73: 
                     74: void
                     75: vstruct_list_insert(
                     76:        vstruct_t vs)
                     77: {
                     78:        VSL_LOCK();
                     79:        queue_enter(&vstruct_list.vsl_queue, vs, vstruct_t, vs_links);
                     80:        vstruct_list.vsl_count++;
                     81:        VSL_UNLOCK();
                     82: }
                     83: 
                     84: void vstruct_list_delete(vstruct_t vs);        /* forward */
                     85: 
                     86: void
                     87: vstruct_list_delete(
                     88:        vstruct_t vs)
                     89: {
                     90:        queue_remove(&vstruct_list.vsl_queue, vs, vstruct_t, vs_links);
                     91:        vstruct_list.vsl_count--;
                     92: }
                     93: 
                     94: /*
                     95:  * We use the sequence numbers on requests to regulate
                     96:  * our parallelism.  In general, we allow multiple reads and writes
                     97:  * to proceed in parallel, with the exception that reads must
                     98:  * wait for previous writes to finish.  (Because the kernel might
                     99:  * generate a data-request for a page on the heels of a data-write
                    100:  * for the same page, and we must avoid returning stale data.)
                    101:  * terminate requests wait for proceeding reads and writes to finish.
                    102:  */
                    103: 
                    104: unsigned int   default_pager_total = 0;                /* debugging */
                    105: unsigned int   default_pager_wait_seqno = 0;           /* debugging */
                    106: unsigned int   default_pager_wait_read = 0;            /* debugging */
                    107: unsigned int   default_pager_wait_write = 0;           /* debugging */
                    108: unsigned int   default_pager_wait_refs = 0;            /* debugging */
                    109: 
                    110: void vs_async_wait(vstruct_t); /* forward */
                    111: 
                    112: void
                    113: vs_async_wait(
                    114:        vstruct_t       vs)
                    115: {
                    116:        static char here[] = "vs_async_wait";
                    117: 
                    118:        ASSERT(vs->vs_async_pending >= 0);
                    119:        while (vs->vs_async_pending > 0) {
                    120:                vs->vs_waiting_async = TRUE;
                    121:                assert_wait(&vs->vs_waiting_async, THREAD_UNINT);
                    122:                VS_UNLOCK(vs);
                    123:                thread_block((void (*)(void))0);
                    124:                VS_LOCK(vs);
                    125:        }
                    126:        ASSERT(vs->vs_async_pending == 0);
                    127: }
                    128: 
                    129: #if    PARALLEL
                    130: void vs_lock(vstruct_t, mach_port_seqno_t);
                    131: void vs_unlock(vstruct_t);
                    132: void vs_start_read(vstruct_t);
                    133: void vs_wait_for_readers(vstruct_t);
                    134: void vs_finish_read(vstruct_t);
                    135: void vs_start_write(vstruct_t);
                    136: void vs_wait_for_writers(vstruct_t);
                    137: void vs_finish_write(vstruct_t);
                    138: void vs_wait_for_refs(vstruct_t);
                    139: void vs_finish_refs(vstruct_t);
                    140: 
                    141: /* 
                    142:  * Waits for correct sequence number.  Leaves pager locked.
                    143:  * JMM - Sequence numbers guarantee ordering, but in a preemptible
                    144:  *       kernel, they are generated without locks, and so their
                    145:  *       generation order is undefined (and therefore unreliable).
                    146:  *      Since we ned to fix this anyway, and I needed to get rid
                    147:  *      rid of asymmetry in the interface definitions, I have
                    148:  *       punted this to here.
                    149:  */
                    150: void
                    151: vs_lock(
                    152:        vstruct_t               vs,
                    153:        mach_port_seqno_t       seqno)
                    154: {
                    155:        default_pager_total++;
                    156:        VS_LOCK(vs);
                    157: 
                    158:        seqno = vs->vs_next_seqno++;
                    159: 
                    160:        while (vs->vs_seqno != seqno) {
                    161:                default_pager_wait_seqno++;
                    162:                vs->vs_waiting_seqno = TRUE;
                    163:                assert_wait(&vs->vs_waiting_seqno, THREAD_UNINT);
                    164:                VS_UNLOCK(vs);
                    165:                thread_block((void (*)(void))0);
                    166:                VS_LOCK(vs);
                    167:        }
                    168: }
                    169: 
                    170: /*
                    171:  * Increments sequence number and unlocks pager.
                    172:  */
                    173: void
                    174: vs_unlock(vstruct_t vs)
                    175: {
                    176:        boolean_t need_wakeups = vs->vs_waiting_seqno;
                    177: 
                    178:        vs->vs_waiting_seqno = FALSE;
                    179:        vs->vs_seqno++;
                    180:        VS_UNLOCK(vs);
                    181:        if (need_wakeups)
                    182:                thread_wakeup(&vs->vs_waiting_seqno);
                    183: }
                    184: 
                    185: /* 
                    186:  * Start a read - one more reader.  Pager must be locked.
                    187:  */
                    188: void
                    189: vs_start_read(
                    190:        vstruct_t vs)
                    191: {
                    192:        vs->vs_readers++;
                    193: }
                    194: 
                    195: /*
                    196:  * Wait for readers.  Unlocks and relocks pager if wait needed.
                    197:  */
                    198: void
                    199: vs_wait_for_readers(
                    200:        vstruct_t vs)
                    201: {
                    202:        while (vs->vs_readers != 0) {
                    203:                default_pager_wait_read++;
                    204:                vs->vs_waiting_read = TRUE;
                    205:                assert_wait(&vs->vs_waiting_read, THREAD_UNINT);
                    206:                VS_UNLOCK(vs);
                    207:                thread_block((void (*)(void))0);
                    208:                VS_LOCK(vs);
                    209:        }
                    210: }
                    211: 
                    212: /*
                    213:  * Finish a read.  Pager is unlocked and returns unlocked.
                    214:  */
                    215: void
                    216: vs_finish_read(
                    217:        vstruct_t vs)
                    218: {
                    219:        VS_LOCK(vs);
                    220:        if (--vs->vs_readers == 0) {
                    221:                boolean_t need_wakeups = vs->vs_waiting_read;
                    222: 
                    223:                vs->vs_waiting_read = FALSE;
                    224:                VS_UNLOCK(vs);
                    225:                if (need_wakeups)
                    226:                        thread_wakeup(&vs->vs_waiting_read);
                    227:        } else
                    228:                VS_UNLOCK(vs);
                    229: }
                    230: 
                    231: /*
                    232:  * Start a write - one more writer.  Pager must be locked.
                    233:  */
                    234: void
                    235: vs_start_write(
                    236:        vstruct_t vs)
                    237: {
                    238:        vs->vs_writers++;
                    239: }
                    240: 
                    241: /* 
                    242:  * Wait for writers.  Unlocks and relocks pager if wait needed.
                    243:  */
                    244: void
                    245: vs_wait_for_writers(
                    246:        vstruct_t vs)
                    247: {
                    248:        while (vs->vs_writers != 0) {
                    249:                default_pager_wait_write++;
                    250:                vs->vs_waiting_write = TRUE;
                    251:                assert_wait(&vs->vs_waiting_write, THREAD_UNINT);
                    252:                VS_UNLOCK(vs);
                    253:                thread_block((void (*)(void))0);
                    254:                VS_LOCK(vs);
                    255:        }
                    256:        vs_async_wait(vs);
                    257: }
                    258: 
                    259: /* This is to be used for the transfer from segment code ONLY */
                    260: /* The transfer code holds off vs destruction by keeping the  */
                    261: /* vs_async_wait count non-zero.  It will not ocnflict with   */
                    262: /* other writers on an async basis because it only writes on  */
                    263: /* a cluster basis into fresh (as of sync time) cluster locations */
                    264: void 
                    265: vs_wait_for_sync_writers(
                    266:         vstruct_t vs)
                    267: {
                    268:         while (vs->vs_writers != 0) {
                    269:                 default_pager_wait_write++;
                    270:                vs->vs_waiting_write = TRUE;
                    271:                 assert_wait(&vs->vs_waiting_write, THREAD_UNINT);
                    272:                 VS_UNLOCK(vs);
                    273:                 thread_block((void (*)(void))0);
                    274:                 VS_LOCK(vs);
                    275:         }
                    276: }       
                    277: 
                    278: 
                    279: /*
                    280:  * Finish a write.  Pager is unlocked and returns unlocked.
                    281:  */
                    282: void
                    283: vs_finish_write(
                    284:        vstruct_t vs)
                    285: {
                    286:        VS_LOCK(vs);
                    287:        if (--vs->vs_writers == 0) {
                    288:                boolean_t need_wakeups = vs->vs_waiting_write;
                    289: 
                    290:                vs->vs_waiting_write = FALSE;
                    291:                VS_UNLOCK(vs);
                    292:                if (need_wakeups)
                    293:                        thread_wakeup(&vs->vs_waiting_write);
                    294:        } else
                    295:                VS_UNLOCK(vs);
                    296: }
                    297: 
                    298: /*
                    299:  * Wait for concurrent default_pager_objects.
                    300:  * Unlocks and relocks pager if wait needed.
                    301:  */
                    302: void
                    303: vs_wait_for_refs(
                    304:        vstruct_t vs)
                    305: {
                    306:        while (vs->vs_name_refs == 0) {
                    307:                default_pager_wait_refs++;
                    308:                vs->vs_waiting_refs = TRUE;
                    309:                assert_wait(&vs->vs_waiting_refs, THREAD_UNINT);
                    310:                VS_UNLOCK(vs);
                    311:                thread_block((void (*)(void))0);
                    312:                VS_LOCK(vs);
                    313:        }
                    314: }
                    315: 
                    316: /*
                    317:  * Finished creating name refs - wake up waiters.
                    318:  */
                    319: void
                    320: vs_finish_refs(
                    321:        vstruct_t vs)
                    322: {
                    323:        boolean_t need_wakeups = vs->vs_waiting_refs;
                    324:        vs->vs_waiting_refs = FALSE;
                    325:        if (need_wakeups)
                    326:                thread_wakeup(&vs->vs_waiting_refs);
                    327: }
                    328: 
                    329: #else  /* PARALLEL */
                    330: 
                    331: #define        vs_lock(vs,seqno)
                    332: #define        vs_unlock(vs)
                    333: #define        vs_start_read(vs)
                    334: #define        vs_wait_for_readers(vs)
                    335: #define        vs_finish_read(vs)
                    336: #define        vs_start_write(vs)
                    337: #define        vs_wait_for_writers(vs)
                    338: #define        vs_wait_for_sync_writers(vs)
                    339: #define        vs_finish_write(vs)
                    340: #define vs_wait_for_refs(vs)
                    341: #define vs_finish_refs(vs)
                    342: 
                    343: #endif /* PARALLEL */
                    344: 
                    345: vstruct_t vs_object_create(vm_size_t); /* forward */
                    346: 
                    347: vstruct_t
                    348: vs_object_create(
                    349:        vm_size_t size)
                    350: {
                    351:        vstruct_t       vs;
                    352:        static char here[] = "vs_object_create";
                    353: 
                    354:        /*
                    355:         * Allocate a vstruct. If there are any problems, then report them
                    356:         * to the console.
                    357:         */
                    358:        vs = ps_vstruct_create(size);
                    359:        if (vs == VSTRUCT_NULL) {
                    360:                dprintf(("vs_object_create: unable to allocate %s\n",
                    361:                         "-- either run swapon command or reboot"));
                    362:                return VSTRUCT_NULL;
                    363:        }
                    364: 
                    365:        return vs;
                    366: }
                    367: 
                    368: mach_port_urefs_t default_pager_max_urefs = 10000;
                    369: 
                    370: /*
                    371:  * Check user reference count on memory object control port.
                    372:  * Vstruct must be locked.
                    373:  * Unlocks and re-locks vstruct if needs to call kernel.
                    374:  */
                    375: void vs_check_request(vstruct_t, MACH_PORT_FACE);      /* forward */
                    376: 
                    377: void
                    378: vs_check_request(
                    379:        vstruct_t       vs,
                    380:        MACH_PORT_FACE  control_port)
                    381: {
                    382:        mach_port_delta_t delta;
                    383:        kern_return_t   kr;
                    384:        static char     here[] = "vs_check_request";
                    385: 
                    386:        if (++vs->vs_control_refs > default_pager_max_urefs) {
                    387:                delta = 1 - vs->vs_control_refs;
                    388:                vs->vs_control_refs = 1;
                    389: 
                    390:                VS_UNLOCK(vs);
                    391: 
                    392:                /*
                    393:                 * Deallocate excess user references.
                    394:                 */
                    395: 
                    396:                {
                    397: /* find a better interface for this, what will we use as a component */
                    398:                        int i;
                    399:                        delta = -delta;
                    400:                        for(i=0; i<delta; i++)
                    401:                                ipc_port_release_send(control_port);
                    402:                }
                    403: 
                    404:                VS_LOCK(vs);
                    405:        }
                    406: }
                    407: 
                    408: void default_pager_add(vstruct_t, boolean_t);  /* forward */
                    409: 
                    410: void
                    411: default_pager_add(
                    412:        vstruct_t vs,
                    413:        boolean_t internal)
                    414: {
                    415:        MACH_PORT_FACE          mem_obj = vs->vs_mem_obj_port;
                    416:        MACH_PORT_FACE          pset;
                    417:        mach_port_mscount_t     sync;
                    418:        MACH_PORT_FACE          previous;
                    419:        kern_return_t           kr;
                    420:        static char             here[] = "default_pager_add";
                    421: 
                    422:        /*
                    423:         * The port currently has a make-send count of zero,
                    424:         * because either we just created the port or we just
                    425:         * received the port in a memory_object_create request.
                    426:         */
                    427: 
                    428:        if (internal) {
                    429:                /* possibly generate an immediate no-senders notification */
                    430:                sync = 0;
                    431:                pset = default_pager_internal_set;
                    432:        } else {
                    433:                /* delay notification till send right is created */
                    434:                sync = 1;
                    435:                pset = default_pager_external_set;
                    436:        }
                    437: 
                    438:        ipc_port_make_sonce(mem_obj);
                    439:        ip_lock(mem_obj);  /* unlocked in nsrequest below */
                    440:        ipc_port_nsrequest(mem_obj, sync, mem_obj, &previous);
                    441: }
                    442: 
                    443: 
                    444: /*
                    445:  * Routine:    dp_memory_object_create
                    446:  * Purpose:
                    447:  *     Handle requests for memory objects from the
                    448:  *     kernel.
                    449:  * Notes:
                    450:  *     Because we only give out the default memory
                    451:  *     manager port to the kernel, we don't have to
                    452:  *     be so paranoid about the contents.
                    453:  */
                    454: kern_return_t
                    455: dp_memory_object_create(
                    456:        MACH_PORT_FACE          dmm,
                    457:        MACH_PORT_FACE          *new_mem_obj,
                    458:        vm_size_t               new_size)
                    459: {
                    460:        mach_port_seqno_t       seqno;
                    461:        vstruct_t               vs;
                    462:        MACH_PORT_FACE          pager;
                    463:        static char             here[] = "memory_object_create";
                    464: 
                    465:        assert(dmm == default_pager_default_port);
                    466: 
                    467:        vs = vs_object_create(new_size);
                    468:        if (vs == VSTRUCT_NULL)
                    469:                return KERN_RESOURCE_SHORTAGE;
                    470: 
                    471:        pager = *new_mem_obj = ipc_port_alloc_kernel();
                    472:        assert (pager != IP_NULL);
                    473:        (void) ipc_port_make_send(pager);
                    474: 
                    475:        {
                    476:           struct vstruct_alias *alias_struct;
                    477: 
                    478:           alias_struct = (struct vstruct_alias *)
                    479:                        kalloc(sizeof(struct vstruct_alias));
                    480:           if(alias_struct != NULL) {
                    481:                alias_struct->vs = vs;
                    482:                alias_struct->name = ISVS;
                    483:                pager->alias = (int) alias_struct;
                    484:           }
                    485:           else Panic("Out of kernel memory");
                    486: 
                    487:           /* JMM - Add binding to this pager under components */
                    488:           pager_mux_hash_insert(pager, &dp_memory_object_subsystem);
                    489:           vs->vs_next_seqno = 0;
                    490:           pager->ip_receiver = ipc_space_kernel;
                    491:        }
                    492: 
                    493:        /*
                    494:         * Set up associations between this port
                    495:         * and this default_pager structure
                    496:         */
                    497: 
                    498:        vs->vs_mem_obj_port = pager;
                    499: 
                    500:        /*
                    501:         * After this, other threads might receive requests
                    502:         * for this memory object or find it in the port list.
                    503:         */
                    504: 
                    505:        vstruct_list_insert(vs);
                    506:        default_pager_add(vs, TRUE);
                    507: 
                    508:        return KERN_SUCCESS;
                    509: }
                    510: 
                    511: kern_return_t
                    512: dp_memory_object_init(
                    513:        MACH_PORT_FACE          mem_obj,
                    514:        MACH_PORT_FACE          control_port,
                    515:        vm_size_t               pager_page_size)
                    516: {
                    517:        mach_port_seqno_t       seqno;
                    518:        vstruct_t               vs;
                    519:        static char             here[] = "memory_object_init";
                    520: 
                    521:        assert(pager_page_size == vm_page_size);
                    522: 
                    523:        vs_lookup(mem_obj, vs);
                    524:        vs_lock(vs, seqno);
                    525: 
                    526:        if (vs->vs_control_port != MACH_PORT_NULL)
                    527:                Panic("bad request");
                    528: 
                    529:        vs->vs_control_port = control_port;
                    530:        vs->vs_control_refs = 1;
                    531:        vs->vs_object_name = MACH_PORT_NULL;
                    532:        vs->vs_name_refs = 1;
                    533: 
                    534:        vs_unlock(vs);
                    535: 
                    536:        return KERN_SUCCESS;
                    537: }
                    538: 
                    539: kern_return_t
                    540: dp_memory_object_synchronize(
                    541:        MACH_PORT_FACE          mem_obj,
                    542:        MACH_PORT_FACE          control_port,
                    543:        vm_offset_t             offset,
                    544:        vm_offset_t             length,
                    545:        vm_sync_t               flags)
                    546: {
                    547:        mach_port_seqno_t       seqno;
                    548:        vstruct_t       vs;
                    549:        static char     here[] = "memory_object_synchronize";
                    550: 
                    551:        vs_lookup(mem_obj, vs);
                    552:        vs_lock(vs, seqno);
                    553:        vs_check_request(vs, control_port);
                    554:        vs_unlock(vs);
                    555: 
                    556:        memory_object_synchronize_completed(
                    557:                                vm_object_lookup(control_port), 
                    558:                                offset, length);
                    559: 
                    560:        return KERN_SUCCESS;
                    561: }
                    562: 
                    563: kern_return_t
                    564: dp_memory_object_terminate(
                    565:        MACH_PORT_FACE          mem_obj,
                    566:        MACH_PORT_FACE          control_port)
                    567: {
                    568:        mach_port_seqno_t       seqno;
                    569:        vstruct_t               vs;
                    570:        mach_port_urefs_t       request_refs;
                    571:        kern_return_t           kr;
                    572:        static char             here[] = "memory_object_terminate";
                    573: 
                    574:        /* 
                    575:         * control port is a receive right, not a send right.
                    576:         */
                    577: 
                    578:        vs_lookup(mem_obj, vs);
                    579:        vs_lock(vs, seqno);
                    580: 
                    581:        /*
                    582:         * Wait for read and write requests to terminate.
                    583:         */
                    584: 
                    585:        vs_wait_for_readers(vs);
                    586:        vs_wait_for_writers(vs);
                    587: 
                    588:        /*
                    589:         * After memory_object_terminate both memory_object_init
                    590:         * and a no-senders notification are possible, so we need
                    591:         * to clean up the request and name ports but leave
                    592:         * the mem_obj port.
                    593:         *
                    594:         * A concurrent default_pager_objects might be allocating
                    595:         * more references for the name port.  In this case,
                    596:         * we must first wait for it to finish.
                    597:         */
                    598: 
                    599:        vs_wait_for_refs(vs);
                    600: 
                    601:        vs->vs_control_port = MACH_PORT_NULL;
                    602: 
                    603:        /* a bit of special case ugliness here.  Wakeup any waiting reads */
                    604:        /* these data requests had to be removed from the seqno traffic   */
                    605:        /* based on a performance bottleneck with large memory objects    */
                    606:        /* the problem will right itself with the new component based     */
                    607:        /* synchronous interface.  The new async will be able to return   */
                    608:        /* failure during its sync phase.   In the mean time ... */
                    609: 
                    610:                thread_wakeup(&vs->vs_waiting_write);
                    611:                thread_wakeup(&vs->vs_waiting_async);
                    612: 
                    613:        request_refs = vs->vs_control_refs;
                    614:        vs->vs_control_refs = 0;
                    615: 
                    616:        vs->vs_object_name = MACH_PORT_NULL;
                    617: 
                    618:        assert(vs->vs_name_refs != 0);
                    619:        vs->vs_name_refs = 0;
                    620: 
                    621:        vs_unlock(vs);
                    622: 
                    623:        /*
                    624:         * Now we deallocate our various port rights.
                    625:         */
                    626: 
                    627:        {
                    628:                int i;
                    629:                for(i=0; i<request_refs; i++)
                    630:                        ipc_port_release_send(control_port);
                    631:        }
                    632:         if(control_port->alias != (int)NULL) 
                    633:                 kfree((vm_offset_t) (control_port->alias), 
                    634:                                        sizeof(struct vstruct_alias));
                    635:        ipc_port_release_receive(control_port);
                    636:        return KERN_SUCCESS;
                    637: }
                    638: 
                    639: void
                    640: default_pager_no_senders(
                    641:        MACH_PORT_FACE          mem_obj,
                    642:        mach_port_seqno_t       seqno,
                    643:        mach_port_mscount_t     mscount)
                    644: {
                    645:        vstruct_t               vs;
                    646:        static char             here[] = "default_pager_no_senders";
                    647: 
                    648:        /*
                    649:         * Because we don't give out multiple send rights
                    650:         * for a memory object, there can't be a race
                    651:         * between getting a no-senders notification
                    652:         * and creating a new send right for the object.
                    653:         * Hence we don't keep track of mscount.
                    654:         */
                    655: 
                    656:        vs_lookup(mem_obj, vs);
                    657:        vs_lock(vs, seqno);
                    658:        vs_async_wait(vs);      /* wait for pending async IO */
                    659: 
                    660:        /* do not delete the vs structure until the referencing pointers */
                    661:        /* in the vstruct list have been expunged */
                    662: 
                    663:        /* get VSL_LOCK out of order by using TRY mechanism */
                    664:        while(!VSL_LOCK_TRY()) {
                    665:                VS_UNLOCK(vs);
                    666:                VSL_LOCK();
                    667:                VSL_UNLOCK();
                    668:                VS_LOCK(vs);
                    669:                vs_async_wait(vs);      /* wait for pending async IO */
                    670:        }
                    671:        /*
                    672:         * We shouldn't get a no-senders notification
                    673:         * when the kernel has the object cached.
                    674:         */
                    675:        if (vs->vs_control_port != MACH_PORT_NULL)
                    676:                Panic("bad request");
                    677: 
                    678:        /*
                    679:         * Unlock the pager (though there should be no one
                    680:         * waiting for it).
                    681:         */
                    682:        VS_UNLOCK(vs);
                    683: 
                    684:        /*
                    685:         * Remove the memory object port association, and then
                    686:         * the destroy the port itself.  We must remove the object
                    687:         * from the port list before deallocating the pager,
                    688:         * because of default_pager_objects.
                    689:         */
                    690:        vstruct_list_delete(vs);
                    691:        ps_vstruct_dealloc(vs);
                    692: 
                    693:        /*
                    694:         * Recover memory that we might have wasted because
                    695:         * of name conflicts
                    696:         */
                    697:        while (!queue_empty(&vstruct_list.vsl_leak_queue)) {
                    698:                vs = (vstruct_t) queue_first(&vstruct_list.vsl_leak_queue);
                    699:                queue_remove_first(&vstruct_list.vsl_leak_queue, vs, vstruct_t,
                    700:                                   vs_links);
                    701:                kfree((vm_offset_t) vs, sizeof *vs);
                    702:        }
                    703:        VSL_UNLOCK();
                    704: }
                    705: 
                    706: kern_return_t
                    707: dp_memory_object_data_request(
                    708:        MACH_PORT_FACE          mem_obj,
                    709:        MACH_PORT_FACE          reply_to,
                    710:        vm_offset_t             offset,
                    711:        vm_size_t               length,
                    712:        vm_prot_t               protection_required)
                    713: {
                    714:        mach_port_seqno_t       seqno;
                    715:        vstruct_t               vs;
                    716:        static char             here[] = "memory_object_data_request";
                    717: 
                    718:        GSTAT(global_stats.gs_pagein_calls++);
                    719: 
                    720: 
                    721:        /* CDY at this moment vs_lookup panics when presented with the wrong */
                    722:        /* port.  As we are expanding this pager to support user interfaces */
                    723:        /* this should be changed to return kern_failure */
                    724:        vs_lookup(mem_obj, vs);
                    725:        vs_lock(vs, seqno);
                    726:        vs_check_request(vs, reply_to);
                    727: 
                    728:        /* We are going to relax the strict sequencing here for performance */
                    729:        /* reasons.  We can do this because we know that the read and */
                    730:        /* write threads are different and we rely on synchronization */
                    731:        /* of read and write requests at the cache memory_object level */
                    732:        /* break out wait_for_writers, all of this goes away when */
                    733:        /* we get real control of seqno with the new component interface */
                    734:        if (vs->vs_writers != 0) {
                    735:                /* you can't hold on to the seqno and go */
                    736:                /* to sleep like that */
                    737:                vs_unlock(vs);  /* bump internal count of seqno */
                    738:                VS_LOCK(vs);
                    739:                while (vs->vs_writers != 0) {
                    740:                        default_pager_wait_write++;
                    741:                        vs->vs_waiting_write = TRUE;
                    742:                        assert_wait(&vs->vs_waiting_write, THREAD_UNINT);
                    743:                        VS_UNLOCK(vs);
                    744:                        thread_block((void (*)(void))0);
                    745:                        VS_LOCK(vs);
                    746:                        vs_async_wait(vs);
                    747:                }
                    748:                if(vs->vs_control_port == MACH_PORT_NULL) {
                    749:                        VS_UNLOCK(vs);
                    750:                        return KERN_FAILURE;
                    751:                }
                    752:                vs_start_read(vs);
                    753:                VS_UNLOCK(vs);
                    754:        } else {
                    755:                vs_start_read(vs);
                    756:                vs_unlock(vs);
                    757:        }
                    758: 
                    759:        /*
                    760:         * Request must be on a page boundary and a multiple of pages.
                    761:         */
                    762:        if ((offset & vm_page_mask) != 0 || (length & vm_page_mask) != 0)
                    763:                Panic("bad alignment");
                    764: 
                    765:        pvs_cluster_read(vs, offset, length);
                    766: 
                    767:        vs_finish_read(vs);
                    768: 
                    769:        return KERN_SUCCESS;
                    770: }
                    771: 
                    772: /*
                    773:  * memory_object_data_initialize: check whether we already have each page, and
                    774:  * write it if we do not.  The implementation is far from optimized, and
                    775:  * also assumes that the default_pager is single-threaded.
                    776:  */
                    777: /*  It is questionable whether or not a pager should decide what is relevant */
                    778: /* and what is not in data sent from the kernel.  Data initialize has been */
                    779: /* changed to copy back all data sent to it in preparation for its eventual */
                    780: /* merge with data return.  It is the kernel that should decide what pages */
                    781: /* to write back.  As of the writing of this note, this is indeed the case */
                    782: /* the kernel writes back one page at a time through this interface */
                    783: 
                    784: kern_return_t
                    785: dp_memory_object_data_initialize(
                    786:        MACH_PORT_FACE          mem_obj,
                    787:        MACH_PORT_FACE          control_port,
                    788:        vm_offset_t             offset,
                    789:        pointer_t               addr,
                    790:        vm_size_t               data_cnt)
                    791: {
                    792:        mach_port_seqno_t       seqno;
                    793:        vstruct_t       vs;
                    794:        static char     here[] = "memory_object_data_initialize";
                    795: 
                    796: #ifdef lint
                    797:        control_port++;
                    798: #endif /* lint */
                    799: 
                    800:        DEBUG(DEBUG_MO_EXTERNAL,
                    801:              ("mem_obj=0x%x,offset=0x%x,cnt=0x%x\n",
                    802:               (int)mem_obj, (int)offset, (int)data_cnt));
                    803:        GSTAT(global_stats.gs_pages_init += atop(data_cnt));
                    804: 
                    805:        vs_lookup(mem_obj, vs);
                    806:        vs_lock(vs, seqno);
                    807:        vs_check_request(vs, control_port);
                    808:        vs_start_write(vs);
                    809:        vs_unlock(vs);
                    810: 
                    811:        /*
                    812:         * Write the data via clustered writes. vs_cluster_write will
                    813:         * loop if the address range specified crosses cluster
                    814:         * boundaries.
                    815:         */
                    816:        vs_cluster_write(vs, offset, addr, data_cnt, FALSE);
                    817: 
                    818:        vs_finish_write(vs);
                    819: 
                    820:        return KERN_SUCCESS;
                    821: }
                    822: 
                    823: kern_return_t
                    824: dp_memory_object_lock_completed(
                    825:        memory_object_t         mem_obj,
                    826:        MACH_PORT_FACE          control_port,
                    827:        vm_offset_t             offset,
                    828:        vm_size_t               length)
                    829: {
                    830:        mach_port_seqno_t       seqno;
                    831:        static char     here[] = "memory_object_lock_completed";
                    832: 
                    833: #ifdef lint
                    834:        mem_obj++; 
                    835:        seqno++; 
                    836:        control_port++; 
                    837:        offset++; 
                    838:        length++;
                    839: #endif /* lint */
                    840: 
                    841:        Panic("illegal");
                    842:        return KERN_FAILURE;
                    843: }
                    844: 
                    845: kern_return_t
                    846: dp_memory_object_data_unlock(
                    847:        memory_object_t         mem_obj,
                    848:        MACH_PORT_FACE          control_port,
                    849:        vm_offset_t             offset,
                    850:        vm_size_t               data_cnt,
                    851:        vm_prot_t               desired_access)
                    852: {
                    853:        static char     here[] = "memory_object_data_unlock";
                    854: 
                    855:        Panic("illegal");
                    856:        return KERN_FAILURE;
                    857: }
                    858: 
                    859: 
                    860: kern_return_t
                    861: dp_memory_object_supply_completed(
                    862:        memory_object_t         mem_obj,
                    863:        MACH_PORT_FACE          control_port,
                    864:        vm_offset_t             offset,
                    865:        vm_size_t               length,
                    866:        kern_return_t           result,
                    867:        vm_offset_t             error_offset)
                    868: {
                    869:        static char     here[] = "memory_object_supply_completed";
                    870: 
                    871:        Panic("illegal");
                    872:        return KERN_FAILURE;
                    873: }
                    874: 
                    875: kern_return_t
                    876: dp_memory_object_data_return(
                    877:        MACH_PORT_FACE          mem_obj,
                    878:        MACH_PORT_FACE          control_port,
                    879:        vm_offset_t             offset,
                    880:        pointer_t               addr,
                    881:        vm_size_t               data_cnt,
                    882:        boolean_t               dirty,
                    883:        boolean_t               kernel_copy)
                    884: {
                    885:        mach_port_seqno_t       seqno;
                    886:        vstruct_t       vs;
                    887:        vm_offset_t     pageout_address;
                    888:        static char     here[] = "memory_object_data_return";
                    889: 
                    890: #ifdef lint
                    891:        control_port++;
                    892:        dirty++;
                    893:        kernel_copy++;
                    894: #endif /* lint */
                    895: 
                    896:        DEBUG(DEBUG_MO_EXTERNAL,
                    897:              ("mem_obj=0x%x,offset=0x%x,addr=0x%xcnt=0x%x\n",
                    898:               (int)mem_obj, (int)offset, (int)addr, (int)data_cnt));
                    899:        GSTAT(global_stats.gs_pageout_calls++);
                    900: 
                    901:        /* This routine is called by the pageout thread.  The pageout thread */
                    902:        /* cannot be blocked by read activities unless the read activities   */
                    903:        /* Therefore the grant of vs lock must be done on a try versus a      */
                    904:        /* blocking basis.  The code below relies on the fact that the       */
                    905:        /* interface is synchronous.  Should this interface be again async   */
                    906:        /* for some type  of pager in the future the pages will have to be   */
                    907:        /* returned through a separate, asynchronous path.                   */
                    908: 
                    909:        vs_lookup(mem_obj, vs);
                    910: 
                    911:         default_pager_total++;
                    912:        if(!VS_TRY_LOCK(vs)) {
                    913:                /* the call below will not be done by caller when we have */
                    914:                /* a synchronous interface */
                    915:                /* return KERN_LOCK_OWNED; */
                    916:                upl_t           page_list;
                    917:                upl_system_list_request((vm_object_t)
                    918:                                 vs->vs_control_port->ip_kobject,
                    919:                                 offset, data_cnt, data_cnt, &page_list, NULL, 0,
                    920:                                        UPL_NOBLOCK | UPL_CLEAN_IN_PLACE | 
                    921:                                                UPL_NO_SYNC | UPL_COPYOUT_FROM);
                    922: 
                    923:                upl_abort(page_list,0);
                    924:                return KERN_SUCCESS;
                    925:        }
                    926: 
                    927: 
                    928: 
                    929:        if ((vs->vs_seqno != vs->vs_next_seqno++) || (vs->vs_xfer_pending)) {
                    930:                upl_t   page_list;
                    931:                vs->vs_next_seqno--;
                    932:                 VS_UNLOCK(vs);
                    933:                /* the call below will not be done by caller when we have */
                    934:                /* a synchronous interface */
                    935:                /* return KERN_LOCK_OWNED; */
                    936:                upl_system_list_request((vm_object_t)
                    937:                                 vs->vs_control_port->ip_kobject,
                    938:                                 offset, data_cnt, data_cnt, &page_list, NULL, 0,
                    939:                                        UPL_NOBLOCK | UPL_CLEAN_IN_PLACE | 
                    940:                                                UPL_NO_SYNC | UPL_COPYOUT_FROM);
                    941:                upl_abort(page_list,0);
                    942:                return KERN_SUCCESS;
                    943:        }
                    944: 
                    945:        if ((data_cnt % vm_page_size) != 0)
                    946:                Panic("bad alignment");
                    947: 
                    948: /*
                    949:        vs_check_request(vs, control_port);
                    950: */
                    951:        vs_start_write(vs);
                    952:        vs_unlock(vs);
                    953: 
                    954:        /*
                    955:         * Write the data via clustered writes. vs_cluster_write will
                    956:         * loop if the address range specified crosses cluster
                    957:         * boundaries.
                    958:         */
                    959:        vs_cluster_write(vs, offset, addr, data_cnt, FALSE);
                    960: 
                    961:        vs_finish_write(vs);
                    962: 
                    963:        return KERN_SUCCESS;
                    964: }
                    965: 
                    966: kern_return_t
                    967: dp_memory_object_discard_request(
                    968:        memory_object_t         mem_obj, 
                    969:        memory_object_control_t memory_control,
                    970:        vm_offset_t             offset, 
                    971:        vm_size_t               length)
                    972: {
                    973:        panic("illegal");
                    974:        return KERN_FAILURE;
                    975: }
                    976: 
                    977: kern_return_t
                    978: dp_memory_object_change_completed(
                    979:        memory_object_t         mem_obj,
                    980:        memory_object_control_t memory_control,
                    981:        memory_object_flavor_t  flavor)
                    982: {
                    983:        static char     here[] = "memory_object_change_completed";
                    984: 
                    985:        Panic("illegal");
                    986:        return KERN_FAILURE;
                    987: }
                    988: 
                    989: /*
                    990:  * Create an external object.
                    991:  */
                    992: kern_return_t
                    993: default_pager_object_create(
                    994:        MACH_PORT_FACE  pager,
                    995:        MACH_PORT_FACE  *mem_obj,
                    996:        vm_size_t       size)
                    997: {
                    998:        vstruct_t       vs;
                    999:        MACH_PORT_FACE  port;
                   1000:        kern_return_t   result;
                   1001:        struct vstruct_alias    *alias_struct;
                   1002:        static char     here[] = "default_pager_object_create";
                   1003: 
                   1004: 
                   1005:        if (pager != default_pager_default_port)
                   1006:                return KERN_INVALID_ARGUMENT;
                   1007: 
                   1008:        vs = vs_object_create(size);
                   1009: 
                   1010:        port = ipc_port_alloc_kernel();
                   1011:        ipc_port_make_send(port);
                   1012:        /* register abstract memory object port with pager mux routine */
                   1013:        /* (directs kernel internal calls to the right pager). */
                   1014:        alias_struct = (struct vstruct_alias *)
                   1015:                        kalloc(sizeof(struct vstruct_alias));
                   1016:        if(alias_struct != NULL) {
                   1017:                alias_struct->vs = vs;
                   1018:                alias_struct->name = ISVS;
                   1019:                port->alias = (int) alias_struct;
                   1020:        }
                   1021:        else Panic("Out of kernel memory");
                   1022:                
                   1023:        /*
                   1024:         * Set up associations between these ports
                   1025:         * and this vstruct structure
                   1026:         */
                   1027: 
                   1028:        vs->vs_mem_obj_port = port;
                   1029:        vstruct_list_insert(vs);
                   1030:        default_pager_add(vs, FALSE);
                   1031: 
                   1032:        *mem_obj = port;
                   1033: 
                   1034:        return KERN_SUCCESS;
                   1035: }
                   1036: 
                   1037: kern_return_t
                   1038: default_pager_objects(
                   1039:        MACH_PORT_FACE                  pager,
                   1040:        default_pager_object_array_t    *objectsp,
                   1041:        mach_msg_type_number_t          *ocountp,
                   1042:        mach_port_array_t               *portsp,
                   1043:        mach_msg_type_number_t          *pcountp)
                   1044: {
                   1045:        vm_offset_t             oaddr = 0;      /* memory for objects */
                   1046:        vm_size_t               osize = 0;      /* current size */
                   1047:        default_pager_object_t  * objects;
                   1048:        unsigned int            opotential;
                   1049: 
                   1050:        vm_offset_t             paddr = 0;      /* memory for ports */
                   1051:        vm_size_t               psize = 0;      /* current size */
                   1052:        MACH_PORT_FACE           * ports;
                   1053:        unsigned int            ppotential;
                   1054: 
                   1055:        unsigned int            actual;
                   1056:        unsigned int            num_objects;
                   1057:        kern_return_t           kr;
                   1058:        vstruct_t               entry;
                   1059:        static char             here[] = "default_pager_objects";
                   1060: /*
                   1061:        if (pager != default_pager_default_port)
                   1062:                return KERN_INVALID_ARGUMENT;
                   1063: */
                   1064: 
                   1065:        /* start with the inline memory */
                   1066: 
                   1067:        kr = vm_map_copyout(ipc_kernel_map, (vm_offset_t *)&objects, 
                   1068:                                                (vm_map_copy_t) *objectsp);
                   1069: 
                   1070:        if (kr != KERN_SUCCESS)
                   1071:                return kr;
                   1072: 
                   1073:        osize = round_page(*ocountp * sizeof * objects);
                   1074:        kr = vm_map_wire(ipc_kernel_map, 
                   1075:                        trunc_page((vm_offset_t)objects),
                   1076:                        round_page(((vm_offset_t)objects) + osize), 
                   1077:                        VM_PROT_READ|VM_PROT_WRITE, FALSE);
                   1078:        osize=0;
                   1079: 
                   1080:        *objectsp = objects;
                   1081:        /* we start with the inline space */
                   1082: 
                   1083: 
                   1084:        num_objects = 0;
                   1085:        opotential = *ocountp;
                   1086: 
                   1087:        ports = (MACH_PORT_FACE *) *portsp;
                   1088:        ppotential = *pcountp;
                   1089: 
                   1090:        VSL_LOCK();
                   1091: 
                   1092:        /*
                   1093:         * We will send no more than this many
                   1094:         */
                   1095:        actual = vstruct_list.vsl_count;
                   1096:        VSL_UNLOCK();
                   1097: 
                   1098:        if (opotential < actual) {
                   1099:                vm_offset_t     newaddr;
                   1100:                vm_size_t       newsize;
                   1101: 
                   1102:                newsize = 2 * round_page(actual * sizeof * objects);
                   1103: 
                   1104:                kr = vm_allocate(kernel_map, &newaddr, newsize, TRUE);
                   1105:                if (kr != KERN_SUCCESS)
                   1106:                        goto nomemory;
                   1107: 
                   1108:                oaddr = newaddr;
                   1109:                osize = newsize;
                   1110:                opotential = osize / sizeof * objects;
                   1111:                objects = (default_pager_object_t *)oaddr;
                   1112:        }
                   1113: 
                   1114:        if (ppotential < actual) {
                   1115:                vm_offset_t     newaddr;
                   1116:                vm_size_t       newsize;
                   1117: 
                   1118:                newsize = 2 * round_page(actual * sizeof * ports);
                   1119: 
                   1120:                kr = vm_allocate(kernel_map, &newaddr, newsize, TRUE);
                   1121:                if (kr != KERN_SUCCESS)
                   1122:                        goto nomemory;
                   1123: 
                   1124:                paddr = newaddr;
                   1125:                psize = newsize;
                   1126:                ppotential = psize / sizeof * ports;
                   1127:                ports = (MACH_PORT_FACE *)paddr;
                   1128:        }
                   1129: 
                   1130:        /*
                   1131:         * Now scan the list.
                   1132:         */
                   1133: 
                   1134:        VSL_LOCK();
                   1135: 
                   1136:        num_objects = 0;
                   1137:        queue_iterate(&vstruct_list.vsl_queue, entry, vstruct_t, vs_links) {
                   1138: 
                   1139:                MACH_PORT_FACE          port;
                   1140:                vm_size_t               size;
                   1141: 
                   1142:                if ((num_objects >= opotential) ||
                   1143:                    (num_objects >= ppotential)) {
                   1144: 
                   1145:                        /*
                   1146:                         * This should be rare.  In any case,
                   1147:                         * we will only miss recent objects,
                   1148:                         * because they are added at the end.
                   1149:                         */
                   1150:                        break;
                   1151:                }
                   1152: 
                   1153:                /*
                   1154:                 * Avoid interfering with normal operations
                   1155:                 */
                   1156:                if (!VS_MAP_TRY_LOCK(entry))
                   1157:                        goto not_this_one;
                   1158:                size = ps_vstruct_allocated_size(entry);
                   1159:                VS_MAP_UNLOCK(entry);
                   1160: 
                   1161:                VS_LOCK(entry);
                   1162: 
                   1163:                port = entry->vs_object_name;
                   1164:                if (port == MACH_PORT_NULL) {
                   1165: 
                   1166:                        /*
                   1167:                         * The object is waiting for no-senders
                   1168:                         * or memory_object_init.
                   1169:                         */
                   1170:                        VS_UNLOCK(entry);
                   1171:                        goto not_this_one;
                   1172:                }
                   1173: 
                   1174:                /*
                   1175:                 * We need a reference for the reply message.
                   1176:                 * While we are unlocked, the bucket queue
                   1177:                 * can change and the object might be terminated.
                   1178:                 * memory_object_terminate will wait for us,
                   1179:                 * preventing deallocation of the entry.
                   1180:                 */
                   1181: 
                   1182:                if (--entry->vs_name_refs == 0) {
                   1183:                        VS_UNLOCK(entry);
                   1184: 
                   1185:                        /* keep the list locked, wont take long */
                   1186: 
                   1187:                        {
                   1188:                                int i;
                   1189:                                for(i=0; i<default_pager_max_urefs; i++)
                   1190:                                        ipc_port_make_send(port);
                   1191:                        }
                   1192:                        VS_LOCK(entry);
                   1193: 
                   1194:                        entry->vs_name_refs += default_pager_max_urefs;
                   1195:                        vs_finish_refs(entry);
                   1196:                }
                   1197:                VS_UNLOCK(entry);
                   1198: 
                   1199:                /* the arrays are wired, so no deadlock worries */
                   1200: 
                   1201:                objects[num_objects].dpo_object = (vm_offset_t) entry;
                   1202:                objects[num_objects].dpo_size = size;
                   1203:                ports  [num_objects++] = port;
                   1204:                continue;
                   1205: 
                   1206:            not_this_one:
                   1207:                /*
                   1208:                 * Do not return garbage
                   1209:                 */
                   1210:                objects[num_objects].dpo_object = (vm_offset_t) 0;
                   1211:                objects[num_objects].dpo_size = 0;
                   1212:                ports  [num_objects++] = MACH_PORT_NULL;
                   1213: 
                   1214:        }
                   1215: 
                   1216:        VSL_UNLOCK();
                   1217: 
                   1218:        /*
                   1219:         * Deallocate and clear unused memory.
                   1220:         * (Returned memory will automagically become pageable.)
                   1221:         */
                   1222: 
                   1223:        if (objects == *objectsp) {
                   1224: 
                   1225:                /*
                   1226:                 * Our returned information fit inline.
                   1227:                 * Nothing to deallocate.
                   1228:                 */
                   1229:                *ocountp = num_objects;
                   1230:        } else if (actual == 0) {
                   1231:                (void) vm_deallocate(kernel_map, oaddr, osize);
                   1232: 
                   1233:                /* return zero items inline */
                   1234:                *ocountp = 0;
                   1235:        } else {
                   1236:                vm_offset_t used;
                   1237: 
                   1238:                used = round_page(actual * sizeof * objects);
                   1239: 
                   1240:                if (used != osize)
                   1241:                        (void) vm_deallocate(kernel_map,
                   1242:                                             oaddr + used, osize - used);
                   1243: 
                   1244:                *objectsp = objects;
                   1245:                *ocountp = num_objects;
                   1246:        }
                   1247: 
                   1248:        if (ports == (MACH_PORT_FACE *)*portsp) {
                   1249: 
                   1250:                /*
                   1251:                 * Our returned information fit inline.
                   1252:                 * Nothing to deallocate.
                   1253:                 */
                   1254: 
                   1255:                *pcountp = num_objects;
                   1256:        } else if (actual == 0) {
                   1257:                (void) vm_deallocate(kernel_map, paddr, psize);
                   1258: 
                   1259:                /* return zero items inline */
                   1260:                *pcountp = 0;
                   1261:        } else {
                   1262:                vm_offset_t used;
                   1263: 
                   1264:                used = round_page(actual * sizeof * ports);
                   1265: 
                   1266:                if (used != psize)
                   1267:                        (void) vm_deallocate(kernel_map,
                   1268:                                             paddr + used, psize - used);
                   1269: 
                   1270:                *portsp = (mach_port_array_t)ports;
                   1271:                *pcountp = num_objects;
                   1272:        }
                   1273:        (void) vm_map_unwire(kernel_map, (vm_offset_t)objects, 
                   1274:                        *ocountp + (vm_offset_t)objects, FALSE); 
                   1275:        (void) vm_map_copyin(kernel_map, (vm_offset_t)objects, 
                   1276:                        *ocountp, TRUE, (vm_map_copy_t *)objectsp);
                   1277: 
                   1278:        return KERN_SUCCESS;
                   1279: 
                   1280:     nomemory:
                   1281:        {
                   1282:                register int    i;
                   1283:                for (i = 0; i < num_objects; i++)
                   1284:                        ipc_port_dealloc_kernel(ports[i]);
                   1285:        }
                   1286: 
                   1287:        if (objects != *objectsp)
                   1288:                (void) vm_deallocate(kernel_map, oaddr, osize);
                   1289: 
                   1290:        if (ports != (MACH_PORT_FACE *)*portsp)
                   1291:                (void) vm_deallocate(kernel_map, paddr, psize);
                   1292: 
                   1293:        return KERN_RESOURCE_SHORTAGE;
                   1294: }
                   1295: 
                   1296: kern_return_t
                   1297: default_pager_object_pages(
                   1298:        MACH_PORT_FACE                  pager,
                   1299:        MACH_PORT_FACE                  object,
                   1300:        default_pager_page_array_t      *pagesp,
                   1301:        mach_msg_type_number_t          *countp)
                   1302: {
                   1303:        vm_offset_t                     addr;   /* memory for page offsets */
                   1304:        vm_size_t                       size = 0; /* current memory size */
                   1305:        default_pager_page_t            * pages;
                   1306:        unsigned int                    potential, actual;
                   1307:        kern_return_t                   kr;
                   1308: 
                   1309: /*
                   1310:        if (pager != default_pager_default_port)
                   1311:                return KERN_INVALID_ARGUMENT;
                   1312: */
                   1313:        kr = vm_map_copyout(ipc_kernel_map, (vm_offset_t *)&pages, 
                   1314:                                                (vm_map_copy_t) *pagesp);
                   1315: 
                   1316:        if (kr != KERN_SUCCESS)
                   1317:                return kr;
                   1318: 
                   1319:        size = round_page(*countp * sizeof * pages);
                   1320:        kr = vm_map_wire(ipc_kernel_map, 
                   1321:                        trunc_page((vm_offset_t)pages),
                   1322:                        round_page(((vm_offset_t)pages) + size), 
                   1323:                        VM_PROT_READ|VM_PROT_WRITE, FALSE);
                   1324:        size=0;
                   1325: 
                   1326:        *pagesp = pages;
                   1327:        /* we start with the inline space */
                   1328: 
                   1329:        addr = (vm_offset_t)pages;
                   1330:        potential = *countp;
                   1331: 
                   1332:        for (;;) {
                   1333:                vstruct_t       entry;
                   1334: 
                   1335:                VSL_LOCK();
                   1336:                queue_iterate(&vstruct_list.vsl_queue, entry, vstruct_t,
                   1337:                              vs_links) {
                   1338:                        VS_LOCK(entry);
                   1339:                        if (entry->vs_object_name == object) {
                   1340:                                VSL_UNLOCK();
                   1341:                                goto found_object;
                   1342:                        }
                   1343:                        VS_UNLOCK(entry);
                   1344:                }
                   1345:                VSL_UNLOCK();
                   1346: 
                   1347:                /* did not find the object */
                   1348: 
                   1349:                if (pages != *pagesp)
                   1350:                        (void) vm_deallocate(kernel_map, addr, size);
                   1351:                return KERN_INVALID_ARGUMENT;
                   1352: 
                   1353:            found_object:
                   1354: 
                   1355:                if (!VS_MAP_TRY_LOCK(entry)) {
                   1356:                        /* oh well bad luck */
                   1357: 
                   1358:                        VS_UNLOCK(entry);
                   1359: 
                   1360:                        assert_wait_timeout( 1, THREAD_INTERRUPTIBLE);
                   1361:                        thread_block((void (*)(void)) 0);
                   1362:                        thread_cancel_timer();
                   1363:                        continue;
                   1364:                }
                   1365: 
                   1366:                actual = ps_vstruct_allocated_pages(entry, pages, potential);
                   1367:                VS_MAP_UNLOCK(entry);
                   1368:                VS_UNLOCK(entry);
                   1369: 
                   1370:                if (actual <= potential)
                   1371:                        break;
                   1372: 
                   1373:                /* allocate more memory */
                   1374: 
                   1375:                if (pages != *pagesp)
                   1376:                        (void) vm_deallocate(kernel_map, addr, size);
                   1377:                size = round_page(actual * sizeof * pages);
                   1378:                kr = vm_allocate(kernel_map, &addr, size, TRUE);
                   1379:                if (kr != KERN_SUCCESS)
                   1380:                        return kr;
                   1381:                pages = (default_pager_page_t *)addr;
                   1382:                potential = size / sizeof * pages;
                   1383:        }
                   1384: 
                   1385:        /*
                   1386:         * Deallocate and clear unused memory.
                   1387:         * (Returned memory will automagically become pageable.)
                   1388:         */
                   1389: 
                   1390:        if (pages == *pagesp) {
                   1391: 
                   1392:                /*
                   1393:                 * Our returned information fit inline.
                   1394:                 * Nothing to deallocate.
                   1395:                 */
                   1396: 
                   1397:                *countp = actual;
                   1398:        } else if (actual == 0) {
                   1399:                (void) vm_deallocate(kernel_map, addr, size);
                   1400: 
                   1401:                /* return zero items inline */
                   1402:                *countp = 0;
                   1403:        } else {
                   1404:                vm_offset_t used;
                   1405: 
                   1406:                used = round_page(actual * sizeof * pages);
                   1407: 
                   1408:                if (used != size)
                   1409:                        (void) vm_deallocate(kernel_map,
                   1410:                                             addr + used, size - used);
                   1411: 
                   1412:                *pagesp = pages;
                   1413:                *countp = actual;
                   1414:        }
                   1415:        (void) vm_map_unwire(kernel_map, (vm_offset_t)pages, 
                   1416:                        *countp + (vm_offset_t)pages, FALSE); 
                   1417:        (void) vm_map_copyin(kernel_map, (vm_offset_t)pages, 
                   1418:                        *countp, TRUE, (vm_map_copy_t *)pagesp);
                   1419:        return KERN_SUCCESS;
                   1420: }

unix.superglobalmegacorp.com

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