|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: ! 27: #include "mach_kdb.h" ! 28: #if MACH_KDB ! 29: ! 30: #include <machine/db_machdep.h> ! 31: #include <ddb/db_task_thread.h> ! 32: #include <ddb/db_variables.h> ! 33: ! 34: ! 35: ! 36: /* ! 37: * Following constants are used to prevent infinite loop of task ! 38: * or thread search due to the incorrect list. ! 39: */ ! 40: #define DB_MAX_TASKID 0x10000 /* max # of tasks */ ! 41: #define DB_MAX_THREADID 0x10000 /* max # of threads in a task */ ! 42: #define DB_MAX_PSETS 0x10000 /* max # of processor sets */ ! 43: ! 44: task_t db_default_task; /* default target task */ ! 45: thread_t db_default_thread; /* default target thread */ ! 46: ! 47: /* ! 48: * search valid task queue, and return the queue position as the task id ! 49: */ ! 50: int ! 51: db_lookup_task(target_task) ! 52: task_t target_task; ! 53: { ! 54: register task_t task; ! 55: register task_id; ! 56: register processor_set_t pset; ! 57: register npset = 0; ! 58: ! 59: task_id = 0; ! 60: if (queue_first(&all_psets) == 0) ! 61: return(-1); ! 62: queue_iterate(&all_psets, pset, processor_set_t, all_psets) { ! 63: if (npset++ >= DB_MAX_PSETS) ! 64: return(-1); ! 65: if (queue_first(&pset->tasks) == 0) ! 66: continue; ! 67: queue_iterate(&pset->tasks, task, task_t, pset_tasks) { ! 68: if (target_task == task) ! 69: return(task_id); ! 70: if (task_id++ >= DB_MAX_TASKID) ! 71: return(-1); ! 72: } ! 73: } ! 74: return(-1); ! 75: } ! 76: ! 77: /* ! 78: * search thread queue of the task, and return the queue position ! 79: */ ! 80: int ! 81: db_lookup_task_thread(task, target_thread) ! 82: task_t task; ! 83: thread_t target_thread; ! 84: { ! 85: register thread_t thread; ! 86: register thread_id; ! 87: ! 88: thread_id = 0; ! 89: if (queue_first(&task->thread_list) == 0) ! 90: return(-1); ! 91: queue_iterate(&task->thread_list, thread, thread_t, thread_list) { ! 92: if (target_thread == thread) ! 93: return(thread_id); ! 94: if (thread_id++ >= DB_MAX_THREADID) ! 95: return(-1); ! 96: } ! 97: return(-1); ! 98: } ! 99: ! 100: /* ! 101: * search thread queue of every valid task, and return the queue position ! 102: * as the thread id. ! 103: */ ! 104: int ! 105: db_lookup_thread(target_thread) ! 106: thread_t target_thread; ! 107: { ! 108: register thread_id; ! 109: register task_t task; ! 110: register processor_set_t pset; ! 111: register ntask = 0; ! 112: register npset = 0; ! 113: ! 114: if (queue_first(&all_psets) == 0) ! 115: return(-1); ! 116: queue_iterate(&all_psets, pset, processor_set_t, all_psets) { ! 117: if (npset++ >= DB_MAX_PSETS) ! 118: return(-1); ! 119: if (queue_first(&pset->tasks) == 0) ! 120: continue; ! 121: queue_iterate(&pset->tasks, task, task_t, pset_tasks) { ! 122: if (ntask++ > DB_MAX_TASKID) ! 123: return(-1); ! 124: if (task->thread_count == 0) ! 125: continue; ! 126: thread_id = db_lookup_task_thread(task, target_thread); ! 127: if (thread_id >= 0) ! 128: return(thread_id); ! 129: } ! 130: } ! 131: return(-1); ! 132: } ! 133: ! 134: /* ! 135: * check the address is a valid thread address ! 136: */ ! 137: boolean_t ! 138: db_check_thread_address_valid(thread) ! 139: thread_t thread; ! 140: { ! 141: if (db_lookup_thread(thread) < 0) { ! 142: db_printf("Bad thread address 0x%x\n", thread); ! 143: db_flush_lex(); ! 144: return(FALSE); ! 145: } else ! 146: return(TRUE); ! 147: } ! 148: ! 149: /* ! 150: * convert task_id(queue postion) to task address ! 151: */ ! 152: task_t ! 153: db_lookup_task_id(task_id) ! 154: register task_id; ! 155: { ! 156: register task_t task; ! 157: register processor_set_t pset; ! 158: register npset = 0; ! 159: ! 160: if (task_id > DB_MAX_TASKID) ! 161: return(TASK_NULL); ! 162: if (queue_first(&all_psets) == 0) ! 163: return(TASK_NULL); ! 164: queue_iterate(&all_psets, pset, processor_set_t, all_psets) { ! 165: if (npset++ >= DB_MAX_PSETS) ! 166: return(TASK_NULL); ! 167: if (queue_first(&pset->tasks) == 0) ! 168: continue; ! 169: queue_iterate(&pset->tasks, task, task_t, pset_tasks) { ! 170: if (task_id-- <= 0) ! 171: return(task); ! 172: } ! 173: } ! 174: return(TASK_NULL); ! 175: } ! 176: ! 177: /* ! 178: * convert (task_id, thread_id) pair to thread address ! 179: */ ! 180: static thread_t ! 181: db_lookup_thread_id(task, thread_id) ! 182: task_t task; ! 183: register thread_id; ! 184: { ! 185: register thread_t thread; ! 186: ! 187: ! 188: if (thread_id > DB_MAX_THREADID) ! 189: return(THREAD_NULL); ! 190: if (queue_first(&task->thread_list) == 0) ! 191: return(THREAD_NULL); ! 192: queue_iterate(&task->thread_list, thread, thread_t, thread_list) { ! 193: if (thread_id-- <= 0) ! 194: return(thread); ! 195: } ! 196: return(THREAD_NULL); ! 197: } ! 198: ! 199: /* ! 200: * get next parameter from a command line, and check it as a valid ! 201: * thread address ! 202: */ ! 203: boolean_t ! 204: db_get_next_thread(threadp, position) ! 205: thread_t *threadp; ! 206: int position; ! 207: { ! 208: db_expr_t value; ! 209: thread_t thread; ! 210: ! 211: *threadp = THREAD_NULL; ! 212: if (db_expression(&value)) { ! 213: thread = (thread_t) value; ! 214: if (!db_check_thread_address_valid(thread)) { ! 215: db_flush_lex(); ! 216: return(FALSE); ! 217: } ! 218: } else if (position <= 0) { ! 219: thread = db_default_thread; ! 220: } else ! 221: return(FALSE); ! 222: *threadp = thread; ! 223: return(TRUE); ! 224: } ! 225: ! 226: /* ! 227: * check the default thread is still valid ! 228: * ( it is called in entering DDB session ) ! 229: */ ! 230: void ! 231: db_init_default_thread() ! 232: { ! 233: if (db_lookup_thread(db_default_thread) < 0) { ! 234: db_default_thread = THREAD_NULL; ! 235: db_default_task = TASK_NULL; ! 236: } else ! 237: db_default_task = db_default_thread->task; ! 238: } ! 239: ! 240: /* ! 241: * set or get default thread which is used when /t or :t option is specified ! 242: * in the command line ! 243: */ ! 244: /* ARGSUSED */ ! 245: int ! 246: db_set_default_thread(vp, valuep, flag) ! 247: struct db_variable *vp; ! 248: db_expr_t *valuep; ! 249: int flag; ! 250: { ! 251: thread_t thread; ! 252: ! 253: if (flag != DB_VAR_SET) { ! 254: *valuep = (db_expr_t) db_default_thread; ! 255: return(0); ! 256: } ! 257: thread = (thread_t) *valuep; ! 258: if (thread != THREAD_NULL && !db_check_thread_address_valid(thread)) ! 259: db_error(0); ! 260: /* NOTREACHED */ ! 261: db_default_thread = thread; ! 262: if (thread) ! 263: db_default_task = thread->task; ! 264: return(0); ! 265: } ! 266: ! 267: /* ! 268: * convert $taskXXX[.YYY] type DDB variable to task or thread address ! 269: */ ! 270: int ! 271: db_get_task_thread(vp, valuep, flag, ap) ! 272: struct db_variable *vp; ! 273: db_expr_t *valuep; ! 274: int flag; ! 275: db_var_aux_param_t ap; ! 276: { ! 277: task_t task; ! 278: thread_t thread; ! 279: ! 280: if (flag != DB_VAR_GET) { ! 281: db_error("Cannot set to $task variable\n"); ! 282: /* NOTREACHED */ ! 283: } ! 284: if ((task = db_lookup_task_id(ap->suffix[0])) == TASK_NULL) { ! 285: db_printf("no such task($task%d)\n", ap->suffix[0]); ! 286: db_error(0); ! 287: /* NOTREACHED */ ! 288: } ! 289: if (ap->level <= 1) { ! 290: *valuep = (db_expr_t) task; ! 291: return(0); ! 292: } ! 293: if ((thread = db_lookup_thread_id(task, ap->suffix[1])) == THREAD_NULL){ ! 294: db_printf("no such thread($task%d.%d)\n", ! 295: ap->suffix[0], ap->suffix[1]); ! 296: db_error(0); ! 297: /* NOTREACHED */ ! 298: } ! 299: *valuep = (db_expr_t) thread; ! 300: return(0); ! 301: } ! 302: ! 303: #endif MACH_KDB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.