Annotation of Gnu-Mach/kern/task.c, revision 1.1.1.7

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1993-1988 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.2   root        5:  *
1.1       root        6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
1.1.1.2   root       11:  *
1.1       root       12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2   root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.2   root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.2   root       22:  *
1.1       root       23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     File:   kern/task.c
                     28:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young, David Golub,
                     29:  *             David Black
                     30:  *
                     31:  *     Task management primitives implementation.
                     32:  */
                     33: 
1.1.1.3   root       34: #include <string.h>
1.1       root       35: 
                     36: #include <mach/machine/vm_types.h>
                     37: #include <mach/vm_param.h>
                     38: #include <mach/task_info.h>
                     39: #include <mach/task_special_ports.h>
1.1.1.4   root       40: #include <mach_debug/mach_debug_types.h>
1.1       root       41: #include <ipc/ipc_space.h>
                     42: #include <ipc/ipc_types.h>
1.1.1.3   root       43: #include <kern/debug.h>
1.1       root       44: #include <kern/task.h>
                     45: #include <kern/thread.h>
1.1.1.3   root       46: #include <kern/slab.h>
1.1       root       47: #include <kern/kalloc.h>
                     48: #include <kern/processor.h>
1.1.1.4   root       49: #include <kern/printf.h>
1.1       root       50: #include <kern/sched_prim.h>   /* for thread_wakeup */
                     51: #include <kern/ipc_tt.h>
1.1.1.4   root       52: #include <kern/syscall_emulation.h>
                     53: #include <kern/task_notify.user.h>
1.1       root       54: #include <vm/vm_kern.h>                /* for kernel_map, ipc_kernel_map */
                     55: #include <machine/machspl.h>   /* for splsched */
                     56: 
                     57: task_t kernel_task = TASK_NULL;
1.1.1.3   root       58: struct kmem_cache task_cache;
1.1       root       59: 
1.1.1.4   root       60: /* Where to send notifications about newly created tasks.  */
                     61: ipc_port_t new_task_notification = NULL;
