Commit 0502638e authored by Alexandre Julliard's avatar Alexandre Julliard

Convert the per-process thread list to a standard list.

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