/branches/tracing/kernel/generic/include/proc/task.h |
---|
93,6 → 93,12 |
* certain extent. |
*/ |
atomic_t active_calls; |
/** Debugging stuff */ |
bool being_debugged; |
bool stop_request; |
call_t *debug_begin_call; |
call_t *debug_go_call; |
/** Architecture specific task data. */ |
task_arch_t arch; |
/branches/tracing/kernel/generic/include/proc/thread.h |
---|
203,6 → 203,9 |
/** Thread's kernel stack. */ |
uint8_t *kstack; |
/** Debugging stuff */ |
waitq_t go_wq; |
} thread_t; |
/** Thread list lock. |
/branches/tracing/kernel/generic/include/udebug.h |
---|
0,0 → 1,16 |
/** @addtogroup generic |
* @{ |
*/ |
/** @file |
*/ |
#ifndef KERN_UDEBUG_H_ |
#define KERN_UDEBUG_H_ |
void udebug_syscall_event(void); |
void udebug_stopping_point(void); |
#endif |
/** @} |
*/ |
/branches/tracing/kernel/generic/include/syscall/syscall.h |
---|
66,6 → 66,7 |
SYS_SYSINFO_VALID, |
SYS_SYSINFO_VALUE, |
SYS_DEBUG_ENABLE_CONSOLE, |
SYS_IPC_CONNECT_TASK, |
SYSCALL_END |
} syscall_t; |
/branches/tracing/kernel/generic/include/ipc/sysipc.h |
---|
57,6 → 57,7 |
unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method, |
irq_code_t *ucode); |
unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno); |
unative_t sys_ipc_connect_task(sysarg64_t *task_id); |
#endif |
/branches/tracing/kernel/generic/include/ipc/ipc.h |
---|
195,6 → 195,35 |
*/ |
#define IPC_M_DATA_READ 7 |
/** Start debugging the recipient. |
* Causes all threads in the receiving task to stop. When they |
* are all stoped, an answer with retval 0 is generated. |
*/ |
#define IPC_M_DEBUG_BEGIN 8 |
/** Finish debugging the recipient. |
* Answers all pending GO and GUARD messages. |
*/ |
#define IPC_M_DEBUG_END 9 |
/** Make sure the debugged task is still there. |
* This message is answered when the debugged task dies |
* or the debugging session ends. |
*/ |
#define IPC_M_DEBUG_GUARD 10 |
/** Run a thread until a debugging event occurs. |
* This message is answered when the thread stops |
* in a debugging event. |
*/ |
#define IPC_M_DEBUG_GO 11 |
/** Stop a thread being debugged. |
* Creates a special STOP event in the thread, causing |
* it to answer a pending GO message (if any). |
*/ |
#define IPC_M_DEBUG_STOP 12 |
/* Well-known methods */ |
#define IPC_M_LAST_SYSTEM 511 |
#define IPC_M_PING 512 |
299,6 → 328,7 |
extern int ipc_phone_hangup(phone_t *phone); |
extern void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err); |
extern void ipc_print_task(task_id_t taskid); |
extern int ipc_connect_task(task_id_t taskid); |
extern answerbox_t *ipc_phone_0; |
/branches/tracing/kernel/generic/src/proc/thread.c |
---|
341,6 → 341,8 |
avltree_node_initialize(&t->threads_tree_node); |
t->threads_tree_node.key = (uintptr_t) t; |
waitq_initialize(&t->go_wq); |
/* might depend on previous initialization */ |
thread_create_arch(t); |
/branches/tracing/kernel/generic/src/syscall/syscall.c |
---|
52,6 → 52,7 |
#include <sysinfo/sysinfo.h> |
#include <console/console.h> |
#include <console/klog.h> |
#include <udebug.h> |
/** Print using kernel facility |
* |
108,6 → 109,9 |
if (THREAD->interrupted) |
thread_exit(); |
udebug_syscall_event(); |
udebug_stopping_point(); |
return rc; |
} |
158,7 → 162,9 |
(syshandler_t) sys_sysinfo_value, |
/* Debug calls */ |
(syshandler_t) sys_debug_enable_console |
(syshandler_t) sys_debug_enable_console, |
(syshandler_t) sys_ipc_connect_task |
}; |
/** @} |
/branches/tracing/kernel/generic/src/ipc/sysipc.c |
---|
290,13 → 290,76 |
return 0; |
} |
static task_t *get_lock_callee_task(phone_t *phone) |
{ |
answerbox_t *answerbox; |
task_t *ta; |
// FIXME: locking!!! |
answerbox = phone->callee; |
ta = answerbox->task; |
spinlock_lock(&ta->lock); |
return ta; |
} |
#include <console/klog.h> |
static void debug_begin(call_t *call, phone_t *phone) |
{ |
task_t *ta; |
klog_printf("debug_begin()"); |
ta = get_lock_callee_task(phone); |
klog_printf("debugging task %llu\n", ta->taskid); |
if (ta->being_debugged != false) { |
IPC_SET_RETVAL(call->data, EBUSY); |
ipc_answer(&ta->answerbox, call); |
spinlock_unlock(&ta->lock); |
return; |
} |
ta->being_debugged = true; |
ta->stop_request = true; |
ta->debug_begin_call = call; |
spinlock_unlock(&ta->lock); |
klog_printf("debug_begin() done"); |
} |
static void debug_go(call_t *call, phone_t *phone) |
{ |
thread_t *t; |
link_t *l; |
task_t *ta; |
klog_printf("debug_go()"); |
ta = get_lock_callee_task(phone); |
l = ta->th_head.next; |
if (l != &TASK->th_head) { |
t = list_get_instance(l, thread_t, th_link); |
waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
} |
ta->debug_go_call = call; |
spinlock_unlock(&ta->lock); |
} |
/** Called before the request is sent. |
* |
* @param call Call structure with the request. |
* @param phone Phone that the call will be sent through. |
* |
* @return Return 0 on success, ELIMIT or EPERM on error. |
*/ |
static int request_preprocess(call_t *call) |
static int request_preprocess(call_t *call, phone_t *phone) |
{ |
int newphid; |
size_t size; |
338,6 → 401,12 |
return rc; |
} |
break; |
case IPC_M_DEBUG_BEGIN: |
debug_begin(call, phone); |
break; |
case IPC_M_DEBUG_GO: |
debug_go(call, phone); |
break; |
default: |
break; |
} |
397,7 → 466,17 |
return -1; |
} |
IPC_SET_ARG5(call->data, phoneid); |
} |
} |
switch (IPC_GET_METHOD(call->data)) { |
case IPC_M_DEBUG_BEGIN: |
case IPC_M_DEBUG_END: |
case IPC_M_DEBUG_GO: |
case IPC_M_DEBUG_STOP: |
case IPC_M_DEBUG_GUARD: |
return -1; |
default: |
break; |
} |
return 0; |
} |
439,7 → 518,7 |
IPC_SET_ARG4(call.data, 0); |
IPC_SET_ARG5(call.data, 0); |
if (!(res = request_preprocess(&call))) { |
if (!(res = request_preprocess(&call, phone))) { |
ipc_call_sync(phone, &call); |
process_answer(&call); |
} else { |
477,7 → 556,7 |
GET_CHECK_PHONE(phone, phoneid, return ENOENT); |
if (!(res = request_preprocess(&call))) { |
if (!(res = request_preprocess(&call, phone))) { |
ipc_call_sync(phone, &call); |
process_answer(&call); |
} else |
544,7 → 623,7 |
*/ |
IPC_SET_ARG5(call->data, 0); |
if (!(res = request_preprocess(call))) |
if (!(res = request_preprocess(call, phone))) |
ipc_call(phone, call); |
else |
ipc_backsend_err(phone, call, res); |
578,7 → 657,7 |
ipc_call_free(call); |
return (unative_t) rc; |
} |
if (!(res = request_preprocess(call))) |
if (!(res = request_preprocess(call, phone))) |
ipc_call(phone, call); |
else |
ipc_backsend_err(phone, call, res); |
862,5 → 941,26 |
return 0; |
} |
#include <console/klog.h> |
/** |
* Syscall connect to a task by id. |
* |
* @return Phone id on success, or negative error code. |
*/ |
unative_t sys_ipc_connect_task(sysarg64_t *uspace_taskid_arg) |
{ |
sysarg64_t taskid_arg; |
int rc; |
rc = copy_from_uspace(&taskid_arg, uspace_taskid_arg, sizeof(sysarg64_t)); |
if (rc != 0) |
return (unative_t) rc; |
klog_printf("sys_ipc_connect_kbox(%lld, %d)", taskid_arg.value); |
return ipc_connect_task(taskid_arg.value); |
} |
/** @} |
*/ |
/branches/tracing/kernel/generic/src/ipc/ipc.c |
---|
606,5 → 606,38 |
spinlock_unlock(&task->lock); |
} |
#include <ipc/ipcrsc.h> |
#include <console/klog.h> |
/** |
* Connect phone to a task specified by id. |
* |
* @return Phone id on success, or negative error code. |
*/ |
int ipc_connect_task(task_id_t taskid) |
{ |
int newphid; |
task_t *ta; |
newphid = phone_alloc(); |
if (newphid < 0) |
return ELIMIT; |
spinlock_lock(&tasks_lock); |
ta = task_find_by_id(taskid); |
if (ta == NULL) { |
spinlock_unlock(&tasks_lock); |
return ENOENT; |
} |
spinlock_lock(&ta->lock); |
spinlock_unlock(&tasks_lock); |
ipc_phone_connect(&TASK->phones[newphid], &ta->answerbox); |
spinlock_unlock(&ta->lock); |
return newphid; |
} |
/** @} |
*/ |
/branches/tracing/kernel/generic/src/udebug/udebug.c |
---|
0,0 → 1,39 |
/** @addtogroup generic |
* @{ |
*/ |
/** |
* @file |
* @brief Tdebug. |
*/ |
#include <synch/waitq.h> |
#include <console/klog.h> |
#include <udebug.h> |
#include <arch.h> |
void udebug_stopping_point(void) |
{ |
if (TASK->stop_request) { /* locking! */ |
klog_printf("udebug_stopping_point"); |
IPC_SET_RETVAL(TASK->debug_begin_call->data, 0); |
ipc_answer(&TASK->answerbox, TASK->debug_begin_call); |
TASK->stop_request = false; |
TASK->debug_begin_call = NULL; |
waitq_sleep(&THREAD->go_wq); |
} |
} |
void udebug_syscall_event(void) |
{ |
/* being debugged + have go */ |
if (TASK->being_debugged && !TASK->stop_request) { /* locking! */ |
klog_printf("udebug_syscall_event"); |
IPC_SET_RETVAL(TASK->debug_go_call->data, 0); |
ipc_answer(&TASK->answerbox, TASK->debug_go_call); |
waitq_sleep(&THREAD->go_wq); |
} |
} |
/** @} |
*/ |
/branches/tracing/kernel/Makefile |
---|
275,6 → 275,7 |
generic/src/ipc/sysipc.c \ |
generic/src/ipc/ipcrsc.c \ |
generic/src/ipc/irq.c \ |
generic/src/udebug/udebug.c \ |
generic/src/security/cap.c \ |
generic/src/sysinfo/sysinfo.c |
/branches/tracing/uspace/app/tester/debug/debug1.def |
---|
0,0 → 1,6 |
{ |
"debug1", |
"Userspace debugging test", |
&test_debug1, |
true |
}, |
/branches/tracing/uspace/app/tester/debug/debug1.c |
---|
0,0 → 1,33 |
#include <stdio.h> |
#include <unistd.h> |
#include <ipc/ipc.h> |
#include "../tester.h" |
char * test_debug1(bool quiet) |
{ |
int taskid; |
int rc; |
int phoneid; |
int i; |
printf("running debug1 test\n"); |
taskid = 12; |
printf("ipc_connect_task(%d)...\n", taskid); |
rc = ipc_connect_task(taskid); |
printf("-> %d\n", rc); |
phoneid = rc; |
printf("send IPC_M_DEBUG_BEGIN message\n"); |
rc = ipc_call_sync_0_0(phoneid, IPC_M_DEBUG_BEGIN); |
printf("-> %d\n", rc); |
while (1) { |
printf("send IPC_M_DEBUG_GO message\n"); |
rc = ipc_call_sync_0_0(phoneid, IPC_M_DEBUG_GO); |
printf("-> %d\n", rc); |
} |
printf("done\n"); |
return NULL; |
} |
/branches/tracing/uspace/app/tester/tester.c |
---|
57,6 → 57,7 |
#include "ipc/hangup.def" |
#include "devmap/devmap1.def" |
#include "vfs/vfs1.def" |
#include "debug/debug1.def" |
{NULL, NULL, NULL} |
}; |
/branches/tracing/uspace/app/tester/tester.h |
---|
70,6 → 70,7 |
extern char * test_hangup(bool quiet); |
extern char * test_devmap1(bool quiet); |
extern char * test_vfs1(bool quiet); |
extern char * test_debug1(bool quiet); |
extern test_t tests[]; |
/branches/tracing/uspace/app/tester/Makefile |
---|
53,7 → 53,8 |
ipc/answer.c \ |
ipc/hangup.c \ |
devmap/devmap1.c \ |
vfs/vfs1.c |
vfs/vfs1.c \ |
debug/debug1.c |
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))) |
/branches/tracing/uspace/lib/libc/include/ipc/ipc.h |
---|
288,6 → 288,10 |
extern int ipc_data_write_receive(ipc_callid_t *callid, size_t *size); |
extern int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size); |
#include <task.h> |
extern int ipc_connect_task(task_id_t id); |
#endif |
/** @} |
/branches/tracing/uspace/lib/libc/generic/ipc.c |
---|
909,6 → 909,18 |
{ |
return ipc_answer_2(callid, EOK, (ipcarg_t) dst, (ipcarg_t) size); |
} |
#include <kernel/syscall/sysarg64.h> |
/** Connect to a task specified by id. |
*/ |
int ipc_connect_task(task_id_t id) |
{ |
sysarg64_t arg; |
arg.value = (unsigned long long) id; |
return __SYSCALL1(SYS_IPC_CONNECT_TASK, (sysarg_t) &arg); |
} |
/** @} |
*/ |