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