Annotation of Gnu-Mach/kern/lock_mon.c, revision 1.1.1.3

1.1.1.2   root        1: /*
1.1       root        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
1.1.1.2   root       13:  *
1.1       root       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.
1.1.1.2   root       22:  *
1.1       root       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 <sys/types.h>
1.1.1.3 ! root       42: #include <string.h>
        !            43: 
1.1       root       44: #include <mach/machine/vm_types.h>
                     45: #include <mach/boolean.h>
                     46: #include <kern/thread.h>
                     47: #include <kern/lock.h>
                     48: #include <kern/time_stamp.h>
                     49: 
                     50: 
                     51: decl_simple_lock_data(extern , kdb_lock)
                     52: decl_simple_lock_data(extern , printf_lock)
                     53: 
                     54: #if    NCPUS > 1 && MACH_LOCK_MON
                     55: 
                     56: #if    TIME_STAMP
                     57: extern time_stamp_t time_stamp;
1.1.1.2   root       58: #else  /* TIME_STAMP */
1.1       root       59: typedef unsigned int time_stamp_t;
                     60: #define        time_stamp 0
1.1.1.2   root       61: #endif /* TIME_STAMP */
1.1       root       62: 
                     63: #define LOCK_INFO_MAX       (1024*32)
                     64: #define LOCK_INFO_HASH_COUNT 1024
                     65: #define LOCK_INFO_PER_BUCKET   (LOCK_INFO_MAX/LOCK_INFO_HASH_COUNT)
                     66: 
                     67: 
                     68: #define HASH_LOCK(lock)        ((long)lock>>5 & (LOCK_INFO_HASH_COUNT-1))
                     69: 
                     70: struct lock_info {
                     71:        unsigned int    success;
                     72:        unsigned int    fail;
                     73:        unsigned int    masked;
1.1.1.2   root       74:        unsigned int    stack;
1.1       root       75:        time_stamp_t    time;
                     76:        decl_simple_lock_data(, *lock)
                     77:        vm_offset_t     caller;
                     78: };
                     79: 
                     80: struct lock_info_bucket {
                     81:        struct lock_info info[LOCK_INFO_PER_BUCKET];
                     82: };
                     83: 
                     84: struct lock_info_bucket lock_info[LOCK_INFO_HASH_COUNT];
                     85: struct lock_info default_lock_info;
                     86: unsigned default_lock_stack = 0;
                     87: 
                     88: extern int curr_ipl[];
                     89: 
                     90: 
                     91: 
                     92: struct lock_info *
                     93: locate_lock_info(lock)
                     94: decl_simple_lock_data(, **lock)
                     95: {
                     96:        struct lock_info *li =  &(lock_info[HASH_LOCK(*lock)].info[0]);
                     97:        register i;
                     98:        register my_cpu = cpu_number();
                     99: 
                    100:        for (i=0; i < LOCK_INFO_PER_BUCKET; i++, li++)
                    101:                if (li->lock) {
                    102:                        if (li->lock == *lock)
                    103:                                return(li);
                    104:                } else {
                    105:                        li->lock = *lock;
                    106:                        li->caller = *((vm_offset_t *)lock - 1);
                    107:                        return(li);
                    108:                }
                    109:        db_printf("out of lock_info slots\n");
                    110:        li = &default_lock_info;
                    111:        return(li);
                    112: }
