Annotation of kernel/kern/syscall_subr.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:  * Mach Operating System
        !            27:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
        !            28:  * All Rights Reserved.
        !            29:  * 
        !            30:  * Permission to use, copy, modify and distribute this software and its
        !            31:  * documentation is hereby granted, provided that both the copyright
        !            32:  * notice and this permission notice appear in all copies of the
        !            33:  * software, derivative works or modified versions, and any portions
        !            34:  * thereof, and that both notices appear in supporting documentation.
        !            35:  * 
        !            36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            39:  * 
        !            40:  * Carnegie Mellon requests users of this software to return to
        !            41:  * 
        !            42:  *  Software Distribution Coordinator  or  [email protected]
        !            43:  *  School of Computer Science
        !            44:  *  Carnegie Mellon University
        !            45:  *  Pittsburgh PA 15213-3890
        !            46:  * 
        !            47:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            48:  * the rights to redistribute these changes.
        !            49:  */
        !            50: 
        !            51: #include <mach_fixpri.h>
        !            52: #include <cpus.h>
        !            53: 
        !            54: #include <mach/boolean.h>
        !            55: #include <mach/thread_switch.h>
        !            56: #include <ipc/ipc_port.h>
        !            57: #include <ipc/ipc_space.h>
        !            58: #include <kern/counters.h>
        !            59: #include <kern/ipc_kobject.h>
        !            60: #include <kern/processor.h>
        !            61: #include <kern/sched.h>
        !            62: #include <kern/sched_prim.h>
        !            63: #include <kern/ipc_sched.h>
        !            64: #include <kern/task.h>
        !            65: #include <kern/thread.h>
        !            66: #include <kern/time_out.h>
        !            67: #include <machine/machspl.h>   /* for splsched */
        !            68: 
        !            69: #if    MACH_FIXPRI
        !            70: #include <mach/policy.h>
        !            71: #endif MACH_FIXPRI
        !            72: 
        !            73: 
        !            74: 
        !            75: /*
        !            76:  *     swtch and swtch_pri both attempt to context switch (logic in
        !            77:  *     thread_block no-ops the context switch if nothing would happen).
        !            78:  *     A boolean is returned that indicates whether there is anything
        !            79:  *     else runnable.
        !            80:  *
        !            81:  *     This boolean can be used by a thread waiting on a
        !            82:  *     lock or condition:  If FALSE is returned, the thread is justified
        !            83:  *     in becoming a resource hog by continuing to spin because there's
        !            84:  *     nothing else useful that the processor could do.  If TRUE is
        !            85:  *     returned, the thread should make one more check on the
        !            86:  *     lock and then be a good citizen and really suspend.
        !            87:  */
        !            88: 
        !            89: extern void thread_depress_priority();
        !            90: extern kern_return_t thread_depress_abort();
        !            91: 
        !            92: void swtch_continue()
        !            93: {
        !            94:        register processor_t    myprocessor;
        !            95: 
        !            96:        myprocessor = current_processor();
        !            97:        thread_syscall_return(myprocessor->runq.count > 0 ||
        !            98:                              myprocessor->processor_set->runq.count > 0);
        !            99:        /*NOTREACHED*/
        !           100: }
        !           101: 
        !           102: boolean_t swtch()
        !           103: {
        !           104:        register processor_t    myprocessor;
        !           105: 
        !           106: #if    NCPUS > 1
        !           107:        myprocessor = current_processor();
        !           108:        if (myprocessor->runq.count == 0 &&
        !           109:            myprocessor->processor_set->runq.count == 0)
        !           110:                return(FALSE);
        !           111: #endif NCPUS > 1
        !           112: 
        !           113:        counter(c_swtch_block++);
        !           114:        thread_block_with_continuation(swtch_continue);
        !           115:        myprocessor = current_processor();
        !           116:        return(myprocessor->runq.count > 0 ||
        !           117:               myprocessor->processor_set->runq.count > 0);
        !           118: }
        !           119: 
        !           120: void swtch_pri_continue()
        !           121: {
        !           122:        register thread_t       thread = current_thread();
        !           123:        register processor_t    myprocessor;
        !           124: 
        !           125:        if (thread->depress_priority >= 0)
        !           126:                (void) thread_depress_abort(thread);
        !           127:        myprocessor = current_processor();
        !           128:        thread_syscall_return(myprocessor->runq.count > 0 ||
        !           129:                              myprocessor->processor_set->runq.count > 0);
        !           130:        /*NOTREACHED*/
        !           131: }
        !           132: 
        !           133: boolean_t  swtch_pri(pri)
        !           134:        int pri;
        !           135: {
        !           136:        register thread_t       thread = current_thread();
        !           137:        register processor_t    myprocessor;
        !           138: 
        !           139: #ifdef lint
        !           140:        pri++;
        !           141: #endif lint
        !           142: 
        !           143: #if    NCPUS > 1
        !           144:        myprocessor = current_processor();
        !           145:        if (myprocessor->runq.count == 0 &&
        !           146:            myprocessor->processor_set->runq.count == 0)
        !           147:                return(FALSE);
        !           148: #endif NCPUS > 1
        !           149: 
        !           150:        /*
        !           151:         *      XXX need to think about depression duration.
        !           152:         *      XXX currently using min quantum.
        !           153:         */
        !           154:        thread_depress_priority(thread, min_quantum);
        !           155: 
        !           156:        counter(c_swtch_pri_block++);
        !           157:        thread_block_with_continuation(swtch_pri_continue);
        !           158: 
        !           159:        if (thread->depress_priority >= 0)
        !           160:                (void) thread_depress_abort(thread);
        !           161:        myprocessor = current_processor();
        !           162:        return(myprocessor->runq.count > 0 ||
        !           163:               myprocessor->processor_set->runq.count > 0);
        !           164: }
        !           165: 
        !           166: extern int hz;
        !           167: 
        !           168: void thread_switch_continue()
        !           169: {
        !           170:        register thread_t       cur_thread = current_thread();
        !           171: 
        !           172:        /*
        !           173:         *  Restore depressed priority                   
        !           174:         */
        !           175:        if (cur_thread->depress_priority >= 0)
        !           176:                (void) thread_depress_abort(cur_thread);
        !           177:        thread_syscall_return(KERN_SUCCESS);
        !           178:        /*NOTREACHED*/
        !           179: }
        !           180: 
        !           181: /*
        !           182:  *     thread_switch:
        !           183:  *
        !           184:  *     Context switch.  User may supply thread hint.
        !           185:  *
        !           186:  *     Fixed priority threads that call this get what they asked for
        !           187:  *     even if that violates priority order.
        !           188:  */
        !           189: kern_return_t thread_switch(thread_name, option, option_time)
        !           190: mach_port_t thread_name;
        !           191: int option;
        !           192: mach_msg_timeout_t option_time;
        !           193: {
        !           194:     register thread_t          cur_thread = current_thread();
        !           195:     register processor_t       myprocessor;
        !           196:     kern_return_t              result;
        !           197:     ipc_port_t                 port;
        !           198: 
        !           199:     /*
        !           200:      * Process option.
        !           201:      */
        !           202:     switch (option) {
        !           203:        case SWITCH_OPTION_NONE:
        !           204:            /*
        !           205:             *  Nothing to do.
        !           206:             */
        !           207:            break;
        !           208: 
        !           209:        case SWITCH_OPTION_DEPRESS:
        !           210:            /*
        !           211:             *  Depress priority for given time.
        !           212:             */
        !           213:            thread_depress_priority(cur_thread, option_time);
        !           214:            break;
        !           215: 
        !           216:        case SWITCH_OPTION_WAIT:
        !           217:            thread_will_wait_with_timeout(cur_thread, option_time);
        !           218:            break;
        !           219: 
        !           220:        default:
        !           221:            return(KERN_INVALID_ARGUMENT);
        !           222:     }
        !           223:     
        !           224:     /*
        !           225:      * Check and act on thread hint if appropriate.
        !           226:      */
        !           227:     if ((thread_name != 0) &&
        !           228:        ((result = ipc_port_translate_send(cur_thread->task->itk_space,
        !           229:                                 thread_name, &port)) == KERN_SUCCESS)) {
        !           230:            /* port is locked, but it might not be active */
        !           231: 
        !           232:            /*
        !           233:             *  Get corresponding thread.
        !           234:             */
        !           235:            if (ip_active(port) && (ip_kotype(port) == IKOT_THREAD)) {
        !           236:                register thread_t thread;
        !           237:                register spl_t s;
        !           238: 
        !           239:                thread = (thread_t) port->ip_kobject;
        !           240:                /*
        !           241:                 *      Check if the thread is in the right pset. Then
        !           242:                 *      pull it off its run queue.  If it
        !           243:                 *      doesn't come, then it's not eligible.
        !           244:                 */
        !           245:                s = splsched();
        !           246:                thread_lock(thread);
        !           247:                if ((thread->processor_set == cur_thread->processor_set)
        !           248:                    && (rem_runq(thread) != RUN_QUEUE_NULL)) {
        !           249:                        /*
        !           250:                         *      Hah, got it!!
        !           251:                         */
        !           252:                        thread_unlock(thread);
        !           253:                        (void) splx(s);
        !           254:                        ip_unlock(port);
        !           255:                        /* XXX thread might disappear on us now? */
        !           256: #if    MACH_FIXPRI
        !           257:                        if (thread->policy == POLICY_FIXEDPRI) {
        !           258:                            myprocessor = current_processor();
        !           259:                            myprocessor->quantum = thread->sched_data;
        !           260:                            myprocessor->first_quantum = TRUE;
        !           261:                        }
        !           262: #endif MACH_FIXPRI
        !           263:                        counter(c_thread_switch_handoff++);
        !           264:                        thread_run(thread_switch_continue, thread);
        !           265:                        /*
        !           266:                         *  Restore depressed priority                   
        !           267:                         */
        !           268:                        if (cur_thread->depress_priority >= 0)
        !           269:                                (void) thread_depress_abort(cur_thread);
        !           270: 
        !           271:                        return(KERN_SUCCESS);
        !           272:                }
        !           273:                thread_unlock(thread);
        !           274:                (void) splx(s);
        !           275:            }
        !           276:            ip_unlock(port);
        !           277:     }
        !           278:     else if (thread_name != 0 && result == KERN_INVALID_NAME)
        !           279:        return (KERN_INVALID_ARGUMENT);
        !           280: 
        !           281:     /*
        !           282:      * No handoff hint supplied, or hint was wrong.  Call thread_block() in
        !           283:      * hopes of running something else.  If nothing else is runnable,
        !           284:      * thread_block will detect this.  WARNING: thread_switch with no
        !           285:      * option will not do anything useful if the thread calling it is the
        !           286:      * highest priority thread (can easily happen with a collection
        !           287:      * of timesharing threads).
        !           288:      */
        !           289: #if    NCPUS > 1
        !           290:     myprocessor = current_processor();
        !           291:     if (myprocessor->processor_set->runq.count > 0 ||
        !           292:        myprocessor->runq.count > 0)
        !           293: #endif NCPUS > 1
        !           294:            thread_block_with_continuation(thread_switch_continue);
        !           295: 
        !           296:     /*
        !           297:      *  Restore depressed priority                      
        !           298:      */
        !           299:     if (cur_thread->depress_priority >= 0)
        !           300:        (void) thread_depress_abort(cur_thread);
        !           301:     return(KERN_SUCCESS);
        !           302: }
        !           303: 
        !           304: /*
        !           305:  *     thread_depress_priority
        !           306:  *
        !           307:  *     Depress thread's priority to lowest possible for specified period.
        !           308:  *     Intended for use when thread wants a lock but doesn't know which
        !           309:  *     other thread is holding it.  As with thread_switch, fixed
        !           310:  *     priority threads get exactly what they asked for.  Users access
        !           311:  *     this by the SWITCH_OPTION_DEPRESS option to thread_switch.  A Time
        !           312:  *      of zero will result in no timeout being scheduled.
        !           313:  */
        !           314: void
        !           315: thread_depress_priority(thread, depress_time)
        !           316: register thread_t thread;
        !           317: mach_msg_timeout_t depress_time;
        !           318: {
        !           319:     unsigned int ticks;
        !           320:     spl_t      s;
        !           321: 
        !           322:     /* convert from milliseconds to ticks */
        !           323:     ticks = convert_ipc_timeout_to_ticks(depress_time);
        !           324: 
        !           325:     s = splsched();
        !           326:     thread_lock(thread);
        !           327: 
        !           328:     /*
        !           329:      * If thread is already depressed, override previous depression.
        !           330:      */
        !           331:     reset_timeout_check(&thread->depress_timer);
        !           332: 
        !           333:     /*
        !           334:      * Save current priority, then set priority and
        !           335:      * sched_pri to their lowest possible values.
        !           336:      */
        !           337:     thread->depress_priority = thread->priority;
        !           338:     thread->priority = 0;
        !           339:     thread->sched_pri = 0;
        !           340:     if (ticks != 0)
        !           341:        set_timeout(&thread->depress_timer, ticks);
        !           342: 
        !           343:     thread_unlock(thread);
        !           344:     (void) splx(s);
        !           345: }      
        !           346: 
        !           347: /*
        !           348:  *     thread_depress_timeout:
        !           349:  *
        !           350:  *     Timeout routine for priority depression.
        !           351:  */
        !           352: void
        !           353: thread_depress_timeout(thread)
        !           354: register thread_t thread;
        !           355: {
        !           356:     spl_t      s;
        !           357: 
        !           358:     s = splsched();
        !           359:     thread_lock(thread);
        !           360: 
        !           361:     /*
        !           362:      * If we lose a race with thread_depress_abort,
        !           363:      * then depress_priority might be -1.
        !           364:      */
        !           365: 
        !           366:     if (thread->depress_priority >= 0) {
        !           367:        thread->priority = thread->depress_priority;
        !           368:        thread->depress_priority = -1;
        !           369:        compute_priority(thread, FALSE);
        !           370:     }
        !           371: 
        !           372:     thread_unlock(thread);
        !           373:     (void) splx(s);
        !           374: }
        !           375: 
        !           376: /*
        !           377:  *     thread_depress_abort:
        !           378:  *
        !           379:  *     Prematurely abort priority depression if there is one.
        !           380:  */
        !           381: kern_return_t
        !           382: thread_depress_abort(thread)
        !           383: register thread_t      thread;
        !           384: {
        !           385:     spl_t      s;
        !           386: 
        !           387:     if (thread == THREAD_NULL)
        !           388:        return(KERN_INVALID_ARGUMENT);
        !           389: 
        !           390:     s = splsched();
        !           391:     thread_lock(thread);
        !           392: 
        !           393:     /*
        !           394:      * Only restore priority if thread is depressed.
        !           395:      */
        !           396:     if (thread->depress_priority >= 0) {
        !           397:        reset_timeout_check(&thread->depress_timer);
        !           398:        thread->priority = thread->depress_priority;
        !           399:        thread->depress_priority = -1;
        !           400:        compute_priority(thread, FALSE);
        !           401:     }
        !           402: 
        !           403:     thread_unlock(thread);
        !           404:     (void) splx(s);
        !           405:     return(KERN_SUCCESS);
        !           406: }

unix.superglobalmegacorp.com

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