~ubuntu-branches/ubuntu/precise/gnupg2/precise-proposed

« back to all changes in this revision

Viewing changes to jnlib/w32-pth.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* w32-pth.c - GNU Pth emulation for W32 (MS Windows).
 
2
 * Copyright (c) 1999-2003 Ralf S. Engelschall <rse@engelschall.com>
 
3
 * Copyright (C) 2004 g10 Code GmbH
 
4
 *
 
5
 * This file is part of GnuPG.
 
6
 *
 
7
 * GnuPG is free software; you can redistribute it and/or modify it
 
8
 * under the terms of the GNU Lesser General Public License as
 
9
 * published by the Free Software Foundation; either version 2.1 of
 
10
 * the License, or (at your option) any later version.
 
11
 *
 
12
 * GnuPG is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 
20
 *
 
21
 * ------------------------------------------------------------------
 
22
 * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive
 
23
 * thread scheduling library which can be found at
 
24
 * http://www.gnu.org/software/pth/.  MS Windows (W32) specific code
 
25
 * written by Timo Schulz, g10 Code.
 
26
 */
 
27
 
 
28
#include <config.h>
 
29
#ifdef HAVE_W32_SYSTEM
 
30
#include <windows.h>
 
31
#include <stdio.h>
 
32
#include <stdlib.h>
 
33
#include <io.h>
 
34
#include <signal.h>
 
35
 
 
36
#include "logging.h" /* For log_get_prefix () */
 
37
 
 
38
/* We don't want to have any Windows specific code in the header, thus
 
39
   we use a macro which defaults to a compatible type in w32-pth.h. */
 
40
#define W32_PTH_HANDLE_INTERNAL  HANDLE
 
41
#include "w32-pth.h"
 
42
 
 
43
 
 
44
#ifndef FALSE
 
45
#define FALSE 0
 
46
#endif
 
47
#ifndef TRUE
 
48
#define TRUE 1
 
49
#endif
 
50
#if FALSE != 0 || TRUE != 1 
 
51
#error TRUE or FALSE defined to wrong values
 
52
#endif
 
53
 
 
54
 
 
55
/* States whether this module has been initialized.  */
 
56
static int pth_initialized;
 
57
 
 
58
/* Keeps the current debug level. Define marcos to test them. */
 
59
static int debug_level;
 
60
#define DBG_ERROR  (debug_level >= 1)
 
61
#define DBG_INFO   (debug_level >= 2)
 
62
#define DBG_CALLS  (debug_level >= 3)
 
63
 
 
64
/* Variables to support event handling. */
 
65
static int pth_signo;
 
66
static HANDLE pth_signo_ev;
 
67
 
 
68
/* Mutex to make sure only one thread is running. */
 
69
static CRITICAL_SECTION pth_shd;
 
70
 
 
71
/* Events are store in a double linked event ring.  */
 
72
struct pth_event_s
 
73
{
 
74
  struct pth_event_s * next;
 
75
  struct pth_event_s * prev;
 
76
  HANDLE hd;
 
77
  union
 
78
  {
 
79
    struct sigset_s * sig;
 
80
    int               fd;
 
81
    struct timeval    tv;
 
82
    pth_mutex_t     * mx;
 
83
  } u;
 
84
  int * val;
 
85
  int u_type;
 
86
  int flags;
 
87
};
 
88
 
 
89
 
 
90
struct pth_attr_s 
 
91
{
 
92
  unsigned int flags;
 
93
  unsigned int stack_size;
 
94
  char * name;
 
95
};
 
96
 
 
97
 
 
98
/* Object to keep information about a thread.  This may eventually be
 
99
   used to implement a scheduler queue.  */
 
100
struct thread_info_s
 
101
{
 
102
  void *(*thread)(void *); /* The actual thread fucntion.  */
 
103
  void * arg;              /* The argument passed to that fucntion.  */
 
104
  int joinable;            /* True if this Thread is joinable.  */
 
105
  HANDLE th;               /* Handle of this thread.  Used by non-joinable
 
106
                              threads to close the handle.  */
 
107
};
 
108
 
 
109
 
 
110
/* Convenience macro to startup the system.  */
 
111
#define implicit_init() do { if (!pth_initialized) pth_init(); } while (0)
 
112
 
 
113
/* Prototypes.  */
 
114
static pth_event_t do_pth_event (unsigned long spec, ...);
 
115
static unsigned int do_pth_waitpid (unsigned pid, int * status, int options);
 
116
static int do_pth_wait (pth_event_t ev);
 
117
static int do_pth_event_status (pth_event_t ev);
 
118
static void *launch_thread (void * ctx);
 
119
 
 
120
 
 
121
 
 
122
 
 
123
int
 
124
pth_init (void)
 
125
{
 
126
  SECURITY_ATTRIBUTES sa;
 
127
  WSADATA wsadat;
 
128
  const char *s;
 
129
  
 
130
  if (pth_initialized)
 
131
    return TRUE;
 
132
 
 
133
  debug_level = (s=getenv ("DEBUG_PTH"))? atoi (s):0;
 
134
  if (debug_level)
 
135
    fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL));
 
136
 
 
137
  if (WSAStartup (0x202, &wsadat))
 
138
    return FALSE;
 
139
  pth_signo = 0;
 
140
  InitializeCriticalSection (&pth_shd);
 
141
  if (pth_signo_ev)
 
142
    CloseHandle (pth_signo_ev);
 
143
  memset (&sa, 0, sizeof sa);
 
144
  sa.bInheritHandle = TRUE;
 
145
  sa.lpSecurityDescriptor = NULL;
 
146
  sa.nLength = sizeof sa;
 
147
  pth_signo_ev = CreateEvent (&sa, TRUE, FALSE, NULL);
 
148
  if (!pth_signo_ev)
 
149
    return FALSE;
 
150
 
 
151
  pth_initialized = 1;
 
152
  EnterCriticalSection (&pth_shd);
 
153
  return TRUE;
 
154
}
 
155
 
 
156
 
 
157
int
 
158
pth_kill (void)
 
159
{
 
160
  pth_signo = 0;
 
161
  if (pth_signo_ev)
 
162
    {
 
163
      CloseHandle (pth_signo_ev);
 
164
      pth_signo_ev = NULL;
 
165
    }
 
166
  if (pth_initialized)
 
167
    DeleteCriticalSection (&pth_shd);
 
168
  WSACleanup ();
 
169
  pth_initialized = 0;
 
170
  return TRUE;
 
171
}
 
172
 
 
173
 
 
174
static char *
 
