diff --git a/server/console.c b/server/console.c index 6f54f66202d..b51f56de2b8 100644 --- a/server/console.c +++ b/server/console.c @@ -78,7 +78,6 @@ struct screen_buffer { struct object obj; /* object header */ struct list entry; /* entry in list of all screen buffers */ - struct screen_buffer *prev; struct console_input *input; /* associated console input */ int mode; /* output mode */ int cursor_size; /* size of cursor (percentage filled) */ @@ -400,7 +399,7 @@ static int propagate_console_signal_cb(struct process *process, void *user) { /* find a suitable thread to signal */ struct thread *thread; - for (thread = process->thread_list; thread; thread = thread->proc_next) + LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) { if (send_thread_signal( thread, csi->signal )) break; } diff --git a/server/debugger.c b/server/debugger.c index 1efea77b38c..3ea9f93a799 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -406,7 +406,7 @@ static int debugger_attach( struct process *process, struct thread *debugger ) if (process->debugger) goto error; /* already being debugged */ if (!is_process_init_done( process )) goto error; /* still starting up */ - if (!process->thread_list) goto error; /* no thread running in the process */ + if (list_empty( &process->thread_list )) goto error; /* no thread running in the process */ /* make sure we don't create a debugging loop */ for (thread = debugger; thread; thread = thread->process->debugger) @@ -489,19 +489,23 @@ int debugger_detach( struct process *process, struct thread *debugger ) void generate_startup_debug_events( struct process *process, void *entry ) { struct process_dll *dll; - struct thread *thread = process->thread_list; + struct thread *thread, *first_thread = get_process_first_thread( process ); /* generate creation events */ - generate_debug_event( thread, CREATE_PROCESS_DEBUG_EVENT, entry ); - while ((thread = thread->proc_next)) - generate_debug_event( thread, CREATE_THREAD_DEBUG_EVENT, NULL ); + LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) + { + if (thread == first_thread) + generate_debug_event( thread, CREATE_PROCESS_DEBUG_EVENT, entry ); + else + generate_debug_event( thread, CREATE_THREAD_DEBUG_EVENT, NULL ); + } /* generate dll events (in loading order, i.e. reverse list order) */ dll = &process->exe; while (dll->next) dll = dll->next; while (dll != &process->exe) { - generate_debug_event( process->thread_list, LOAD_DLL_DEBUG_EVENT, dll ); + generate_debug_event( first_thread, LOAD_DLL_DEBUG_EVENT, dll ); dll = dll->prev; } } @@ -603,6 +607,7 @@ DECL_HANDLER(debug_process) else if (debugger_attach( process, current )) { struct debug_event_exception data; + struct thread *thread = get_process_first_thread( process ); generate_startup_debug_events( process, NULL ); resume_process( process ); @@ -610,10 +615,10 @@ DECL_HANDLER(debug_process) data.record.ExceptionCode = EXCEPTION_BREAKPOINT; data.record.ExceptionFlags = EXCEPTION_CONTINUABLE; data.record.ExceptionRecord = NULL; - data.record.ExceptionAddress = get_thread_ip( process->thread_list ); + data.record.ExceptionAddress = get_thread_ip( thread ); data.record.NumberParameters = 0; data.first = 1; - generate_debug_event( process->thread_list, EXCEPTION_DEBUG_EVENT, &data ); + generate_debug_event( thread, EXCEPTION_DEBUG_EVENT, &data ); } release_object( process ); } @@ -695,13 +700,15 @@ DECL_HANDLER(debug_break) { /* find a suitable thread to signal */ struct thread *thread; - for (thread = process->thread_list; thread; thread = thread->proc_next) + LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) { - if (send_thread_signal( thread, SIGTRAP )) break; + if (send_thread_signal( thread, SIGTRAP )) goto done; } - if (!thread) set_error( STATUS_ACCESS_DENIED ); + set_error( STATUS_ACCESS_DENIED ); } else reply->self = 1; + +done: release_object( process ); } diff --git a/server/process.c b/server/process.c index 779f8fbd0fa..4b8d6f23c8f 100644 --- a/server/process.c +++ b/server/process.c @@ -192,6 +192,14 @@ void *get_ptid_entry( unsigned int id ) return ptid_entries[id - PTID_OFFSET].ptr; } +/* return the main thread of the process */ +struct thread *get_process_first_thread( struct process *process ) +{ + struct list *ptr = list_head( &process->thread_list ); + if (!ptr) return NULL; + return LIST_ENTRY( ptr, struct thread, proc_entry ); +} + /* set the state of the process startup info */ static void set_process_startup_state( struct process *process, enum startup_state state ) { @@ -250,7 +258,6 @@ struct thread *create_process( int fd ) if (!(process = alloc_object( &process_ops ))) goto error; process->parent = NULL; - process->thread_list = NULL; process->debugger = NULL; process->handles = NULL; process->msg_fd = NULL; @@ -277,6 +284,7 @@ struct thread *create_process( int fd ) process->exe.filename = NULL; process->group_id = 0; process->token = create_admin_token(); + list_init( &process->thread_list ); list_init( &process->locks ); list_init( &process->classes ); @@ -400,7 +408,7 @@ static void process_destroy( struct object *obj ) assert( obj->ops == &process_ops ); /* we can't have a thread remaining */ - assert( !process->thread_list ); + assert( list_empty( &process->thread_list )); set_process_startup_state( process, STARTUP_ABORTED ); if (process->console) release_object( process->console ); @@ -576,7 +584,7 @@ void kill_console_processes( struct thread *renderer, int exit_code ) /* a process has been killed (i.e. its last thread died) */ static void process_killed( struct process *process ) { - assert( !process->thread_list ); + assert( list_empty( &process->thread_list )); gettimeofday( &process->end_time, NULL ); if (process->handles) release_object( process->handles ); process->handles = NULL; @@ -603,10 +611,7 @@ static void process_killed( struct process *process ) /* add a thread to a process running threads list */ void add_process_thread( struct process *process, struct thread *thread ) { - thread->proc_next = process->thread_list; - thread->proc_prev = NULL; - if (thread->proc_next) thread->proc_next->proc_prev = thread; - process->thread_list = thread; + list_add_head( &process->thread_list, &thread->proc_entry ); if (!process->running_threads++) running_processes++; grab_object( thread ); } @@ -615,11 +620,9 @@ void add_process_thread( struct process *process, struct thread *thread ) void remove_process_thread( struct process *process, struct thread *thread ) { assert( process->running_threads > 0 ); - assert( process->thread_list ); + assert( !list_empty( &process->thread_list )); - if (thread->proc_next) thread->proc_next->proc_prev = thread->proc_prev; - if (thread->proc_prev) thread->proc_prev->proc_next = thread->proc_next; - else process->thread_list = thread->proc_next; + list_remove( &thread->proc_entry ); if (!--process->running_threads) { @@ -637,12 +640,12 @@ void suspend_process( struct process *process ) { if (!process->suspend++) { - struct thread *thread = process->thread_list; - while (thread) + struct list *ptr, *next; + + LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list ) { - struct thread *next = thread->proc_next; + struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry ); if (!thread->suspend) stop_thread( thread ); - thread = next; } } } @@ -653,12 +656,12 @@ void resume_process( struct process *process ) assert (process->suspend > 0); if (!--process->suspend) { - struct thread *thread = process->thread_list; - while (thread) + struct list *ptr, *next; + + LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list ) { - struct thread *next = thread->proc_next; + struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry ); if (!thread->suspend) wake_thread( thread ); - thread = next; } } } @@ -666,14 +669,14 @@ void resume_process( struct process *process ) /* kill a process on the spot */ void kill_process( struct process *process, struct thread *skip, int exit_code ) { - struct thread *thread = process->thread_list; + struct list *ptr, *next; - while (thread) + LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list ) { - struct thread *next = thread->proc_next; + struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry ); + thread->exit_code = exit_code; if (thread != skip) kill_thread( thread, 1 ); - thread = next; } } @@ -728,7 +731,7 @@ void enum_processes( int (*cb)(struct process*, void*), void *user ) /* len is the total size (in ints) */ static int read_process_memory( struct process *process, const int *addr, size_t len, int *dest ) { - struct thread *thread = process->thread_list; + struct thread *thread = get_process_first_thread( process ); assert( !((unsigned int)addr % sizeof(int)) ); /* address must be aligned */ @@ -771,7 +774,7 @@ static int check_process_write_access( struct thread *thread, int *addr, size_t static int write_process_memory( struct process *process, int *addr, size_t len, unsigned int first_mask, unsigned int last_mask, const int *src ) { - struct thread *thread = process->thread_list; + struct thread *thread = get_process_first_thread( process ); int ret = 0; assert( !((unsigned int)addr % sizeof(int) )); /* address must be aligned */ diff --git a/server/process.h b/server/process.h index 00d935eab79..dae1aa8de07 100644 --- a/server/process.h +++ b/server/process.h @@ -52,7 +52,7 @@ struct process struct object obj; /* object header */ struct list entry; /* entry in system-wide process list */ struct process *parent; /* parent process */ - struct thread *thread_list; /* head of the thread list */ + struct list thread_list; /* thread list */ struct thread *debugger; /* thread debugging this process */ struct handle_table *handles; /* handle entries */ struct fd *msg_fd; /* fd for sendmsg/recvmsg */ @@ -103,6 +103,7 @@ extern unsigned int alloc_ptid( void *ptr ); extern void free_ptid( unsigned int id ); extern void *get_ptid_entry( unsigned int id ); extern struct thread *create_process( int fd ); +extern struct thread *get_process_first_thread( struct process *process ); extern struct process *get_process_from_id( process_id_t id ); extern struct process *get_process_from_handle( obj_handle_t handle, unsigned int access ); extern int process_set_debugger( struct process *process, struct thread *thread ); diff --git a/server/ptrace.c b/server/ptrace.c index 42a0d3a7b36..c1a8cb785c9 100644 --- a/server/ptrace.c +++ b/server/ptrace.c @@ -228,12 +228,13 @@ int attach_process( struct process *process ) struct thread *thread; int ret = 1; - if (!process->thread_list) /* need at least one running thread */ + if (list_empty( &process->thread_list )) /* need at least one running thread */ { set_error( STATUS_ACCESS_DENIED ); return 0; } - for (thread = process->thread_list; thread; thread = thread->proc_next) + + LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) { if (thread->attached) continue; if (suspend_for_ptrace( thread )) resume_after_ptrace( thread ); @@ -247,7 +248,7 @@ void detach_process( struct process *process ) { struct thread *thread; - for (thread = process->thread_list; thread; thread = thread->proc_next) + LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) { if (thread->attached) detach_thread( thread, 0 ); } diff --git a/server/request.c b/server/request.c index 1292dd8d104..a035e1679c6 100644 --- a/server/request.c +++ b/server/request.c @@ -362,7 +362,7 @@ int receive_fd( struct process *process ) struct thread *thread; if (data.tid) thread = get_thread_from_id( data.tid ); - else thread = (struct thread *)grab_object( process->thread_list ); + else thread = (struct thread *)grab_object( get_process_first_thread( process )); if (!thread || thread->process != process || thread->state == TERMINATED) { diff --git a/server/thread.h b/server/thread.h index a7c544b0dd4..d13199b6ffc 100644 --- a/server/thread.h +++ b/server/thread.h @@ -51,8 +51,7 @@ struct thread { struct object obj; /* object header */ struct list entry; /* entry in system-wide thread list */ - struct thread *proc_next; /* per-process thread list */ - struct thread *proc_prev; + struct list proc_entry; /* entry in per-process thread list */ struct process *process; thread_id_t id; /* thread id */ struct list mutex_list; /* list of currently owned mutexes */