Annotation of kernel/kern/mach_clock.c, revision 1.1.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 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:  *     File:   clock_prim.c
                     52:  *     Author: Avadis Tevanian, Jr.
                     53:  *     Date:   1986
                     54:  *
                     55:  *     Clock primitives.
                     56:  */
                     57: #import <mach/features.h>
                     58: 
                     59: #include <mach/boolean.h>
                     60: #include <mach/machine.h>
                     61: #include <mach/time_value.h>
                     62: #include <mach/vm_param.h>
                     63: #include <mach/vm_prot.h>
                     64: #include <kern/counters.h>
                     65: #include <kern/cpu_number.h>
                     66: #include <kern/clock.h>
                     67: #include <kern/host.h>
                     68: #include <kern/lock.h>
                     69: #include <kern/mach_param.h>
                     70: #include <kern/processor.h>
                     71: #include <kern/sched.h>
                     72: #include <kern/sched_prim.h>
                     73: #include <kern/thread.h>
                     74: #include <kern/time_out.h>
                     75: #include <kern/time_stamp.h>
                     76: #include <vm/vm_kern.h>
                     77: #include <machine/mach_param.h>        /* HZ */
                     78: #include <machine/machspl.h>
                     79: 
                     80: 
                     81: 
                     82: extern void    thread_quantum_update();
                     83: 
                     84: int            hz = HZ;                /* number of ticks per second */
                     85: int            tick = (1000000 / HZ);  /* number of usec per tick */
                     86: 
                     87: tvalspec_t     tick_stamp;             /* timestamp of the last 'tick' */
                     88: 
                     89: /*
                     90:  *     Handle clock interrupts.
                     91:  *
                     92:  *     The clock interrupt is assumed to be called at a (more or less)
                     93:  *     constant rate.  The rate must be identical on all CPUS (XXX - fix).
                     94:  *
                     95:  *     Usec is the number of microseconds that have elapsed since the
                     96:  *     last clock tick.  It may be constant or computed, depending on
                     97:  *     the accuracy of the hardware clock.
                     98:  *
                     99:  */
                    100: void clock_interrupt(usec, usermode, basepri)
                    101:        register int    usec;           /* microseconds per tick */
                    102:        boolean_t       usermode;       /* executing user code */
                    103:        boolean_t       basepri;        /* at base priority */
                    104: {
                    105:        register int            my_cpu = cpu_number();
                    106:        register thread_t       thread = current_thread();
                    107: 
                    108:        counter(c_clock_ticks++);
                    109:        counter(c_threads_total += c_threads_current);
                    110:        counter(c_stacks_total += c_stacks_current);
                    111: 
                    112: #if    STAT_TIME
                    113:        /*
                    114:         *      Increment the thread time, if using
                    115:         *      statistical timing.
                    116:         */
                    117:        if (usermode) {
                    118:            timer_bump(&thread->user_timer, usec);
                    119:        }
                    120:        else {
                    121:            timer_bump(&thread->system_timer, usec);
                    122:        }
                    123: #endif STAT_TIME
                    124: 
                    125:        /*
                    126:         *      Increment the CPU time statistics.
                    127:         */
                    128:        {
                    129:            register int        state;
                    130: 
                    131:            if (usermode)
                    132:                state = CPU_STATE_USER;
                    133:            else if (!cpu_idle(my_cpu))
                    134:                state = CPU_STATE_SYSTEM;
                    135:            else
                    136:                state = CPU_STATE_IDLE;
                    137: 
                    138:            machine_slot[my_cpu].cpu_ticks[state]++;
                    139: 
                    140:            /*
                    141:             *  Adjust the thread's priority and check for
                    142:             *  quantum expiration.
                    143:             */
                    144: 
                    145:            if (!(thread->state & TH_IDLE))
                    146:                thread_quantum_update(my_cpu, thread, 1, state);
                    147:        }
                    148: 
                    149:        if (my_cpu == master_cpu) {
                    150: 
                    151:            /*
                    152:             *  Perform scheduler housekeeping activities.
                    153:             */
                    154:            recompute_priorities();
                    155: 
                    156:            /*
                    157:             *  Save a timestamp for this clock tick.  This
                    158:             *  is used by set_timeout(), et al. to apply
                    159:             *  appropriate rounding to timeout intervals.
                    160:             *  This is really a hack which assumes that
                    161:             *  'timer interrupts' have the same period and
                    162:             *  phase as a clock tick.
                    163:             */
                    164:            tick_stamp = clock_get_counter(System);
                    165: 
                    166: #if    TS_FORMAT == 1
                    167:            /*
                    168:             *  Increment the tick count for the timestamping routine.
                    169:             */
                    170:            ts_tick_count++;
                    171: #endif TS_FORMAT == 1
                    172: 
                    173:        }
                    174: }
                    175: 
                    176: #if    SIMPLE_CLOCK
                    177: 
                    178: int
                    179: sched_usec_elapsed(void)
                    180: {
                    181:        static tvalspec_t       sched_stamp;
                    182:        tvalspec_t              delta_stamp,
                    183:                                new_stamp = clock_get_counter(System);
                    184:        int                     new_usec;
                    185: 
                    186:        delta_stamp = new_stamp;
                    187:        SUB_TVALSPEC(&delta_stamp, &sched_stamp);
                    188:        new_usec = (delta_stamp.tv_sec * USEC_PER_SEC) +
                    189:                        (delta_stamp.tv_nsec / NSEC_PER_USEC);
                    190:        sched_stamp = new_stamp;
                    191:        
                    192:        return (new_usec);
                    193: }
                    194: #endif /* SIMPLE_CLOCK */
                    195: 
                    196: tvalspec_t
                    197: ticks_to_tvalspec(
                    198:        unsigned int    ticks)
                    199: {
                    200:        tvalspec_t              result;
                    201:     
                    202:        result.tv_sec = ticks / TICKS_PER_SEC;
                    203:        result.tv_nsec = (ticks % TICKS_PER_SEC) * NSEC_PER_TICK;
                    204:     
                    205:        return (result);
                    206: }
                    207: 
                    208: decl_simple_lock_data(static,  timer_lock)     /* lock for ... */
                    209: 
                    210: static void
                    211: service_timer(
                    212:        timer_elt_t     telt)
                    213: {
                    214:        spl_t           s;
                    215:        int             (*fcn)();
                    216:        char            *param; 
                    217:        
                    218:        s = splsched();
                    219:        simple_lock(&timer_lock);
                    220:        
                    221:        fcn = telt->fcn;
                    222:        param = telt->param;
                    223: 
                    224:        telt->set = TELT_UNSET;
                    225:        
                    226:        simple_unlock(&timer_lock);
                    227:        splx(s);
                    228:        
                    229:        (*fcn)(param);
                    230: }
                    231: 
                    232: static __inline__ void
                    233: init_timeout_element(
                    234:        timer_elt_t     telt)
                    235: {
                    236:        telt->call.func = (thread_call_func_t)service_timer;
                    237:        telt->call.spec_proto = telt;
                    238:        telt->call.status = IDLE;
                    239: }
                    240: 
                    241: /*
                    242:  *     Set timeout.
                    243:  *
                    244:  *     Parameters:
                    245:  *             telt     timer element.  Function and param are already set.
                    246:  *             interval time-out interval, in hz.
                    247:  */
                    248: void set_timeout(telt, interval)
                    249:        register timer_elt_t    telt;   /* already loaded */
                    250:        register unsigned int   interval;
                    251: {
                    252:        spl_t           s;
                    253:        tvalspec_t      deadline;
                    254: 
                    255:        s = splsched();
                    256:        simple_lock(&timer_lock);
                    257: 
                    258:        if (telt->call.spec_proto != telt)
                    259:            init_timeout_element(telt);
                    260: 
                    261:        deadline = ticks_to_tvalspec(interval);
                    262:        ADD_TVALSPEC(&deadline, &tick_stamp);
                    263:        
                    264:        thread_call_enter_delayed(&telt->call, deadline);
                    265: 
                    266:        telt->set = TELT_SET;
                    267: 
                    268:        simple_unlock(&timer_lock);
                    269:        splx(s);
                    270: }
                    271: 
                    272: boolean_t reset_timeout(telt)
                    273:        register timer_elt_t    telt;
                    274: {
                    275:        spl_t           s;
                    276: 
                    277:        s = splsched();
                    278:        simple_lock(&timer_lock);
                    279: 
                    280:        if (telt->set) {
                    281:            thread_call_cancel(&telt->call);
                    282: 
                    283:            telt->set = TELT_UNSET;
                    284: 
                    285:            simple_unlock(&timer_lock);
                    286:            splx(s);
                    287:            return TRUE;
                    288:        }
                    289:        else {
                    290:            simple_unlock(&timer_lock);
                    291:            splx(s);
                    292:            return FALSE;
                    293:        }
                    294: }
                    295: 
                    296: void init_timeout()
                    297: {
                    298:        simple_lock_init(&timer_lock);
                    299: }

unix.superglobalmegacorp.com

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