175
w32_strerror (char *strerr, size_t strerrsize)
 
176
{
 
177
  if (strerrsize > 1)
 
178
    FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (),
 
179
                   MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
 
180
                   strerr, strerrsize, NULL);
 
181
  return strerr;
 
182
}
 
183
 
 
184
 
 
185
static void
 
186
enter_pth (const char *function)
 
187
{
 
188
  /* Fixme: I am not sure whether the same thread my enter a critical
 
189
     section twice.  */
 
190
  if (DBG_CALLS)
 
191
    fprintf (stderr, "%s: enter_pth (%s)\n",
 
192
             log_get_prefix (NULL), function? function:"");
 
193
  LeaveCriticalSection (&pth_shd);
 
194
}
 
195
 
 
196
 
 
197
static void
 
198
leave_pth (const char *function)
 
199
{
 
200
  EnterCriticalSection (&pth_shd);
 
201
  if (DBG_CALLS)
 
202
    fprintf (stderr, "%s: leave_pth (%s)\n",
 
203
             log_get_prefix (NULL), function? function:"");
 
204
}
 
205
 
 
206
 
 
207
long 
 
208
pth_ctrl (unsigned long query, ...)
 
209
{
 
210
  implicit_init ();
 
211
 
 
212
  switch (query)
 
213
    {
 
214
    case PTH_CTRL_GETAVLOAD:
 
215
    case PTH_CTRL_GETPRIO:
 
216
    case PTH_CTRL_GETNAME:
 
217
    case PTH_CTRL_GETTHREADS_NEW:
 
218
    case PTH_CTRL_GETTHREADS_READY:
 
219
    case PTH_CTRL_GETTHREADS_RUNNING:
 
220
    case PTH_CTRL_GETTHREADS_WAITING:
 
221
    case PTH_CTRL_GETTHREADS_SUSPENDED:
 
222
    case PTH_CTRL_GETTHREADS_DEAD:
 
223
    case PTH_CTRL_GETTHREADS:
 
224
    default:
 
225
      return -1;
 
226
    }
 
227
  return 0;
 
228
}
 
229
 
 
230
 
 
231
 
 
232
pth_time_t
 
233
pth_timeout (long sec, long usec)
 
234
{
 
235
  pth_time_t tvd;
 
236
 
 
237
  tvd.tv_sec  = sec;
 
238
  tvd.tv_usec = usec;    
 
239
  return tvd;
 
240
}
 
241
 
 
242
 
 
243
int
 
244
pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev)
 
245
{
 
246
  implicit_init ();
 
247
  return 0;
 
248
}
 
249
 
 
250
 
 
251
int
 
252
pth_read (int fd,  void * buffer, size_t size)
 
253
{
 
254
  int n;
 
255
 
 
256
  implicit_init ();
 
257
  enter_pth (__FUNCTION__);
 
258
 
 
259
  n = recv (fd, buffer, size, 0);
 
260
  if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
 
261
    {
 
262
      DWORD nread = 0;
 
263
      n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL);
 
264
      if (!n)
 
265
        {
 
266
          char strerr[256];
 
267
 
 
268
          if (DBG_ERROR)
 
269
            fprintf (stderr, "%s: pth_read(%d) failed read from file: %s\n",
 
270
                     log_get_prefix (NULL), fd,
 
271
                     w32_strerror (strerr, sizeof strerr));
 
272
          n = -1;
 
273
        }
 
274
      else
 
275
        n = (int)nread;
 
276
    }
 
277
  leave_pth (__FUNCTION__);
 
278
  return n;
 
279
}
 
280
 
 
281
 
 
282
int
 
283
pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev)
 
284
{
 
285
  implicit_init ();
 
286
  return 0;
 
287
}
 
288
 
 
289
 
 
290
int
 
291
pth_write (int fd, const void * buffer, size_t size)
 
292
{
 
293
  int n;
 
294
 
 
295
  implicit_init ();
 
296
  enter_pth (__FUNCTION__);
 
297
  n = send (fd, buffer, size, 0);
 
298
  if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
 
299
    {
 
300
      DWORD nwrite;
 
301
      char strerr[256];
 
302
 
 
303
      /* This is no real error because we first need to figure out if
 
304
         we have a handle or a socket.  */
 
305
 
 
306
      n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL);
 
307
      if (!n)
 
308
        {
 
309
          if (DBG_ERROR)
 
310
            fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n",
 
311
                     log_get_prefix (NULL), fd,
 
312
                     w32_strerror (strerr, sizeof strerr));
 
313
          n = -1;
 
314
        }
 
315
      else
 
316
        n = (int)nwrite;
 
317
    }
 
318
  leave_pth (__FUNCTION__);
 
319
  return n;
 
320
}
 
321
 
 
322
 
 
323
int
 
324
pth_select (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds,
 
325
            const struct timeval * timeout)
 
326
{
 
327
  int n;
 
328
 
 
329
  implicit_init ();
 
330
  enter_pth (__FUNCTION__);
 
331
  n = select (nfds, rfds, wfds, efds, timeout);
 
332
  leave_pth (__FUNCTION__);
 
333
  return n;
 
334
}
 
335
 
 
336
 
 
337
int
 
338
pth_fdmode (int fd, int mode)
 
339
{
 
340
  unsigned long val;
 
341
  int ret = PTH_FDMODE_BLOCK;
 
342
 
 
343
  implicit_init ();
 
344
  /* Note: we don't do the eter/leave pth here because this is for one
 
345
     a fast fucntion and secondly already called from inside such a
 
346
     block.  */
 
347
  /* XXX: figure out original fd mode */
 
348
  switch (mode)
 
349
    {
 
350
    case PTH_FDMODE_NONBLOCK:
 
351
      val = 1;
 
352
      if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR)
 
353
        ret = PTH_FDMODE_ERROR;
 
354
      break;
 
355
 
 
356
    case PTH_FDMODE_BLOCK:
 
357
      val = 0;
 
358
      if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR)
 
359
        ret = PTH_FDMODE_ERROR;
 
360
      break;
 
361
    }
 
362
  return ret;
 
363
}
 
364
 
 
365
 
 
366
int
 
367
pth_accept (int fd, struct sockaddr *addr, int *addrlen)
 
368
{
 
369
  int rc;
 
370
 
 
371
  implicit_init ();
 
372
  enter_pth (__FUNCTION__);
 
373
  rc = accept (fd, addr, addrlen);
 
374
  leave_pth (__FUNCTION__);
 
375
  return rc;
 
376
}
 