1.1       root       62: 
                     63: void task_init(void)
                     64: {
1.1.1.3   root       65:        kmem_cache_init(&task_cache, "task", sizeof(struct task), 0,
1.1.1.6   root       66:                        NULL, 0);
1.1       root       67: 
                     68:        eml_init();
1.1.1.3   root       69:        machine_task_module_init ();
1.1       root       70: 
                     71:        /*
                     72:         * Create the kernel task as the first task.
                     73:         * Task_create must assign to kernel_task as a side effect,
                     74:         * for other initialization. (:-()
                     75:         */
                     76:        (void) task_create(TASK_NULL, FALSE, &kernel_task);
1.1.1.4   root       77:        (void) task_set_name(kernel_task, "gnumach");
1.1.1.7 ! root       78:        vm_map_set_name(kernel_map, kernel_task->name);
1.1       root       79: }
                     80: 
                     81: kern_return_t task_create(
                     82:        task_t          parent_task,
                     83:        boolean_t       inherit_memory,
                     84:        task_t          *child_task)            /* OUT */
                     85: {
1.1.1.4   root       86:        task_t          new_task;
                     87:        processor_set_t pset;
1.1.1.3   root       88: #if FAST_TAS
1.1       root       89:        int i;
1.1.1.3   root       90: #endif
1.1       root       91: 
1.1.1.3   root       92:        new_task = (task_t) kmem_cache_alloc(&task_cache);
1.1.1.5   root       93:        if (new_task == TASK_NULL)
                     94:                return KERN_RESOURCE_SHORTAGE;
1.1       root       95: 
                     96:        /* one ref for just being alive; one for our caller */
                     97:        new_task->ref_count = 2;
                     98: 
                     99:        if (child_task == &kernel_task)  {
1.1.1.2   root      100:                new_task->map = kernel_map;
1.1       root      101:        } else if (inherit_memory) {
                    102:                new_task->map = vm_map_fork(parent_task->map);
                    103:        } else {
1.1.1.7 ! root      104:                pmap_t new_pmap = pmap_create((vm_size_t) 0);
        !           105:                if (new_pmap == PMAP_NULL)
        !           106:                        new_task->map = VM_MAP_NULL;
        !           107:                else {
        !           108:                        new_task->map = vm_map_create(new_pmap,
1.1       root      109:                                        round_page(VM_MIN_ADDRESS),
1.1.1.7 ! root      110:                                        trunc_page(VM_MAX_ADDRESS));
        !           111:                        if (new_task->map == VM_MAP_NULL)
        !           112:                                pmap_destroy(new_pmap);
        !           113:                }
        !           114:        }
        !           115:        if (new_task->map == VM_MAP_NULL) {
        !           116:                kmem_cache_free(&task_cache, (vm_address_t) new_task);
        !           117:                return KERN_RESOURCE_SHORTAGE;
1.1       root      118:        }
1.1.1.7 ! root      119:        if (child_task != &kernel_task)
        !           120:                vm_map_set_name(new_task->map, new_task->name);
1.1       root      121: 
                    122:        simple_lock_init(&new_task->lock);
                    123:        queue_init(&new_task->thread_list);
                    124:        new_task->suspend_count = 0;
                    125:        new_task->active = TRUE;
                    126:        new_task->user_stop_count = 0;
                    127:        new_task->thread_count = 0;
1.1.1.3   root      128:        new_task->faults = 0;
                    129:        new_task->zero_fills = 0;
                    130:        new_task->reactivations = 0;
                    131:        new_task->pageins = 0;
                    132:        new_task->cow_faults = 0;
                    133:        new_task->messages_sent = 0;
                    134:        new_task->messages_received = 0;
1.1       root      135: 
                    136:        eml_task_reference(new_task, parent_task);
                    137: 
                    138:        ipc_task_init(new_task, parent_task);
1.1.1.3   root      139:        machine_task_init (new_task);
1.1       root      140: 
                    141:        new_task->total_user_time.seconds = 0;
                    142:        new_task->total_user_time.microseconds = 0;
                    143:        new_task->total_system_time.seconds = 0;
                    144:        new_task->total_system_time.microseconds = 0;
                    145: 
1.1.1.2   root      146:        record_time_stamp (&new_task->creation_time);
                    147: 
1.1       root      148:        if (parent_task != TASK_NULL) {
                    149:                task_lock(parent_task);
                    150:                pset = parent_task->processor_set;
                    151:                if (!pset->active)
                    152:                        pset = &default_pset;
                    153:                pset_reference(pset);
                    154:                new_task->priority = parent_task->priority;
                    155:                task_unlock(parent_task);
                    156:        }
                    157:        else {
                    158:                pset = &default_pset;
                    159:                pset_reference(pset);
                    160:                new_task->priority = BASEPRI_USER;
                    161:        }
                    162:        pset_lock(pset);
                    163:        pset_add_task(pset, new_task);
                    164:        pset_unlock(pset);
                    165: 
                    166:        new_task->may_assign = TRUE;
                    167:        new_task->assign_active = FALSE;
                    168: 
                    169: #if    MACH_PCSAMPLE
                    170:        new_task->pc_sample.buffer = 0;
                    171:        new_task->pc_sample.seqno = 0;
                    172:        new_task->pc_sample.sampletypes = 0;
                    173: #endif /* MACH_PCSAMPLE */
                    174: 
                    175: #if    FAST_TAS
                    176:        for (i = 0; i < TASK_FAST_TAS_NRAS; i++)  {
                    177:            if (inherit_memory) {
                    178:                new_task->fast_tas_base[i] = parent_task->fast_tas_base[i];
                    179:                new_task->fast_tas_end[i]  = parent_task->fast_tas_end[i];
                    180:            } else {
                    181:                new_task->fast_tas_base[i] = (vm_offset_t)0;
                    182:                new_task->fast_tas_end[i]  = (vm_offset_t)0;
                    183:            }
                    184:        }
                    185: #endif /* FAST_TAS */
1.1.1.2   root      186: 
1.1.1.4   root      187:        if (parent_task == TASK_NULL)
                    188:                snprintf (new_task->name, sizeof new_task->name, "%p",
                    189:                          new_task);
                    190:        else
                    191:                snprintf (new_task->name, sizeof new_task->name, "(%.*s)",
                    192:                          sizeof new_task->name - 3, parent_task->name);
                    193: 
                    194:        if (new_task_notification != NULL) {
                    195:                task_reference (new_task);
                    196:                task_reference (parent_task);
                    197:                mach_notify_new_task (new_task_notification,
                    198:                                      convert_task_to_port (new_task),
                    199:                                      convert_task_to_port (parent_task));
                    200:        }
                    201: 
1.1       root      202:        ipc_task_enable(new_task);
                    203: 
                    204:        *child_task = new_task;
                    205:        return KERN_SUCCESS;
                    206: }
                    207: 
                    208: /*
                    209:  *     task_deallocate:
                    210:  *
                    211:  *     Give up a reference to the specified task and destroy it if there
                    212:  *     are no other references left.  It is assumed that the current thread
                    213:  *     is never in this task.
                    214:  */
                    215: void task_deallocate(
1.1.1.4   root      216:        task_t  task)
1.1       root      217: {
1.1.1.4   root      218:        int c;
                    219:        processor_set_t pset;
1.1       root      220: 
                    221:        if (task == TASK_NULL)
                    222:                return;
                    223: 
                    224:        task_lock(task);
                    225:        c = --(task->ref_count);
                    226:        task_unlock(task);
                    227:        if (c != 0)
                    228:                return;
                    229: 
1.1.1.3   root      230:        machine_task_terminate (task);
1.1       root      231: 
                    232:        eml_task_deallocate(task);
                    233: 
                    234:        pset = task->processor_set;
                    235:        pset_lock(pset);
                    236:        pset_remove_task(pset,task);
                    237:        pset_unlock(pset);
                    238:        pset_deallocate(pset);
                    239:        vm_map_deallocate(task->map);
                    240:        is_release(task->itk_space);
1.1.1.3   root      241:        kmem_cache_free(&task_cache, (vm_offset_t) task);
1.1       root      242: }
                    243: 
                    244: void task_reference(
1.1.1.4   root      245:        task_t  task)
1.1       root      246: {
                    247:        if (task == TASK_NULL)
                    248:                return;
                    249: 
                    250:        task_lock(task);
                    251:        task->ref_count++;
                    252:        task_unlock(task);
                    253: }
                    254: 
                    255: /*
                    256:  *     task_terminate:
                    257:  *
                    258:  *     Terminate the specified task.  See comments on thread_terminate
                    259:  *     (kern/thread.c) about problems with terminating the "current task."
                    260:  */
                    261: kern_return_t task_terminate(
1.1.1.4   root      262:        task_t  task)
1.1       root      263: {
1.1.1.4   root      264:        thread_t                thread, cur_thread;
                    265:        queue_head_t            *list;
                    266:        task_t                  cur_task;
1.1       root      267:        spl_t                   s;
                    268: 
                    269:        if (task == TASK_NULL)
                    270:                return KERN_INVALID_ARGUMENT;
                    271: 
                    272:        list = &task->thread_list;
                    273:        cur_task = current_task();
                    274:        cur_thread = current_thread();
                    275: 
                    276:        /*
                    277:         *      Deactivate task so that it can't be terminated again,
                    278:         *      and so lengthy operations in progress will abort.
                    279:         *
                    280:         *      If the current thread is in this task, remove it from
                    281:         *      the task's thread list to keep the thread-termination
                    282:         *      loop simple.
                    283:         */
                    284:        if (task == cur_task) {
                    285:                task_lock(task);
                    286:                if (!task->active) {
                    287:                        /*
                    288:                         *      Task is already being terminated.
                    289:                         */
                    290:                        task_unlock(task);
                    291:                        return KERN_FAILURE;
                    292:                }
                    293:                /*
                    294:                 *      Make sure current thread is not being terminated.
                    295:                 */
                    296:                s = splsched();
                    297:                thread_lock(cur_thread);
                    298:                if (!cur_thread->active) {
                    299:                        thread_unlock(cur_thread);
                    300:                        (void) splx(s);
                    301:                        task_unlock(task);
                    302:                        thread_terminate(cur_thread);
                    303:                        return KERN_FAILURE;
                    304:                }
1.1.1.4   root      305:                task_hold_locked(task);
1.1       root      306:                task->active = FALSE;
                    307:                queue_remove(list, cur_thread, thread_t, thread_list);
                    308:                thread_unlock(cur_thread);
                    309:                (void) splx(s);
                    310:                task_unlock(task);
                    311: 
                    312:                /*
                    313:                 *      Shut down this thread's ipc now because it must
                    314:                 *      be left alone to terminate the task.
                    315:                 */
                    316:                ipc_thread_disable(cur_thread);
                    317:                ipc_thread_terminate(cur_thread);
                    318:        }
                    319:        else {
                    320:                /*
                    321:                 *      Lock both current and victim task to check for
                    322:                 *      potential deadlock.
                    323:                 */
                    324:                if ((vm_offset_t)task < (vm_offset_t)cur_task) {
                    325:                        task_lock(task);
                    326:                        task_lock(cur_task);
                    327:                }
                    328:                else {
                    329:                        task_lock(cur_task);
                    330:                        task_lock(task);
                    331:                }
                    332:                /*
                    333:                 *      Check if current thread or task is being terminated.
                    334:                 */
                    335:                s = splsched();
                    336:                thread_lock(cur_thread);
                    337:                if ((!cur_task->active) ||(!cur_thread->active)) {
                    338:                        /*
                    339:                         * Current task or thread is being terminated.
                    340:                         */
                    341:                        thread_unlock(cur_thread);
                    342:                        (void) splx(s);
                    343:                        task_unlock(task);
                    344:                        task_unlock(cur_task);
                    345:                        thread_terminate(cur_thread);
                    346:                        return KERN_FAILURE;
                    347:                }
                    348:                thread_unlock(cur_thread);
                    349:                (void) splx(s);
                    350:                task_unlock(cur_task);
                    351: 
                    352:                if (!task->active) {
                    353:                        /*
                    354:                         *      Task is already being terminated.
                    355:                         */
                    356:                        task_unlock(task);
                    357:                        return KERN_FAILURE;
                    358:                }
1.1.1.4   root      359:                task_hold_locked(task);
1.1       root      360:                task->active = FALSE;
                    361:                task_unlock(task);
                    362:        }
                    363: 
                    364:        /*
                    365:         *      Prevent further execution of the task.  ipc_task_disable
                    366:         *      prevents further task operations via the task port.
                    367:         *      If this is the current task, the current thread will
                    368:         *      be left running.
                    369:         */
                    370:        (void) task_dowait(task,TRUE);                  /* may block */
1.1.1.4   root      371:        ipc_task_disable(task);
1.1       root      372: 
                    373:        /*
                    374:         *      Terminate each thread in the task.
                    375:         *
                    376:          *      The task_port is closed down, so no more thread_create
                    377:          *      operations can be done.  Thread_force_terminate closes the
                    378:          *      thread port for each thread; when that is done, the
                    379:          *      thread will eventually disappear.  Thus the loop will
                    380:          *      terminate.  Call thread_force_terminate instead of
                    381:          *      thread_terminate to avoid deadlock checks.  Need
                    382:          *      to call thread_block() inside loop because some other
                    383:          *      thread (e.g., the reaper) may have to run to get rid
                    384:          *      of all references to the thread; it won't vanish from
                    385:          *      the task's thread list until the last one is gone.
                    386:          */
                    387:         task_lock(task);
                    388:         while (!queue_empty(list)) {
                    389:                 thread = (thread_t) queue_first(list);
                    390:                 thread_reference(thread);
                    391:                 task_unlock(task);
                    392:                 thread_force_terminate(thread);
                    393:                 thread_deallocate(thread);
1.1.1.5   root      394:                 thread_block(thread_no_continuation);
1.1       root      395:                 task_lock(task);
                    396:         }
                    397:         task_unlock(task);
                    398: 
                    399:        /*
                    400:         *      Shut down IPC.
                    401:         */
                    402:        ipc_task_terminate(task);
                    403: 
                    404: 
                    405:        /*
                    406:         *      Deallocate the task's reference to itself.
                    407:         */
                    408:        task_deallocate(task);
                    409: 
                    410:        /*
                    411:         *      If the current thread is in this task, it has not yet
                    412:         *      been terminated (since it was removed from the task's
                    413:         *      thread-list).  Put it back in the thread list (for
                    414:         *      completeness), and terminate it.  Since it holds the
                    415:         *      last reference to the task, terminating it will deallocate
                    416:         *      the task.
                    417:         */
                    418:        if (cur_thread->task == task) {
                    419:                task_lock(task);
                    420:                s = splsched();
                    421:                queue_enter(list, cur_thread, thread_t, thread_list);
                    422:                (void) splx(s);
                    423:                task_unlock(task);
                    424:                (void) thread_terminate(cur_thread);
                    425:        }
                    426: 
                    427:        return KERN_SUCCESS;
                    428: }
                    429: 
                    430: /*
                    431:  *     task_hold:
                    432:  *
                    433:  *     Suspend execution of the specified task.
                    434:  *     This is a recursive-style suspension of the task, a count of
                    435:  *     suspends is maintained.
1.1.1.4   root      436:  *
                    437:  *     CONDITIONS: the task is locked and active.
1.1       root      438:  */
1.1.1.4   root      439: void task_hold_locked(
                    440:        task_t  task)
