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

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