Annotation of kernel/machdep/i386/pcb.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:  * Copyright (c) 1992 NeXT Computer, Inc.
        !            27:  *
        !            28:  * Intel386 Family:    Machine dependent thread module.
        !            29:  *
        !            30:  * HISTORY
        !            31:  *
        !            32:  * 6 April 1992 ? at NeXT
        !            33:  *     Created.
        !            34:  */
        !            35: 
        !            36: #import <mach/mach_types.h>
        !            37: 
        !            38: #import <kern/mach_param.h>
        !            39: 
        !            40: #import <architecture/i386/table.h>
        !            41: 
        !            42: #import <machdep/i386/fp_exported.h>
        !            43: #import <machdep/i386/configure.h>
        !            44: 
        !            45: #import <machdep/i386/ldt.h>
        !            46: #import <machdep/i386/table_inline.h>
        !            47: #import <machdep/i386/desc_inline.h>
        !            48: #import <machdep/i386/sel_inline.h>
        !            49: #import <machdep/i386/cpu_inline.h>
        !            50: 
        !            51: /* U**X crap!! */
        !            52: #import <sys/param.h>
        !            53: #import <sys/proc.h>
        !            54: 
        !            55: #import <fp_emul.h>
        !            56: #import <pc_support.h>
        !            57: 
        !            58: zone_t         pcb_zone;
        !            59: 
        !            60: vm_offset_t    stack_pointers[NCPUS];
        !            61: boolean_t      empty_stacks[NCPUS];
        !            62: 
        !            63: /*
        !            64:  * The base of the kernel stack
        !            65:  * is different when a thread is
        !            66:  * in v86 mode.
        !            67:  */
        !            68: #define KERNEL_STACK_BASE(state) \
        !            69:     ((unsigned int) &(state)->frame.v_es)
        !            70:     
        !            71: #define KERNEL_V86_STACK_BASE(state) \
        !            72:     ((unsigned int) &(&(state)->frame)[1])
        !            73:     
        !            74: void
        !            75: stack_attach(
        !            76:     thread_t           thread,
        !            77:     vm_offset_t                stack,
        !            78:     void               (*continuation)(void)
        !            79: )
        !            80: {
        !            81:     tss_t              *tss;
        !            82:     extern void                _stack_attach(void);
        !            83:     
        !            84:     thread->kernel_stack = stack;
        !            85: 
        !            86:     tss = thread->pcb->tss;
        !            87:     tss->esp = tss->ebp = stack + KERNEL_STACK_SIZE;
        !            88:     tss->eip = (unsigned int)_stack_attach;
        !            89:     tss->ebx = (unsigned int)continuation;
        !            90: }
        !            91: 
        !            92: 
        !            93: vm_offset_t
        !            94: stack_detach(
        !            95:     thread_t           thread
        !            96: )
        !            97: {
        !            98:     vm_offset_t                stack;
        !            99:         
        !           100:     stack = thread->kernel_stack;
        !           101:     thread->kernel_stack = 0;
        !           102:     
        !           103:     return (stack);
        !           104: }
        !           105: 
        !           106: void
        !           107: stack_handoff(
        !           108:     thread_t           old,
        !           109:     thread_t           new
        !           110: )
        !           111: {
        !           112:     struct pcb         *new_pcb = new->pcb,
        !           113:                        *old_pcb = old->pcb;
        !           114:     vm_offset_t                stack = stack_detach(old);
        !           115:     
        !           116:     stack_attach(new, stack, 0);
        !           117: 
        !           118:     /*
        !           119:      * Change software state.
        !           120:      */
        !           121:     if (new->task != old->task) {
        !           122:        int             mycpu = cpu_number();
        !           123: 
        !           124:        PMAP_DEACTIVATE(vm_map_pmap(old->task->map), old, mycpu);
        !           125:        PMAP_ACTIVATE(vm_map_pmap(new->task->map), new, mycpu);
        !           126:     }
        !           127: 
        !           128:     current_thread() = new;
        !           129: 
        !           130:     /*
        !           131:      * Change hardware state.
        !           132:      */
        !           133:     if (new_pcb->tss->cr3 != old_pcb->tss->cr3)
        !           134:        set_cr3(new_pcb->tss->cr3);
        !           135: 
        !           136:     if (new_pcb->ldt != old_pcb->ldt
        !           137:            || new_pcb->ldt_size != old_pcb->ldt_size) {
        !           138:        map_ldt(sel_to_gdt_entry(LDT_SEL),
        !           139:                    (vm_offset_t) new_pcb->ldt,
        !           140:                            (vm_size_t) new_pcb->ldt_size);
        !           141:        lldt();         
        !           142:     }
        !           143: 
        !           144:     map_tss(sel_to_gdt_entry(TSS_SEL),
        !           145:                (vm_offset_t) new_pcb->tss
        !           146:                    + KERNEL_LINEAR_BASE,
        !           147:                        (vm_size_t) new_pcb->tss_size);
        !           148:     ltr(); setts();
        !           149: }
        !           150: 
        !           151: extern
        !           152: thread_t
        !           153: _switch_tss(
        !           154:        tss_t                   *old_tss,
        !           155:        tss_t                   *new_tss,
        !           156:        thread_t                old
        !           157: );
        !           158: 
        !           159: thread_t
        !           160: switch_context(
        !           161:     thread_t           old,
        !           162:     void               (*continuation)(void),
        !           163:     thread_t           new
        !           164: )
        !           165: {
        !           166:     struct pcb         *new_pcb = new->pcb,
        !           167:                        *old_pcb = old->pcb;
        !           168: 
        !           169:     /*
        !           170:      * Change software state.
        !           171:      */
        !           172:     if (new->task != old->task) {
        !           173:        int             mycpu = cpu_number();
        !           174: 
        !           175:        PMAP_DEACTIVATE(vm_map_pmap(old->task->map), old, mycpu);
        !           176:        PMAP_ACTIVATE(vm_map_pmap(new->task->map), new, mycpu);
        !           177:     }
        !           178: 
        !           179:     current_thread() = new;
        !           180:     current_stack() = new->kernel_stack;
        !           181:     current_stack_pointer() = new->kernel_stack + KERNEL_STACK_SIZE;
        !           182: 
        !           183:     /*
        !           184:      * Change hardware state.
        !           185:      */
        !           186:     if (new_pcb->tss->cr3 != old_pcb->tss->cr3)
        !           187:        set_cr3(new_pcb->tss->cr3);
        !           188: 
        !           189:     if (new_pcb->ldt != old_pcb->ldt
        !           190:            || new_pcb->ldt_size != old_pcb->ldt_size) {
        !           191:        map_ldt(sel_to_gdt_entry(LDT_SEL),
        !           192:                    (vm_offset_t) new_pcb->ldt,
        !           193:                            (vm_size_t) new_pcb->ldt_size);
        !           194:        lldt();         
        !           195:     }
        !           196: 
        !           197:     map_tss(sel_to_gdt_entry(TSS_SEL),
        !           198:                (vm_offset_t) new_pcb->tss
        !           199:                    + KERNEL_LINEAR_BASE,
        !           200:                        (vm_size_t) new_pcb->tss_size);
        !           201:     ltr(); setts();
        !           202:     
        !           203:     if (old->swap_func = continuation)
        !           204:        return _switch_tss(0, new_pcb->tss, old);
        !           205:     else
        !           206:        return _switch_tss(old_pcb->tss, new_pcb->tss, old);
        !           207: }
        !           208: 
        !           209: void
        !           210: call_continuation(
        !           211:     void               (*continuation)(void)
        !           212: )
        !           213: {
        !           214:     _call_with_stack(continuation, current_stack_pointer());
        !           215:     /* NOTREACHED */
        !           216: }
        !           217: 
        !           218: void
        !           219: pcb_module_init(void)
        !           220: {
        !           221:     pcb_zone = zinit(
        !           222:                    sizeof (struct pcb),
        !           223:                    THREAD_MAX * sizeof (struct pcb),
        !           224:                    THREAD_CHUNK * sizeof (struct pcb),
        !           225:                    FALSE, "pcb");
        !           226: }
        !           227: 
        !           228: /*
        !           229:  * Initialize a pcb for a
        !           230:  * new thread.
        !           231:  */
        !           232: void pcb_init(
        !           233:     thread_t           thread
        !           234: )
        !           235: {
        !           236:     struct pcb                 *pcb;
        !           237:     tss_t                      *tss;
        !           238: 
        !           239:     /*
        !           240:      * Allocate a new pcb.
        !           241:      */        
        !           242:     thread->pcb = pcb = (void *)zalloc(pcb_zone);
        !           243:     *pcb = (struct pcb) { 0 };
        !           244: 
        !           245:     /*
        !           246:      * Setup with internal TSS.
        !           247:      */
        !           248:     pcb->tss = tss = &pcb->tss_store.internal;
        !           249:     pcb->tss_size = TSS_SIZE(0);
        !           250: 
        !           251:     /*
        !           252:      * Context from pmap.
        !           253:      */
        !           254:     tss->cr3 = vm_map_pmap(thread->task->map)->cr3;
        !           255:     
        !           256:     /*
        !           257:      * Setup with default LDT.
        !           258:      */
        !           259:     pcb->ldt = (vm_offset_t)ldt + KERNEL_LINEAR_BASE;
        !           260:     pcb->ldt_size = LDTSZ * sizeof (ldt_entry_t);
        !           261:     
        !           262:     tss->ldt = LDT_SEL;
        !           263: 
        !           264:     /*
        !           265:      * Kernel state.
        !           266:      */
        !           267:     tss->ss0 = KDS_SEL;
        !           268:     tss->eflags = EFL_IF;
        !           269:     tss->ss = KDS_SEL;
        !           270:     tss->cs = KCS_SEL;
        !           271:     tss->ds = KDS_SEL;
        !           272:     tss->es = KDS_SEL;
        !           273:     tss->fs = LDATA_SEL;
        !           274:     tss->gs = NULL_SEL;
        !           275:     tss->io_bmap = TSS_SIZE(0);
        !           276: }
        !           277: 
        !           278: void
        !           279: pcb_common_init(
        !           280:     task_t             task
        !           281: )
        !           282: {
        !           283:     pcb_common_t       *common = (void *)kalloc(sizeof (*common));
        !           284:     
        !           285:     lock_init(&common->lock, TRUE);
        !           286:     common->ldt = (vm_offset_t)ldt + KERNEL_LINEAR_BASE;
        !           287:     common->ldt_size = LDTSZ * sizeof (ldt_entry_t);
        !           288:     common->io_bmap.length = common->io_bmap.base = 0;
        !           289:     task->pcb_common = common;
        !           290: }
        !           291: 
        !           292: /*
        !           293:  * Set the thread's io space to the region
        !           294:  * defined by base and length.  The TSS is
        !           295:  * expanded if necessary.  Thread must either
        !           296:  * be the current thread, or suspended.
        !           297:  * N.B. On exit, the thread is guaranteed to
        !           298:  * have an external TSS.
        !           299:  */
        !           300: static void
        !           301: thread_set_io_bmap(
        !           302:     thread_t           thread,
        !           303:     vm_offset_t                base,
        !           304:     vm_size_t          length
        !           305: )
        !           306: {
        !           307:     struct pcb         *pcb = thread->pcb;
        !           308:     
        !           309:     if (pcb->tss_size < TSS_SIZE(length + 1)) {
        !           310:        struct tss_alloc        new_tss_alloc, old_tss_alloc;
        !           311:        tss_t                   *new_tss, *old_tss;
        !           312: 
        !           313:        /*
        !           314:         * TSS needs to be enlarged.
        !           315:         */
        !           316:        new_tss_alloc.length = TSS_SIZE(length + 1);
        !           317:        new_tss_alloc.base = (vm_offset_t)kalloc(new_tss_alloc.length);
        !           318:                
        !           319:        new_tss = (tss_t *)new_tss_alloc.base;
        !           320:        old_tss = pcb->tss;
        !           321: 
        !           322:        /*
        !           323:         * Copy old TSS to new one.
        !           324:         */
        !           325:        *new_tss = *old_tss;
        !           326: 
        !           327:        if (pcb->extern_tss) {
        !           328:            /*
        !           329:             * Deal with old external tss.
        !           330:             */ 
        !           331:            old_tss_alloc = pcb->tss_store.external;
        !           332:     
        !           333:            /*
        !           334:             * Switch to new TSS.
        !           335:             */ 
        !           336:            pcb->tss_store.external = new_tss_alloc;
        !           337:            pcb->tss = new_tss;
        !           338:            pcb->tss_size = new_tss_alloc.length;
        !           339:            pcb->extern_tss = TRUE;
        !           340:                
        !           341:            /*
        !           342:             * Free old TSS.
        !           343:             */
        !           344:            kfree((void *)old_tss_alloc.base, old_tss_alloc.length);
        !           345:        }
        !           346:        else {
        !           347:            /*
        !           348:             * Switch to new TSS.
        !           349:             */ 
        !           350:            pcb->tss_store.external = new_tss_alloc;
        !           351:            pcb->tss = new_tss;
        !           352:            pcb->tss_size = new_tss_alloc.length;
        !           353:            pcb->extern_tss = TRUE;
        !           354:        }
        !           355: 
        !           356:        /*
        !           357:         * If changing the current
        !           358:         * thread, remap its tss now.
        !           359:         */     
        !           360:        if (thread == current_thread()) {
        !           361:            map_tss(sel_to_gdt_entry(TSS_SEL),
        !           362:                        (vm_offset_t) thread->pcb->tss
        !           363:                            + KERNEL_LINEAR_BASE,
        !           364:                                (vm_size_t) thread->pcb->tss_size);
        !           365:            ltr();
        !           366:        }
        !           367:     }
        !           368:     
        !           369:     memcpy(
        !           370:        (void *)pcb->tss + pcb->tss->io_bmap,
        !           371:                (void *)base, length);
        !           372: }
        !           373: 
        !           374: static void
        !           375: task_update_io_bmap(
        !           376:     task_t             task
        !           377: )
        !           378: {
        !           379:     queue_head_t       *list;
        !           380:     thread_t           thread, prev_thread;
        !           381:     pcb_common_t       *common = task->pcb_common;
        !           382:     
        !           383:     list = &task->thread_list;
        !           384:     prev_thread = THREAD_NULL;
        !           385:     task_lock(task);
        !           386:     thread = (thread_t)queue_first(list);
        !           387:     while (!queue_end(list, (queue_entry_t)thread)) {
        !           388:        thread_reference(thread);
        !           389:        task_unlock(task);
        !           390:        if (prev_thread != THREAD_NULL)
        !           391:            thread_deallocate(prev_thread);
        !           392:        thread_set_io_bmap(thread,
        !           393:                            common->io_bmap.base,
        !           394:                            common->io_bmap.length);
        !           395:        prev_thread = thread;
        !           396:        task_lock(task);
        !           397:        thread = (thread_t)queue_next(&thread->thread_list);
        !           398:     }
        !           399:     task_unlock(task);
        !           400:     if (prev_thread != THREAD_NULL)
        !           401:        thread_deallocate(prev_thread);
        !           402: }
        !           403: 
        !           404: kern_return_t
        !           405: task_map_io_ports(
        !           406:     task_t             task,
        !           407:     unsigned int       port,
        !           408:     unsigned int       length,
        !           409:     boolean_t          unmap
        !           410: )
        !           411: {
        !           412:     pcb_common_t       *common = task->pcb_common;
        !           413:     vm_offset_t                new_io_bmap_base;
        !           414:     vm_size_t          new_io_bmap_length;
        !           415:     int                        i;
        !           416: 
        !           417:     /*
        !           418:      * Bad port range.
        !           419:      */        
        !           420:     if ((port + length) > 65536)
        !           421:        return (KERN_INVALID_ADDRESS);
        !           422:        
        !           423:     if (task->kernel_vm_space)
        !           424:        return (KERN_SUCCESS);
        !           425: 
        !           426:     /*
        !           427:      * If task is being terminated,
        !           428:      * don't bother.
        !           429:      */ 
        !           430:     if (task_hold(task) != KERN_SUCCESS)
        !           431:        return (KERN_INVALID_ARGUMENT);
        !           432:     
        !           433:     new_io_bmap_length = roundup(port + length, NBBY) / NBBY;
        !           434:     
        !           435:     lock_write(&common->lock);
        !           436:     
        !           437:     if (common->io_bmap.length < new_io_bmap_length) {
        !           438:        new_io_bmap_base = (vm_offset_t)kalloc(new_io_bmap_length);
        !           439:        
        !           440:        /*
        !           441:         * Invalidate all of new IO bitmap.
        !           442:         */
        !           443:        memset(
        !           444:            (void *)new_io_bmap_base,
        !           445:                    0xff, new_io_bmap_length);
        !           446:        
        !           447:        /*
        !           448:         * Copy old IO bitmap.
        !           449:         */
        !           450:        memcpy(
        !           451:            (void *)new_io_bmap_base,
        !           452:                (void *)common->io_bmap.base, common->io_bmap.length);
        !           453:                
        !           454:        kfree((void *)common->io_bmap.base, common->io_bmap.length);
        !           455:        
        !           456:        common->io_bmap.base = new_io_bmap_base;
        !           457:        common->io_bmap.length = new_io_bmap_length;
        !           458:     }
        !           459:     
        !           460:     for (i = port; i < (port + length); i++)
        !           461:        if (unmap)
        !           462:            setbit(common->io_bmap.base, i);
        !           463:        else
        !           464:            clrbit(common->io_bmap.base, i);
        !           465:            
        !           466:     (void) task_dowait(task, TRUE);
        !           467:     
        !           468:     task_update_io_bmap(task);
        !           469:     
        !           470:     (void) task_release(task);
        !           471:     
        !           472:     lock_done(&common->lock);
        !           473:     
        !           474:     return (KERN_SUCCESS);
        !           475: }
        !           476: 
        !           477: static void
        !           478: thread_set_ldt(
        !           479:     thread_t           thread,
        !           480:     vm_offset_t                address,
        !           481:     vm_size_t          size
        !           482: )
        !           483: {
        !           484:     thread->pcb->ldt = address;
        !           485:     thread->pcb->ldt_size = size;
        !           486: 
        !           487:     /*
        !           488:      * If changing the current
        !           489:      * thread, remap its LDT now.
        !           490:      */        
        !           491:     if (thread == current_thread()) {
        !           492:        map_ldt(sel_to_gdt_entry(LDT_SEL),
        !           493:                    (vm_offset_t) thread->pcb->ldt,
        !           494:                            (vm_size_t) thread->pcb->ldt_size);
        !           495:        lldt();
        !           496:     }
        !           497: }
        !           498: 
        !           499: static void
        !           500: task_update_ldt(
        !           501:     task_t             task
        !           502: )
        !           503: {
        !           504:     queue_head_t       *list;
        !           505:     thread_t           thread, prev_thread;
        !           506:     pcb_common_t       *common = task->pcb_common;
        !           507:     
        !           508:     list = &task->thread_list;
        !           509:     prev_thread = THREAD_NULL;
        !           510:     task_lock(task);
        !           511:     thread = (thread_t)queue_first(list);
        !           512:     while (!queue_end(list, (queue_entry_t)thread)) {
        !           513:        thread_reference(thread);
        !           514:        task_unlock(task);
        !           515:        if (prev_thread != THREAD_NULL)
        !           516:            thread_deallocate(prev_thread);
        !           517:        thread_set_ldt(thread, common->ldt, common->ldt_size);
        !           518:        prev_thread = thread;
        !           519:        task_lock(task);
        !           520:        thread = (thread_t)queue_next(&thread->thread_list);
        !           521:     }
        !           522:     task_unlock(task);
        !           523:     if (prev_thread != THREAD_NULL)
        !           524:        thread_deallocate(prev_thread);
        !           525: }
        !           526: 
        !           527: kern_return_t
        !           528: task_locate_ldt(
        !           529:     task_t             task,
        !           530:     vm_offset_t                address,
        !           531:     vm_size_t          size
        !           532: )
        !           533: {
        !           534:     pcb_common_t       *common = task->pcb_common;
        !           535:     
        !           536:     if (vm_map_min(task->map) > address ||
        !           537:            vm_map_max(task->map) <= (address + size))
        !           538:        return (KERN_INVALID_ADDRESS);
        !           539: 
        !           540:     /*
        !           541:      * If task is being terminated,
        !           542:      * don't bother.
        !           543:      */ 
        !           544:     if (task_hold(task) != KERN_SUCCESS)
        !           545:        return (KERN_INVALID_ARGUMENT);
        !           546:     
        !           547:     lock_write(&common->lock);
        !           548:     
        !           549:     common->ldt = address;
        !           550:     common->ldt_size = size;
        !           551:     
        !           552:     (void) task_dowait(task, TRUE);
        !           553:     
        !           554:     task_update_ldt(task);
        !           555:     
        !           556:     (void) task_release(task);
        !           557:     
        !           558:     lock_done(&common->lock);
        !           559:     
        !           560:     return (KERN_SUCCESS);
        !           561: }
        !           562: 
        !           563: kern_return_t
        !           564: task_default_ldt(
        !           565:     task_t             task
        !           566: )
        !           567: {
        !           568:     pcb_common_t       *common = task->pcb_common;
        !           569: 
        !           570:     /*
        !           571:      * If task is being terminated,
        !           572:      * don't bother.
        !           573:      */ 
        !           574:     if (task_hold(task) != KERN_SUCCESS)
        !           575:        return (KERN_INVALID_ARGUMENT);
        !           576:     
        !           577:     lock_write(&common->lock);
        !           578:     
        !           579:     common->ldt = (vm_offset_t)ldt + KERNEL_LINEAR_BASE;
        !           580:     common->ldt_size = LDTSZ * sizeof (ldt_entry_t);
        !           581:     
        !           582:     (void) task_dowait(task, TRUE);
        !           583:     
        !           584:     task_update_ldt(task);
        !           585:     
        !           586:     (void) task_release(task);
        !           587:     
        !           588:     lock_done(&common->lock);
        !           589:     
        !           590:     return (KERN_SUCCESS);
        !           591: }
        !           592: 
        !           593: thread_saved_state_t *
        !           594: thread_user_state(
        !           595:     thread_t           thread
        !           596: )
        !           597: {
        !           598:     thread_save_area_t *save_area = thread->pcb->save_area;
        !           599: 
        !           600:     if (save_area == 0) {
        !           601:        thread_saved_state_t    *saved_state;
        !           602: 
        !           603:        thread->pcb->save_area =
        !           604:                save_area = (void *)kalloc(sizeof (*save_area));
        !           605: 
        !           606:        saved_state = &save_area->sa_u;
        !           607:        *saved_state = (thread_saved_state_t) { 0 };
        !           608:        saved_state->frame.eflags = EFL_IF;
        !           609:        saved_state->frame.cs = UCODE_SEL;
        !           610:        saved_state->frame.ss = UDATA_SEL;
        !           611:        saved_state->regs.ds = UDATA_SEL;
        !           612:        saved_state->regs.es = UDATA_SEL;
        !           613:        saved_state->regs.fs = NULL_SEL;
        !           614:        saved_state->regs.gs = NULL_SEL;
        !           615:        
        !           616:        return (saved_state);
        !           617:     }
        !           618:     else
        !           619:        return (&save_area->sa_u);
        !           620: }
        !           621: 
        !           622: /*
        !           623:  * Entry point for new user
        !           624:  * threads.
        !           625:  */
        !           626: void
        !           627: thread_bootstrap_return(void)
        !           628: {
        !           629:     thread_t           thread = current_thread();
        !           630:     pcb_common_t       *common = thread->task->pcb_common;
        !           631:     struct pcb         *pcb = thread->pcb;
        !           632: 
        !           633:     lock_read(&common->lock);
        !           634:     
        !           635:     if (common->io_bmap.length > 0)
        !           636:        thread_set_io_bmap(thread,
        !           637:                            common->io_bmap.base,
        !           638:                            common->io_bmap.length);
        !           639:     
        !           640:     if (common->ldt != pcb->ldt)
        !           641:        thread_set_ldt(thread, common->ldt, common->ldt_size);
        !           642:        
        !           643:     lock_done(&common->lock);
        !           644:     
        !           645:     thread_exception_return();
        !           646:     /* NOTREACHED */
        !           647: }
        !           648: 
        !           649: void
        !           650: thread_exception_return(void)
        !           651: {
        !           652:     thread_t                   thread = current_thread();
        !           653:     thread_saved_state_t       *saved_state = USER_REGS(thread);
        !           654: 
        !           655:     check_for_ast(saved_state);                // *may* not return
        !           656: 
        !           657:     thread->pcb->tss->esp0 =
        !           658:            ((saved_state->frame.eflags & EFL_VM) ?
        !           659:                                        KERNEL_V86_STACK_BASE(saved_state) :
        !           660:                                        KERNEL_STACK_BASE(saved_state));
        !           661: 
        !           662:     _return_with_state(saved_state);
        !           663:     /* NOTREACHED */
        !           664: }
        !           665: 
        !           666: void __volatile__
        !           667: thread_syscall_return(
        !           668:     kern_return_t      result
        !           669: )
        !           670: {
        !           671:     thread_t                   thread = current_thread();
        !           672:     thread_saved_state_t       *saved_state = USER_REGS(thread);
        !           673:     
        !           674:     saved_state->regs.eax = result;
        !           675: 
        !           676:     check_for_ast(saved_state);                // *may* not return
        !           677: 
        !           678:     thread->pcb->tss->esp0 =
        !           679:            ((saved_state->frame.eflags & EFL_VM) ?
        !           680:                                        KERNEL_V86_STACK_BASE(saved_state) :
        !           681:                                        KERNEL_STACK_BASE(saved_state));
        !           682: 
        !           683:     _return_with_state(saved_state);
        !           684:     /* NOTREACHED */
        !           685: }
        !           686: 
        !           687: void
        !           688: thread_set_syscall_return(
        !           689:     thread_t           thread,
        !           690:     kern_return_t      result
        !           691: )
        !           692: {
        !           693:     thread_saved_state_t       *saved_state = USER_REGS(thread);
        !           694:     
        !           695:     saved_state->regs.eax = result;
        !           696: }
        !           697: 
        !           698: /*
        !           699:  * Called from locore to
        !           700:  * startup the first thread. (never returns)
        !           701:  */
        !           702: void
        !           703: start_initial_context(
        !           704:     thread_t           thread
        !           705: )
        !           706: {
        !           707:     struct pcb         *pcb = thread->pcb;
        !           708: 
        !           709:     /*
        !           710:      * Initialize the common,
        !           711:      * static LDT.
        !           712:      */
        !           713:     ldt_init();
        !           714: 
        !           715:     /*
        !           716:      * Change software state.
        !           717:      */
        !           718:    PMAP_ACTIVATE(vm_map_pmap(thread->task->map), thread, 0);
        !           719: 
        !           720:    current_thread() = thread;
        !           721:    current_stack() = thread->kernel_stack;
        !           722:    current_stack_pointer() = thread->kernel_stack + KERNEL_STACK_SIZE;
        !           723: 
        !           724:     /*
        !           725:      * Change hardware state.
        !           726:      */
        !           727:     set_cr3(pcb->tss->cr3);
        !           728: 
        !           729:     map_ldt(sel_to_gdt_entry(LDT_SEL),
        !           730:                (vm_offset_t) pcb->ldt,
        !           731:                        (vm_size_t) pcb->ldt_size);
        !           732:     lldt();
        !           733: 
        !           734:     map_tss(sel_to_gdt_entry(TSS_SEL),
        !           735:                (vm_offset_t) pcb->tss
        !           736:                    + KERNEL_LINEAR_BASE,
        !           737:                        (vm_size_t) pcb->tss_size);
        !           738:     ltr(); setts();
        !           739:                        
        !           740:     _switch_tss(0, pcb->tss, 0);
        !           741: }
        !           742: 
        !           743: /*
        !           744:  * Set externally visible thread
        !           745:  * state.
        !           746:  */
        !           747: kern_return_t
        !           748: thread_setstatus(
        !           749:     thread_t                   thread,
        !           750:     int                                flavor,
        !           751:     thread_state_t             tstate,
        !           752:     unsigned int               count
        !           753: )
        !           754: {
        !           755:     switch (flavor) {
        !           756: 
        !           757:     case i386_THREAD_STATE:
        !           758:        return (set_thread_state(thread, tstate, count));
        !           759:     
        !           760:     case i386_THREAD_FPSTATE:
        !           761:        return (set_thread_fpstate(thread, tstate, count));
        !           762: 
        !           763:     default:
        !           764:        return (KERN_INVALID_ARGUMENT);
        !           765:     }
        !           766: }
        !           767: 
        !           768: static void set_thread_v86_state(
        !           769:                thread_t                        thread,
        !           770:                i386_thread_state_t             *state);
        !           771: 
        !           772: kern_return_t
        !           773: set_thread_state(
        !           774:     thread_t                   thread,
        !           775:     thread_state_t             tstate,
        !           776:     unsigned int               count
        !           777: )
        !           778: {
        !           779:     thread_saved_state_t       *saved_state;
        !           780:     i386_thread_state_t                *state;
        !           781:     
        !           782:     if (count < i386_THREAD_STATE_COUNT)
        !           783:        return (KERN_INVALID_ARGUMENT);
        !           784:        
        !           785:     state = (i386_thread_state_t *)tstate;
        !           786:     
        !           787:     if ((state->eflags & EFL_VM) != 0)
        !           788:        set_thread_v86_state(thread, state);
        !           789:     else {
        !           790:        if (!thread->task->kernel_privilege) {
        !           791:            /*
        !           792:             * Validate segment selector values.
        !           793:             */
        !           794:            if (
        !           795:                    !valid_user_code_selector(state->cs) ||
        !           796:                    !valid_user_data_selector(state->ds) ||
        !           797:                    !valid_user_data_selector(state->es) ||
        !           798:                    !valid_user_data_selector(state->fs) ||
        !           799:                    !valid_user_data_selector(state->gs) ||
        !           800:                    !valid_user_stack_selector(state->ss)
        !           801:                )
        !           802:                return (KERN_INVALID_ARGUMENT);
        !           803:        }
        !           804:        else {
        !           805:            tss_t       *tss = thread->pcb->tss;
        !           806:            /*
        !           807:             * State for kernel threads
        !           808:             * can only be set before thread
        !           809:             * is first started.
        !           810:             *
        !           811:             * XXX This hack is due to the
        !           812:             * fact that the &^%$#@! kernel loader
        !           813:             * uses the thread_set_state() call to
        !           814:             * start a thread in kernel mode.
        !           815:             */
        !           816:            if (thread->swap_func != thread_bootstrap_return)
        !           817:                return (KERN_INVALID_ARGUMENT);
        !           818:                
        !           819:            tss->eax = state->eax;
        !           820:            tss->ebx = state->ebx;
        !           821:            tss->ecx = state->ecx;
        !           822:            tss->edx = state->edx;
        !           823:            tss->edi = state->edi;
        !           824:            tss->esi = state->esi;
        !           825:                
        !           826:            thread_start(thread, state->eip);
        !           827:            
        !           828:            return (KERN_SUCCESS);
        !           829:        }
        !           830: 
        !           831:        saved_state = USER_REGS(thread);
        !           832:            
        !           833:        saved_state->regs.eax = state->eax;
        !           834:        saved_state->regs.ebx = state->ebx;
        !           835:        saved_state->regs.ecx = state->ecx;
        !           836:        saved_state->regs.edx = state->edx;
        !           837:        saved_state->regs.edi = state->edi;
        !           838:        saved_state->regs.esi = state->esi;
        !           839:        saved_state->regs.ebp = state->ebp;
        !           840:        saved_state->frame.esp = state->esp;
        !           841:        saved_state->frame.ss = selector_to_sel(state->ss);
        !           842:        saved_state->frame.eflags = state->eflags;
        !           843:        saved_state->frame.eflags &= ~( EFL_VM | EFL_NT | EFL_IOPL | EFL_CLR );
        !           844:        saved_state->frame.eflags |=  ( EFL_IF | EFL_SET );
        !           845:        saved_state->frame.eip = state->eip;
        !           846:        saved_state->frame.cs = selector_to_sel(state->cs);
        !           847:        saved_state->regs.ds = selector_to_sel(state->ds);
        !           848:        saved_state->regs.es = selector_to_sel(state->es);
        !           849:        saved_state->regs.fs = selector_to_sel(state->fs);
        !           850:        saved_state->regs.gs = selector_to_sel(state->gs);
        !           851:     }
        !           852: 
        !           853:     return (KERN_SUCCESS);
        !           854: }
        !           855: 
        !           856: static
        !           857: void
        !           858: set_thread_v86_state(
        !           859:     thread_t                   thread,
        !           860:     i386_thread_state_t                *state
        !           861: )
        !           862: {
        !           863:     thread_saved_state_t       *saved_state = USER_REGS(thread);
        !           864: 
        !           865:     saved_state->regs.eax = state->eax;
        !           866:     saved_state->regs.ebx = state->ebx;
        !           867:     saved_state->regs.ecx = state->ecx;
        !           868:     saved_state->regs.edx = state->edx;
        !           869:     saved_state->regs.edi = state->edi;
        !           870:     saved_state->regs.esi = state->esi;
        !           871:     saved_state->regs.ebp = state->ebp;
        !           872:     saved_state->frame.esp = state->esp;
        !           873:     saved_state->frame.ss = selector_to_sel(state->ss);
        !           874:     saved_state->frame.eflags = state->eflags;
        !           875:     saved_state->frame.eflags &= ~( EFL_NT | EFL_IOPL | EFL_CLR );
        !           876:     saved_state->frame.eflags |=  ( EFL_VM | EFL_IF | EFL_SET );
        !           877:     saved_state->frame.eip = state->eip;
        !           878:     saved_state->frame.cs = selector_to_sel(state->cs);
        !           879:     saved_state->regs.ds = NULL_SEL;
        !           880:     saved_state->regs.es = NULL_SEL;
        !           881:     saved_state->regs.fs = NULL_SEL;
        !           882:     saved_state->regs.gs = NULL_SEL;
        !           883:     saved_state->frame.v_ds = state->ds;
        !           884:     saved_state->frame.v_es = state->es;
        !           885:     saved_state->frame.v_fs = state->fs;
        !           886:     saved_state->frame.v_gs = state->gs;
        !           887: }
        !           888: 
        !           889: kern_return_t
        !           890: set_thread_fpstate(
        !           891:     thread_t                   thread,
        !           892:     thread_state_t             tstate,
        !           893:     unsigned int               count
        !           894: )
        !           895: {
        !           896:     fp_state_t                 *saved_state;
        !           897:     i386_thread_fpstate_t      *state;
        !           898:     
        !           899:     if (count < i386_THREAD_FPSTATE_COUNT)
        !           900:        return (KERN_INVALID_ARGUMENT);
        !           901:        
        !           902:     state = (i386_thread_fpstate_t *)tstate;
        !           903:     saved_state = &thread->pcb->fpstate;
        !           904:     
        !           905:     fp_terminate(thread);
        !           906:        
        !           907:     saved_state->environ = state->environ;
        !           908:     saved_state->stack = state->stack;
        !           909:     
        !           910:     thread->pcb->fpvalid = TRUE;
        !           911: 
        !           912:     return (KERN_SUCCESS);
        !           913: }
        !           914: 
        !           915: kern_return_t
        !           916: thread_set_cthread_self(
        !           917:     int                                self
        !           918: )
        !           919: {
        !           920:    current_thread()->pcb->cthread_self = (unsigned int)self;
        !           921:    
        !           922:    return (KERN_SUCCESS);
        !           923: }
        !           924: 
        !           925: /*
        !           926:  * Return externally visible
        !           927:  * thread status.
        !           928:  */
        !           929: kern_return_t
        !           930: thread_getstatus(
        !           931:     thread_t                   thread,
        !           932:     int                                flavor,
        !           933:     thread_state_t             tstate,
        !           934:     unsigned int               *count
        !           935: )
        !           936: {
        !           937:     switch (flavor) {
        !           938: 
        !           939:     case i386_THREAD_STATE:
        !           940:        return (get_thread_state(thread, tstate, count));
        !           941:        
        !           942:     case i386_THREAD_FPSTATE:
        !           943:        return (get_thread_fpstate(thread, tstate, count));
        !           944:        
        !           945:     case i386_THREAD_EXCEPTSTATE:
        !           946:        return (get_thread_exceptstate(thread, tstate, count));
        !           947:        
        !           948:     case i386_THREAD_CTHREADSTATE:
        !           949:        return (get_thread_cthreadstate(thread, tstate, count));
        !           950: 
        !           951:     case THREAD_STATE_FLAVOR_LIST:
        !           952:        return (get_thread_state_flavor_list(tstate, count));
        !           953: 
        !           954:     default:
        !           955:        return (KERN_INVALID_ARGUMENT);
        !           956:     }
        !           957: }
        !           958: 
        !           959: kern_return_t
        !           960: get_thread_state(
        !           961:     thread_t                   thread,
        !           962:     thread_state_t             tstate,
        !           963:     unsigned int               *count
        !           964: )
        !           965: {
        !           966:     thread_saved_state_t       *saved_state;
        !           967:     i386_thread_state_t                *state;
        !           968:     
        !           969:     if (*count < i386_THREAD_STATE_COUNT)
        !           970:        return (KERN_INVALID_ARGUMENT);
        !           971:        
        !           972:     state = (i386_thread_state_t *)tstate;
        !           973:     saved_state = USER_REGS(thread);
        !           974: 
        !           975:     state->eax = saved_state->regs.eax;
        !           976:     state->ebx = saved_state->regs.ebx;
        !           977:     state->ecx = saved_state->regs.ecx;
        !           978:     state->edx = saved_state->regs.edx;
        !           979:     state->edi = saved_state->regs.edi;
        !           980:     state->esi = saved_state->regs.esi;
        !           981:     state->ebp = saved_state->regs.ebp;
        !           982:     state->esp = saved_state->frame.esp;
        !           983:     state->ss = sel_to_selector(saved_state->frame.ss);
        !           984:     state->eflags = saved_state->frame.eflags;
        !           985:     state->eip = saved_state->frame.eip;
        !           986:     state->cs = sel_to_selector(saved_state->frame.cs);
        !           987:     if ((saved_state->frame.eflags & EFL_VM) == 0) {
        !           988:        state->ds = sel_to_selector(saved_state->regs.ds);
        !           989:        state->es = sel_to_selector(saved_state->regs.es);
        !           990:        state->fs = sel_to_selector(saved_state->regs.fs);
        !           991:        state->gs = sel_to_selector(saved_state->regs.gs);
        !           992:     }
        !           993:     else {
        !           994:        state->ds = saved_state->frame.v_ds;
        !           995:        state->es = saved_state->frame.v_es;
        !           996:        state->fs = saved_state->frame.v_fs;
        !           997:        state->gs = saved_state->frame.v_gs;
        !           998:     }
        !           999:        
        !          1000:     *count = i386_THREAD_STATE_COUNT;
        !          1001:     
        !          1002:     return (KERN_SUCCESS);
        !          1003: }
        !          1004: 
        !          1005: kern_return_t
        !          1006: get_thread_fpstate(
        !          1007:     thread_t                   thread,
        !          1008:     thread_state_t             tstate,
        !          1009:     unsigned int               *count
        !          1010: )
        !          1011: {
        !          1012:     fp_state_t                 *saved_state;
        !          1013:     i386_thread_fpstate_t      *state;
        !          1014:     
        !          1015:     if (*count < i386_THREAD_FPSTATE_COUNT)
        !          1016:        return (KERN_INVALID_ARGUMENT);
        !          1017:        
        !          1018:     state = (i386_thread_fpstate_t *)tstate;
        !          1019:     saved_state = &thread->pcb->fpstate;
        !          1020:     
        !          1021:     fp_synch(thread);
        !          1022:     
        !          1023:     state->environ = saved_state->environ;
        !          1024:     state->stack = saved_state->stack;
        !          1025:     
        !          1026:     *count = i386_THREAD_FPSTATE_COUNT;
        !          1027:     
        !          1028:     return (KERN_SUCCESS);
        !          1029: }
        !          1030: 
        !          1031: kern_return_t
        !          1032: get_thread_exceptstate(
        !          1033:     thread_t                   thread,
        !          1034:     thread_state_t             tstate,
        !          1035:     unsigned int               *count
        !          1036: )
        !          1037: {
        !          1038:     thread_saved_state_t       *saved_state;
        !          1039:     i386_thread_exceptstate_t  *state;
        !          1040:     
        !          1041:     if (*count < i386_THREAD_EXCEPTSTATE_COUNT)
        !          1042:        return (KERN_INVALID_ARGUMENT);
        !          1043:        
        !          1044:     state = (i386_thread_exceptstate_t *)tstate;
        !          1045:     saved_state = USER_REGS(thread);
        !          1046:     
        !          1047:     state->trapno = saved_state->trapno;
        !          1048:     state->err = saved_state->frame.err;
        !          1049:     
        !          1050:     *count = i386_THREAD_EXCEPTSTATE_COUNT;
        !          1051:     
        !          1052:     return (KERN_SUCCESS);
        !          1053: }
        !          1054: 
        !          1055: kern_return_t
        !          1056: get_thread_cthreadstate(
        !          1057:     thread_t                   thread,
        !          1058:     thread_state_t             tstate,
        !          1059:     unsigned int               *count
        !          1060: )
        !          1061: {
        !          1062:     i386_thread_cthreadstate_t *state;
        !          1063:     
        !          1064:     if (*count < i386_THREAD_CTHREADSTATE_COUNT)
        !          1065:        return (KERN_INVALID_ARGUMENT);
        !          1066:        
        !          1067:     state = (i386_thread_cthreadstate_t *)tstate;
        !          1068:     state->self = thread->pcb->cthread_self;
        !          1069:     
        !          1070:     *count = i386_THREAD_CTHREADSTATE_COUNT;
        !          1071:     
        !          1072:     return (KERN_SUCCESS);
        !          1073: }
        !          1074: 
        !          1075: kern_return_t
        !          1076: thread_get_cthread_self(
        !          1077:     void
        !          1078: )
        !          1079: {
        !          1080:     return ((kern_return_t)current_thread()->pcb->cthread_self);
        !          1081: }
        !          1082: 
        !          1083: kern_return_t
        !          1084: get_thread_state_flavor_list(
        !          1085:     thread_state_t             tstate,
        !          1086:     unsigned int               *count
        !          1087: )
        !          1088: {
        !          1089:     struct thread_state_flavor *state;
        !          1090: #define i386_THREAD_STATE_FLAVOR_COUNT 4
        !          1091: 
        !          1092: #define i386_THREAD_STATE_FLAVOR_LIST_COUNT                    \
        !          1093:     ( i386_THREAD_STATE_FLAVOR_COUNT *                         \
        !          1094:        ( sizeof (struct thread_state_flavor) / sizeof (int) ) )
        !          1095:     
        !          1096:     if (*count < i386_THREAD_STATE_FLAVOR_COUNT)
        !          1097:        return (KERN_INVALID_ARGUMENT);
        !          1098:        
        !          1099:     state = (struct thread_state_flavor *)tstate;
        !          1100: 
        !          1101:     state->flavor = i386_THREAD_STATE;
        !          1102:     state->count = i386_THREAD_STATE_COUNT;
        !          1103:     
        !          1104:     (++state)->flavor = i386_THREAD_FPSTATE;
        !          1105:     state->count = i386_THREAD_FPSTATE_COUNT;
        !          1106:     
        !          1107:     (++state)->flavor = i386_THREAD_EXCEPTSTATE;
        !          1108:     state->count = i386_THREAD_EXCEPTSTATE_COUNT;
        !          1109:     
        !          1110:     (++state)->flavor = i386_THREAD_CTHREADSTATE;
        !          1111:     state->count = i386_THREAD_CTHREADSTATE_COUNT;
        !          1112:     
        !          1113:     *count = i386_THREAD_STATE_FLAVOR_LIST_COUNT;
        !          1114:     
        !          1115:     return (KERN_SUCCESS);
        !          1116: }
        !          1117: 
        !          1118: /*
        !          1119:  * thread_userstack:
        !          1120:  *
        !          1121:  * Return the user stack pointer from the machine dependent thread state info.
        !          1122:  */
        !          1123: kern_return_t
        !          1124: thread_userstack(
        !          1125:     thread_t           thread,
        !          1126:     int                        flavor,
        !          1127:     thread_state_t     tstate,
        !          1128:     unsigned int       count,
        !          1129:     vm_offset_t                *user_stack
        !          1130: )
        !          1131: {
        !          1132:     i386_thread_state_t        *state;
        !          1133: 
        !          1134:     /*
        !          1135:      * Set a default.
        !          1136:      */
        !          1137:     if (*user_stack == 0)
        !          1138:        *user_stack = VM_MAX_ADDRESS;
        !          1139:                
        !          1140:     switch (flavor) {
        !          1141: 
        !          1142:     case i386_THREAD_STATE:
        !          1143:        if (count < i386_THREAD_STATE_COUNT)
        !          1144:            return (KERN_INVALID_ARGUMENT);
        !          1145: 
        !          1146:        state = (i386_thread_state_t *) tstate;
        !          1147: 
        !          1148:        /*
        !          1149:         * If a valid user stack is specified, use it.
        !          1150:         */
        !          1151:        *user_stack = state->esp ? state->esp: VM_MAX_ADDRESS;
        !          1152:        break;
        !          1153:     }
        !          1154: 
        !          1155:     return (KERN_SUCCESS);
        !          1156: }
        !          1157: kern_return_t
        !          1158: thread_entrypoint(
        !          1159:     thread_t           thread,
        !          1160:     int                        flavor,
        !          1161:     thread_state_t     tstate,
        !          1162:     unsigned int       count,
        !          1163:     vm_offset_t                *entry_point
        !          1164: )
        !          1165: {
        !          1166:     i386_thread_state_t        *state;
        !          1167: 
        !          1168:     /*
        !          1169:      * Set a default.
        !          1170:      */
        !          1171:     if (*entry_point == 0)
        !          1172:        *entry_point = VM_MIN_ADDRESS;
        !          1173:                
        !          1174:     switch (flavor) {
        !          1175: 
        !          1176:     case i386_THREAD_STATE:
        !          1177:        if (count < i386_THREAD_STATE_COUNT)
        !          1178:            return (KERN_INVALID_ARGUMENT);
        !          1179: 
        !          1180:        state = (i386_thread_state_t *) tstate;
        !          1181: 
        !          1182:        /*
        !          1183:         * If a valid entry point is specified, use it.
        !          1184:         */
        !          1185:        *entry_point = state->eip ? state->eip: VM_MIN_ADDRESS;
        !          1186:        break;
        !          1187:     }
        !          1188: 
        !          1189:     return (KERN_SUCCESS);
        !          1190: }
        !          1191: 
        !          1192: /*
        !          1193:  * Duplicate parent state in child
        !          1194:  * for U**X fork.
        !          1195:  */
        !          1196: thread_dup(
        !          1197:     thread_t           parent,
        !          1198:     thread_t           child
        !          1199: )
        !          1200: {
        !          1201:     struct thread_saved_state  *parent_state, *child_state;
        !          1202: 
        !          1203:     parent_state = USER_REGS(parent);
        !          1204:     child_state = thread_user_state(child);
        !          1205: 
        !          1206:     *child_state = *parent_state;
        !          1207: 
        !          1208:     child_state->regs.eax = child->task->proc->p_pid;
        !          1209: 
        !          1210:     child_state->regs.edx = 1;
        !          1211:     child_state->frame.eflags &= ~EFL_CF;
        !          1212: }
        !          1213: 
        !          1214: /*
        !          1215:  * Release resources on
        !          1216:  * thread termination.
        !          1217:  */
        !          1218: pcb_terminate(
        !          1219:     thread_t           thread
        !          1220: )
        !          1221: {
        !          1222:     struct pcb         *pcb = thread->pcb;
        !          1223: 
        !          1224:     /*
        !          1225:      * Give up the fpu if
        !          1226:      * necessary.
        !          1227:      */
        !          1228:     fp_terminate(thread);
        !          1229: 
        !          1230: #if    PC_SUPPORT    
        !          1231:     if (pcb->PCpriv)
        !          1232:        PCdestroy(thread);
        !          1233: #endif
        !          1234: 
        !          1235:     /*
        !          1236:      * Free save area.
        !          1237:      */
        !          1238:     if (pcb->save_area)
        !          1239:        kfree((void *)pcb->save_area,
        !          1240:                sizeof (*pcb->save_area));
        !          1241: 
        !          1242:     /*
        !          1243:      * Free external tss.
        !          1244:      */
        !          1245:     if (pcb->extern_tss)
        !          1246:        kfree(
        !          1247:            (void *)pcb->tss_store.external.base,
        !          1248:                        pcb->tss_store.external.length);
        !          1249:                        
        !          1250:     thread->pcb = 0;
        !          1251:     zfree(pcb_zone, pcb);
        !          1252: }
        !          1253: 
        !          1254: /*
        !          1255:  * Synchronize pcb with
        !          1256:  * hardware state.
        !          1257:  */
        !          1258: pcb_synch(
        !          1259:     thread_t           thread
        !          1260: )
        !          1261: {
        !          1262:     /*
        !          1263:      * Write out our fp state
        !          1264:      * if necessary.
        !          1265:      */
        !          1266:     fp_synch(thread);
        !          1267: }
        !          1268: 
        !          1269: void
        !          1270: pcb_common_terminate(
        !          1271:     task_t             task
        !          1272: )
        !          1273: {
        !          1274:     pcb_common_t       *common = task->pcb_common;
        !          1275:     
        !          1276:     kfree((void *)common, sizeof (*common));
        !          1277: }

unix.superglobalmegacorp.com

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