1.1       root      441: {
1.1.1.4   root      442:        queue_head_t    *list;
                    443:        thread_t        thread, cur_thread;
1.1       root      444: 
1.1.1.4   root      445:        assert(task->active);
1.1       root      446: 
1.1.1.4   root      447:        cur_thread = current_thread();
1.1       root      448: 
                    449:        task->suspend_count++;
                    450: 
                    451:        /*
                    452:         *      Iterate through all the threads and hold them.
                    453:         *      Do not hold the current thread if it is within the
                    454:         *      task.
                    455:         */
                    456:        list = &task->thread_list;
                    457:        queue_iterate(list, thread, thread_t, thread_list) {
                    458:                if (thread != cur_thread)
                    459:                        thread_hold(thread);
                    460:        }
1.1.1.4   root      461: }
                    462: 
                    463: /*
                    464:  *     task_hold:
                    465:  *
                    466:  *     Suspend execution of the specified task.
                    467:  *     This is a recursive-style suspension of the task, a count of
                    468:  *     suspends is maintained.
                    469:  */
                    470: kern_return_t task_hold(
                    471:        task_t  task)
                    472: {
                    473:        task_lock(task);
                    474:        if (!task->active) {
                    475:                task_unlock(task);
                    476:                return KERN_FAILURE;
                    477:        }
                    478: 
                    479:        task_hold_locked(task);
                    480: 
1.1       root      481:        task_unlock(task);
                    482:        return KERN_SUCCESS;
                    483: }
                    484: 
                    485: /*
                    486:  *     task_dowait:
                    487:  *
                    488:  *     Wait until the task has really been suspended (all of the threads
                    489:  *     are stopped).  Skip the current thread if it is within the task.
                    490:  *
                    491:  *     If task is deactivated while waiting, return a failure code unless
                    492:  *     must_wait is true.
                    493:  */
                    494: kern_return_t task_dowait(
1.1.1.4   root      495:        task_t  task,
1.1       root      496:        boolean_t must_wait)
                    497: {
1.1.1.4   root      498:        queue_head_t    *list;
                    499:        thread_t        thread, cur_thread, prev_thread;
                    500:        kern_return_t   ret = KERN_SUCCESS;
1.1       root      501: 
                    502:        /*
                    503:         *      Iterate through all the threads.
                    504:         *      While waiting for each thread, we gain a reference to it
                    505:         *      to prevent it from going away on us.  This guarantees
                    506:         *      that the "next" thread in the list will be a valid thread.
                    507:         *
                    508:         *      We depend on the fact that if threads are created while
                    509:         *      we are looping through the threads, they will be held
                    510:         *      automatically.  We don't care about threads that get
                    511:         *      deallocated along the way (the reference prevents it
                    512:         *      from happening to the thread we are working with).
                    513:         *
                    514:         *      If the current thread is in the affected task, it is skipped.
                    515:         *
                    516:         *      If the task is deactivated before we're done, and we don't
                    517:         *      have to wait for it (must_wait is FALSE), just bail out.
                    518:         */
                    519:        cur_thread = current_thread();
                    520: 
                    521:        list = &task->thread_list;
                    522:        prev_thread = THREAD_NULL;
                    523:        task_lock(task);
                    524:        queue_iterate(list, thread, thread_t, thread_list) {
                    525:                if (!(task->active) && !(must_wait)) {
                    526:                        ret = KERN_FAILURE;
                    527:                        break;
                    528:                }
                    529:                if (thread != cur_thread) {
                    530:                        thread_reference(thread);
                    531:                        task_unlock(task);
                    532:                        if (prev_thread != THREAD_NULL)
                    533:                                thread_deallocate(prev_thread);
                    534:                                                        /* may block */
                    535:                        (void) thread_dowait(thread, TRUE);  /* may block */
                    536:                        prev_thread = thread;
                    537:                        task_lock(task);
                    538:                }
                    539:        }
                    540:        task_unlock(task);
                    541:        if (prev_thread != THREAD_NULL)
                    542:                thread_deallocate(prev_thread);         /* may block */
                    543:        return ret;
                    544: }
                    545: 
                    546: kern_return_t task_release(
1.1.1.4   root      547:        task_t  task)
1.1       root      548: {
1.1.1.4   root      549:        queue_head_t    *list;
                    550:        thread_t        thread, next;
1.1       root      551: 
                    552:        task_lock(task);
                    553:        if (!task->active) {
                    554:                task_unlock(task);
                    555:                return KERN_FAILURE;
                    556:        }
                    557: 
                    558:        task->suspend_count--;
                    559: 
                    560:        /*
                    561:         *      Iterate through all the threads and release them
                    562:         */
                    563:        list = &task->thread_list;
                    564:        thread = (thread_t) queue_first(list);
                    565:        while (!queue_end(list, (queue_entry_t) thread)) {
                    566:                next = (thread_t) queue_next(&thread->thread_list);
                    567:                thread_release(thread);
                    568:                thread = next;
                    569:        }
                    570:        task_unlock(task);
                    571:        return KERN_SUCCESS;
                    572: }
                    573: 
                    574: kern_return_t task_threads(
                    575:        task_t          task,
                    576:        thread_array_t  *thread_list,
                    577:        natural_t       *count)
                    578: {
                    579:        unsigned int actual;    /* this many threads */
                    580:        thread_t thread;
                    581:        thread_t *threads;
1.1.1.6   root      582:        unsigned i;
1.1       root      583: 
                    584:        vm_size_t size, size_needed;
                    585:        vm_offset_t addr;
                    586: 
                    587:        if (task == TASK_NULL)
                    588:                return KERN_INVALID_ARGUMENT;
                    589: 
                    590:        size = 0; addr = 0;
                    591: 
                    592:        for (;;) {
                    593:                task_lock(task);
                    594:                if (!task->active) {
                    595:                        task_unlock(task);
                    596:                        return KERN_FAILURE;
                    597:                }
                    598: 
                    599:                actual = task->thread_count;
                    600: 
                    601:                /* do we have the memory we need? */
                    602: 
                    603:                size_needed = actual * sizeof(mach_port_t);
                    604:                if (size_needed <= size)
                    605:                        break;
                    606: 
                    607:                /* unlock the task and allocate more memory */
                    608:                task_unlock(task);
                    609: 
                    610:                if (size != 0)
                    611:                        kfree(addr, size);
                    612: 
                    613:                assert(size_needed > 0);
                    614:                size = size_needed;
                    615: 
                    616:                addr = kalloc(size);
                    617:                if (addr == 0)
                    618:                        return KERN_RESOURCE_SHORTAGE;
                    619:        }
                    620: 
                    621:        /* OK, have memory and the task is locked & active */
                    622: 
                    623:        threads = (thread_t *) addr;
                    624: 
                    625:        for (i = 0, thread = (thread_t) queue_first(&task->thread_list);
                    626:             i < actual;
                    627:             i++, thread = (thread_t) queue_next(&thread->thread_list)) {
                    628:                /* take ref for convert_thread_to_port */
                    629:                thread_reference(thread);
                    630:                threads[i] = thread;
                    631:        }
                    632:        assert(queue_end(&task->thread_list, (queue_entry_t) thread));
                    633: 
                    634:        /* can unlock task now that we've got the thread refs */
                    635:        task_unlock(task);
                    636: 
                    637:        if (actual == 0) {
                    638:                /* no threads, so return null pointer and deallocate memory */
                    639: 
                    640:                *thread_list = 0;
                    641:                *count = 0;
                    642: 
                    643:                if (size != 0)
                    644:                        kfree(addr, size);
                    645:        } else {
                    646:                /* if we allocated too much, must copy */
                    647: 
                    648:                if (size_needed < size) {
                    649:                        vm_offset_t newaddr;
                    650: 
                    651:                        newaddr = kalloc(size_needed);
                    652:                        if (newaddr == 0) {
                    653:                                for (i = 0; i < actual; i++)
                    654:                                        thread_deallocate(threads[i]);
                    655:                                kfree(addr, size);
                    656:                                return KERN_RESOURCE_SHORTAGE;
                    657:                        }
                    658: 
1.1.1.3   root      659:                        memcpy((void *) newaddr, (void *) addr, size_needed);
1.1       root      660:                        kfree(addr, size);
                    661:                        threads = (thread_t *) newaddr;
                    662:                }
                    663: 
                    664:                *thread_list = (mach_port_t *) threads;
                    665:                *count = actual;
                    666: 
                    667:                /* do the conversion that Mig should handle */
                    668: 
                    669:                for (i = 0; i < actual; i++)
                    670:                        ((ipc_port_t *) threads)[i] =
                    671:                                convert_thread_to_port(threads[i]);
                    672:        }
                    673: 
                    674:        return KERN_SUCCESS;
                    675: }
                    676: 
                    677: kern_return_t task_suspend(
1.1.1.4   root      678:        task_t  task)
1.1       root      679: {
1.1.1.4   root      680:        boolean_t       hold;
1.1       root      681: 
                    682:        if (task == TASK_NULL)
                    683:                return KERN_INVALID_ARGUMENT;
                    684: 
                    685:        hold = FALSE;
                    686:        task_lock(task);
                    687:        if ((task->user_stop_count)++ == 0)
                    688:                hold = TRUE;
                    689:        task_unlock(task);
                    690: 
                    691:        /*
                    692:         *      If the stop count was positive, the task is
                    693:         *      already stopped and we can exit.
                    694:         */
                    695:        if (!hold) {
                    696:                return KERN_SUCCESS;
                    697:        }
                    698: 
                    699:        /*
                    700:         *      Hold all of the threads in the task, and wait for
                    701:         *      them to stop.  If the current thread is within
                    702:         *      this task, hold it separately so that all of the
                    703:         *      other threads can stop first.
                    704:         */
                    705: 
                    706:        if (task_hold(task) != KERN_SUCCESS)
                    707:                return KERN_FAILURE;
                    708: 
                    709:        if (task_dowait(task, FALSE) != KERN_SUCCESS)
                    710:                return KERN_FAILURE;
                    711: 
                    712:        if (current_task() == task) {
                    713:                spl_t s;
                    714: 
                    715:                thread_hold(current_thread());
                    716:                /*
                    717:                 *      We want to call thread_block on our way out,
                    718:                 *      to stop running.
                    719:                 */
                    720:                s = splsched();
                    721:                ast_on(cpu_number(), AST_BLOCK);
                    722:                (void) splx(s);
                    723:        }
                    724: 
                    725:        return KERN_SUCCESS;
                    726: }
                    727: 
                    728: kern_return_t task_resume(
1.1.1.4   root      729:        task_t  task)
1.1       root      730: {
1.1.1.4   root      731:        boolean_t       release;
1.1       root      732: 
                    733:        if (task == TASK_NULL)
                    734:                return KERN_INVALID_ARGUMENT;
                    735: 
                    736:        release = FALSE;
                    737:        task_lock(task);
                    738:        if (task->user_stop_count > 0) {
                    739:                if (--(task->user_stop_count) == 0)
                    740:                        release = TRUE;
                    741:        }
                    742:        else {
                    743:                task_unlock(task);
                    744:                return KERN_FAILURE;
                    745:        }
                    746:        task_unlock(task);
                    747: 
                    748:        /*
                    749:         *      Release the task if necessary.
                    750:         */
                    751:        if (release)
                    752:                return task_release(task);
                    753: 
                    754:        return KERN_SUCCESS;
                    755: }
                    756: 
                    757: kern_return_t task_info(
                    758:        task_t                  task,
                    759:        int                     flavor,
                    760:        task_info_t             task_info_out,  /* pointer to OUT array */
                    761:        natural_t               *task_info_count)       /* IN/OUT */
                    762: {
                    763:        vm_map_t                map;
                    764: 
                    765:        if (task == TASK_NULL)
                    766:                return KERN_INVALID_ARGUMENT;
                    767: 
                    768:        switch (flavor) {
                    769:            case TASK_BASIC_INFO:
                    770:            {
1.1.1.4   root      771:                task_basic_info_t       basic_info;
1.1       root      772: 
1.1.1.2   root      773:                /* Allow *task_info_count to be two words smaller than
                    774:                   the usual amount, because creation_time is a new member
                    775:                   that some callers might not know about. */
                    776: 
                    777:                if (*task_info_count < TASK_BASIC_INFO_COUNT - 2) {
1.1       root      778:                    return KERN_INVALID_ARGUMENT;
                    779:                }
                    780: 
                    781:                basic_info = (task_basic_info_t) task_info_out;
                    782: 
                    783:                map = (task == kernel_task) ? kernel_map : task->map;
                    784: 
                    785:                basic_info->virtual_size  = map->size;
                    786:                basic_info->resident_size = pmap_resident_count(map->pmap)
                    787:                                                   * PAGE_SIZE;
                    788: 
                    789:                task_lock(task);
                    790:                basic_info->base_priority = task->priority;
                    791:                basic_info->suspend_count = task->user_stop_count;
                    792:                basic_info->user_time.seconds
                    793:                                = task->total_user_time.seconds;
                    794:                basic_info->user_time.microseconds
                    795:                                = task->total_user_time.microseconds;
                    796:                basic_info->system_time.seconds
                    797:                                = task->total_system_time.seconds;
1.1.1.2   root      798:                basic_info->system_time.microseconds
1.1       root      799:                                = task->total_system_time.microseconds;
1.1.1.5   root      800:                read_time_stamp(&task->creation_time,
                    801:                                &basic_info->creation_time);
1.1       root      802:                task_unlock(task);
                    803: 
1.1.1.2   root      804:                if (*task_info_count > TASK_BASIC_INFO_COUNT)
                    805:                  *task_info_count = TASK_BASIC_INFO_COUNT;
1.1       root      806:                break;
                    807:            }
                    808: 
1.1.1.3   root      809:            case TASK_EVENTS_INFO:
                    810:            {
1.1.1.4   root      811:                task_events_info_t      event_info;
1.1.1.3   root      812: 
                    813:                if (*task_info_count < TASK_EVENTS_INFO_COUNT) {
                    814:                    return KERN_INVALID_ARGUMENT;
                    815:                }
                    816: 
                    817:                event_info = (task_events_info_t) task_info_out;
                    818: 
1.1.1.4   root      819:                task_lock(task);
1.1.1.3   root      820:                event_info->faults = task->faults;
                    821:                event_info->zero_fills = task->zero_fills;
                    822:                event_info->reactivations = task->reactivations;
                    823:                event_info->pageins = task->pageins;
                    824:                event_info->cow_faults = task->cow_faults;
                    825:                event_info->messages_sent = task->messages_sent;
                    826:                event_info->messages_received = task->messages_received;
1.1.1.4   root      827:                task_unlock(task);
1.1.1.3   root      828: 
                    829:                *task_info_count = TASK_EVENTS_INFO_COUNT;
                    830:                break;
                    831:            }
                    832: 
1.1       root      833:            case TASK_THREAD_TIMES_INFO:
                    834:            {
1.1.1.4   root      835:                task_thread_times_info_t times_info;
                    836:                thread_t        thread;
1.1       root      837: 
                    838:                if (*task_info_count < TASK_THREAD_TIMES_INFO_COUNT) {
                    839:                    return KERN_INVALID_ARGUMENT;
                    840:                }
                    841: 
                    842:                times_info = (task_thread_times_info_t) task_info_out;
                    843:                times_info->user_time.seconds = 0;
                    844:                times_info->user_time.microseconds = 0;
                    845:                times_info->system_time.seconds = 0;
                    846:                times_info->system_time.microseconds = 0;
                    847: 
                    848:                task_lock(task);
                    849:                queue_iterate(&task->thread_list, thread,
                    850:                              thread_t, thread_list)
                    851:                {
                    852:                    time_value_t user_time, system_time;
                    853:                    spl_t                s;
                    854: 
                    855:                    s = splsched();
                    856:                    thread_lock(thread);
                    857: 
                    858:                    thread_read_times(thread, &user_time, &system_time);
                    859: 
                    860:                    thread_unlock(thread);
                    861:                    splx(s);
                    862: 
                    863:                    time_value_add(&times_info->user_time, &user_time);
                    864:                    time_value_add(&times_info->system_time, &system_time);
                    865:                }
                    866:                task_unlock(task);
                    867: 
                    868:                *task_info_count = TASK_THREAD_TIMES_INFO_COUNT;
                    869:                break;
                    870:            }
                    871: 
                    872:            default:
                    873:                return KERN_INVALID_ARGUMENT;
                    874:        }
                    875: 
                    876:        return KERN_SUCCESS;
                    877: }
                    878: 
                    879: #if    MACH_HOST
                    880: /*
                    881:  *     task_assign:
                    882:  *
                    883:  *     Change the assigned processor set for the task
                    884:  */
                    885: kern_return_t
                    886: task_assign(
                    887:        task_t          task,
                    888:        processor_set_t new_pset,
                    889:        boolean_t       assign_threads)
                    890: {
                    891:        kern_return_t           ret = KERN_SUCCESS;
1.1.1.4   root      892:        thread_t        thread, prev_thread;
                    893:        queue_head_t    *list;
                    894:        processor_set_t pset;
1.1       root      895: 
                    896:        if (task == TASK_NULL || new_pset == PROCESSOR_SET_NULL) {
                    897:                return KERN_INVALID_ARGUMENT;
                    898:        }
                    899: 
                    900:        /*
                    901:         *      Freeze task`s assignment.  Prelude to assigning
                    902:         *      task.  Only one freeze may be held per task.
                    903:         */
                    904: 
                    905:        task_lock(task);
                    906:        while (task->may_assign == FALSE) {
                    907:                task->assign_active = TRUE;
                    908:                assert_wait((event_t)&task->assign_active, TRUE);
                    909:                task_unlock(task);
1.1.1.5   root      910:                thread_block(thread_no_continuation);
1.1       root      911:                task_lock(task);
                    912:        }
                    913: 
                    914:        /*
                    915:         *      Avoid work if task already in this processor set.
                    916:         */
                    917:        if (task->processor_set == new_pset)  {
                    918:                /*
                    919:                 *      No need for task->assign_active wakeup:
                    920:                 *      task->may_assign is still TRUE.
                    921:                 */
                    922:                task_unlock(task);
                    923:                return KERN_SUCCESS;
                    924:        }
                    925: 
                    926:        task->may_assign = FALSE;
                    927:        task_unlock(task);
                    928: 
                    929:        /*
                    930:         *      Safe to get the task`s pset: it cannot change while
                    931:         *      task is frozen.
                    932:         */
                    933:        pset = task->processor_set;
                    934: 
                    935:        /*
                    936:         *      Lock both psets now.  Use ordering to avoid deadlock.
                    937:         */
                    938:     Restart:
                    939:        if ((vm_offset_t) pset < (vm_offset_t) new_pset) {
                    940:            pset_lock(pset);
                    941:            pset_lock(new_pset);
                    942:        }
                    943:        else {
                    944:            pset_lock(new_pset);
                    945:            pset_lock(pset);
                    946:        }
                    947: 
                    948:        /*
                    949:         *      Check if new_pset is ok to assign to.  If not,
                    950:         *      reassign to default_pset.
                    951:         */
                    952:        if (!new_pset->active) {
                    953:            pset_unlock(pset);
                    954:            pset_unlock(new_pset);
                    955:            new_pset = &default_pset;
                    956:            goto Restart;
                    957:        }
                    958: 
                    959:        pset_reference(new_pset);
                    960: 
                    961:        /*
                    962:         *      Now grab the task lock and move the task.
                    963:         */
                    964: 
                    965:        task_lock(task);
                    966:        pset_remove_task(pset, task);
                    967:        pset_add_task(new_pset, task);
                    968: 
                    969:        pset_unlock(pset);
                    970:        pset_unlock(new_pset);
                    971: 
                    972:        if (assign_threads == FALSE) {
                    973:                /*
                    974:                 *      We leave existing threads at their
                    975:                 *      old assignments.  Unfreeze task`s
                    976:                 *      assignment.
                    977:                 */
                    978:                task->may_assign = TRUE;
                    979:                if (task->assign_active) {
                    980:                        task->assign_active = FALSE;
                    981:                        thread_wakeup((event_t) &task->assign_active);
                    982:                }
                    983:                task_unlock(task);
                    984:                pset_deallocate(pset);
                    985:                return KERN_SUCCESS;
                    986:        }
                    987: 
                    988:        /*
                    989:         *      If current thread is in task, freeze its assignment.
                    990:         */
                    991:        if (current_thread()->task == task) {
                    992:                task_unlock(task);
                    993:                thread_freeze(current_thread());
                    994:                task_lock(task);
                    995:        }
                    996: 
                    997:        /*
                    998:         *      Iterate down the thread list reassigning all the threads.
                    999:         *      New threads pick up task's new processor set automatically.
                   1000:         *      Do current thread last because new pset may be empty.
                   1001:         */
                   1002:        list = &task->thread_list;
                   1003:        prev_thread = THREAD_NULL;
                   1004:        queue_iterate(list, thread, thread_t, thread_list) {
                   1005:                if (!(task->active)) {
                   1006:                        ret = KERN_FAILURE;
                   1007:                        break;
                   1008:                }
                   1009:                if (thread != current_thread()) {
                   1010:                        thread_reference(thread);
                   1011:                        task_unlock(task);
                   1012:                        if (prev_thread != THREAD_NULL)
                   1013:                            thread_deallocate(prev_thread); /* may block */
                   1014:                        thread_assign(thread,new_pset);     /* may block */
                   1015:                        prev_thread = thread;
                   1016:                        task_lock(task);
                   1017:                }
                   1018:        }
                   1019: 
                   1020:        /*
                   1021:         *      Done, wakeup anyone waiting for us.
                   1022:         */
                   1023:        task->may_assign = TRUE;
                   1024:        if (task->assign_active) {
                   1025:                task->assign_active = FALSE;
                   1026:                thread_wakeup((event_t)&task->assign_active);
                   1027:        }
                   1028:        task_unlock(task);
                   1029:        if (prev_thread != THREAD_NULL)
                   1030:                thread_deallocate(prev_thread);         /* may block */
                   1031: 
                   1032:        /*
                   1033:         *      Finish assignment of current thread.
                   1034:         */
                   1035:        if (current_thread()->task == task)
                   1036:                thread_doassign(current_thread(), new_pset, TRUE);
                   1037: 
                   1038:        pset_deallocate(pset);
                   1039: 
                   1040:        return ret;
                   1041: }
                   1042: #else  /* MACH_HOST */
                   1043: /*
                   1044:  *     task_assign:
                   1045:  *
                   1046:  *     Change the assigned processor set for the task
                   1047:  */
                   1048: kern_return_t
                   1049: task_assign(
                   1050:        task_t          task,
                   1051:        processor_set_t new_pset,
                   1052:        boolean_t       assign_threads)
                   1053: {
                   1054:        return KERN_FAILURE;
                   1055: }
                   1056: #endif /* MACH_HOST */
