Do not send a debug event for a thread until the previous event for
the same thread has been continued.
This commit is contained in:
parent
08b289d7a6
commit
f6507ed235
|
@ -36,7 +36,6 @@ struct debug_ctx
|
||||||
struct object obj; /* object header */
|
struct object obj; /* object header */
|
||||||
struct debug_event *event_head; /* head of pending events queue */
|
struct debug_event *event_head; /* head of pending events queue */
|
||||||
struct debug_event *event_tail; /* tail of pending events queue */
|
struct debug_event *event_tail; /* tail of pending events queue */
|
||||||
struct debug_event *to_send; /* next event on the queue to send to debugger */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,8 +215,8 @@ static void unlink_event( struct debug_ctx *debug_ctx, struct debug_event *event
|
||||||
else debug_ctx->event_head = event->next;
|
else debug_ctx->event_head = event->next;
|
||||||
if (event->next) event->next->prev = event->prev;
|
if (event->next) event->next->prev = event->prev;
|
||||||
else debug_ctx->event_tail = event->prev;
|
else debug_ctx->event_tail = event->prev;
|
||||||
if (debug_ctx->to_send == event) debug_ctx->to_send = event->next;
|
|
||||||
event->next = event->prev = NULL;
|
event->next = event->prev = NULL;
|
||||||
|
if (event->sender->debug_event == event) event->sender->debug_event = NULL;
|
||||||
release_object( event );
|
release_object( event );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,11 +229,20 @@ static void link_event( struct debug_ctx *debug_ctx, struct debug_event *event )
|
||||||
debug_ctx->event_tail = event;
|
debug_ctx->event_tail = event;
|
||||||
if (event->prev) event->prev->next = event;
|
if (event->prev) event->prev->next = event;
|
||||||
else debug_ctx->event_head = event;
|
else debug_ctx->event_head = event;
|
||||||
if (!debug_ctx->to_send)
|
if (!event->sender->debug_event) wake_up( &debug_ctx->obj, 0 );
|
||||||
{
|
|
||||||
debug_ctx->to_send = event;
|
|
||||||
wake_up( &debug_ctx->obj, 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* find the next event that we can send to the debugger */
|
||||||
|
static struct debug_event *find_event_to_send( struct debug_ctx *debug_ctx )
|
||||||
|
{
|
||||||
|
struct debug_event *event;
|
||||||
|
for (event = debug_ctx->event_head; event; event = event->next)
|
||||||
|
{
|
||||||
|
if (event->state == EVENT_SENT) continue; /* already sent */
|
||||||
|
if (event->sender->debug_event) continue; /* thread busy with another one */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build a reply for the wait_debug_event request */
|
/* build a reply for the wait_debug_event request */
|
||||||
|
@ -245,14 +253,14 @@ static void build_wait_debug_reply( struct thread *thread, struct object *obj, i
|
||||||
if (obj)
|
if (obj)
|
||||||
{
|
{
|
||||||
struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
|
struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
|
||||||
struct debug_event *event = debug_ctx->to_send;
|
struct debug_event *event = find_event_to_send( debug_ctx );
|
||||||
|
|
||||||
/* the object that woke us has to be our debug context */
|
/* the object that woke us has to be our debug context */
|
||||||
assert( obj->ops == &debug_ctx_ops );
|
assert( obj->ops == &debug_ctx_ops );
|
||||||
assert( event );
|
assert( event );
|
||||||
|
|
||||||
event->state = EVENT_SENT;
|
event->state = EVENT_SENT;
|
||||||
debug_ctx->to_send = event->next;
|
event->sender->debug_event = event;
|
||||||
req->event.code = event->data.code;
|
req->event.code = event->data.code;
|
||||||
req->pid = event->sender->process;
|
req->pid = event->sender->process;
|
||||||
req->tid = event->sender;
|
req->tid = event->sender;
|
||||||
|
@ -330,15 +338,15 @@ static void debug_ctx_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
|
struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
|
||||||
assert( obj->ops == &debug_ctx_ops );
|
assert( obj->ops == &debug_ctx_ops );
|
||||||
fprintf( stderr, "Debug context head=%p tail=%p to_send=%p\n",
|
fprintf( stderr, "Debug context head=%p tail=%p\n",
|
||||||
debug_ctx->event_head, debug_ctx->event_tail, debug_ctx->to_send );
|
debug_ctx->event_head, debug_ctx->event_tail );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int debug_ctx_signaled( struct object *obj, struct thread *thread )
|
static int debug_ctx_signaled( struct object *obj, struct thread *thread )
|
||||||
{
|
{
|
||||||
struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
|
struct debug_ctx *debug_ctx = (struct debug_ctx *)obj;
|
||||||
assert( obj->ops == &debug_ctx_ops );
|
assert( obj->ops == &debug_ctx_ops );
|
||||||
return debug_ctx->to_send != NULL;
|
return find_event_to_send( debug_ctx ) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debug_ctx_destroy( struct object *obj )
|
static void debug_ctx_destroy( struct object *obj )
|
||||||
|
@ -378,11 +386,13 @@ static int continue_debug_event( struct process *process, struct thread *thread,
|
||||||
/* find the event in the queue */
|
/* find the event in the queue */
|
||||||
for (event = debug_ctx->event_head; event; event = event->next)
|
for (event = debug_ctx->event_head; event; event = event->next)
|
||||||
{
|
{
|
||||||
if (event == debug_ctx->to_send) goto error;
|
if (event->state != EVENT_SENT) continue;
|
||||||
if (event->sender == thread) break;
|
if (event->sender == thread) break;
|
||||||
}
|
}
|
||||||
if (!event) goto error;
|
if (!event) goto error;
|
||||||
|
|
||||||
|
assert( event->sender->debug_event == event );
|
||||||
|
|
||||||
event->status = status;
|
event->status = status;
|
||||||
event->state = EVENT_CONTINUED;
|
event->state = EVENT_CONTINUED;
|
||||||
wake_up( &event->obj, 0 );
|
wake_up( &event->obj, 0 );
|
||||||
|
@ -503,7 +513,6 @@ int set_process_debugger( struct process *process, struct thread *debugger )
|
||||||
if (!(debug_ctx = alloc_object( &debug_ctx_ops, -1 ))) return 0;
|
if (!(debug_ctx = alloc_object( &debug_ctx_ops, -1 ))) return 0;
|
||||||
debug_ctx->event_head = NULL;
|
debug_ctx->event_head = NULL;
|
||||||
debug_ctx->event_tail = NULL;
|
debug_ctx->event_tail = NULL;
|
||||||
debug_ctx->to_send = NULL;
|
|
||||||
debugger->debug_ctx = debug_ctx;
|
debugger->debug_ctx = debug_ctx;
|
||||||
}
|
}
|
||||||
process->debugger = debugger;
|
process->debugger = debugger;
|
||||||
|
|
|
@ -130,6 +130,7 @@ struct thread *create_thread( int fd, struct process *process, int suspend )
|
||||||
thread->teb = NULL;
|
thread->teb = NULL;
|
||||||
thread->mutex = NULL;
|
thread->mutex = NULL;
|
||||||
thread->debug_ctx = NULL;
|
thread->debug_ctx = NULL;
|
||||||
|
thread->debug_event = NULL;
|
||||||
thread->wait = NULL;
|
thread->wait = NULL;
|
||||||
thread->apc = NULL;
|
thread->apc = NULL;
|
||||||
thread->apc_count = 0;
|
thread->apc_count = 0;
|
||||||
|
@ -584,7 +585,7 @@ void kill_thread( struct thread *thread, int violent_death )
|
||||||
/* signal that we are finished booting on the client side */
|
/* signal that we are finished booting on the client side */
|
||||||
DECL_HANDLER(boot_done)
|
DECL_HANDLER(boot_done)
|
||||||
{
|
{
|
||||||
debug_level = req->debug_level;
|
debug_level = max( debug_level, req->debug_level );
|
||||||
/* Make sure last_req is initialized */
|
/* Make sure last_req is initialized */
|
||||||
current->last_req = REQ_BOOT_DONE;
|
current->last_req = REQ_BOOT_DONE;
|
||||||
if (current == booting_thread)
|
if (current == booting_thread)
|
||||||
|
|
|
@ -20,6 +20,7 @@ struct thread_wait;
|
||||||
struct thread_apc;
|
struct thread_apc;
|
||||||
struct mutex;
|
struct mutex;
|
||||||
struct debug_ctx;
|
struct debug_ctx;
|
||||||
|
struct debug_event;
|
||||||
|
|
||||||
enum run_state
|
enum run_state
|
||||||
{
|
{
|
||||||
|
@ -38,6 +39,7 @@ struct thread
|
||||||
struct process *process;
|
struct process *process;
|
||||||
struct mutex *mutex; /* list of currently owned mutexes */
|
struct mutex *mutex; /* list of currently owned mutexes */
|
||||||
struct debug_ctx *debug_ctx; /* debugger context if this thread is a debugger */
|
struct debug_ctx *debug_ctx; /* debugger context if this thread is a debugger */
|
||||||
|
struct debug_event *debug_event; /* debug event being sent to debugger */
|
||||||
struct thread_wait *wait; /* current wait condition if sleeping */
|
struct thread_wait *wait; /* current wait condition if sleeping */
|
||||||
struct thread_apc *apc; /* list of async procedure calls */
|
struct thread_apc *apc; /* list of async procedure calls */
|
||||||
int apc_count; /* number of outstanding APCs */
|
int apc_count; /* number of outstanding APCs */
|
||||||
|
|
Loading…
Reference in New Issue