377
 
 
378
 
 
379
int
 
380
pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen,
 
381
               pth_event_t ev_extra)
 
382
{
 
383
  pth_key_t ev_key;
 
384
  pth_event_t ev;
 
385
  int rv;
 
386
  int fdmode;
 
387
 
 
388
  implicit_init ();
 
389
  enter_pth (__FUNCTION__);
 
390
 
 
391
  fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK);
 
392
  if (fdmode == PTH_FDMODE_ERROR)
 
393
    {
 
394
      leave_pth (__FUNCTION__);
 
395
      return -1;
 
396
    }
 
397
 
 
398
  ev = NULL;
 
399
  while ((rv = accept (fd, addr, addrlen)) == -1 && 
 
400
         (WSAGetLastError () == WSAEINPROGRESS || 
 
401
          WSAGetLastError () == WSAEWOULDBLOCK))
 
402
    {
 
403
      if (!ev)
 
404
        {
 
405
          ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|
 
406
                             PTH_MODE_STATIC, &ev_key, fd);
 
407
          if (!ev)
 
408
            {
 
409
              leave_pth (__FUNCTION__);
 
410
              return -1;
 
411
            }
 
412
          if (ev_extra)
 
413
            pth_event_concat (ev, ev_extra, NULL);
 
414
        }
 
415
      /* Wait until accept has a chance. */
 
416
      do_pth_wait (ev);
 
417
      if (ev_extra)
 
418
        {
 
419
          pth_event_isolate (ev);
 
420
          if (do_pth_event_status (ev) != PTH_STATUS_OCCURRED)
 
421
            {
 
422
              pth_fdmode (fd, fdmode);
 
423
              leave_pth (__FUNCTION__);
 
424
              return -1;
 
425
            }
 
426
        }
 
427
    }
 
428
 
 
429
  pth_fdmode (fd, fdmode);
 
430
  leave_pth (__FUNCTION__);
 
431
  return rv;   
 
432
}
 
433
 
 
434
 
 
435
int
 
436
pth_connect (int fd, struct sockaddr *name, int namelen)
 
437
{
 
438
  int rc;
 
439
 
 
440
  implicit_init ();
 
441
  enter_pth (__FUNCTION__);
 
442
  rc = connect (fd, name, namelen);
 
443
  leave_pth (__FUNCTION__);
 
444
  return rc;
 
445
}
 
446
 
 
447
 
 
448
int
 
449
pth_mutex_release (pth_mutex_t *mutex)
 
450
{
 
451
  int rc;
 
452
 
 
453
  implicit_init ();
 
454
  enter_pth (__FUNCTION__);
 
455
 
 
456
  if (!ReleaseMutex (*mutex))
 
457
    {
 
458
      char strerr[256];
 
459
 
 
460
      if (DBG_ERROR)
 
461
        fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n",
 
462
                 log_get_prefix (NULL), *mutex,
 
463
                 w32_strerror (strerr, sizeof strerr));
 
464
      rc = FALSE;
 
465
    }
 
466
  else
 
467
    rc = TRUE;
 
468
 
 
469
  leave_pth (__FUNCTION__);
 
470
  return rc;
 
471
}
 
472
 
 
473
 
 
474
int
 
475
pth_mutex_acquire (pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra)
 
476
{
 
477
  int code;
 
478
  int rc;
 
479
 
 
480
  implicit_init ();
 
481
  enter_pth (__FUNCTION__);
 
482
 
 
483
  /* FIXME: ev_extra is not yet supported.  */
 
484
  
 
485
  code = WaitForSingleObject (*mutex, INFINITE);
 
486
  switch (code) 
 
487
    {
 
488
      case WAIT_FAILED:
 
489
        {
 
490
          char strerr[256];
 
491
          
 
492
          if (DBG_ERROR)
 
493
            fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n",
 
494
                     log_get_prefix (NULL), *mutex,
 
495
                     w32_strerror (strerr, sizeof strerr));
 
496
        }
 
497
        rc = FALSE;
 
498
        break;
 
499
        
 
500
      case WAIT_OBJECT_0:
 
501
        rc = TRUE;
 
502
        break;
 
503
 
 
504
      default:
 
505
        if (DBG_ERROR)
 
506
          fprintf (stderr, "%s: WaitForSingleObject returned unexpected "
 
507
                   "code %d for mutex %p\n",
 
508
                   log_get_prefix (NULL), code, *mutex);
 
509
        rc = FALSE;
 
510
        break;
 
511
    }
 
512
 
 
513
  leave_pth (__FUNCTION__);
 
514
  return rc;
 
515
}
 
516
 
 
517
 
 
518
 
 
519
int
 
520
pth_mutex_init (pth_mutex_t *mutex)
 
521
{
 
522
  SECURITY_ATTRIBUTES sa;
 
523
  
 
524
  implicit_init ();
 
525
  enter_pth (__FUNCTION__);
 
526
 
 
527
  memset (&sa, 0, sizeof sa);
 
528
  sa.bInheritHandle = TRUE;
 
529
  sa.lpSecurityDescriptor = NULL;
 
530
  sa.nLength = sizeof sa;
 
531
  *mutex = CreateMutex (&sa, FALSE, NULL);
 
532
  if (!*mutex)
 
533
   {
 
534
      free (*mutex);
 
535
      *mutex = NULL;
 
536
      leave_pth (__FUNCTION__);
 
537
      return FALSE;
 
538
    }
 
539
    
 
540
  leave_pth (__FUNCTION__);
 
541
  return TRUE;
 
542
}
 
543
 
 
544
 
 
545
pth_attr_t
 
546
pth_attr_new (void)
 
547
{
 
548
  pth_attr_t hd;
 
549
 
 
550
  implicit_init ();
 
551
  hd = calloc (1, sizeof *hd);
 
552
  return hd;
 
553
}
 
554
 
 
555
 
 
556
int
 
557
pth_attr_destroy (pth_attr_t hd)
 
558
{
 
559
  if (!hd)
 
560
    return -1;
 
561
  implicit_init ();
 
562
  if (hd->name)
 
563
    free (hd->name);
 
564
  free (hd);
 
565
  return TRUE;
 
566
}
 
567
 
 
568
 
 
569
int
 
570
pth_attr_set (pth_attr_t hd, int field, ...)
 
