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
5
* This file is part of GnuPG.
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.
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.
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
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.
29
#ifdef HAVE_W32_SYSTEM
36
#include "logging.h" /* For log_get_prefix () */
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
50
#if FALSE != 0 || TRUE != 1
51
#error TRUE or FALSE defined to wrong values
55
/* States whether this module has been initialized. */
56
static int pth_initialized;
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)
64
/* Variables to support event handling. */
66
static HANDLE pth_signo_ev;
68
/* Mutex to make sure only one thread is running. */
69
static CRITICAL_SECTION pth_shd;
71
/* Events are store in a double linked event ring. */
74
struct pth_event_s * next;
75
struct pth_event_s * prev;
79
struct sigset_s * sig;
93
unsigned int stack_size;
98
/* Object to keep information about a thread. This may eventually be
99
used to implement a scheduler queue. */
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. */
110
/* Convenience macro to startup the system. */
111
#define implicit_init() do { if (!pth_initialized) pth_init(); } while (0)
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);
126
SECURITY_ATTRIBUTES sa;
133
debug_level = (s=getenv ("DEBUG_PTH"))? atoi (s):0;
135
fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL));
137
if (WSAStartup (0x202, &wsadat))
140
InitializeCriticalSection (&pth_shd);
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);
152
EnterCriticalSection (&pth_shd);
163
CloseHandle (pth_signo_ev);
167
DeleteCriticalSection (&pth_shd);
175
w32_strerror (char *strerr, size_t strerrsize)
178
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (),
179
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
180
strerr, strerrsize, NULL);
186
enter_pth (const char *function)
188
/* Fixme: I am not sure whether the same thread my enter a critical
191
fprintf (stderr, "%s: enter_pth (%s)\n",
192
log_get_prefix (NULL), function? function:"");
193
LeaveCriticalSection (&pth_shd);
198
leave_pth (const char *function)
200
EnterCriticalSection (&pth_shd);
202
fprintf (stderr, "%s: leave_pth (%s)\n",
203
log_get_prefix (NULL), function? function:"");
208
pth_ctrl (unsigned long query, ...)
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:
233
pth_timeout (long sec, long usec)
244
pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev)
252
pth_read (int fd, void * buffer, size_t size)
257
enter_pth (__FUNCTION__);
259
n = recv (fd, buffer, size, 0);
260
if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
263
n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL);
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));
277
leave_pth (__FUNCTION__);
283
pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev)
291
pth_write (int fd, const void * buffer, size_t size)
296
enter_pth (__FUNCTION__);
297
n = send (fd, buffer, size, 0);
298
if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
303
/* This is no real error because we first need to figure out if
304
we have a handle or a socket. */
306
n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL);
310
fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n",
311
log_get_prefix (NULL), fd,
312
w32_strerror (strerr, sizeof strerr));
318
leave_pth (__FUNCTION__);
324
pth_select (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds,
325
const struct timeval * timeout)
330
enter_pth (__FUNCTION__);
331
n = select (nfds, rfds, wfds, efds, timeout);
332
leave_pth (__FUNCTION__);
338
pth_fdmode (int fd, int mode)
341
int ret = PTH_FDMODE_BLOCK;
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
347
/* XXX: figure out original fd mode */
350
case PTH_FDMODE_NONBLOCK:
352
if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR)
353
ret = PTH_FDMODE_ERROR;
356
case PTH_FDMODE_BLOCK:
358
if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR)
359
ret = PTH_FDMODE_ERROR;
367
pth_accept (int fd, struct sockaddr *addr, int *addrlen)
372
enter_pth (__FUNCTION__);
373
rc = accept (fd, addr, addrlen);
374
leave_pth (__FUNCTION__);
380
pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen,
381
pth_event_t ev_extra)
389
enter_pth (__FUNCTION__);
391
fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK);
392
if (fdmode == PTH_FDMODE_ERROR)
394
leave_pth (__FUNCTION__);
399
while ((rv = accept (fd, addr, addrlen)) == -1 &&
400
(WSAGetLastError () == WSAEINPROGRESS ||
401
WSAGetLastError () == WSAEWOULDBLOCK))
405
ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|
406
PTH_MODE_STATIC, &ev_key, fd);
409
leave_pth (__FUNCTION__);
413
pth_event_concat (ev, ev_extra, NULL);
415
/* Wait until accept has a chance. */
419
pth_event_isolate (ev);
420
if (do_pth_event_status (ev) != PTH_STATUS_OCCURRED)
422
pth_fdmode (fd, fdmode);
423
leave_pth (__FUNCTION__);
429
pth_fdmode (fd, fdmode);
430
leave_pth (__FUNCTION__);
436
pth_connect (int fd, struct sockaddr *name, int namelen)
441
enter_pth (__FUNCTION__);
442
rc = connect (fd, name, namelen);
443
leave_pth (__FUNCTION__);
449
pth_mutex_release (pth_mutex_t *mutex)
454
enter_pth (__FUNCTION__);
456
if (!ReleaseMutex (*mutex))
461
fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n",
462
log_get_prefix (NULL), *mutex,
463
w32_strerror (strerr, sizeof strerr));
469
leave_pth (__FUNCTION__);
475
pth_mutex_acquire (pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra)
481
enter_pth (__FUNCTION__);
483
/* FIXME: ev_extra is not yet supported. */
485
code = WaitForSingleObject (*mutex, INFINITE);
493
fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n",
494
log_get_prefix (NULL), *mutex,
495
w32_strerror (strerr, sizeof strerr));
506
fprintf (stderr, "%s: WaitForSingleObject returned unexpected "
507
"code %d for mutex %p\n",
508
log_get_prefix (NULL), code, *mutex);
513
leave_pth (__FUNCTION__);
520
pth_mutex_init (pth_mutex_t *mutex)
522
SECURITY_ATTRIBUTES sa;
525
enter_pth (__FUNCTION__);
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);
536
leave_pth (__FUNCTION__);
540
leave_pth (__FUNCTION__);
551
hd = calloc (1, sizeof *hd);
557
pth_attr_destroy (pth_attr_t hd)
570
pth_attr_set (pth_attr_t hd, int field, ...)
579
va_start (args, field);
582
case PTH_ATTR_JOINABLE:
583
val = va_arg (args, int);
586
hd->flags |= PTH_ATTR_JOINABLE;
588
fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n",
589
log_get_prefix (NULL));
593
case PTH_ATTR_STACK_SIZE:
594
val = va_arg (args, int);
597
hd->flags |= PTH_ATTR_STACK_SIZE;
598
hd->stack_size = val;
600
fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n",
601
log_get_prefix (NULL), val);
606
str = va_arg (args, char*);
611
hd->name = strdup (str);
614
hd->flags |= PTH_ATTR_NAME;
616
fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n",
617
log_get_prefix (NULL), hd->name);
631
do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg)
633
SECURITY_ATTRIBUTES sa;
636
struct thread_info_s *ctx;
641
memset (&sa, 0, sizeof sa);
642
sa.bInheritHandle = TRUE;
643
sa.lpSecurityDescriptor = NULL;
644
sa.nLength = sizeof sa;
646
ctx = calloc (1, sizeof *ctx);
651
ctx->joinable = (hd->flags & PTH_ATTR_JOINABLE);
653
/* XXX: we don't use all thread attributes. */
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.
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. */
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);
669
fprintf (stderr, "%s: do_pth_spawn created thread %p\n",
670
log_get_prefix (NULL),th);
680
pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg)
688
enter_pth (__FUNCTION__);
689
th = do_pth_spawn (hd, func, arg);
690
leave_pth (__FUNCTION__);
698
return GetCurrentThread ();
702
pth_join (pth_t hd, void **value)
710
pth_cancel (pth_t hd)
715
enter_pth (__FUNCTION__);
716
WaitForSingleObject (hd, 1000);
717
TerminateThread (hd, 0);
718
leave_pth (__FUNCTION__);
730
enter_pth (__FUNCTION__);
731
TerminateThread (hd, 0);
732
leave_pth (__FUNCTION__);
738
pth_exit (void *value)
741
enter_pth (__FUNCTION__);
743
leave_pth (__FUNCTION__);
744
exit ((int)(long)value);
749
do_pth_waitpid (unsigned pid, int * status, int options)
753
static pth_key_t ev_key = PTH_KEY_INIT;
756
pth_debug2("pth_waitpid: called from thread \"%s\"", pth_current->name);
760
/* do a non-blocking poll for the pid */
761
while ( (pid = pth_sc(waitpid)(wpid, status, options|WNOHANG)) < 0
765
/* if pid was found or caller requested a polling return immediately */
766
if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG)))
769
/* else wait a little bit */
770
ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key,
771
pth_timeout (0,250000));
775
pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name);
782
pth_waitpid (unsigned pid, int * status, int options)
787
enter_pth (__FUNCTION__);
788
n = do_pth_waitpid (pid, status, options);
789
leave_pth (__FUNCTION__);
795
sig_handler (DWORD signo)
799
case CTRL_C_EVENT: pth_signo = SIGINT; break;
800
case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break;
802
SetEvent (pth_signo_ev);
804
fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo);
810
do_pth_event_body (unsigned long spec, va_list arg)
812
SECURITY_ATTRIBUTES sa;
817
fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec);
818
ev = calloc (1, sizeof *ev);
823
else if (spec & PTH_EVENT_SIGS)
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);
830
fprintf (stderr, "%s: pth_event: sigs rc=%d\n",
831
log_get_prefix (NULL), rc);
833
else if (spec & PTH_EVENT_FD)
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);
843
fprintf (stderr, "%s: pth_event: fd=%d\n",
844
log_get_prefix (NULL), ev->u.fd);
846
else if (spec & PTH_EVENT_TIME)
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;
857
else if (spec & PTH_EVENT_MUTEX)
859
va_arg (arg, pth_key_t);
860
ev->u_type = PTH_EVENT_MUTEX;
861
ev->u.mx = va_arg (arg, pth_mutex_t*);
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);
881
do_pth_event (unsigned long spec, ...)
886
va_start (arg, spec);
887
ev = do_pth_event_body (spec, arg);
894
pth_event (unsigned long spec, ...)
900
enter_pth (__FUNCTION__);
902
va_start (arg, spec);
903
ev = do_pth_event_body (spec, arg);
906
leave_pth (__FUNCTION__);
912
pth_event_add (pth_event_t root, pth_event_t node)
916
for (n=root; n->next; n = n->next)
923
pth_event_concat (pth_event_t evf, ...)
934
while ((evn = va_arg(ap, pth_event_t)) != NULL)
935
pth_event_add (evf, evn);
943
wait_for_fd (int fd, int is_read, int nwait)
952
FD_SET (fd, is_read ? &r : &w);
959
n = select (fd+1, &r, &w, NULL, &tv);
961
fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n",
962
log_get_prefix (NULL), n, fd,(int)WSAGetLastError ());
969
if (is_read && FD_ISSET (fd, &r))
971
else if (FD_ISSET (fd, &w))
980
launch_thread (void *arg)
982
struct thread_info_s *c = arg;
986
leave_pth (__FUNCTION__);
988
if (!c->joinable && c->th)
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__);
1004
/* sigemptyset (struct sigset_s * ss) */
1007
/* memset (ss->sigs, 0, sizeof ss->sigs); */
1014
/* sigaddset (struct sigset_s * ss, int signo) */
1018
/* if (ss->idx + 1 > 64) */
1020
/* ss->sigs[ss->idx] = signo; */
1027
sigpresent (struct sigset_s * ss, int signo)
1030
/* for (i=0; i < ss->idx; i++) { */
1031
/* if (ss->sigs[i] == signo) */
1034
/* FIXME: See how to implement it. */
1040
do_pth_event_occurred (pth_event_t ev)
1051
if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
1055
case PTH_EVENT_SIGS:
1056
if (sigpresent (ev->u.sig, pth_signo) &&
1057
WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0)
1060
fprintf (stderr, "%s: pth_event_occurred: sig signaled.\n",
1061
log_get_prefix (NULL));
1062
(*ev->val) = pth_signo;
1068
if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
1078
pth_event_occurred (pth_event_t ev)
1083
enter_pth (__FUNCTION__);
1084
ret = do_pth_event_occurred (ev);
1085
leave_pth (__FUNCTION__);
1091
do_pth_event_status (pth_event_t ev)
1095
if (do_pth_event_occurred (ev))
1096
return PTH_STATUS_OCCURRED;
1101
pth_event_status (pth_event_t ev)
1105
if (pth_event_occurred (ev))
1106
return PTH_STATUS_OCCURRED;
1112
do_pth_event_free (pth_event_t ev, int mode)
1117
if (mode == PTH_FREE_ALL)
1119
pth_event_t cur = ev;
1122
pth_event_t next = cur->next;
1123
CloseHandle (cur->hd);
1130
else if (mode == PTH_FREE_THIS)
1132
ev->prev->next = ev->next;
1133
ev->next->prev = ev->prev;
1134
CloseHandle (ev->hd);
1145
pth_event_free (pth_event_t ev, int mode)
1150
enter_pth (__FUNCTION__);
1151
rc = do_pth_event_free (ev, mode);
1152
leave_pth (__FUNCTION__);
1158
pth_event_isolate (pth_event_t ev)
1164
if (ev->next == ev && ev->prev == ev)
1165
return NULL; /* Only one event. */
1168
ev->prev->next = ev->next;
1169
ev->next->prev = ev->prev;
1177
event_count (pth_event_t ev)
1199
spawn_helper_thread (void *(*func)(void *), void *arg)
1201
SECURITY_ATTRIBUTES sa;
1205
memset (&sa, 0, sizeof sa);
1206
sa.bInheritHandle = TRUE;
1207
sa.lpSecurityDescriptor = NULL;
1208
sa.nLength = sizeof sa;
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,
1217
fprintf (stderr, "%s: spawn_helper_thread created thread %p\n",
1218
log_get_prefix (NULL), th);
1225
free_helper_threads (HANDLE *waitbuf, int *hdidx, int n)
1229
for (i=0; i < n; i++)
1231
CloseHandle (waitbuf[hdidx[i]]);
1232
waitbuf[hdidx[i]] = NULL;
1238
wait_fd_thread (void * ctx)
1240
pth_event_t ev = ctx;
1242
wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600);
1244
fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL));
1252
wait_timer_thread (void * ctx)
1254
pth_event_t ev = ctx;
1255
int n = ev->u.tv.tv_sec*1000;
1259
fprintf (stderr, "%s: wait_timer_thread: exit.\n", log_get_prefix (NULL));
1266
do_pth_wait (pth_event_t ev)
1268
HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2];
1269
int hdidx[MAXIMUM_WAIT_OBJECTS/2];
1276
n = event_count (ev);
1277
if (n > MAXIMUM_WAIT_OBJECTS/2)
1281
fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n);
1290
waitbuf[pos++] = r->hd;
1293
case PTH_EVENT_SIGS:
1294
waitbuf[pos++] = pth_signo_ev;
1296
fprintf (stderr, "pth_wait: add signal event.\n");
1301
fprintf (stderr, "pth_wait: spawn event wait thread.\n");
1303
waitbuf[pos++] = spawn_helper_thread (wait_fd_thread, r);
1306
case PTH_EVENT_TIME:
1308
fprintf (stderr, "pth_wait: spawn event timer thread.\n");
1310
waitbuf[pos++] = spawn_helper_thread (wait_timer_thread, r);
1313
case PTH_EVENT_MUTEX:
1315
fprintf (stderr, "pth_wait: ignoring mutex event.\n");
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);
1326
fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n);
1328
if (n != WAIT_TIMEOUT)
1335
pth_wait (pth_event_t ev)
1340
enter_pth (__FUNCTION__);
1341
rc = do_pth_wait (ev);
1342
leave_pth (__FUNCTION__);
1350
static pth_key_t ev_key = PTH_KEY_INIT;
1354
enter_pth (__FUNCTION__);
1358
leave_pth (__FUNCTION__);
1362
ev = do_pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key,
1363
pth_timeout (sec, 0));
1366
leave_pth (__FUNCTION__);
1370
do_pth_event_free (ev, PTH_FREE_ALL);
1372
leave_pth (__FUNCTION__);
1386
void * thread (void * c)
1390
SetEvent (((pth_event_t)c)->hd);
1391
fprintf (stderr, "\n\nhallo!.\n");
1397
int main_1 (int argc, char ** argv)
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);
1412
pth_attr_destroy (t);
1413
pth_event_free (ev, 0);
1421
setup_signals (struct sigset_s *sigs, int *signo)
1426
sigaddset (sigs, SIGINT);
1427
sigaddset (sigs, SIGTERM);
1429
ev = pth_event (PTH_EVENT_SIGS, sigs, signo);
1434
main_2 (int argc, char ** argv)
1437
struct sigset_s sigs;
1441
ev = setup_signals (&sigs, &signo);
1443
if (pth_event_occured (ev) && signo)
1444
fprintf (stderr, "signal caught! signo %d\n", signo);
1446
pth_event_free (ev, PTH_FREE_ALL);
1452
main_3 (int argc, char ** argv)
1454
struct sockaddr_in addr, rem;
1455
int fd, n = 0, infd;
1457
struct sigset_s sigs;
1461
fd = socket (AF_INET, SOCK_STREAM, 0);
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);
1470
ev = setup_signals (&sigs, &signo);
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));
1477
pth_event_free (ev, PTH_FREE_ALL);
1483
main (int argc, char ** argv)
1489
/*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0));
1491
pth_event_free (ev, PTH_FREE_ALL);*/
1498
#endif /*HAVE_W32_SYSTEM*/