1.1.1.2   root      113: 
1.1       root      114: 
                    115: simple_lock(lock)
                    116: decl_simple_lock_data(, *lock)
                    117: {
                    118:        register struct lock_info *li = locate_lock_info(&lock);
                    119:        register my_cpu = cpu_number();
                    120: 
1.1.1.2   root      121:        if (current_thread())
1.1       root      122:                li->stack = current_thread()->lock_stack++;
                    123:        if (curr_ipl[my_cpu])
                    124:                li->masked++;
                    125:        if (_simple_lock_try(lock))
                    126:                li->success++;
                    127:        else {
                    128:                _simple_lock(lock);
                    129:                li->fail++;
                    130:        }
                    131:        li->time = time_stamp - li->time;
                    132: }
                    133: 
                    134: simple_lock_try(lock)
                    135: decl_simple_lock_data(, *lock)
                    136: {
                    137:        register struct lock_info *li = locate_lock_info(&lock);
                    138:        register my_cpu = cpu_number();
                    139: 
                    140:        if (curr_ipl[my_cpu])
                    141:                li->masked++;
                    142:        if (_simple_lock_try(lock)) {
                    143:                li->success++;
                    144:                li->time = time_stamp - li->time;
                    145:                if (current_thread())
                    146:                        li->stack = current_thread()->lock_stack++;
                    147:                return(1);
                    148:        } else {
                    149:                li->fail++;
                    150:                return(0);
                    151:        }
                    152: }
                    153: 
                    154: simple_unlock(lock)
                    155: decl_simple_lock_data(, *lock)
                    156: {
                    157:        register time_stamp_t stamp = time_stamp;
                    158:        register time_stamp_t *time = &locate_lock_info(&lock)->time;
                    159:        register unsigned *lock_stack;
                    160: 
                    161:        *time = stamp - *time;
                    162:        _simple_unlock(lock);
                    163:        if (current_thread()) {
                    164:                lock_stack = &current_thread()->lock_stack;
                    165:                if (*lock_stack)
                    166:                        (*lock_stack)--;
                    167:        }
                    168: }
                    169: 
                    170: lip() {
                    171:        lis(4, 1, 0);
                    172: }
                    173: 
                    174: #define lock_info_sort lis
                    175: 
                    176: unsigned scurval, ssum;
                    177: struct lock_info *sli;
                    178: 
                    179: lock_info_sort(arg, abs, count)
                    180: {
                    181:        struct lock_info *li, mean;
                    182:        int bucket = 0;
                    183:        int i;
                    184:        unsigned max_val;
                    185:        unsigned old_val = (unsigned)-1;
                    186:        struct lock_info *target_li = &lock_info[0].info[0];
                    187:        unsigned sum;
                    188:        unsigned empty, total;
                    189:        unsigned curval;
                    190: 
                    191:        printf("\nSUCCESS       FAIL    MASKED  STACK   TIME    LOCK/CALLER\n");
                    192:        if (!count)
                    193:                count = 8 ;
                    194:        while (count && target_li) {
                    195:                empty = LOCK_INFO_HASH_COUNT;
                    196:                target_li = 0;
                    197:                total = 0;
                    198:                max_val = 0;
                    199:                mean.success = 0;
                    200:                mean.fail = 0;
                    201:                mean.masked = 0;
                    202:                mean.stack = 0;
                    203:                mean.time = 0;
                    204:                mean.lock = (simple_lock_data_t *) &lock_info;
                    205:                mean.caller = (vm_offset_t) &lock_info;
                    206:                for (bucket = 0; bucket < LOCK_INFO_HASH_COUNT; bucket++) {
                    207:                        li = &lock_info[bucket].info[0];
                    208:                        if (li->lock)
                    209:                                empty--;
                    210:                        for (i= 0; i< LOCK_INFO_PER_BUCKET && li->lock; i++, li++) {
                    211:                                if (li->lock == &kdb_lock || li->lock == &printf_lock)
                    212:                                        continue;
                    213:                                total++;
                    214:                                curval = *((int *)li + arg);
                    215:                                sum = li->success + li->fail;
                    216:                                if(!sum && !abs)
                    217:                                        continue;
                    218:                                scurval = curval;
                    219:                                ssum = sum;
                    220:                                sli = li;
                    221:                                if (!abs) switch(arg) {
                    222:                                case 0:
                    223:                                        break;
                    224:                                case 1:
                    225:                                case 2:
                    226:                                        curval = (curval*100) / sum;
                    227:                                        break;
                    228:                                case 3:
                    229:                                case 4:
                    230:                                        curval = curval / sum;
                    231:                                        break;
                    232:                                }
                    233:                                if (curval > max_val && curval < old_val) {
                    234:                                        max_val = curval;
                    235:                                        target_li = li;
                    236:                                }
                    237:                                if (curval == old_val && count != 0) {
                    238:                                        print_lock_info(li);
                    239:                                        count--;
                    240:                                }
                    241:                                mean.success += li->success;
                    242:                                mean.fail += li->fail;
                    243:                                mean.masked += li->masked;
                    244:                                mean.stack += li->stack;
                    245:                                mean.time += li->time;
                    246:                        }
                    247:                }
                    248:                if (target_li)
                    249:                        old_val = max_val;
                    250:        }
                    251:        db_printf("\n%d total locks, %d empty buckets", total, empty );
1.1.1.2   root      252:        if (default_lock_info.success)
                    253:                db_printf(", default: %d", default_lock_info.success + default_lock_info.fail);
1.1       root      254:        db_printf("\n");
                    255:        print_lock_info(&mean);
                    256: }
                    257: 
                    258: #define lock_info_clear lic
                    259: 
                    260: lock_info_clear()
                    261: {
                    262:        struct lock_info *li;
                    263:        int bucket = 0;
                    264:        int i;
                    265:        for (bucket = 0; bucket < LOCK_INFO_HASH_COUNT; bucket++) {
                    266:                li = &lock_info[bucket].info[0];
                    267:                for (i= 0; i< LOCK_INFO_PER_BUCKET; i++, li++) {
1.1.1.3 ! root      268:                        memset(li, 0, sizeof(struct lock_info));
1.1       root      269:                }
                    270:        }
1.1.1.3 ! root      271:        memset(&default_lock_info, 0, sizeof(struct lock_info));
1.1       root      272: }
                    273: 
                    274: print_lock_info(li)
                    275: struct lock_info *li;
                    276: {
                    277:        int off;
                    278:        int sum = li->success + li->fail;
                    279:        db_printf("%d   %d/%d   %d/%d   %d/%d   %d/%d   ", li->success,
                    280:                   li->fail, (li->fail*100)/sum,
                    281:                   li->masked, (li->masked*100)/sum,
                    282:                   li->stack, li->stack/sum,
                    283:                   li->time, li->time/sum);
1.1.1.3 ! root      284:        db_free_symbol(db_search_symbol(li->lock, 0, &off));
1.1       root      285:        if (off < 1024)
                    286:                db_printsym(li->lock, 0);
                    287:        else {
                    288:                db_printsym(li->caller, 0);
                    289:                db_printf("(%X)", li->lock);
                    290:        }
                    291:        db_printf("\n");
                    292: }
                    293: 
