Annotation of OSKit-Mach/kern/lock_mon.c, revision 1.1.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.