|
|
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 <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; 1.1.1.2 ! root 61: #else /* TIME_STAMP */ 1.1 root 62: typedef unsigned int time_stamp_t; 63: #define time_stamp 0 1.1.1.2 ! root 64: #endif /* TIME_STAMP */ 1.1 root 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; 1.1.1.2 ! root 77: unsigned int stack; 1.1 root 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: } 1.1.1.2 ! root 116: 1.1 root 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: 1.1.1.2 ! root 124: if (current_thread()) 1.1 root 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 = ¤t_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 ); 1.1.1.2 ! root 255: if (default_lock_info.success) ! 256: db_printf(", default: %d", default_lock_info.success + default_lock_info.fail); 1.1 root 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: } 1.1.1.2 ! root 274: bzero(&default_lock_info, sizeof(struct lock_info)); 1.1 root 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: 1.1.1.2 ! root 297: #endif /* NCPUS > 1 && MACH_LOCK_MON */ 1.1 root 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); 1.1.1.2 ! root 330: #endif /* MACH_LOCK_MON */ 1.1 root 331: } 1.1.1.2 ! root 332: #endif /* TIME_STAMP */ 1.1 root 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: } 1.1.1.2 ! root 372: #endif /* MACH_MP_DEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.