571
{    
 
572
  va_list args;
 
573
  char * str;
 
574
  int val;
 
575
  int rc = TRUE;
 
576
 
 
577
  implicit_init ();
 
578
 
 
579
  va_start (args, field);
 
580
  switch (field)
 
581
    {
 
582
    case PTH_ATTR_JOINABLE:
 
583
      val = va_arg (args, int);
 
584
      if (val)
 
585
        {
 
586
          hd->flags |= PTH_ATTR_JOINABLE;
 
587
          if (DBG_INFO)
 
588
            fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n",
 
589
                     log_get_prefix (NULL));
 
590
        }
 
591
      break;
 
592
 
 
593
    case PTH_ATTR_STACK_SIZE:
 
594
      val = va_arg (args, int);
 
595
      if (val)
 
596
        {
 
597
          hd->flags |= PTH_ATTR_STACK_SIZE;
 
598
          hd->stack_size = val;
 
599
          if (DBG_INFO)
 
600
            fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n",
 
601
                     log_get_prefix (NULL), val);
 
602
        }
 
603
      break;
 
604
 
 
605
    case PTH_ATTR_NAME:
 
606
      str = va_arg (args, char*);
 
607
      if (hd->name)
 
608
        free (hd->name);
 
609
      if (str)
 
610
        {
 
611
          hd->name = strdup (str);
 
612
          if (!hd->name)
 
613
            return FALSE;
 
614
          hd->flags |= PTH_ATTR_NAME;
 
615
          if (DBG_INFO)
 
616
            fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n",
 
617
                     log_get_prefix (NULL), hd->name);
 
618
        }
 
619
      break;
 
620
 
 
621
    default:
 
622
      rc = FALSE;
 
623
      break;
 
624
    }
 
625
  va_end (args);
 
626
  return rc;
 
627
}
 
628
 
 
629
 
 
630
static pth_t
 
631
do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg)
 
632
{
 
633
  SECURITY_ATTRIBUTES sa;
 
634
  DWORD tid;
 
635
  HANDLE th;
 
636
  struct thread_info_s *ctx;
 
637
 
 
638
  if (!hd)
 
639
    return NULL;
 
640
 
 
641
  memset (&sa, 0, sizeof sa);
 
642
  sa.bInheritHandle = TRUE;
 
643
  sa.lpSecurityDescriptor = NULL;
 
644
  sa.nLength = sizeof sa;
 
645
 
 
646
  ctx = calloc (1, sizeof *ctx);
 
647
  if (!ctx)
 
648
    return NULL;
 
649
  ctx->thread = func;
 
650
  ctx->arg = arg;
 
651
  ctx->joinable = (hd->flags & PTH_ATTR_JOINABLE);
 
652
 
 
653
  /* XXX: we don't use all thread attributes. */
 
654
 
 
655
  /* Note that we create the thread suspended so that we are able to
 
656
     store the thread's handle in the context structure.  We need to
 
657
     do this to be able to close the handle from the launch helper. 
 
658
 
 
659
     FIXME: We should no use th W32's Thread handle directly but keep
 
660
     our own thread control structure.  CTX may be used for that.  */
 
661
  if (DBG_INFO)
 
662
    fprintf (stderr, "%s: do_pth_spawn creating thread ...\n",
 
663
             log_get_prefix (NULL));
 
664
  th = CreateThread (&sa, hd->stack_size,
 
665
                     (LPTHREAD_START_ROUTINE)launch_thread,
 
666
                     ctx, CREATE_SUSPENDED, &tid);
 
667
  ctx->th = th;
 
668
  if (DBG_INFO)
 
669
    fprintf (stderr, "%s: do_pth_spawn created thread %p\n",
 
670
             log_get_prefix (NULL),th);
 
671
  if (!th)
 
672
    free (ctx);
 
673
  else
 
674
    ResumeThread (th);
 
675
  
 
676
  return th;
 
677
}
 
678
 
 
679
pth_t
 
680
pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg)
 
681
{
 
682
  HANDLE th;
 
683
 
 
684
  if (!hd)
 
685
    return NULL;
 
686
 
 
687
  implicit_init ();
 
688
  enter_pth (__FUNCTION__);
 
689
  th = do_pth_spawn (hd, func, arg);
 
690
  leave_pth (__FUNCTION__);
 
691
  return th;
 
692
}
 
693
 
 
694
 
 
695
pth_t 
 
696
pth_self (void)
 
697
{
 
698
  return GetCurrentThread ();
 
699
}
 
700
 
 
701
int
 
702
pth_join (pth_t hd, void **value)
 
703
{
 
704
  return TRUE;
 
705
}
 
706
 
 
707
 
 
708
/* friendly */
 
709
int
 
710
pth_cancel (pth_t hd)
 
711
{
 
712
  if (!hd)
 
713
    return -1;
 
714
  implicit_init ();
 
715
  enter_pth (__FUNCTION__);
 
716
  WaitForSingleObject (hd, 1000);
 
717
  TerminateThread (hd, 0);
 
718
  leave_pth (__FUNCTION__);
 
719
  return TRUE;
 
720
}
 
721
 
 
722
 
 
723
/* cruel */
 
724
int
 
725
pth_abort (pth_t hd)
 
726
{
 
727
  if (!hd)
 
728
    return -1;
 
729
  implicit_init ();
 
730
  enter_pth (__FUNCTION__);
 
731
  TerminateThread (hd, 0);
 
732
  leave_pth (__FUNCTION__);
 
733
  return TRUE;
 
734
}
 
735
 
 
736
 
 
737
void
 
738
pth_exit (void *value)
 
739
{
 
740
  implicit_init ();
 
741
  enter_pth (__FUNCTION__);
 
742
  pth_kill ();
 
743
  leave_pth (__FUNCTION__);
 
744
  exit ((int)(long)value);
 
745
}
 
746
 
 
747
 
 
748
static unsigned int
 
749
do_pth_waitpid (unsigned pid, int * status, int options)
 
750
{
 
751
#if 0
 
752
  pth_event_t ev;
 
753
  static pth_key_t ev_key = PTH_KEY_INIT;
 
754
  pid_t pid;
 
755
 
 
756
  pth_debug2("pth_waitpid: called from thread \"%s\"", pth_current->name);
 
757
 
 
758
  for (;;)
 
759
    {
 
760
      /* do a non-blocking poll for the pid */
 
761
      while (   (pid = pth_sc(waitpid)(wpid, status, options|WNOHANG)) < 0
 
762
                && errno == EINTR)
 
763
        ;
 
764
 
 
765
      /* if pid was found or caller requested a polling return immediately */
 
766
      if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG)))
 
767
        break;
 
768
 
 
769
      /* else wait a little bit */
 
770
      ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key,
 
771
                     pth_timeout (0,250000));
 
