Convert the per-process thread list to a standard list.
This commit is contained in:
parent
4fe448ddf9
commit
0502638ee1
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue