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

diff --git a/server/console.c b/server/console.c
index 6f54f66..b51f56d 100644
--- a/server/console.c
+++ b/server/console.c
@@ -78,7 +78,6 @@
 {
     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 @@
     {
         /* 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 1efea77..3ea9f93 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -406,7 +406,7 @@
 
     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 @@
 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 @@
     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 @@
         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 @@
     {
         /* 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 779f8fb..4b8d6f2 100644
--- a/server/process.c
+++ b/server/process.c
@@ -192,6 +192,14 @@
     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 @@
 
     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 @@
     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 @@
     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 @@
 /* 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 @@
 /* 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 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 @@
 {
     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 @@
     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 @@
 /* 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 @@
 /* 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 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 00d935e..dae1aa8 100644
--- a/server/process.h
+++ b/server/process.h
@@ -52,7 +52,7 @@
     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 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 42a0d3a..c1a8cb7 100644
--- a/server/ptrace.c
+++ b/server/ptrace.c
@@ -228,12 +228,13 @@
     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 @@
 {
     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 1292dd8..a035e16 100644
--- a/server/request.c
+++ b/server/request.c
@@ -362,7 +362,7 @@
         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 a7c544b..d13199b 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -51,8 +51,7 @@
 {
     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 */