772
      pth_wait(ev);
 
773
    }
 
774
 
 
775
  pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name);
 
776
#endif
 
777
  return 0;
 
778
}
 
779
 
 
780
 
 
781
unsigned int
 
782
pth_waitpid (unsigned pid, int * status, int options)
 
783
{
 
784
  unsigned int n;
 
785
 
 
786
  implicit_init ();
 
787
  enter_pth (__FUNCTION__);
 
788
  n = do_pth_waitpid (pid, status, options);
 
789
  leave_pth (__FUNCTION__);
 
790
  return n;
 
791
}
 
792
 
 
793
 
 
794
static BOOL WINAPI
 
795
sig_handler (DWORD signo)
 
796
{
 
797
  switch (signo)
 
798
    {
 
799
    case CTRL_C_EVENT:     pth_signo = SIGINT; break;
 
800
    case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break;
 
801
    }
 
802
  SetEvent (pth_signo_ev);
 
803
  if (DBG_INFO)
 
804
    fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo);
 
805
  return TRUE;
 
806
}
 
807
 
 
808
 
 
809
static pth_event_t
 
810
do_pth_event_body (unsigned long spec, va_list arg)
 
811
{
 
812
  SECURITY_ATTRIBUTES sa;
 
813
  pth_event_t ev;
 
814
  int rc;
 
815
 
 
816
  if (DBG_INFO)
 
817
    fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec);
 
818
  ev = calloc (1, sizeof *ev);
 
819
  if (!ev)
 
820
    return NULL;
 
821
  if (spec == 0)
 
822
    ;
 
823
  else if (spec & PTH_EVENT_SIGS)
 
824
    {
 
825
      ev->u.sig = va_arg (arg, struct sigset_s *);
 
826
      ev->u_type = PTH_EVENT_SIGS;
 
827
      ev->val = va_arg (arg, int *);    
 
828
      rc = SetConsoleCtrlHandler (sig_handler, TRUE);
 
829
      if (DBG_INFO)
 
830
        fprintf (stderr, "%s: pth_event: sigs rc=%d\n",
 
831
                 log_get_prefix (NULL), rc);
 
832
    }
 
833
  else if (spec & PTH_EVENT_FD)
 
834
    {
 
835
      if (spec & PTH_UNTIL_FD_READABLE)
 
836
        ev->flags |= PTH_UNTIL_FD_READABLE;
 
837
      if (spec & PTH_MODE_STATIC)
 
838
        ev->flags |= PTH_MODE_STATIC;
 
839
      ev->u_type = PTH_EVENT_FD;
 
840
      va_arg (arg, pth_key_t);
 
841
      ev->u.fd = va_arg (arg, int);
 
842
      if (DBG_INFO)
 
843
        fprintf (stderr, "%s: pth_event: fd=%d\n",
 
844
                 log_get_prefix (NULL), ev->u.fd);
 
845
    }
 
846
  else if (spec & PTH_EVENT_TIME)
 
847
    {
 
848
      pth_time_t t;
 
849
      if (spec & PTH_MODE_STATIC)
 
850
        ev->flags |= PTH_MODE_STATIC;
 
851
      va_arg (arg, pth_key_t);
 
852
      t = va_arg (arg, pth_time_t);
 
853
      ev->u_type = PTH_EVENT_TIME;
 
854
      ev->u.tv.tv_sec =  t.tv_sec;
 
855
      ev->u.tv.tv_usec = t.tv_usec;
 
856
    }
 
857
  else if (spec & PTH_EVENT_MUTEX)
 
858
    {
 
859
      va_arg (arg, pth_key_t);
 
860
      ev->u_type = PTH_EVENT_MUTEX;
 
861
      ev->u.mx = va_arg (arg, pth_mutex_t*);
 
862
    }
 
863
    
 
864
  memset (&sa, 0, sizeof sa);
 
865
  sa.bInheritHandle = TRUE;
 
866
  sa.lpSecurityDescriptor = NULL;
 
867
  sa.nLength = sizeof sa;
 
868
  ev->hd = CreateEvent (&sa, FALSE, FALSE, NULL);
 
869
  if (!ev->hd)
 
870
    {
 
871
      free (ev);
 
872
      return NULL;
 
873
    }
 
874
  ev->next = ev;
 
875
  ev->prev = ev;
 
876
 
 
877
  return ev;
 
878
}
 
879
 
 
880
static pth_event_t
 
881
do_pth_event (unsigned long spec, ...)
 
882
{
 
883
  va_list arg;
 
884
  pth_event_t ev;
 
885
 
 
886
  va_start (arg, spec);
 
887
  ev = do_pth_event_body (spec, arg);
 
888
  va_end (arg);
 
889
    
 
890
  return ev;
 
891
}
 
892
 
 
893
pth_event_t
 
894
pth_event (unsigned long spec, ...)
 
895
{
 
896
  va_list arg;
 
897
  pth_event_t ev;
 
898
 
 
899
  implicit_init ();
 
900
  enter_pth (__FUNCTION__);
 
901
  
 
902
  va_start (arg, spec);
 
903
  ev = do_pth_event_body (spec, arg);
 
904
  va_end (arg);
 
905
    
 
906
  leave_pth (__FUNCTION__);
 
907
  return ev;
 
908
}
 
909
 
 
910
 
 
911
static void
 
912
pth_event_add (pth_event_t root, pth_event_t node)
 
913
{
 
914
  pth_event_t n;
 
915
 
 
916
  for (n=root; n->next; n = n->next)
 
917
    ;
 
918
  n->next = node;
 
919
}
 
920
 
 
921
 
 
922
pth_event_t
 
923
pth_event_concat (pth_event_t evf, ...)
 
924
{
 
925
  pth_event_t evn;
 
926
  va_list ap;
 
927
 
 
928
  if (!evf)
 
929
    return NULL;
 
930
 
 
931
  implicit_init ();
 
932
 
 
933
  va_start (ap, evf);
 
934
  while ((evn = va_arg(ap, pth_event_t)) != NULL)
 
935
    pth_event_add (evf, evn);
 
936
  va_end (ap);
 
937
 
 
938
  return evf;
 
939
}
 
940
 
 
941
 
 
942
static int
 
943
wait_for_fd (int fd, int is_read, int nwait)
 
