MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
win32.c
1 /*
2  * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
3  * Copyright 2003 Michael A. Davis <mike@datanerds.net>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 #ifdef _MSC_VER
29 #include "./config.h"
30 #else
31 /* Avoid the windows/msvc thing. */
32 #include "../config.h"
33 #endif
34 
35 #include <winsock2.h>
36 #include <windows.h>
37 #include <sys/types.h>
38 #include <sys/queue.h>
39 #include <signal.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <assert.h>
45 
46 #define RB_AUGMENT(x) (void)(x)
47 #include "./tree.h"
48 #include "log.h"
49 #include "event.h"
50 #include "event-internal.h"
51 
52 #define XFREE(ptr) do { if (ptr) free(ptr); } while(0)
53 
54 extern struct event_list timequeue;
55 extern struct event_list addqueue;
56 #if 0
57 extern struct event_list signalqueue;
58 #endif
59 
60 struct win_fd_set {
61  u_int fd_count;
62  SOCKET fd_array[1];
63 };
64 
65 int evsigcaught[NSIG];
66 volatile sig_atomic_t signal_caught = 0;
67 /* MSDN says this is required to handle SIGFPE */
68 volatile double SIGFPE_REQ = 0.0f;
69 
70 #if 0
71 static void signal_handler(int sig);
72 
73 void signal_process(void);
74 int signal_recalc(void);
75 #endif
76 
77 struct event_entry {
78  RB_ENTRY(event_entry) node;
79  SOCKET sock;
80  int read_pos;
81  int write_pos;
82  struct event *read_event;
83  struct event *write_event;
84 };
85 
86 static int
87 compare(struct event_entry *a, struct event_entry *b)
88 {
89  if (a->sock < b->sock)
90  return -1;
91  else if (a->sock > b->sock)
92  return 1;
93  else
94  return 0;
95 }
96 
97 struct win32op {
98  int fd_setsz;
99  struct win_fd_set *readset_in;
100  struct win_fd_set *writeset_in;
101  struct win_fd_set *readset_out;
102  struct win_fd_set *writeset_out;
103  struct win_fd_set *exset_out;
104  RB_HEAD(event_map, event_entry) event_root;
105 
106  unsigned signals_are_broken : 1;
107 };
108 
109 RB_PROTOTYPE(event_map, event_entry, node, compare);
110 RB_GENERATE(event_map, event_entry, node, compare);
111 
112 void *win32_init (struct event_base *);
113 int win32_insert (void *, struct event *);
114 int win32_del (void *, struct event *);
115 int win32_dispatch (struct event_base *base, void *, struct timeval *);
116 void win32_dealloc (struct event_base *, void *);
117 
118 struct eventop win32ops = {
119  "win32",
120  win32_init,
121  win32_insert,
122  win32_del,
123  win32_dispatch,
124  win32_dealloc,
125  0
126 };
127 
128 #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
129 
130 static int
131 realloc_fd_sets(struct win32op *op, size_t new_size)
132 {
133  size_t size;
134 
135  assert(new_size >= op->readset_in->fd_count &&
136  new_size >= op->writeset_in->fd_count);
137  assert(new_size >= 1);
138 
139  size = FD_SET_ALLOC_SIZE(new_size);
140  if (!(op->readset_in = realloc(op->readset_in, size)))
141  return (-1);
142  if (!(op->writeset_in = realloc(op->writeset_in, size)))
143  return (-1);
144  if (!(op->readset_out = realloc(op->readset_out, size)))
145  return (-1);
146  if (!(op->exset_out = realloc(op->exset_out, size)))
147  return (-1);
148  if (!(op->writeset_out = realloc(op->writeset_out, size)))
149  return (-1);
150  op->fd_setsz = new_size;
151  return (0);
152 }
153 
154 static int
155 timeval_to_ms(struct timeval *tv)
156 {
157  return ((tv->tv_sec * 1000) + (tv->tv_usec / 1000));
158 }
159 
160 static struct event_entry*
161 get_event_entry(struct win32op *op, SOCKET s, int create)
162 {
163  struct event_entry key, *val;
164  key.sock = s;
165  val = RB_FIND(event_map, &op->event_root, &key);
166  if (val || !create)
167  return val;
168  if (!(val = calloc(1, sizeof(struct event_entry)))) {
169  event_warn("%s: calloc", __func__);
170  return NULL;
171  }
172  val->sock = s;
173  val->read_pos = val->write_pos = -1;
174  RB_INSERT(event_map, &op->event_root, val);
175  return val;
176 }
177 
178 static int
179 do_fd_set(struct win32op *op, struct event_entry *ent, int read)
180 {
181  SOCKET s = ent->sock;
182  struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
183  if (read) {
184  if (ent->read_pos >= 0)
185  return (0);
186  } else {
187  if (ent->write_pos >= 0)
188  return (0);
189  }
190  if (set->fd_count == op->fd_setsz) {
191  if (realloc_fd_sets(op, op->fd_setsz*2))
192  return (-1);
193  /* set pointer will have changed and needs reiniting! */
194  set = read ? op->readset_in : op->writeset_in;
195  }
196  set->fd_array[set->fd_count] = s;
197  if (read)
198  ent->read_pos = set->fd_count;
199  else
200  ent->write_pos = set->fd_count;
201  return (set->fd_count++);
202 }
203 
204 static int
205 do_fd_clear(struct win32op *op, struct event_entry *ent, int read)
206 {
207  int i;
208  struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
209  if (read) {
210  i = ent->read_pos;
211  ent->read_pos = -1;
212  } else {
213  i = ent->write_pos;
214  ent->write_pos = -1;
215  }
216  if (i < 0)
217  return (0);
218  if (--set->fd_count != i) {
219  struct event_entry *ent2;
220  SOCKET s2;
221  s2 = set->fd_array[i] = set->fd_array[set->fd_count];
222  ent2 = get_event_entry(op, s2, 0);
223  if (!ent) /* This indicates a bug. */
224  return (0);
225  if (read)
226  ent2->read_pos = i;
227  else
228  ent2->write_pos = i;
229  }
230  return (0);
231 }
232 
233 #define NEVENT 64
234 void *
235 win32_init(struct event_base *_base)
236 {
237  struct win32op *winop;
238  size_t size;
239  if (!(winop = calloc(1, sizeof(struct win32op))))
240  return NULL;
241  winop->fd_setsz = NEVENT;
242  size = FD_SET_ALLOC_SIZE(NEVENT);
243  if (!(winop->readset_in = malloc(size)))
244  goto err;
245  if (!(winop->writeset_in = malloc(size)))
246  goto err;
247  if (!(winop->readset_out = malloc(size)))
248  goto err;
249  if (!(winop->writeset_out = malloc(size)))
250  goto err;
251  if (!(winop->exset_out = malloc(size)))
252  goto err;
253  RB_INIT(&winop->event_root);
254  winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;
255  winop->readset_out->fd_count = winop->writeset_out->fd_count
256  = winop->exset_out->fd_count = 0;
257 
258  if (evsignal_init(_base) < 0)
259  winop->signals_are_broken = 1;
260 
261  return (winop);
262  err:
263  XFREE(winop->readset_in);
264  XFREE(winop->writeset_in);
265  XFREE(winop->readset_out);
266  XFREE(winop->writeset_out);
267  XFREE(winop->exset_out);
268  XFREE(winop);
269  return (NULL);
270 }
271 
272 int
273 win32_insert(void *op, struct event *ev)
274 {
275  struct win32op *win32op = op;
276  struct event_entry *ent;
277 
278  if (ev->ev_events & EV_SIGNAL) {
279  if (win32op->signals_are_broken)
280  return (-1);
281  return (evsignal_add(ev));
282  }
283  if (!(ev->ev_events & (EV_READ|EV_WRITE)))
284  return (0);
285  ent = get_event_entry(win32op, ev->ev_fd, 1);
286  if (!ent)
287  return (-1); /* out of memory */
288 
289  event_debug(("%s: adding event for %d", __func__, (int)ev->ev_fd));
290  if (ev->ev_events & EV_READ) {
291  if (do_fd_set(win32op, ent, 1)<0)
292  return (-1);
293  ent->read_event = ev;
294  }
295  if (ev->ev_events & EV_WRITE) {
296  if (do_fd_set(win32op, ent, 0)<0)
297  return (-1);
298  ent->write_event = ev;
299  }
300  return (0);
301 }
302 
303 int
304 win32_del(void *op, struct event *ev)
305 {
306  struct win32op *win32op = op;
307  struct event_entry *ent;
308 
309  if (ev->ev_events & EV_SIGNAL)
310  return (evsignal_del(ev));
311 
312  if (!(ent = get_event_entry(win32op, ev->ev_fd, 0)))
313  return (-1);
314  event_debug(("%s: Removing event for %d", __func__, ev->ev_fd));
315  if (ev == ent->read_event) {
316  do_fd_clear(win32op, ent, 1);
317  ent->read_event = NULL;
318  }
319  if (ev == ent->write_event) {
320  do_fd_clear(win32op, ent, 0);
321  ent->write_event = NULL;
322  }
323  if (!ent->read_event && !ent->write_event) {
324  RB_REMOVE(event_map, &win32op->event_root, ent);
325  free(ent);
326  }
327 
328  return 0;
329 }
330 
331 static void
332 fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in)
333 {
334  out->fd_count = in->fd_count;
335  memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET)));
336 }
337 
338 /*
339  static void dump_fd_set(struct win_fd_set *s)
340  {
341  unsigned int i;
342  printf("[ ");
343  for(i=0;i<s->fd_count;++i)
344  printf("%d ",(int)s->fd_array[i]);
345  printf("]\n");
346  }
347 */
348 
349 int
350 win32_dispatch(struct event_base *base, void *op,
351  struct timeval *tv)
352 {
353  struct win32op *win32op = op;
354  int res = 0;
355  unsigned j, i;
356  int fd_count;
357  SOCKET s;
358  struct event_entry *ent;
359 
360  fd_set_copy(win32op->readset_out, win32op->readset_in);
361  fd_set_copy(win32op->exset_out, win32op->readset_in);
362  fd_set_copy(win32op->writeset_out, win32op->writeset_in);
363 
364  fd_count =
365  (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?
366  win32op->readset_out->fd_count : win32op->writeset_out->fd_count;
367 
368  if (!fd_count) {
369  /* Windows doesn't like you to call select() with no sockets */
370  Sleep(timeval_to_ms(tv));
371  evsignal_process(base);
372  return (0);
373  }
374 
375  res = select(fd_count,
376  (struct fd_set*)win32op->readset_out,
377  (struct fd_set*)win32op->writeset_out,
378  (struct fd_set*)win32op->exset_out, tv);
379 
380  event_debug(("%s: select returned %d", __func__, res));
381 
382  if(res <= 0) {
383  evsignal_process(base);
384  return res;
385  } else if (base->sig.evsignal_caught) {
386  evsignal_process(base);
387  }
388 
389  if (win32op->readset_out->fd_count) {
390  i = rand() % win32op->readset_out->fd_count;
391  for (j=0; j<win32op->readset_out->fd_count; ++j) {
392  if (++i >= win32op->readset_out->fd_count)
393  i = 0;
394  s = win32op->readset_out->fd_array[i];
395  if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
396  event_active(ent->read_event, EV_READ, 1);
397  }
398  }
399  if (win32op->exset_out->fd_count) {
400  i = rand() % win32op->exset_out->fd_count;
401  for (j=0; j<win32op->exset_out->fd_count; ++j) {
402  if (++i >= win32op->exset_out->fd_count)
403  i = 0;
404  s = win32op->exset_out->fd_array[i];
405  if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
406  event_active(ent->read_event, EV_READ, 1);
407  }
408  }
409  if (win32op->writeset_out->fd_count) {
410  i = rand() % win32op->writeset_out->fd_count;
411  for (j=0; j<win32op->writeset_out->fd_count; ++j) {
412  if (++i >= win32op->exset_out->fd_count)
413  i = 0;
414  s = win32op->writeset_out->fd_array[i];
415  if ((ent = get_event_entry(win32op, s, 0)) && ent->write_event)
416  event_active(ent->write_event, EV_WRITE, 1);
417 
418  }
419  }
420 
421  return (0);
422 }
423 
424 void
425 win32_dealloc(struct event_base *_base, void *arg)
426 {
427  struct win32op *win32op = arg;
428 
429  evsignal_dealloc(_base);
430  if (win32op->readset_in)
431  free(win32op->readset_in);
432  if (win32op->writeset_in)
433  free(win32op->writeset_in);
434  if (win32op->readset_out)
435  free(win32op->readset_out);
436  if (win32op->writeset_out)
437  free(win32op->writeset_out);
438  if (win32op->exset_out)
439  free(win32op->exset_out);
440  /* XXXXX free the tree. */
441 
442  memset(win32op, 0, sizeof(win32op));
443  free(win32op);
444 }
445 
446 #if 0
447 static void
448 signal_handler(int sig)
449 {
450  evsigcaught[sig]++;
451  signal_caught = 1;
452 }
453 
454 int
455 signal_recalc(void)
456 {
457  struct event *ev;
458 
459  /* Reinstall our signal handler. */
460  TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
461  if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
462  return (-1);
463  }
464  return (0);
465 }
466 
467 void
468 signal_process(void)
469 {
470  struct event *ev;
471  short ncalls;
472 
473  TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
474  ncalls = evsigcaught[EVENT_SIGNAL(ev)];
475  if (ncalls) {
476  if (!(ev->ev_events & EV_PERSIST))
477  event_del(ev);
478  event_active(ev, EV_SIGNAL, ncalls);
479  }
480  }
481 
482  memset(evsigcaught, 0, sizeof(evsigcaught));
483  signal_caught = 0;
484 }
485 #endif
486