Changeset 827d73f in mainline for kernel/generic/src
- Timestamp:
- 2010-02-12T14:09:22Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a70bda4
- Parents:
- 918e9910 (diff), e70edd1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- kernel/generic/src
- Files:
-
- 1 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/console/kconsole.c
r918e9910 r827d73f 543 543 if (str_lcmp(hlp->name, cmdline + start, 544 544 max(str_length(hlp->name), 545 str_nlength(cmdline + start, (size_t) (end - start) - 1))) == 0) {545 str_nlength(cmdline + start, (size_t) (end - start)))) == 0) { 546 546 cmd = hlp; 547 547 break; -
kernel/generic/src/ddi/irq.c
r918e9910 r827d73f 74 74 #include <synch/spinlock.h> 75 75 #include <console/console.h> 76 #include <interrupt.h> 76 77 #include <memstr.h> 77 78 #include <arch.h> … … 169 170 irq->inr = -1; 170 171 irq->devno = -1; 172 173 irq_initialize_arch(irq); 171 174 } 172 175 -
kernel/generic/src/debug/symtab.c
r918e9910 r827d73f 46 46 /** Get name of a symbol that seems most likely to correspond to address. 47 47 * 48 * @param addr Address. 49 * @param name Place to store pointer to the symbol name. 48 * @param addr Address. 49 * @param name Place to store pointer to the symbol name. 50 * @param offset Place to store offset from the symbol address. 50 51 * 51 52 * @return Zero on success or negative error code, ENOENT if not found, … … 53 54 * 54 55 */ 55 int symtab_name_lookup(u native_t addr, char **name)56 int symtab_name_lookup(uintptr_t addr, char **name, uintptr_t *offset) 56 57 { 57 58 #ifdef CONFIG_SYMTAB … … 65 66 if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le)) { 66 67 *name = symbol_table[i - 1].symbol_name; 68 if (offset) 69 *offset = addr - 70 uint64_t_le2host(symbol_table[i - 1].address_le); 67 71 return EOK; 68 72 } … … 88 92 * 89 93 */ 90 char *symtab_fmt_name_lookup(u native_t addr)94 char *symtab_fmt_name_lookup(uintptr_t addr) 91 95 { 92 96 char *name; 93 int rc = symtab_name_lookup(addr, &name );97 int rc = symtab_name_lookup(addr, &name, NULL); 94 98 95 99 switch (rc) { -
kernel/generic/src/interrupt/interrupt.c
r918e9910 r827d73f 44 44 #include <console/console.h> 45 45 #include <console/cmd.h> 46 #include <ipc/event.h> 47 #include <synch/mutex.h> 48 #include <time/delay.h> 49 #include <macros.h> 46 50 #include <panic.h> 47 51 #include <print.h> … … 107 111 fault_if_from_uspace(istate, "Unhandled exception %d.", n); 108 112 panic("Unhandled exception %d.", n); 113 } 114 115 /** Terminate thread and task if exception came from userspace. */ 116 void fault_if_from_uspace(istate_t *istate, char *fmt, ...) 117 { 118 task_t *task = TASK; 119 va_list args; 120 121 if (!istate_from_uspace(istate)) 122 return; 123 124 printf("Task %s (%" PRIu64 ") killed due to an exception at " 125 "program counter %p.\n", task->name, task->taskid, 126 istate_get_pc(istate)); 127 128 stack_trace_istate(istate); 129 130 printf("Kill message: "); 131 va_start(args, fmt); 132 vprintf(fmt, args); 133 va_end(args); 134 printf("\n"); 135 136 /* 137 * Userspace can subscribe for FAULT events to take action 138 * whenever a thread faults. (E.g. take a dump, run a debugger). 139 * The notification is always available, but unless Udebug is enabled, 140 * that's all you get. 141 */ 142 if (event_is_subscribed(EVENT_FAULT)) { 143 /* Notify the subscriber that a fault occurred. */ 144 event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid), 145 UPPER32(TASK->taskid), (unative_t) THREAD); 146 147 #ifdef CONFIG_UDEBUG 148 /* Wait for a debugging session. */ 149 udebug_thread_fault(); 150 #endif 151 } 152 153 task_kill(task->taskid); 154 thread_exit(); 109 155 } 110 156 -
kernel/generic/src/ipc/ipc.c
r918e9910 r827d73f 212 212 * 213 213 * @param call Call structure to be answered. 214 */ 215 static void _ipc_answer_free_call(call_t *call) 214 * @param selflocked If true, then TASK->answebox is locked. 215 */ 216 static void _ipc_answer_free_call(call_t *call, bool selflocked) 216 217 { 217 218 answerbox_t *callerbox = call->callerbox; 219 bool do_lock = ((!selflocked) || callerbox != (&TASK->answerbox)); 218 220 219 221 call->flags |= IPC_CALL_ANSWERED; … … 226 228 } 227 229 228 spinlock_lock(&callerbox->lock); 230 if (do_lock) 231 spinlock_lock(&callerbox->lock); 229 232 list_append(&call->link, &callerbox->answers); 230 spinlock_unlock(&callerbox->lock); 233 if (do_lock) 234 spinlock_unlock(&callerbox->lock); 231 235 waitq_wakeup(&callerbox->wq, WAKEUP_FIRST); 232 236 } … … 244 248 spinlock_unlock(&box->lock); 245 249 /* Send back answer */ 246 _ipc_answer_free_call(call );250 _ipc_answer_free_call(call, false); 247 251 } 248 252 … … 261 265 atomic_inc(&phone->active_calls); 262 266 IPC_SET_RETVAL(call->data, err); 263 _ipc_answer_free_call(call );267 _ipc_answer_free_call(call, false); 264 268 } 265 269 … … 300 304 if (call->flags & IPC_CALL_FORWARDED) { 301 305 IPC_SET_RETVAL(call->data, EFORWARD); 302 _ipc_answer_free_call(call );306 _ipc_answer_free_call(call, false); 303 307 } else { 304 308 if (phone->state == IPC_PHONE_HUNGUP) … … 455 459 456 460 IPC_SET_RETVAL(call->data, EHANGUP); 457 _ipc_answer_free_call(call );461 _ipc_answer_free_call(call, true); 458 462 } 459 463 } -
kernel/generic/src/mm/as.c
r918e9910 r827d73f 1920 1920 } 1921 1921 1922 /** Get list of adress space areas. 1923 * 1924 * @param as Address space. 1925 * @param obuf Place to save pointer to returned buffer. 1926 * @param osize Place to save size of returned buffer. 1927 */ 1928 void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize) 1929 { 1930 ipl_t ipl; 1931 size_t area_cnt, area_idx, i; 1932 link_t *cur; 1933 1934 as_area_info_t *info; 1935 size_t isize; 1936 1937 ipl = interrupts_disable(); 1938 mutex_lock(&as->lock); 1939 1940 /* First pass, count number of areas. */ 1941 1942 area_cnt = 0; 1943 1944 for (cur = as->as_area_btree.leaf_head.next; 1945 cur != &as->as_area_btree.leaf_head; cur = cur->next) { 1946 btree_node_t *node; 1947 1948 node = list_get_instance(cur, btree_node_t, leaf_link); 1949 area_cnt += node->keys; 1950 } 1951 1952 isize = area_cnt * sizeof(as_area_info_t); 1953 info = malloc(isize, 0); 1954 1955 /* Second pass, record data. */ 1956 1957 area_idx = 0; 1958 1959 for (cur = as->as_area_btree.leaf_head.next; 1960 cur != &as->as_area_btree.leaf_head; cur = cur->next) { 1961 btree_node_t *node; 1962 1963 node = list_get_instance(cur, btree_node_t, leaf_link); 1964 1965 for (i = 0; i < node->keys; i++) { 1966 as_area_t *area = node->value[i]; 1967 1968 ASSERT(area_idx < area_cnt); 1969 mutex_lock(&area->lock); 1970 1971 info[area_idx].start_addr = area->base; 1972 info[area_idx].size = FRAMES2SIZE(area->pages); 1973 info[area_idx].flags = area->flags; 1974 ++area_idx; 1975 1976 mutex_unlock(&area->lock); 1977 } 1978 } 1979 1980 mutex_unlock(&as->lock); 1981 interrupts_restore(ipl); 1982 1983 *obuf = info; 1984 *osize = isize; 1985 } 1986 1987 1922 1988 /** Print out information about address space. 1923 1989 * -
kernel/generic/src/udebug/udebug.c
r918e9910 r827d73f 69 69 mutex_initialize(&ut->lock, MUTEX_PASSIVE); 70 70 waitq_initialize(&ut->go_wq); 71 condvar_initialize(&ut->active_cv); 71 72 72 73 ut->go_call = NULL; … … 446 447 waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST); 447 448 } 449 mutex_unlock(&t->udebug.lock); 450 condvar_broadcast(&t->udebug.active_cv); 451 } else { 452 mutex_unlock(&t->udebug.lock); 448 453 } 449 mutex_unlock(&t->udebug.lock);450 454 } 451 455 … … 456 460 } 457 461 462 /** Wait for debugger to handle a fault in this thread. 463 * 464 * When a thread faults and someone is subscribed to the FAULT kernel event, 465 * this function is called to wait for a debugging session to give userspace 466 * a chance to examine the faulting thead/task. When the debugging session 467 * is over, this function returns (so that thread/task cleanup can continue). 468 */ 469 void udebug_thread_fault(void) 470 { 471 udebug_stoppable_begin(); 472 473 /* Wait until a debugger attends to us. */ 474 mutex_lock(&THREAD->udebug.lock); 475 while (!THREAD->udebug.active) 476 condvar_wait(&THREAD->udebug.active_cv, &THREAD->udebug.lock); 477 mutex_unlock(&THREAD->udebug.lock); 478 479 /* Make sure the debugging session is over before proceeding. */ 480 mutex_lock(&THREAD->udebug.lock); 481 while (THREAD->udebug.active) 482 condvar_wait(&THREAD->udebug.active_cv, &THREAD->udebug.lock); 483 mutex_unlock(&THREAD->udebug.lock); 484 485 udebug_stoppable_end(); 486 } 458 487 459 488 /** @} -
kernel/generic/src/udebug/udebug_ipc.c
r918e9910 r827d73f 41 41 #include <proc/task.h> 42 42 #include <proc/thread.h> 43 #include <mm/as.h> 43 44 #include <arch.h> 44 45 #include <errno.h> … … 165 166 static void udebug_receive_thread_read(call_t *call) 166 167 { 168 uintptr_t uspace_addr; 169 size_t buf_size; 170 void *buffer; 171 size_t copied, needed; 172 int rc; 173 174 uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */ 175 buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */ 176 177 /* 178 * Read thread list. Variable n will be filled with actual number 179 * of threads times thread-id size. 180 */ 181 rc = udebug_thread_read(&buffer, buf_size, &copied, &needed); 182 if (rc < 0) { 183 IPC_SET_RETVAL(call->data, rc); 184 ipc_answer(&TASK->kb.box, call); 185 return; 186 } 187 188 /* 189 * Make use of call->buffer to transfer data to caller's userspace 190 */ 191 192 IPC_SET_RETVAL(call->data, 0); 193 /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that 194 same code in process_answer() can be used 195 (no way to distinguish method in answer) */ 196 IPC_SET_ARG1(call->data, uspace_addr); 197 IPC_SET_ARG2(call->data, copied); 198 IPC_SET_ARG3(call->data, needed); 199 call->buffer = buffer; 200 201 ipc_answer(&TASK->kb.box, call); 202 } 203 204 /** Process a NAME_READ call. 205 * 206 * Returns a string containing the name of the task. 207 * 208 * @param call The call structure. 209 */ 210 static void udebug_receive_name_read(call_t *call) 211 { 167 212 unative_t uspace_addr; 168 213 unative_t to_copy; 169 unsigned total_bytes; 170 unsigned buf_size; 171 void *buffer; 172 size_t n; 173 int rc; 214 size_t data_size; 215 size_t buf_size; 216 void *data; 174 217 175 218 uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */ … … 177 220 178 221 /* 179 * Read thread list. Variable n will be filled with actual number 180 * of threads times thread-id size. 181 */ 182 rc = udebug_thread_read(&buffer, buf_size, &n); 183 if (rc < 0) { 184 IPC_SET_RETVAL(call->data, rc); 185 ipc_answer(&TASK->kb.box, call); 186 return; 187 } 188 189 total_bytes = n; 190 191 /* Copy MAX(buf_size, total_bytes) bytes */ 192 193 if (buf_size > total_bytes) 194 to_copy = total_bytes; 222 * Read task name. 223 */ 224 udebug_name_read((char **) &data, &data_size); 225 226 /* Copy MAX(buf_size, data_size) bytes */ 227 228 if (buf_size > data_size) 229 to_copy = data_size; 195 230 else 196 231 to_copy = buf_size; … … 207 242 IPC_SET_ARG2(call->data, to_copy); 208 243 209 IPC_SET_ARG3(call->data, total_bytes); 210 call->buffer = buffer; 211 212 ipc_answer(&TASK->kb.box, call); 213 } 244 IPC_SET_ARG3(call->data, data_size); 245 call->buffer = data; 246 247 ipc_answer(&TASK->kb.box, call); 248 } 249 250 /** Process an AREAS_READ call. 251 * 252 * Returns a list of address space areas in the current task, as an array 253 * of as_area_info_t structures. 254 * 255 * @param call The call structure. 256 */ 257 static void udebug_receive_areas_read(call_t *call) 258 { 259 unative_t uspace_addr; 260 unative_t to_copy; 261 size_t data_size; 262 size_t buf_size; 263 void *data; 264 265 uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */ 266 buf_size = IPC_GET_ARG3(call->data); /* Dest. buffer size */ 267 268 /* 269 * Read area list. 270 */ 271 as_get_area_info(AS, (as_area_info_t **) &data, &data_size); 272 273 /* Copy MAX(buf_size, data_size) bytes */ 274 275 if (buf_size > data_size) 276 to_copy = data_size; 277 else 278 to_copy = buf_size; 279 280 /* 281 * Make use of call->buffer to transfer data to caller's userspace 282 */ 283 284 IPC_SET_RETVAL(call->data, 0); 285 /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that 286 same code in process_answer() can be used 287 (no way to distinguish method in answer) */ 288 IPC_SET_ARG1(call->data, uspace_addr); 289 IPC_SET_ARG2(call->data, to_copy); 290 291 IPC_SET_ARG3(call->data, data_size); 292 call->buffer = data; 293 294 ipc_answer(&TASK->kb.box, call); 295 } 296 214 297 215 298 /** Process an ARGS_READ call. … … 250 333 ipc_answer(&TASK->kb.box, call); 251 334 } 335 336 /** Receive a REGS_READ call. 337 * 338 * Reads the thread's register state (istate structure). 339 */ 340 static void udebug_receive_regs_read(call_t *call) 341 { 342 thread_t *t; 343 unative_t uspace_addr; 344 unative_t to_copy; 345 void *buffer; 346 int rc; 347 348 t = (thread_t *) IPC_GET_ARG2(call->data); 349 350 rc = udebug_regs_read(t, &buffer); 351 if (rc < 0) { 352 IPC_SET_RETVAL(call->data, rc); 353 ipc_answer(&TASK->kb.box, call); 354 return; 355 } 356 357 /* 358 * Make use of call->buffer to transfer data to caller's userspace 359 */ 360 361 uspace_addr = IPC_GET_ARG3(call->data); 362 to_copy = sizeof(istate_t); 363 364 IPC_SET_RETVAL(call->data, 0); 365 /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that 366 same code in process_answer() can be used 367 (no way to distinguish method in answer) */ 368 IPC_SET_ARG1(call->data, uspace_addr); 369 IPC_SET_ARG2(call->data, to_copy); 370 371 call->buffer = buffer; 372 373 ipc_answer(&TASK->kb.box, call); 374 } 375 252 376 253 377 /** Process an MEM_READ call. … … 331 455 udebug_receive_thread_read(call); 332 456 break; 457 case UDEBUG_M_NAME_READ: 458 udebug_receive_name_read(call); 459 break; 460 case UDEBUG_M_AREAS_READ: 461 udebug_receive_areas_read(call); 462 break; 333 463 case UDEBUG_M_ARGS_READ: 334 464 udebug_receive_args_read(call); 335 465 break; 466 case UDEBUG_M_REGS_READ: 467 udebug_receive_regs_read(call); 468 break; 336 469 case UDEBUG_M_MEM_READ: 337 470 udebug_receive_mem_read(call); -
kernel/generic/src/udebug/udebug_ops.c
r918e9910 r827d73f 46 46 #include <errno.h> 47 47 #include <print.h> 48 #include <string.h> 48 49 #include <syscall/copy.h> 49 50 #include <ipc/ipc.h> … … 209 210 210 211 mutex_lock(&t->udebug.lock); 211 if ((t->flags & THREAD_FLAG_USPACE) != 0) 212 if ((t->flags & THREAD_FLAG_USPACE) != 0) { 212 213 t->udebug.active = true; 213 mutex_unlock(&t->udebug.lock); 214 mutex_unlock(&t->udebug.lock); 215 condvar_broadcast(&t->udebug.active_cv); 216 } else { 217 mutex_unlock(&t->udebug.lock); 218 } 214 219 } 215 220 … … 355 360 * 356 361 * If the sequence is longer than @a buf_size bytes, only as much hashes 357 * as can fit are copied. The number of thread hashes copied is stored 358 * in @a n. 362 * as can fit are copied. The number of bytes copied is stored in @a stored. 363 * The total number of thread bytes that could have been saved had there been 364 * enough space is stored in @a needed. 359 365 * 360 366 * The rationale for having @a buf_size is that this function is only … … 364 370 * @param buffer The buffer for storing thread hashes. 365 371 * @param buf_size Buffer size in bytes. 366 * @param n The actual number of hashes copied will be stored here. 367 */ 368 int udebug_thread_read(void **buffer, size_t buf_size, size_t *n) 372 * @param stored The actual number of bytes copied will be stored here. 373 * @param needed Total number of hashes that could have been saved. 374 */ 375 int udebug_thread_read(void **buffer, size_t buf_size, size_t *stored, 376 size_t *needed) 369 377 { 370 378 thread_t *t; 371 379 link_t *cur; 372 380 unative_t tid; 373 unsigned copied_ids; 381 size_t copied_ids; 382 size_t extra_ids; 374 383 ipl_t ipl; 375 384 unative_t *id_buffer; … … 380 389 381 390 /* Allocate a buffer to hold thread IDs */ 382 id_buffer = malloc(buf_size , 0);391 id_buffer = malloc(buf_size + 1, 0); 383 392 384 393 mutex_lock(&TASK->udebug.lock); … … 396 405 max_ids = buf_size / sizeof(unative_t); 397 406 copied_ids = 0; 407 extra_ids = 0; 398 408 399 409 /* FIXME: make sure the thread isn't past debug shutdown... */ 400 410 for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) { 401 /* Do not write past end of buffer */402 if (copied_ids >= max_ids) break;403 404 411 t = list_get_instance(cur, thread_t, th_link); 405 412 … … 409 416 410 417 /* Not interested in kernel threads. */ 411 if ((flags & THREAD_FLAG_USPACE) != 0) { 418 if ((flags & THREAD_FLAG_USPACE) == 0) 419 continue; 420 421 if (copied_ids < max_ids) { 412 422 /* Using thread struct pointer as identification hash */ 413 423 tid = (unative_t) t; 414 424 id_buffer[copied_ids++] = tid; 425 } else { 426 extra_ids++; 415 427 } 416 428 } … … 422 434 423 435 *buffer = id_buffer; 424 *n = copied_ids * sizeof(unative_t); 436 *stored = copied_ids * sizeof(unative_t); 437 *needed = (copied_ids + extra_ids) * sizeof(unative_t); 438 439 return 0; 440 } 441 442 /** Read task name. 443 * 444 * Returns task name as non-terminated string in a newly allocated buffer. 445 * Also returns the size of the data. 446 * 447 * @param data Place to store pointer to newly allocated block. 448 * @param data_size Place to store size of the data. 449 * 450 * @returns EOK. 451 */ 452 int udebug_name_read(char **data, size_t *data_size) 453 { 454 size_t name_size; 455 456 name_size = str_size(TASK->name) + 1; 457 *data = malloc(name_size, 0); 458 *data_size = name_size; 459 460 memcpy(*data, TASK->name, name_size); 425 461 426 462 return 0; … … 437 473 * this function will fail with an EINVAL error code. 438 474 * 439 * @param buffer The buffer for storing thread hashes. 475 * @param t Thread where call arguments are to be read. 476 * @param buffer Place to store pointer to new buffer. 477 * @return EOK on success, ENOENT if @a t is invalid, EINVAL 478 * if thread state is not valid for this operation. 440 479 */ 441 480 int udebug_args_read(thread_t *t, void **buffer) … … 469 508 } 470 509 510 /** Read the register state of the thread. 511 * 512 * The contents of the thread's istate structure are copied to a newly 513 * allocated buffer and a pointer to it is written to @a buffer. The size of 514 * the buffer will be sizeof(istate_t). 515 * 516 * Currently register state cannot be read if the thread is inside a system 517 * call (as opposed to an exception). This is an implementation limit. 518 * 519 * @param t Thread whose state is to be read. 520 * @param buffer Place to store pointer to new buffer. 521 * @return EOK on success, ENOENT if @a t is invalid, EINVAL 522 * if thread is not in valid state, EBUSY if istate 523 * is not available. 524 */ 525 int udebug_regs_read(thread_t *t, void **buffer) 526 { 527 istate_t *state, *state_buf; 528 int rc; 529 530 /* Prepare a buffer to hold the data. */ 531 state_buf = malloc(sizeof(istate_t), 0); 532 533 /* On success, this will lock t->udebug.lock */ 534 rc = _thread_op_begin(t, false); 535 if (rc != EOK) { 536 return rc; 537 } 538 539 state = t->udebug.uspace_state; 540 if (state == NULL) { 541 _thread_op_end(t); 542 return EBUSY; 543 } 544 545 /* Copy to the allocated buffer */ 546 memcpy(state_buf, state, sizeof(istate_t)); 547 548 _thread_op_end(t); 549 550 *buffer = (void *) state_buf; 551 return 0; 552 } 553 471 554 /** Read the memory of the debugged task. 472 555 *
Note:
See TracChangeset
for help on using the changeset viewer.