944
{
 
945
  struct timeval tv;
 
946
  fd_set r;
 
947
  fd_set w;
 
948
  int n;
 
949
 
 
950
  FD_ZERO (&r);
 
951
  FD_ZERO (&w);    
 
952
  FD_SET (fd, is_read ? &r : &w);
 
953
 
 
954
  tv.tv_sec = nwait;
 
955
  tv.tv_usec = 0;
 
956
 
 
957
  while (1)
 
958
    {
 
959
      n = select (fd+1, &r, &w, NULL, &tv);
 
960
      if (DBG_INFO)
 
961
        fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n",
 
962
                 log_get_prefix (NULL), n, fd,(int)WSAGetLastError ());
 
963
      if (n == -1)
 
964
        break;
 
965
      if (!n)
 
966
        continue;
 
967
      if (n == 1)
 
968
        {
 
969
          if (is_read && FD_ISSET (fd, &r))
 
970
            break;
 
971
          else if (FD_ISSET (fd, &w))
 
972
            break;
 
973
        }
 
974
    }
 
975
  return 0;
 
976
}
 
977
 
 
978
 
 
979
static void *
 
980
launch_thread (void *arg)
 
981
{
 
982
  struct thread_info_s *c = arg;
 
983
 
 
984
  if (c)
 
985
    {
 
986
      leave_pth (__FUNCTION__);
 
987
      c->thread (c->arg);
 
988
      if (!c->joinable && c->th)
 
989
        {
 
990
          CloseHandle (c->th);
 
991
          c->th = NULL;
 
992
        }
 
993
      /* FIXME: We would badly fail if someone accesses the now
 
994
         deallocated handle. Don't use it directly but setup proper
 
995
         scheduling queues.  */
 
996
      enter_pth (__FUNCTION__);
 
997
      free (c);
 
998
    }
 
999
  ExitThread (0);
 
1000
  return NULL;
 
1001
}
 
1002
 
 
1003
/* void */
 
1004
/* sigemptyset (struct sigset_s * ss) */
 
1005
/* { */
 
1006
/*     if (ss) { */
 
1007
/*      memset (ss->sigs, 0, sizeof ss->sigs); */
 
1008
/*      ss->idx = 0; */
 
1009
/*     } */
 
1010
/* } */
 
1011
 
 
1012
 
 
1013
/* int */
 
1014
/* sigaddset (struct sigset_s * ss, int signo) */
 
1015
/* { */
 
1016
/*     if (!ss) */
 
1017
/*      return -1; */
 
1018
/*     if (ss->idx + 1 > 64) */
 
1019
/*      return -1; */
 
1020
/*     ss->sigs[ss->idx] = signo; */
 
1021
/*     ss->idx++; */
 
1022
/*     return 0; */
 
1023
/* }  */
 
1024
 
 
1025
 
 
1026
static int
 
1027
sigpresent (struct sigset_s * ss, int signo)
 
1028
{
 
1029
/*     int i; */
 
1030
/*     for (i=0; i < ss->idx; i++) { */
 
1031
/*      if (ss->sigs[i] == signo) */
 
1032
/*          return 1; */
 
1033
/*     } */
 
1034
/* FIXME: See how to implement it.  */
 
1035
    return 0;
 
1036
}
 
1037
 
 
1038
 
 
1039
static int
 
1040
do_pth_event_occurred (pth_event_t ev)
 
1041
{
 
1042
  int ret;
 
1043
 
 
1044
  if (!ev)
 
1045
    return 0;
 
1046
 
 
1047
  ret = 0;
 
1048
  switch (ev->u_type)
 
1049
    {
 
1050
    case 0:
 
1051
      if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
 
1052
        ret = 1;
 
1053
      break;
 
1054
 
 
1055
    case PTH_EVENT_SIGS:
 
1056
      if (sigpresent (ev->u.sig, pth_signo) &&
 
1057
          WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0)
 
1058
        {
 
1059
          if (DBG_INFO)
 
1060
            fprintf (stderr, "%s: pth_event_occurred: sig signaled.\n",
 
1061
                     log_get_prefix (NULL));
 
1062
          (*ev->val) = pth_signo;
 
1063
          ret = 1;
 
1064
        }
 
1065
      break;
 
1066
 
 
1067
    case PTH_EVENT_FD:
 
1068
      if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
 
1069
        ret = 1;
 
1070
      break;
 
1071
    }
 
1072
 
 
1073
  return ret;
 
1074
}
 
1075
 
 
1076
 
 
1077
int
 
1078
pth_event_occurred (pth_event_t ev)
 
1079
{
 
1080
  int ret;
 
1081
 
 
1082
  implicit_init ();
 
1083
  enter_pth (__FUNCTION__);
 
1084
  ret = do_pth_event_occurred (ev);
 
1085
  leave_pth (__FUNCTION__);
 
1086
  return ret;
 
1087
}
 
1088
 
 
1089
 
 
1090
static int
 
1091
do_pth_event_status (pth_event_t ev)
 
1092
{
 
1093
  if (!ev)
 
1094
    return 0;
 
1095
  if (do_pth_event_occurred (ev))
 
1096
    return PTH_STATUS_OCCURRED;
 
1097
  return 0;
 
1098
}
 
1099
 
 
1100
int
 
1101
pth_event_status (pth_event_t ev)
 
1102
{
 
1103
  if (!ev)
 
1104
    return 0;
 
1105
  if (pth_event_occurred (ev))
 
1106
    return PTH_STATUS_OCCURRED;
 
1107
  return 0;
 
1108
}
 
1109
 
 
1110
 
 
1111
static int
 
1112
do_pth_event_free (pth_event_t ev, int mode)
 
1113
{
 
1114
  if (!ev)
 
1115
    return FALSE;
 
1116
 
 
1117
  if (mode == PTH_FREE_ALL)
 
1118
    {
 
1119
      pth_event_t cur = ev;
 
1120
      do
 
1121
        {
 
1122
          pth_event_t next = cur->next;
 
1123
          CloseHandle (cur->hd);
 
1124
          cur->hd = NULL;
 
1125
          free (cur);
 
1126
          cur = next;
 
1127
        }
 
1128
      while (cur != ev);
 
1129
    }
 
1130
  else if (mode == PTH_FREE_THIS)
 
1131
    {
 
1132
      ev->prev->next = ev->next;
 
1133
      ev->next->prev = ev->prev;
 
1134
      CloseHandle (ev->hd);
 
1135
      ev->hd = NULL;        
 
1136
      free (ev);
 
1137
    }
 
1138
  else
 
1139
    return FALSE;
 
1140
 
 
1141
  return TRUE;
 
1142
}
 
1143
 
 
1144
int
 
1145
pth_event_free (pth_event_t ev, int mode)
 
