Annotation of XNU/osfmk/kern/lock_mon.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: /*
        !            26:  * HISTORY
        !            27:  * 
        !            28:  * Revision 1.1.1.1  1998/09/22 21:05:34  wsanchez
        !            29:  * Import of Mac OS X kernel (~semeria)
        !            30:  *
        !            31:  * Revision 1.1.1.1  1998/03/07 02:25:55  wsanchez
        !            32:  * Import of OSF Mach kernel (~mburg)
        !            33:  *
        !            34:  * Revision 1.3.19.1  1997/09/22  17:39:46  barbou
        !            35:  *     MP+RT: protect cpu_number() usage against preemption.
        !            36:  *     [97/09/16            barbou]
        !            37:  *
        !            38:  * Revision 1.3.15.4  1995/02/24  15:20:58  alanl
        !            39:  *     DIPC: Merge from nmk17b2 to nmk18b8.
        !            40:  *     Notes:  major lock cleanup.  Change kdb_lock and printf_lock
        !            41:  *     references to conform with simple_lock declaration rules.
        !            42:  *     This code is broken and non-portable; its functionality
        !            43:  *     should be subsumed in the regular lock package.
        !            44:  *     [95/01/16            alanl]
        !            45:  * 
        !            46:  * Revision 1.3.17.2  1994/11/10  06:13:19  dwm
        !            47:  *     mk6 CR764 - s/spinlock/simple_lock/ (name change only)
        !            48:  *     [1994/11/10  05:28:52  dwm]
        !            49:  * 
        !            50:  * Revision 1.3.17.1  1994/11/04  10:07:54  dwm
        !            51:  *     mk6 CR668 - 1.3b26 merge
        !            52:  *     This file is obviously UNUSED - hence broken; merged anyway
        !            53:  *     * Revision 1.3.4.4  1994/05/06  18:50:11  tmt
        !            54:  *     Merge in DEC Alpha changes to osc1.3b19.
        !            55:  *     Merge Alpha changes into osc1.312b source code.
        !            56:  *     64bit cleanup.
        !            57:  *     * End1.3merge
        !            58:  *     [1994/11/04  09:25:58  dwm]
        !            59:  * 
        !            60:  * Revision 1.3.15.1  1994/09/23  02:21:48  ezf
        !            61:  *     change marker to not FREE
        !            62:  *     [1994/09/22  21:34:22  ezf]
        !            63:  * 
        !            64:  * Revision 1.3.13.1  1994/06/09  14:11:30  dswartz
        !            65:  *     Preemption merge.
        !            66:  *     [1994/06/09  14:07:06  dswartz]
        !            67:  * 
        !            68:  * Revision 1.3.4.2  1993/06/09  02:36:12  gm
        !            69:  *     Added to OSF/1 R1.3 from NMK15.0.
        !            70:  *     [1993/06/02  21:13:15  jeffc]
        !            71:  * 
        !            72:  * Revision 1.3  1993/04/19  16:26:56  devrcs
        !            73:  *     Fix for TIME_STAMP configuration.
        !            74:  *     [Patrick Petit <[email protected]>]
        !            75:  *     [93/02/11            bernadat]
        !            76:  * 
        !            77:  * Revision 1.2  1992/11/25  01:11:05  robert
        !            78:  *     integrate changes below for norma_14
        !            79:  * 
        !            80:  *     Philippe Bernadat (bernadat) at gr.osf.org
        !            81:  *     Moved MACH_MP_DEBUG code to kern/lock.c
        !            82:  *     [1992/11/13  19:33:47  robert]
        !            83:  * 
        !            84:  * Revision 1.1  1992/09/30  02:09:28  robert
        !            85:  *     Initial revision
        !            86:  * 
        !            87:  * $EndLog$
        !            88:  */
        !            89: /* CMU_HIST */
        !            90: /*
        !            91:  * Revision 2.1.2.1.3.1  92/02/18  19:08:45  jeffreyh
        !            92:  *     Created. Might need some work if used on anything but a 386.
        !            93:  *     [92/02/11  07:56:50  bernadat]
        !            94:  */
        !            95: /* CMU_ENDHIST */
        !            96: 
        !            97: /* 
        !            98:  * Mach Operating System
        !            99:  * Copyright (c) 1990 Carnegie-Mellon University
        !           100:  * Copyright (c) 1989 Carnegie-Mellon University
        !           101:  * All rights reserved.  The CMU software License Agreement specifies
        !           102:  * the terms and conditions for use and redistribution.
        !           103:  */
        !           104: 
        !           105: /*
        !           106:  */
        !           107: 
        !           108: /*
        !           109:  *     Support For MP Debugging
        !           110:  *             if MACH_MP_DEBUG is on, we use alternate locking
        !           111:  *             routines do detect dealocks
        !           112:  *     Support for MP lock monitoring (MACH_LOCK_MON).
        !           113:  *             Registers use of locks, contention.
        !           114:  *             Depending on hardware also records time spent with locks held
        !           115:  */
        !           116: 
        !           117: #include <cpus.h>
        !           118: #include <mach_mp_debug.h>
        !           119: #include <mach_lock_mon.h>
        !           120: #include <time_stamp.h>
        !           121: 
        !           122: #include <sys/types.h>
        !           123: #include <mach/machine/vm_types.h>
        !           124: #include <mach/boolean.h>
        !           125: #include <kern/thread.h>
        !           126: #include <kern/lock.h>
        !           127: 
        !           128: 
        !           129: decl_simple_lock_data(extern, kdb_lock)
        !           130: decl_simple_lock_data(extern, printf_lock)
        !           131: 
        !           132: #if    NCPUS > 1 && MACH_LOCK_MON
        !           133: 
        !           134: #if    TIME_STAMP
        !           135: extern time_stamp_t time_stamp;
        !           136: #else  TIME_STAMP
        !           137: typedef unsigned int time_stamp_t;
        !           138: #define        time_stamp 0
        !           139: #endif TIME_STAMP
        !           140: 
        !           141: #define LOCK_INFO_MAX       (1024*32)
        !           142: #define LOCK_INFO_HASH_COUNT 1024
        !           143: #define LOCK_INFO_PER_BUCKET   (LOCK_INFO_MAX/LOCK_INFO_HASH_COUNT)
        !           144: 
        !           145: 
        !           146: #define HASH_LOCK(lock)        ((long)lock>>5 & (LOCK_INFO_HASH_COUNT-1))
        !           147: 
        !           148: struct lock_info {
        !           149:        unsigned int    success;
        !           150:        unsigned int    fail;
        !           151:        unsigned int    masked;
        !           152:        unsigned int    stack; 
        !           153:        unsigned int    time;
        !           154: #if    MACH_SLOCKS
        !           155:        simple_lock_data_t      * lock;
        !           156: #endif
        !           157:        vm_offset_t     caller;
        !           158: };
        !           159: 
        !           160: struct lock_info_bucket {
        !           161:        struct lock_info info[LOCK_INFO_PER_BUCKET];
        !           162: };
        !           163: 
        !           164: struct lock_info_bucket lock_info[LOCK_INFO_HASH_COUNT];
        !           165: struct lock_info default_lock_info;
        !           166: unsigned default_lock_stack = 0;
        !           167: 
        !           168: extern int curr_ipl[];
        !           169: 
        !           170: 
        !           171: 
        !           172: struct lock_info *
        !           173: locate_lock_info(lock)
        !           174: simple_lock_data_t     ** lock;
        !           175: {
        !           176:        struct lock_info *li =  &(lock_info[HASH_LOCK(*lock)].info[0]);
        !           177:        register i;
        !           178: 
        !           179:        for (i=0; i < LOCK_INFO_PER_BUCKET; i++, li++)
        !           180:                if (li->lock) {
        !           181:                        if (li->lock == *lock)
        !           182:                                return(li);
        !           183:                } else {
        !           184:                        li->lock = *lock;
        !           185:                        li->caller = *((vm_offset_t *)lock - 1);
        !           186:                        return(li);
        !           187:                }
        !           188:        db_printf("out of lock_info slots\n");
        !           189:        li = &default_lock_info;
        !           190:        return(li);
        !           191: }
        !           192:                
        !           193: 
        !           194: simple_lock(lock)
        !           195: decl_simple_lock_data(, *lock)
        !           196: {
        !           197:        register struct lock_info *li = locate_lock_info(&lock);
        !           198: 
        !           199:        if (current_thread()) 
        !           200:                li->stack = current_thread()->lock_stack++;
        !           201:        mp_disable_preemption();
        !           202:        if (curr_ipl[cpu_number()])
        !           203:                li->masked++;
        !           204:        mp_enable_preemption();
        !           205:        if (_simple_lock_try(lock))
        !           206:                li->success++;
        !           207:        else {
        !           208:                _simple_lock(lock);
        !           209:                li->fail++;
        !           210:        }
        !           211:        li->time = time_stamp - li->time;
        !           212: }
        !           213: 
        !           214: simple_lock_try(lock)
        !           215: decl_simple_lock_data(, *lock)
        !           216: {
        !           217:        register struct lock_info *li = locate_lock_info(&lock);
        !           218: 
        !           219:        mp_disable_preemption();
        !           220:        if (curr_ipl[cpu_number()])
        !           221:                li->masked++;
        !           222:        mp_enable_preemption();
        !           223:        if (_simple_lock_try(lock)) {
        !           224:                li->success++;
        !           225:                li->time = time_stamp - li->time;
        !           226:                if (current_thread())
        !           227:                        li->stack = current_thread()->lock_stack++;
        !           228:                return(1);
        !           229:        } else {
        !           230:                li->fail++;
        !           231:                return(0);
        !           232:        }
        !           233: }
        !           234: 
        !           235: simple_unlock(lock)
        !           236: decl_simple_lock_data(, *lock)
        !           237: {
        !           238:        register time_stamp_t stamp = time_stamp;
        !           239:        register time_stamp_t *time = &locate_lock_info(&lock)->time;
        !           240:        register unsigned *lock_stack;
        !           241: 
        !           242:        *time = stamp - *time;
        !           243:        _simple_unlock(lock);
        !           244:        if (current_thread()) {
        !           245:                lock_stack = &current_thread()->lock_stack;
        !           246:                if (*lock_stack)
        !           247:                        (*lock_stack)--;
        !           248:        }
        !           249: }
        !           250: 
        !           251: lip() {
        !           252:        lis(4, 1, 0);
        !           253: }
        !           254: 
        !           255: #define lock_info_sort lis
        !           256: 
        !           257: unsigned scurval, ssum;
        !           258: struct lock_info *sli;
        !           259: 
        !           260: lock_info_sort(arg, abs, count)
        !           261: {
        !           262:        struct lock_info *li, mean;
        !           263:        int bucket = 0;
        !           264:        int i;
        !           265:        unsigned max_val;
        !           266:        unsigned old_val = (unsigned)-1;
        !           267:        struct lock_info *target_li = &lock_info[0].info[0];
        !           268:        unsigned sum;
        !           269:        unsigned empty, total;
        !           270:        unsigned curval;
        !           271: 
        !           272:        printf("\nSUCCESS       FAIL    MASKED  STACK   TIME    LOCK/CALLER\n");
        !           273:        if (!count)
        !           274:                count = 8 ;
        !           275:        while (count && target_li) {
        !           276:                empty = LOCK_INFO_HASH_COUNT;
        !           277:                target_li = 0;
        !           278:                total = 0;
        !           279:                max_val = 0;
        !           280:                mean.success = 0;
        !           281:                mean.fail = 0;
        !           282:                mean.masked = 0;
        !           283:                mean.stack = 0;
        !           284:                mean.time = 0;
        !           285:                mean.lock = (simple_lock_data_t *) &lock_info;
        !           286:                mean.caller = (vm_offset_t) &lock_info;
        !           287:                for (bucket = 0; bucket < LOCK_INFO_HASH_COUNT; bucket++) {
        !           288:                        li = &lock_info[bucket].info[0];
        !           289:                        if (li->lock)
        !           290:                                empty--;
        !           291:                        for (i= 0; i< LOCK_INFO_PER_BUCKET && li->lock; i++, li++) {
        !           292:                                if (li->lock == &kdb_lock || li->lock == &printf_lock)
        !           293:                                        continue;
        !           294:                                total++;
        !           295:                                curval = *((int *)li + arg);
        !           296:                                sum = li->success + li->fail;
        !           297:                                if(!sum && !abs)
        !           298:                                        continue;
        !           299:                                scurval = curval;
        !           300:                                ssum = sum;
        !           301:                                sli = li;
        !           302:                                if (!abs) switch(arg) {
        !           303:                                case 0:
        !           304:                                        break;
        !           305:                                case 1:
        !           306:                                case 2:
        !           307:                                        curval = (curval*100) / sum;
        !           308:                                        break;
        !           309:                                case 3:
        !           310:                                case 4:
        !           311:                                        curval = curval / sum;
        !           312:                                        break;
        !           313:                                }
        !           314:                                if (curval > max_val && curval < old_val) {
        !           315:                                        max_val = curval;
        !           316:                                        target_li = li;
        !           317:                                }
        !           318:                                if (curval == old_val && count != 0) {
        !           319:                                        print_lock_info(li);
        !           320:                                        count--;
        !           321:                                }
        !           322:                                mean.success += li->success;
        !           323:                                mean.fail += li->fail;
        !           324:                                mean.masked += li->masked;
        !           325:                                mean.stack += li->stack;
        !           326:                                mean.time += li->time;
        !           327:                        }
        !           328:                }
        !           329:                if (target_li)
        !           330:                        old_val = max_val;
        !           331:        }
        !           332:        db_printf("\n%d total locks, %d empty buckets", total, empty );
        !           333:        if (default_lock_info.success) 
        !           334:                db_printf(", default: %d", default_lock_info.success + default_lock_info.fail); 
        !           335:        db_printf("\n");
        !           336:        print_lock_info(&mean);
        !           337: }
        !           338: 
        !           339: #define lock_info_clear lic
        !           340: 
        !           341: lock_info_clear()
        !           342: {
        !           343:        struct lock_info *li;
        !           344:        int bucket = 0;
        !           345:        int i;
        !           346:        for (bucket = 0; bucket < LOCK_INFO_HASH_COUNT; bucket++) {
        !           347:                li = &lock_info[bucket].info[0];
        !           348:                for (i= 0; i< LOCK_INFO_PER_BUCKET; i++, li++) {
        !           349:                        bzero(li, sizeof(struct lock_info));
        !           350:                }
        !           351:        }
        !           352:        bzero(&default_lock_info, sizeof(struct lock_info)); 
        !           353: }
        !           354: 
        !           355: print_lock_info(li)
        !           356: struct lock_info *li;
        !           357: {
        !           358:        int off;
        !           359:        int sum = li->success + li->fail;
        !           360:        db_printf("%d   %d/%d   %d/%d   %d/%d   %d/%d   ", li->success,
        !           361:                   li->fail, (li->fail*100)/sum,
        !           362:                   li->masked, (li->masked*100)/sum,
        !           363:                   li->stack, li->stack/sum,
        !           364:                   li->time, li->time/sum);
        !           365:        db_search_symbol(li->lock, 0, &off);
        !           366:        if (off < 1024)
        !           367:                db_printsym(li->lock, 0);
        !           368:        else {
        !           369:                db_printsym(li->caller, 0);
        !           370:                db_printf("(%X)", li->lock);
        !           371:        }
        !           372:        db_printf("\n");
        !           373: }
        !           374: 
        !           375: #endif NCPUS > 1 && MACH_LOCK_MON
        !           376: 
        !           377: #if    TIME_STAMP
        !           378: 
        !           379: /*
        !           380:  *     Measure lock/unlock operations
        !           381:  */
        !           382: 
        !           383: time_lock(loops)
        !           384: {
        !           385:        decl_simple_lock_data(, lock)
        !           386:        register time_stamp_t stamp;
        !           387:        register int i;
        !           388: 
        !           389: 
        !           390:        if (!loops)
        !           391:                loops = 1000;
        !           392:        simple_lock_init(&lock);
        !           393:        stamp = time_stamp;
        !           394:        for (i = 0; i < loops; i++) {
        !           395:                simple_lock(&lock);
        !           396:                simple_unlock(&lock);
        !           397:        }
        !           398:        stamp = time_stamp - stamp;
        !           399:        db_printf("%d stamps for simple_locks\n", stamp/loops);
        !           400: #if    MACH_LOCK_MON
        !           401:        stamp = time_stamp;
        !           402:        for (i = 0; i < loops; i++) {
        !           403:                _simple_lock(&lock);
        !           404:                _simple_unlock(&lock);
        !           405:         }
        !           406:        stamp = time_stamp - stamp;
        !           407:        db_printf("%d stamps for _simple_locks\n", stamp/loops);
        !           408: #endif MACH_LOCK_MON
        !           409: }
        !           410: #endif TIME_STAMP
        !           411: 
        !           412: 
        !           413: 
        !           414: 
        !           415: 

unix.superglobalmegacorp.com

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