Further server optimizations:
[wine] / server / request.c
1 /*
2  * Server-side request handling
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <signal.h>
13 #include <sys/types.h>
14 #include <sys/uio.h>
15 #include <unistd.h>
16
17 #include "winerror.h"
18 #include "winnt.h"
19 #include "winbase.h"
20 #include "wincon.h"
21 #include "thread.h"
22 #include "server.h"
23 #define WANT_REQUEST_HANDLERS
24 #include "request.h"
25  
26 struct thread *current = NULL;  /* thread handling the current request */
27
28 /* complain about a protocol error and terminate the client connection */
29 void fatal_protocol_error( struct thread *thread, const char *err, ... )
30 {
31     va_list args;
32
33     va_start( args, err );
34     fprintf( stderr, "Protocol error:%p: ", thread );
35     vfprintf( stderr, err, args );
36     va_end( args );
37     remove_client( thread->client, PROTOCOL_ERROR );
38 }
39
40 /* call a request handler */
41 void call_req_handler( struct thread *thread, enum request req, int fd )
42 {
43     current = thread;
44     clear_error();
45
46     if (debug_level) trace_request( req, fd );
47
48     if (req < REQ_NB_REQUESTS)
49     {
50         req_handlers[req].handler( current->buffer, fd );
51         if (current && current->state != SLEEPING) send_reply( current );
52         current = NULL;
53         return;
54     }
55     fatal_protocol_error( current, "bad request %d\n", req );
56 }
57
58 /* handle a client timeout */
59 void call_timeout_handler( void *thread )
60 {
61     current = (struct thread *)thread;
62     if (debug_level) trace_timeout();
63     clear_error();
64     thread_timeout();
65     current = NULL;
66 }
67
68 /* a thread has been killed */
69 void call_kill_handler( struct thread *thread, int exit_code )
70 {
71     /* must be reentrant WRT call_req_handler */
72     struct thread *old_current = current;
73     current = thread;
74     if (current)
75     {
76         if (debug_level) trace_kill( exit_code );
77         thread_killed( current, exit_code );
78     }
79     current = (old_current != thread) ? old_current : NULL;
80 }
81
82 /* set the fd to pass to the thread */
83 void set_reply_fd( struct thread *thread, int pass_fd )
84 {
85     client_pass_fd( thread->client, pass_fd );
86 }
87
88 /* send a reply to a thread */
89 void send_reply( struct thread *thread )
90 {
91     if (thread->state == SLEEPING) thread->state = RUNNING;
92     client_reply( thread->client, thread->error );
93 }
94
95 /* set the debug level */
96 DECL_HANDLER(set_debug)
97 {
98     debug_level = req->level;
99     /* Make sure last_req is initialized */
100     current->last_req = REQ_SET_DEBUG;
101 }
102
103 /* debugger support operations */
104 DECL_HANDLER(debugger)
105 {
106     switch ( req->op )
107     {
108     case DEBUGGER_FREEZE_ALL:
109         suspend_all_threads();
110         break;
111
112     case DEBUGGER_UNFREEZE_ALL:
113         resume_all_threads();
114         break;
115     }
116 }