1146
{
 
1147
  int rc;
 
1148
 
 
1149
  implicit_init ();
 
1150
  enter_pth (__FUNCTION__);
 
1151
  rc = do_pth_event_free (ev, mode);
 
1152
  leave_pth (__FUNCTION__);
 
1153
  return rc;
 
1154
}
 
1155
 
 
1156
 
 
1157
pth_event_t
 
1158
pth_event_isolate (pth_event_t ev)
 
1159
{
 
1160
  pth_event_t ring;
 
1161
 
 
1162
  if (!ev)
 
1163
    return NULL;
 
1164
  if (ev->next == ev && ev->prev == ev)
 
1165
    return NULL; /* Only one event.  */
 
1166
 
 
1167
  ring = ev->next;
 
1168
  ev->prev->next = ev->next;
 
1169
  ev->next->prev = ev->prev;
 
1170
  ev->prev = ev;
 
1171
  ev->next = ev;
 
1172
  return ring;    
 
1173
}
 
1174
 
 
1175
 
 
1176
static int
 
1177
event_count (pth_event_t ev)
 
1178
{
 
1179
  pth_event_t r;
 
1180
  int cnt = 0;
 
1181
 
 
1182
  if (ev)
 
1183
    {
 
1184
      r = ev;
 
1185
      do
 
1186
        {
 
1187
          cnt++;
 
1188
          r = r->next;
 
1189
        }
 
1190
      while (r != ev);
 
1191
    }
 
1192
 
 
1193
  return cnt;
 
1194
}
 
1195
 
 
1196
 
 
1197
 
 
1198
static pth_t
 
1199
spawn_helper_thread (void *(*func)(void *), void *arg)
 
1200
{
 
1201
  SECURITY_ATTRIBUTES sa;
 
1202
  DWORD tid;
 
1203
  HANDLE th;
 
1204
 
 
1205
  memset (&sa, 0, sizeof sa);
 
1206
  sa.bInheritHandle = TRUE;
 
1207
  sa.lpSecurityDescriptor = NULL;
 
1208
  sa.nLength = sizeof sa;
 
1209
 
 
1210
  if (DBG_INFO)
 
1211
    fprintf (stderr, "%s: spawn_helper_thread creating thread ...\n",
 
1212
             log_get_prefix (NULL));
 
1213
  th = CreateThread (&sa, 32*1024,
 
1214
                     (LPTHREAD_START_ROUTINE)func,
 
1215
                     arg, 0, &tid);
 
1216
  if (DBG_INFO)
 
1217
    fprintf (stderr, "%s: spawn_helper_thread created thread %p\n",
 
1218
             log_get_prefix (NULL), th);
 
1219
 
 
1220
  return th;
 
1221
}
 
1222
 
 
1223
 
 
1224
static void 
 
1225
free_helper_threads (HANDLE *waitbuf, int *hdidx, int n)
 
1226
{
 
1227
  int i;
 
1228
 
 
1229
  for (i=0; i < n; i++)
 
1230
    {
 
1231
      CloseHandle (waitbuf[hdidx[i]]);
 
1232
      waitbuf[hdidx[i]] = NULL;
 
1233
    }
 
1234
}
 
1235
 
 
1236
 
 
1237
static void *
 
1238
wait_fd_thread (void * ctx)
 
1239
{
 
1240
  pth_event_t ev = ctx;
 
1241
 
 
1242
  wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600);
 
1243
  if (DBG_INFO)
 
1244
    fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL));
 
1245
  SetEvent (ev->hd);
 
1246
  ExitThread (0);
 
1247
  return NULL;
 
1248
}
 
1249
 
 
1250
 
 
1251
static void *
 
1252
wait_timer_thread (void * ctx)
 
1253
{
 
1254
  pth_event_t ev = ctx;
 
1255
  int n = ev->u.tv.tv_sec*1000;
 
1256
  Sleep (n);
 
1257
  SetEvent (ev->hd);
 
1258
  if (DBG_INFO)
 
1259
    fprintf (stderr, "%s: wait_timer_thread: exit.\n", log_get_prefix (NULL));
 
1260
  ExitThread (0);
 
1261
  return NULL;
 
1262
}
 
1263
 
 
1264
 
 
1265
static int
 
1266
do_pth_wait (pth_event_t ev)
 
1267
{
 
1268
  HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2];
 
1269
  int    hdidx[MAXIMUM_WAIT_OBJECTS/2];
 
1270
  DWORD n = 0;
 
1271
  int pos=0, i=0;
 
1272
 
 
1273
  if (!ev)
 
1274
    return 0;
 
1275
 
 
1276
  n = event_count (ev);
 
1277
  if (n > MAXIMUM_WAIT_OBJECTS/2)
 
1278
    return -1;
 
1279
 
 
1280
  if (DBG_INFO)
 
1281
    fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n);
 
1282
  if (ev)
 
1283
    {
 
1284
      pth_event_t r = ev;
 
1285
      do
 
1286
        {
 
1287
          switch (r->u_type)
 
1288
            {
 
1289
            case 0:
 
1290
              waitbuf[pos++] = r->hd;
 
1291
              break;
 
1292
              
 
1293
            case PTH_EVENT_SIGS:
 
1294
              waitbuf[pos++] = pth_signo_ev;
 
1295
              if (DBG_INFO)
 
1296
                fprintf (stderr, "pth_wait: add signal event.\n");
 
1297
              break;
 
1298
              
 
1299
            case PTH_EVENT_FD:
 
1300
              if (DBG_INFO)
 
1301
                fprintf (stderr, "pth_wait: spawn event wait thread.\n");
 
1302
              hdidx[i++] = pos;
 
1303
              waitbuf[pos++] = spawn_helper_thread (wait_fd_thread, r);
 
1304
              break;
 
1305
              
 
1306
            case PTH_EVENT_TIME:
 
1307
              if (DBG_INFO)
 
1308
                fprintf (stderr, "pth_wait: spawn event timer thread.\n");
 
1309
              hdidx[i++] = pos;
 
1310
              waitbuf[pos++] = spawn_helper_thread (wait_timer_thread, r);
 
1311
              break;
 
1312
          
 
1313
            case PTH_EVENT_MUTEX:
 
1314
              if (DBG_INFO)
 
1315
                fprintf (stderr, "pth_wait: ignoring mutex event.\n");
 
1316
              break;
 
1317
            }
 
1318
        }
 
1319
      while ( r != ev );
 
1320
    }
 
1321
  if (DBG_INFO)
 
1322
    fprintf (stderr, "%s: pth_wait: set %d\n", log_get_prefix (NULL), pos);
 
