Jacek Caban : server: Make thread context a server object.

Alexandre Julliard julliard at winehq.org
Wed Apr 22 15:29:26 CDT 2020


Module: wine
Branch: master
Commit: 40e849ffa46ae3cd060e2db83305dda1c4d2648e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=40e849ffa46ae3cd060e2db83305dda1c4d2648e

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Apr 22 14:31:36 2020 +0200

server: Make thread context a server object.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 server/thread.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++----------
 server/thread.h |  2 +-
 2 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/server/thread.c b/server/thread.c
index 534fab6597..341693b7bd 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -126,6 +126,40 @@ static const struct object_ops thread_apc_ops =
 };
 
 
+/* thread CPU context */
+
+struct context
+{
+    struct object   obj;        /* object header */
+    context_t       regs;       /* context data */
+};
+
+static void dump_context( struct object *obj, int verbose );
+
+static const struct object_ops context_ops =
+{
+    sizeof(struct context),     /* size */
+    dump_context,               /* dump */
+    no_get_type,                /* get_type */
+    add_queue,                  /* add_queue */
+    remove_queue,               /* remove_queue */
+    NULL,                       /* signaled */
+    no_satisfied,               /* satisfied */
+    no_signal,                  /* signal */
+    no_get_fd,                  /* get_fd */
+    no_map_access,              /* map_access */
+    default_get_sd,             /* get_sd */
+    default_set_sd,             /* set_sd */
+    no_lookup_name,             /* lookup_name */
+    no_link_name,               /* link_name */
+    NULL,                       /* unlink_name */
+    no_open_file,               /* open_file */
+    no_kernel_obj_list,         /* get_kernel_obj_list */
+    no_close_handle,            /* close_handle */
+    no_destroy                  /* destroy */
+};
+
+
 /* thread operations */
 
 static void dump_thread( struct object *obj, int verbose );
@@ -221,6 +255,27 @@ static inline int is_valid_address( client_ptr_t addr )
     return addr && !(addr % sizeof(int));
 }
 
+
+/* dump a context on stdout for debugging purposes */
+static void dump_context( struct object *obj, int verbose )
+{
+    struct context *context = (struct context *)obj;
+    assert( obj->ops == &context_ops );
+
+    fprintf( stderr, "context flags=%x\n", context->regs.flags );
+}
+
+
+static struct context *create_thread_context( struct thread *thread )
+{
+    struct context *context;
+    if (!(context = alloc_object( &context_ops ))) return NULL;
+    memset( &context->regs, 0, sizeof(context->regs) );
+    context->regs.cpu = thread->process->cpu;
+    return context;
+}
+
+
 /* create a new thread */
 struct thread *create_thread( int fd, struct process *process, const struct security_descriptor *sd )
 {
@@ -317,6 +372,11 @@ static void cleanup_thread( struct thread *thread )
 {
     int i;
 
+    if (thread->context)
+    {
+        release_object( thread->context );
+        thread->context = NULL;
+    }
     clear_apc_queue( &thread->system_apc );
     clear_apc_queue( &thread->user_apc );
     free( thread->req_data );
@@ -324,7 +384,6 @@ static void cleanup_thread( struct thread *thread )
     if (thread->request_fd) release_object( thread->request_fd );
     if (thread->reply_fd) release_object( thread->reply_fd );
     if (thread->wait_fd) release_object( thread->wait_fd );
-    free( thread->context );
     cleanup_clipboard_thread(thread);
     destroy_thread_windows( thread );
     free_msg_queue( thread );
@@ -343,7 +402,6 @@ static void cleanup_thread( struct thread *thread )
     thread->request_fd = NULL;
     thread->reply_fd = NULL;
     thread->wait_fd = NULL;
-    thread->context = NULL;
     thread->desktop = 0;
     thread->desc = NULL;
     thread->desc_len = 0;
@@ -776,9 +834,9 @@ static int send_thread_wakeup( struct thread *thread, client_ptr_t cookie, int s
     if (thread->context && thread->suspend_cookie == cookie
         && signaled != STATUS_KERNEL_APC && signaled != STATUS_USER_APC)
     {
-        if (!thread->context->flags)
+        if (!thread->context->regs.flags)
         {
-            free( thread->context );
+            release_object( thread->context );
             thread->context = NULL;
         }
         else signaled = STATUS_KERNEL_APC; /* signal a fake APC so that client calls select to get a new context */
@@ -1556,9 +1614,8 @@ DECL_HANDLER(select)
             return;
         }
 
-        if (!(current->context = mem_alloc( sizeof(*context) ))) return;
-        memcpy( current->context, context, sizeof(*context) );
-        current->context->flags = 0;  /* to keep track of what is modified */
+        if (!(current->context = create_thread_context( current ))) return;
+        copy_context( &current->context->regs, context, context->flags );
         current->suspend_cookie = req->cookie;
     }
 
@@ -1633,10 +1690,8 @@ DECL_HANDLER(select)
     else if (get_error() != STATUS_PENDING && get_reply_max_size() == sizeof(context_t) &&
              current->context && current->suspend_cookie == req->cookie)
     {
-        if (current->context->flags)
-            set_reply_data_ptr( current->context, sizeof(context_t) );
-        else
-            free( current->context );
+        if (current->context->regs.flags) set_reply_data( &current->context->regs, sizeof(context_t) );
+        release_object( current->context );
         current->context = NULL;
     }
 }
@@ -1777,7 +1832,7 @@ DECL_HANDLER(get_thread_context)
         context->cpu = thread->process->cpu;
         if (thread->context)
         {
-            copy_context( context, thread->context, req->flags & ~flags );
+            copy_context( context, &thread->context->regs, req->flags & ~flags );
             context->flags |= req->flags & ~flags;
         }
         if (req->flags & flags) get_thread_context( thread, context, req->flags & flags );
@@ -1823,8 +1878,8 @@ DECL_HANDLER(set_thread_context)
         if (system_flags) set_thread_context( thread, context, system_flags );
         if (thread->context && !get_error())
         {
-            copy_context( thread->context, context, context->flags );
-            thread->context->flags |= client_flags;
+            copy_context( &thread->context->regs, context, context->flags );
+            thread->context->regs.flags |= client_flags;
         }
     }
     else set_error( STATUS_INVALID_PARAMETER );
diff --git a/server/thread.h b/server/thread.h
index b86d8d3dbe..5d12d24dd8 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -75,7 +75,7 @@ struct thread
     int                    exit_code;     /* thread exit code */
     int                    unix_pid;      /* Unix pid of client */
     int                    unix_tid;      /* Unix tid of client */
-    context_t             *context;       /* current context */
+    struct context        *context;       /* current context */
     client_ptr_t           suspend_cookie;/* wait cookie of suspending select */
     client_ptr_t           teb;           /* TEB address (in client address space) */
     client_ptr_t           entry_point;   /* entry point (in client address space) */




More information about the wine-cvs mailing list