1.1.1.2   root      294: #endif /* NCPUS > 1 && MACH_LOCK_MON */
1.1       root      295: 
                    296: #if    TIME_STAMP
                    297: 
                    298: /*
                    299:  *     Measure lock/unlock operations
                    300:  */
                    301: 
                    302: time_lock(loops)
                    303: {
                    304:        decl_simple_lock_data(, lock)
                    305:        register time_stamp_t stamp;
                    306:        register int i;
                    307: 
                    308: 
                    309:        if (!loops)
                    310:                loops = 1000;
                    311:        simple_lock_init(&lock);
                    312:        stamp = time_stamp;
                    313:        for (i = 0; i < loops; i++) {
                    314:                simple_lock(&lock);
                    315:                simple_unlock(&lock);
                    316:        }
                    317:        stamp = time_stamp - stamp;
                    318:        db_printf("%d stamps for simple_locks\n", stamp/loops);
                    319: #if    MACH_LOCK_MON
                    320:        stamp = time_stamp;
                    321:        for (i = 0; i < loops; i++) {
                    322:                _simple_lock(&lock);
                    323:                _simple_unlock(&lock);
                    324:         }
                    325:        stamp = time_stamp - stamp;
                    326:        db_printf("%d stamps for _simple_locks\n", stamp/loops);
1.1.1.2   root      327: #endif /* MACH_LOCK_MON */
1.1       root      328: }
1.1.1.2   root      329: #endif /* TIME_STAMP */
1.1       root      330: 
                    331: #if    MACH_MP_DEBUG
                    332: 
                    333: /*
                    334:  *     Arrange in the lock routines to call the following
                    335:  *     routines. This way, when locks are free there is no performance
                    336:  *     penalty
                    337:  */
                    338: 
                    339: void
                    340: retry_simple_lock(lock)
                    341: decl_simple_lock_data(, *lock)
                    342: {
                    343:        register count = 0;
                    344: 
                    345:        while(!simple_lock_try(lock))
                    346:                if (count++ > 1000000 && lock != &kdb_lock) {
                    347:                        if (lock == &printf_lock)
                    348:                                return;
                    349:                        db_printf("cpu %d looping on simple_lock(%x) called by %x\n",
                    350:                                cpu_number(), lock, *(((int *)&lock) -1));
1.1.1.3 ! root      351:                        SoftDebugger("simple_lock timeout");
1.1       root      352:                        count = 0;
                    353:                }
                    354: }
                    355: 
                    356: void
                    357: retry_bit_lock(index, addr)
                    358: {
                    359:        register count = 0;
                    360: 
                    361:        while(!bit_lock_try(index, addr))
                    362:                if (count++ > 1000000) {
                    363:                        db_printf("cpu %d looping on bit_lock(%x, %x) called by %x\n",
                    364:                                cpu_number(), index, addr, *(((int *)&index) -1));
1.1.1.3 ! root      365:                        SoftDebugger("bit_lock timeout");
1.1       root      366:                        count = 0;
                    367:                }
                    368: }
1.1.1.2   root      369: #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.