1323
  n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE);
 
1324
  free_helper_threads (waitbuf, hdidx, i);
 
1325
  if (DBG_INFO)
 
1326
    fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n);
 
1327
 
 
1328
  if (n != WAIT_TIMEOUT)
 
1329
    return 1;
 
1330
    
 
1331
  return 0;
 
1332
}
 
1333
 
 
1334
int
 
1335
pth_wait (pth_event_t ev)
 
1336
{
 
1337
  int rc;
 
1338
 
 
1339
  implicit_init ();
 
1340
  enter_pth (__FUNCTION__);
 
1341
  rc = do_pth_wait (ev);
 
1342
  leave_pth (__FUNCTION__);
 
1343
  return rc;
 
1344
}
 
1345
 
 
1346
 
 
1347
int
 
1348
pth_sleep (int sec)
 
1349
{
 
1350
  static pth_key_t ev_key = PTH_KEY_INIT;
 
1351
  pth_event_t ev;
 
1352
 
 
1353
  implicit_init ();
 
1354
  enter_pth (__FUNCTION__);
 
1355
 
 
1356
  if (sec == 0)
 
1357
    {
 
1358
      leave_pth (__FUNCTION__);
 
1359
      return 0;
 
1360
    }
 
1361
 
 
1362
  ev = do_pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key,
 
1363
                     pth_timeout (sec, 0));
 
1364
  if (ev == NULL)
 
1365
    {
 
1366
      leave_pth (__FUNCTION__);
 
1367
      return -1;
 
1368
    }
 
1369
  do_pth_wait (ev);
 
1370
  do_pth_event_free (ev, PTH_FREE_ALL);
 
1371
 
 
1372
  leave_pth (__FUNCTION__);
 
1373
  return 0;
 
1374
}
 
1375
 
 
1376
 
 
1377
 
 
1378
 
 
1379
 
 
1380
/* 
 
1381
   Some simple tests.  
 
1382
 */
 
1383
#ifdef TEST
 
1384
#include <stdio.h>
 
1385
 
 
1386
void * thread (void * c)
 
1387
{
 
1388
 
 
1389
  Sleep (2000);
 
1390
  SetEvent (((pth_event_t)c)->hd);
 
1391
  fprintf (stderr, "\n\nhallo!.\n");
 
1392
  pth_exit (NULL);
 
1393
  return NULL;
 
1394
}
 
1395
 
 
1396
 
 
1397
int main_1 (int argc, char ** argv)
 
1398
{
 
1399
  pth_attr_t t;
 
1400
  pth_t hd;
 
1401
  pth_event_t ev;
 
1402
 
 
1403
  pth_init ();
 
1404
  ev = pth_event (0, NULL);
 
1405
  t = pth_attr_new ();
 
1406
  pth_attr_set (t, PTH_ATTR_JOINABLE, 1);
 
1407
  pth_attr_set (t, PTH_ATTR_STACK_SIZE, 4096);
 
1408
  pth_attr_set (t, PTH_ATTR_NAME, "hello");
 
1409
  hd = pth_spawn (t, thread, ev);
 
1410
 
 
1411
  pth_wait (ev);
 
1412
  pth_attr_destroy (t);
 
1413
  pth_event_free (ev, 0);
 
1414
  pth_kill ();
 
1415
 
 
1416
  return 0;
 
1417
}
 
1418
 
 
1419
 
 
1420
static pth_event_t 
 
1421
setup_signals (struct sigset_s *sigs, int *signo)
 
1422
{
 
1423
  pth_event_t ev;
 
1424
 
 
1425
  sigemptyset (sigs);
 
1426
  sigaddset (sigs, SIGINT);
 
1427
  sigaddset (sigs, SIGTERM);
 
1428
 
 
1429
  ev = pth_event (PTH_EVENT_SIGS, sigs, signo);
 
1430
  return ev;
 
1431
}
 
1432
 
 
1433
int
 
1434
main_2 (int argc, char ** argv)
 
1435
{
 
1436
  pth_event_t ev;
 
1437
  struct sigset_s sigs;
 
1438
  int signo = 0;
 
1439
 
 
1440
  pth_init ();
 
1441
  ev = setup_signals (&sigs, &signo);
 
1442
  pth_wait (ev);
 
1443
  if (pth_event_occured (ev) && signo)
 
1444
    fprintf (stderr, "signal caught! signo %d\n", signo);
 
1445
 
 
1446
  pth_event_free (ev, PTH_FREE_ALL);
 
1447
  pth_kill ();
 
1448
  return 0;
 
1449
}
 
1450
 
 
1451
int
 
1452
main_3 (int argc, char ** argv)
 
1453
{
 
1454
  struct sockaddr_in addr, rem;
 
1455
  int fd, n = 0, infd;
 
1456
  int signo = 0;
 
1457
  struct sigset_s sigs;
 
1458
  pth_event_t ev;
 
1459
 
 
1460
  pth_init ();
 
1461
  fd = socket (AF_INET, SOCK_STREAM, 0);
 
1462
 
 
1463
  memset (&addr, 0, sizeof addr);
 
1464
  addr.sin_addr.s_addr = INADDR_ANY;
 
1465
  addr.sin_port = htons (5050);
 
1466
  addr.sin_family = AF_INET;
 
1467
  bind (fd, (struct sockaddr*)&addr, sizeof addr);
 
1468
  listen (fd, 5);
 
1469
 
 
1470
  ev = setup_signals (&sigs, &signo);
 
1471
  n = sizeof addr;
 
1472
  infd = pth_accept_ev (fd, (struct sockaddr *)&rem, &n, ev);
 
1473
  fprintf (stderr, "infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr),
 
1474
          htons (rem.sin_port));
 
1475
 
 
1476
  closesocket (infd);
 
1477
  pth_event_free (ev, PTH_FREE_ALL);
 
1478
  pth_kill ();
 
1479
  return 0;
 
1480
}
 
1481
 
 
1482
int
 
1483
main (int argc, char ** argv)
 
1484
{
 
1485
  pth_event_t ev;
 
1486
  pth_key_t ev_key;
 
1487
 
 
1488
  pth_init ();
 
1489
  /*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0));
 
1490
    pth_wait (ev);
 
1491
    pth_event_free (ev, PTH_FREE_ALL);*/
 
1492
  pth_sleep (5);
 
1493
  pth_kill ();
 
1494
  return 0;
 
1495
}
 
1496
#endif
 
1497
 
 
1498
#endif /*HAVE_W32_SYSTEM*/
 
1499