Annotation of OSKit-Mach/kern/lock_mon.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1990 Carnegie-Mellon University
        !             4:  * Copyright (c) 1989 Carnegie-Mellon University
        !             5:  * All rights reserved.  The CMU software License Agreement specifies
        !             6:  * the terms and conditions for use and redistribution.
        !             7:  */
        !             8: /*
        !             9:  * Copyright 1990 by Open Software Foundation,
        !            10:  * Grenoble, FRANCE
        !            11:  *
        !            12:  *             All Rights Reserved
        !            13:  *
        !            14:  *   Permission to use, copy, modify, and distribute this software and
        !            15:  * its documentation for any purpose and without fee is hereby granted,
        !            16:  * provided that the above copyright notice appears in all copies and
        !            17:  * that both the copyright notice and this permission notice appear in
        !            18:  * supporting documentation, and that the name of OSF or Open Software
        !            19:  * Foundation not be used in advertising or publicity pertaining to
        !            20:  * distribution of the software without specific, written prior
        !            21:  * permission.
        !            22:  *
        !            23:  *   OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
        !            24:  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
        !            25:  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
        !            26:  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
        !            27:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
        !            28:  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
        !            29:  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            30:  */
        !            31: 
        !            32: /*
        !            33:  *     Support For MP Debugging
        !            34:  *             if MACH_MP_DEBUG is on, we use alternate locking
        !            35:  *             routines do detect dealocks
        !            36:  *     Support for MP lock monitoring (MACH_LOCK_MON).
        !            37:  *             Registers use of locks, contention.
        !            38:  *             Depending on hardware also records time spent with locks held
        !            39:  */
        !            40: 
        !            41: #include <cpus.h>
        !            42: #include <mach_mp_debug.h>
        !            43: #include <mach_lock_mon.h>
        !            44: #include <time_stamp.h>
        !            45: 
        !            46: #include <sys/types.h>
        !            47: #include <mach/machine/vm_types.h>
        !            48: #include <mach/boolean.h>
        !            49: #include <kern/thread.h>
        !            50: #include <kern/lock.h>
        !            51: #include <kern/time_stamp.h>
        !            52: 
        !            53: 
        !            54: decl_simple_lock_data(extern , kdb_lock)
        !            55: decl_simple_lock_data(extern , printf_lock)
        !            56: 
        !            57: #if    NCPUS > 1 && MACH_LOCK_MON
        !            58: 
        !            59: #if    TIME_STAMP
        !            60: extern time_stamp_t time_stamp;
        !            61: #else  /* TIME_STAMP */
        !            62: typedef unsigned int time_stamp_t;
        !            63: #define        time_stamp 0
        !            64: #endif /* TIME_STAMP */
        !            65: 
        !            66: #define LOCK_INFO_MAX       (1024*32)
        !            67: #define LOCK_INFO_HASH_COUNT 1024
        !            68: #define LOCK_INFO_PER_BUCKET   (LOCK_INFO_MAX/LOCK_INFO_HASH_COUNT)
        !            69: 
        !            70: 
        !            71: #define HASH_LOCK(lock)        ((long)lock>>5 & (LOCK_INFO_HASH_COUNT-1))
        !            72: 
        !            73: struct lock_info {
        !            74:        unsigned int    success;
        !            75:        unsigned int    fail;
        !            76:        unsigned int    masked;
        !            77:        unsigned int    stack;
        !            78:        time_stamp_t    time;
        !            79:        decl_simple_lock_data(, *lock)
        !            80:        vm_offset_t     caller;
        !            81: };
        !            82: 
        !            83: struct lock_info_bucket {
        !            84:        struct lock_info info[LOCK_INFO_PER_BUCKET];
        !            85: };
        !            86: 
        !            87: struct lock_info_bucket lock_info[LOCK_INFO_HASH_COUNT];
        !            88: struct lock_info default_lock_info;
        !            89: unsigned default_lock_stack = 0;
        !            90: 
        !            91: extern int curr_ipl[];
        !            92: 
        !            93: 
        !            94: 
        !            95: struct lock_info *
        !            96: locate_lock_info(lock)
        !            97: decl_simple_lock_data(, **lock)
        !            98: {
        !            99:        struct lock_info *li =  &(lock_info[HASH_LOCK(*lock)].info[0]);
        !           100:        register i;
        !           101:        register my_cpu = cpu_number();
        !           102: 
        !           103:        for (i=0; i < LOCK_INFO_PER_BUCKET; i++, li++)
        !           104:                if (li->lock) {
        !           105:                        if (li->lock == *lock)
        !           106:                                return(li);
        !           107:                } else {
        !           108:                        li->lock = *lock;
        !           109:                        li->caller = *((vm_offset_t *)lock - 1);
        !           110:                        return(li);
        !           111:                }
        !           112:        db_printf("out of lock_info slots\n");
        !           113:        li = &default_lock_info;
        !           114:        return(li);
        !           115: }
        !           116: 
        !           117: 
        !           118: simple_lock(lock)
        !           119: decl_simple_lock_data(, *lock)
        !           120: {
        !           121:        register struct lock_info *li = locate_lock_info(&lock);
        !           122:        register my_cpu = cpu_number();
        !           123: 
        !           124:        if (current_thread())
        !           125:                li->stack = current_thread()->lock_stack++;
        !           126:        if (curr_ipl[my_cpu])
        !           127:                li->masked++;
        !           128:        if (_simple_lock_try(lock))
        !           129:                li->success++;
        !           130:        else {
        !           131:                _simple_lock(lock);
        !           132:                li->fail++;
        !           133:        }
        !           134:        li->time = time_stamp - li->time;
        !           135: }
        !           136: 
        !           137: simple_lock_try(lock)
        !           138: decl_simple_lock_data(, *lock)
        !           139: {
        !           140:        register struct lock_info *li = locate_lock_info(&lock);
        !           141:        register my_cpu = cpu_number();
        !           142: 
        !           143:        if (curr_ipl[my_cpu])
        !           144:                li->masked++;
        !           145:        if (_simple_lock_try(lock)) {
        !           146:                li->success++;
        !           147:                li->time = time_stamp - li->time;
        !           148:                if (current_thread())
        !           149:                        li->stack = current_thread()->lock_stack++;
        !           150:                return(1);
        !           151:        } else {
        !           152:                li->fail++;
        !           153:                return(0);
        !           154:        }
        !           155: }
        !           156: 
        !           157: simple_unlock(lock)
        !           158: decl_simple_lock_data(, *lock)
        !           159: {
        !           160:        register time_stamp_t stamp = time_stamp;
        !           161:        register time_stamp_t *time = &locate_lock_info(&lock)->time;
        !           162:        register unsigned *lock_stack;
        !           163: 
        !           164:        *time = stamp - *time;
        !           165:        _simple_unlock(lock);
        !           166:        if (current_thread()) {
        !           167:                lock_stack = &current_thread()->lock_stack;
        !           168:                if (*lock_stack)
        !           169:                        (*lock_stack)--;
        !           170:        }
        !           171: }
        !           172: 
        !           173: lip() {
        !           174:        lis(4, 1, 0);
        !           175: }
        !           176: 
        !           177: #define lock_info_sort lis
        !           178: 
        !           179: unsigned scurval, ssum;
        !           180: struct lock_info *sli;
        !           181: 
        !           182: lock_info_sort(arg, abs, count)
        !           183: {
        !           184:        struct lock_info *li, mean;
        !           185:        int bucket = 0;
        !           186:        int i;
        !           187:        unsigned max_val;
        !           188:        unsigned old_val = (unsigned)-1;
        !           189:        struct lock_info *target_li = &lock_info[0].info[0];
        !           190:        unsigned sum;
        !           191:        unsigned empty, total;
        !           192:        unsigned curval;
        !           193: 
        !           194:        printf("\nSUCCESS       FAIL    MASKED  STACK   TIME    LOCK/CALLER\n");
        !           195:        if (!count)
        !           196:                count = 8 ;
        !           197:        while (count && target_li) {
        !           198:                empty = LOCK_INFO_HASH_COUNT;
        !           199:                target_li = 0;
        !           200:                total = 0;
        !           201:                max_val = 0;
        !           202:                mean.success = 0;
        !           203:                mean.fail = 0;
        !           204:                mean.masked = 0;
        !           205:                mean.stack = 0;
        !           206:                mean.time = 0;
        !           207:                mean.lock = (simple_lock_data_t *) &lock_info;
        !           208:                mean.caller = (vm_offset_t) &lock_info;
        !           209:                for (bucket = 0; bucket < LOCK_INFO_HASH_COUNT; bucket++) {
        !           210:                        li = &lock_info[bucket].info[0];
        !           211:                        if (li->lock)
        !           212:                                empty--;
        !           213:                        for (i= 0; i< LOCK_INFO_PER_BUCKET && li->lock; i++, li++) {
        !           214:                                if (li->lock == &kdb_lock || li->lock == &printf_lock)
        !           215:                                        continue;
        !           216:                                total++;
        !           217:                                curval = *((int *)li + arg);
        !           218:                                sum = li->success + li->fail;
        !           219:                                if(!sum && !abs)
        !           220:                                        continue;
        !           221:                                scurval = curval;
        !           222:                                ssum = sum;
        !           223:                                sli = li;
        !           224:                                if (!abs) switch(arg) {
        !           225:                                case 0:
        !           226:                                        break;
        !           227:                                case 1:
        !           228:                                case 2:
        !           229:                                        curval = (curval*100) / sum;
        !           230:                                        break;
        !           231:                                case 3:
        !           232:                                case 4:
        !           233:                                        curval = curval / sum;
        !           234:                                        break;
        !           235:                                }
        !           236:                                if (curval > max_val && curval < old_val) {
        !           237:                                        max_val = curval;
        !           238:                                        target_li = li;
        !           239:                                }
        !           240:                                if (curval == old_val && count != 0) {
        !           241:                                        print_lock_info(li);
        !           242:                                        count--;
        !           243:                                }
        !           244:                                mean.success += li->success;
        !           245:                                mean.fail += li->fail;
        !           246:                                mean.masked += li->masked;
        !           247:                                mean.stack += li->stack;
        !           248:                                mean.time += li->time;
        !           249:                        }
        !           250:                }
        !           251:                if (target_li)
        !           252:                        old_val = max_val;
        !           253:        }
        !           254:        db_printf("\n%d total locks, %d empty buckets", total, empty );
        !           255:        if (default_lock_info.success)
        !           256:                db_printf(", default: %d", default_lock_info.success + default_lock_info.fail);
        !           257:        db_printf("\n");
        !           258:        print_lock_info(&mean);
        !           259: }
        !           260: 
        !           261: #define lock_info_clear lic
        !           262: 
        !           263: lock_info_clear()
        !           264: {
        !           265:        struct lock_info *li;
        !           266:        int bucket = 0;
        !           267:        int i;
        !           268:        for (bucket = 0; bucket < LOCK_INFO_HASH_COUNT; bucket++) {
        !           269:                li = &lock_info[bucket].info[0];
        !           270:                for (i= 0; i< LOCK_INFO_PER_BUCKET; i++, li++) {
        !           271:                        bzero(li, sizeof(struct lock_info));
        !           272:                }
        !           273:        }
        !           274:        bzero(&default_lock_info, sizeof(struct lock_info));
        !           275: }
        !           276: 
        !           277: print_lock_info(li)
        !           278: struct lock_info *li;
        !           279: {
        !           280:        int off;
        !           281:        int sum = li->success + li->fail;
        !           282:        db_printf("%d   %d/%d   %d/%d   %d/%d   %d/%d   ", li->success,
        !           283:                   li->fail, (li->fail*100)/sum,
        !           284:                   li->masked, (li->masked*100)/sum,
        !           285:                   li->stack, li->stack/sum,
        !           286:                   li->time, li->time/sum);
        !           287:        db_search_symbol(li->lock, 0, &off);
        !           288:        if (off < 1024)
        !           289:                db_printsym(li->lock, 0);
        !           290:        else {
        !           291:                db_printsym(li->caller, 0);
        !           292:                db_printf("(%X)", li->lock);
        !           293:        }
        !           294:        db_printf("\n");
        !           295: }
        !           296: 
        !           297: #endif /* NCPUS > 1 && MACH_LOCK_MON */
        !           298: 
        !           299: #if    TIME_STAMP
        !           300: 
        !           301: /*
        !           302:  *     Measure lock/unlock operations
        !           303:  */
        !           304: 
        !           305: time_lock(loops)
        !           306: {
        !           307:        decl_simple_lock_data(, lock)
        !           308:        register time_stamp_t stamp;
        !           309:        register int i;
        !           310: 
        !           311: 
        !           312:        if (!loops)
        !           313:                loops = 1000;
        !           314:        simple_lock_init(&lock);
        !           315:        stamp = time_stamp;
        !           316:        for (i = 0; i < loops; i++) {
        !           317:                simple_lock(&lock);
        !           318:                simple_unlock(&lock);
        !           319:        }
        !           320:        stamp = time_stamp - stamp;
        !           321:        db_printf("%d stamps for simple_locks\n", stamp/loops);
        !           322: #if    MACH_LOCK_MON
        !           323:        stamp = time_stamp;
        !           324:        for (i = 0; i < loops; i++) {
        !           325:                _simple_lock(&lock);
        !           326:                _simple_unlock(&lock);
        !           327:         }
        !           328:        stamp = time_stamp - stamp;
        !           329:        db_printf("%d stamps for _simple_locks\n", stamp/loops);
        !           330: #endif /* MACH_LOCK_MON */
        !           331: }
        !           332: #endif /* TIME_STAMP */
        !           333: 
        !           334: #if    MACH_MP_DEBUG
        !           335: 
        !           336: /*
        !           337:  *     Arrange in the lock routines to call the following
        !           338:  *     routines. This way, when locks are free there is no performance
        !           339:  *     penalty
        !           340:  */
        !           341: 
        !           342: void
        !           343: retry_simple_lock(lock)
        !           344: decl_simple_lock_data(, *lock)
        !           345: {
        !           346:        register count = 0;
        !           347: 
        !           348:        while(!simple_lock_try(lock))
        !           349:                if (count++ > 1000000 && lock != &kdb_lock) {
        !           350:                        if (lock == &printf_lock)
        !           351:                                return;
        !           352:                        db_printf("cpu %d looping on simple_lock(%x) called by %x\n",
        !           353:                                cpu_number(), lock, *(((int *)&lock) -1));
        !           354:                        Debugger();
        !           355:                        count = 0;
        !           356:                }
        !           357: }
        !           358: 
        !           359: void
        !           360: retry_bit_lock(index, addr)
        !           361: {
        !           362:        register count = 0;
        !           363: 
        !           364:        while(!bit_lock_try(index, addr))
        !           365:                if (count++ > 1000000) {
        !           366:                        db_printf("cpu %d looping on bit_lock(%x, %x) called by %x\n",
        !           367:                                cpu_number(), index, addr, *(((int *)&index) -1));
        !           368:                        Debugger();
        !           369:                        count = 0;
        !           370:                }
        !           371: }
        !           372: #endif /* MACH_MP_DEBUG */

unix.superglobalmegacorp.com

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