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
{
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;
}
......
......@@ -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 );
}
......
......@@ -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 */
......
......@@ -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 );
......
......@@ -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 );
}
......
......@@ -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)
{
......
......@@ -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 */
......
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