1.1.1.2   root     1057: 
1.1       root     1058: 
                   1059: /*
                   1060:  *     task_assign_default:
                   1061:  *
                   1062:  *     Version of task_assign to assign to default processor set.
                   1063:  */
                   1064: kern_return_t
                   1065: task_assign_default(
                   1066:        task_t          task,
                   1067:        boolean_t       assign_threads)
                   1068: {
                   1069:        return task_assign(task, &default_pset, assign_threads);
                   1070: }
                   1071: 
                   1072: /*
                   1073:  *     task_get_assignment
                   1074:  *
                   1075:  *     Return name of processor set that task is assigned to.
                   1076:  */
                   1077: kern_return_t task_get_assignment(
                   1078:        task_t          task,
                   1079:        processor_set_t *pset)
                   1080: {
1.1.1.5   root     1081:        if (task == TASK_NULL)
                   1082:                return KERN_INVALID_ARGUMENT;
                   1083: 
1.1       root     1084:        if (!task->active)
                   1085:                return KERN_FAILURE;
                   1086: 
                   1087:        *pset = task->processor_set;
                   1088:        pset_reference(*pset);
                   1089:        return KERN_SUCCESS;
                   1090: }
                   1091: 
                   1092: /*
                   1093:  *     task_priority
                   1094:  *
                   1095:  *     Set priority of task; used only for newly created threads.
                   1096:  *     Optionally change priorities of threads.
                   1097:  */
                   1098: kern_return_t
                   1099: task_priority(
                   1100:        task_t          task,
                   1101:        int             priority,
                   1102:        boolean_t       change_threads)
                   1103: {
                   1104:        kern_return_t   ret = KERN_SUCCESS;
                   1105: 
                   1106:        if (task == TASK_NULL || invalid_pri(priority))
                   1107:                return KERN_INVALID_ARGUMENT;
                   1108: 
                   1109:        task_lock(task);
                   1110:        task->priority = priority;
                   1111: 
                   1112:        if (change_threads) {
1.1.1.4   root     1113:                thread_t        thread;
                   1114:                queue_head_t    *list;
1.1       root     1115: 
                   1116:                list = &task->thread_list;
                   1117:                queue_iterate(list, thread, thread_t, thread_list) {
                   1118:                        if (thread_priority(thread, priority, FALSE)
                   1119:                                != KERN_SUCCESS)
                   1120:                                        ret = KERN_FAILURE;
                   1121:                }
                   1122:        }
                   1123: 
                   1124:        task_unlock(task);
                   1125:        return ret;
                   1126: }
                   1127: 
                   1128: /*
1.1.1.4   root     1129:  *     task_set_name
                   1130:  *
                   1131:  *     Set the name of task TASK to NAME.  This is a debugging aid.
                   1132:  *     NAME will be used in error messages printed by the kernel.
                   1133:  */
                   1134: kern_return_t
                   1135: task_set_name(
                   1136:        task_t                  task,
                   1137:        kernel_debug_name_t     name)
                   1138: {
                   1139:        strncpy(task->name, name, sizeof task->name - 1);
                   1140:        task->name[sizeof task->name - 1] = '\0';
                   1141:        return KERN_SUCCESS;
                   1142: }
                   1143: 
                   1144: /*
1.1       root     1145:  *     task_collect_scan:
                   1146:  *
                   1147:  *     Attempt to free resources owned by tasks.
                   1148:  */
                   1149: 
                   1150: void task_collect_scan(void)
                   1151: {
1.1.1.4   root     1152:        task_t                  task, prev_task;
1.1       root     1153:        processor_set_t         pset, prev_pset;
                   1154: 
                   1155:        prev_task = TASK_NULL;
                   1156:        prev_pset = PROCESSOR_SET_NULL;
                   1157: 
                   1158:        simple_lock(&all_psets_lock);
                   1159:        queue_iterate(&all_psets, pset, processor_set_t, all_psets) {
                   1160:                pset_lock(pset);
                   1161:                queue_iterate(&pset->tasks, task, task_t, pset_tasks) {
                   1162:                        task_reference(task);
                   1163:                        pset_reference(pset);
                   1164:                        pset_unlock(pset);
                   1165:                        simple_unlock(&all_psets_lock);
                   1166: 
1.1.1.3   root     1167:                        machine_task_collect (task);
1.1       root     1168:                        pmap_collect(task->map->pmap);
                   1169: 
                   1170:                        if (prev_task != TASK_NULL)
                   1171:                                task_deallocate(prev_task);
                   1172:                        prev_task = task;
                   1173: 
                   1174:                        if (prev_pset != PROCESSOR_SET_NULL)
                   1175:                                pset_deallocate(prev_pset);
                   1176:                        prev_pset = pset;
                   1177: 
                   1178:                        simple_lock(&all_psets_lock);
                   1179:                        pset_lock(pset);
                   1180:                }
                   1181:                pset_unlock(pset);
                   1182:        }
                   1183:        simple_unlock(&all_psets_lock);
                   1184: 
                   1185:        if (prev_task != TASK_NULL)
                   1186:                task_deallocate(prev_task);
                   1187:        if (prev_pset != PROCESSOR_SET_NULL)
                   1188:                pset_deallocate(prev_pset);
                   1189: }
                   1190: 
                   1191: boolean_t task_collect_allowed = TRUE;
                   1192: unsigned task_collect_last_tick = 0;
                   1193: unsigned task_collect_max_rate = 0;            /* in ticks */
                   1194: 
                   1195: /*
                   1196:  *     consider_task_collect:
                   1197:  *
                   1198:  *     Called by the pageout daemon when the system needs more free pages.
                   1199:  */
                   1200: 
                   1201: void consider_task_collect(void)
                   1202: {
                   1203:        /*
                   1204:         *      By default, don't attempt task collection more frequently
                   1205:         *      than once a second.
                   1206:         */
                   1207: 
                   1208:        if (task_collect_max_rate == 0)
                   1209:                task_collect_max_rate = hz;
                   1210: 
                   1211:        if (task_collect_allowed &&
                   1212:            (sched_tick > (task_collect_last_tick + task_collect_max_rate))) {
                   1213:                task_collect_last_tick = sched_tick;
                   1214:                task_collect_scan();
                   1215:        }
                   1216: }
                   1217: 
                   1218: kern_return_t
                   1219: task_ras_control(
                   1220:        task_t task,
                   1221:        vm_offset_t pc,
                   1222:        vm_offset_t endpc,
                   1223:        int flavor)
                   1224: {
                   1225:     kern_return_t ret = KERN_FAILURE;
1.1.1.2   root     1226: 
1.1       root     1227: #if    FAST_TAS
                   1228:     int i;
                   1229: 
                   1230:     ret = KERN_SUCCESS;
                   1231:     task_lock(task);
                   1232:     switch (flavor)  {
                   1233:     case TASK_RAS_CONTROL_PURGE_ALL:  /* remove all RAS */
                   1234:        for (i = 0; i < TASK_FAST_TAS_NRAS; i++) {
                   1235:            task->fast_tas_base[i] = task->fast_tas_end[i] = 0;
                   1236:        }
                   1237:        break;
                   1238:     case TASK_RAS_CONTROL_PURGE_ONE:  /* remove this RAS, collapse remaining */
                   1239:        for (i = 0; i < TASK_FAST_TAS_NRAS; i++)  {
                   1240:            if ( (task->fast_tas_base[i] == pc)
                   1241:                && (task->fast_tas_end[i] == endpc))  {
                   1242:                        while (i < TASK_FAST_TAS_NRAS-1)  {
                   1243:                          task->fast_tas_base[i] = task->fast_tas_base[i+1];
                   1244:                          task->fast_tas_end[i] = task->fast_tas_end[i+1];
                   1245:                          i++;
                   1246:                         }
                   1247:                        task->fast_tas_base[TASK_FAST_TAS_NRAS-1] = 0;
                   1248:                        task->fast_tas_end[TASK_FAST_TAS_NRAS-1] = 0;
                   1249:                        break;
                   1250:             }
                   1251:        }
                   1252:        if (i == TASK_FAST_TAS_NRAS) {
                   1253:            ret = KERN_INVALID_ADDRESS;
                   1254:        }
                   1255:        break;
1.1.1.2   root     1256:     case TASK_RAS_CONTROL_PURGE_ALL_AND_INSTALL_ONE:
1.1       root     1257:        /* remove all RAS an install this RAS */
                   1258:        for (i = 0; i < TASK_FAST_TAS_NRAS; i++) {
                   1259:            task->fast_tas_base[i] = task->fast_tas_end[i] = 0;
                   1260:        }
                   1261:        /* FALL THROUGH */
                   1262:     case TASK_RAS_CONTROL_INSTALL_ONE: /* install this RAS */
                   1263:        for (i = 0; i < TASK_FAST_TAS_NRAS; i++)  {
                   1264:            if ( (task->fast_tas_base[i] == pc)
                   1265:            && (task->fast_tas_end[i] == endpc))   {
                   1266:                /* already installed */
                   1267:                break;
                   1268:            }
                   1269:            if ((task->fast_tas_base[i] == 0) && (task->fast_tas_end[i] == 0)){
                   1270:                task->fast_tas_base[i] = pc;
                   1271:                task->fast_tas_end[i] = endpc;
                   1272:                break;
                   1273:            }
                   1274:        }
                   1275:        if (i == TASK_FAST_TAS_NRAS)  {
                   1276:            ret = KERN_RESOURCE_SHORTAGE;
1.1.1.2   root     1277:        }
1.1       root     1278:        break;
                   1279:     default: ret = KERN_INVALID_VALUE;
                   1280:        break;
                   1281:     }
                   1282:     task_unlock(task);
1.1.1.4   root     1283: #endif /* FAST_TAS */
1.1       root     1284:     return ret;
                   1285: }
1.1.1.4   root     1286: 
                   1287: /*
                   1288:  *     register_new_task_notification
                   1289:  *
                   1290:  *     Register a port to which a notification about newly created
                   1291:  *     tasks are sent.
                   1292:  */
                   1293: kern_return_t
                   1294: register_new_task_notification(
                   1295:        const host_t host,
                   1296:        ipc_port_t notification)
                   1297: {
                   1298:        if (host == HOST_NULL)
                   1299:                return KERN_INVALID_HOST;
                   1300: 
                   1301:        if (new_task_notification != NULL)
                   1302:                return KERN_NO_ACCESS;
                   1303: 
                   1304:        new_task_notification = notification;
                   1305:        return KERN_SUCCESS;
                   1306: }

unix.superglobalmegacorp.com

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