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:
Alexandre Julliard 2000-04-06 22:05:16 +00:00
parent 08b289d7a6
commit f6507ed235
3 changed files with 25 additions and 13 deletions

View File

@ -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 );
}
/* 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)
{ {
debug_ctx->to_send = event; if (event->state == EVENT_SENT) continue; /* already sent */
wake_up( &debug_ctx->obj, 0 ); 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;

View File

@ -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)

View File

@ -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 */