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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * ------------------------------------------------------------------
23 * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive
24 * thread scheduling library which can be found at
25 * http://www.gnu.org/software/pth/. MS Windows (W32) specific code
26 * written by Timo Schulz, g10 Code.
30 #ifdef HAVE_W32_SYSTEM
37 #include "logging.h" /* For log_get_prefix () */
39 /* We don't want to have any Windows specific code in the header, thus
40 we use a macro which defaults to a compatible type in w32-pth.h. */
41 #define W32_PTH_HANDLE_INTERNAL HANDLE
51 #if FALSE != 0 || TRUE != 1
52 #error TRUE or FALSE defined to wrong values
56 /* States whether this module has been initialized. */
57 static int pth_initialized
;
59 /* Keeps the current debug level. Define marcos to test them. */
60 static int debug_level
;
61 #define DBG_ERROR (debug_level >= 1)
62 #define DBG_INFO (debug_level >= 2)
63 #define DBG_CALLS (debug_level >= 3)
65 /* Variables to support event handling. */
67 static HANDLE pth_signo_ev
;
69 /* Mutex to make sure only one thread is running. */
70 static CRITICAL_SECTION pth_shd
;
72 /* Events are store in a double linked event ring. */
75 struct pth_event_s
* next
;
76 struct pth_event_s
* prev
;
80 struct sigset_s
* sig
;
94 unsigned int stack_size
;
99 /* Object to keep information about a thread. This may eventually be
100 used to implement a scheduler queue. */
103 void *(*thread
)(void *); /* The actual thread fucntion. */
104 void * arg
; /* The argument passed to that fucntion. */
105 int joinable
; /* True if this Thread is joinable. */
106 HANDLE th
; /* Handle of this thread. Used by non-joinable
107 threads to close the handle. */
111 /* Convenience macro to startup the system. */
112 #define implicit_init() do { if (!pth_initialized) pth_init(); } while (0)
115 static pth_event_t
do_pth_event (unsigned long spec
, ...);
116 static unsigned int do_pth_waitpid (unsigned pid
, int * status
, int options
);
117 static int do_pth_wait (pth_event_t ev
);
118 static int do_pth_event_status (pth_event_t ev
);
119 static void *launch_thread (void * ctx
);
127 SECURITY_ATTRIBUTES sa
;
134 debug_level
= (s
=getenv ("DEBUG_PTH"))? atoi (s
):0;
136 fprintf (stderr
, "%s: pth_init: called.\n", log_get_prefix (NULL
));
138 if (WSAStartup (0x202, &wsadat
))
141 InitializeCriticalSection (&pth_shd
);
143 CloseHandle (pth_signo_ev
);
144 memset (&sa
, 0, sizeof sa
);
145 sa
.bInheritHandle
= TRUE
;
146 sa
.lpSecurityDescriptor
= NULL
;
147 sa
.nLength
= sizeof sa
;
148 pth_signo_ev
= CreateEvent (&sa
, TRUE
, FALSE
, NULL
);
153 EnterCriticalSection (&pth_shd
);
164 CloseHandle (pth_signo_ev
);
168 DeleteCriticalSection (&pth_shd
);
176 w32_strerror (char *strerr
, size_t strerrsize
)
179 FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, (int)GetLastError (),
180 MAKELANGID (LANG_NEUTRAL
, SUBLANG_DEFAULT
),
181 strerr
, strerrsize
, NULL
);
187 enter_pth (const char *function
)
189 /* Fixme: I am not sure whether the same thread my enter a critical
192 fprintf (stderr
, "%s: enter_pth (%s)\n",
193 log_get_prefix (NULL
), function
? function
:"");
194 LeaveCriticalSection (&pth_shd
);
199 leave_pth (const char *function
)
201 EnterCriticalSection (&pth_shd
);
203 fprintf (stderr
, "%s: leave_pth (%s)\n",
204 log_get_prefix (NULL
), function
? function
:"");
209 pth_ctrl (unsigned long query
, ...)
215 case PTH_CTRL_GETAVLOAD
:
216 case PTH_CTRL_GETPRIO
:
217 case PTH_CTRL_GETNAME
:
218 case PTH_CTRL_GETTHREADS_NEW
:
219 case PTH_CTRL_GETTHREADS_READY
:
220 case PTH_CTRL_GETTHREADS_RUNNING
:
221 case PTH_CTRL_GETTHREADS_WAITING
:
222 case PTH_CTRL_GETTHREADS_SUSPENDED
:
223 case PTH_CTRL_GETTHREADS_DEAD
:
224 case PTH_CTRL_GETTHREADS
:
234 pth_timeout (long sec
, long usec
)
245 pth_read_ev (int fd
, void *buffer
, size_t size
, pth_event_t ev
)
253 pth_read (int fd
, void * buffer
, size_t size
)
258 enter_pth (__FUNCTION__
);
260 n
= recv (fd
, buffer
, size
, 0);
261 if (n
== -1 && WSAGetLastError () == WSAENOTSOCK
)
264 n
= ReadFile ((HANDLE
)fd
, buffer
, size
, &nread
, NULL
);
270 fprintf (stderr
, "%s: pth_read(%d) failed read from file: %s\n",
271 log_get_prefix (NULL
), fd
,
272 w32_strerror (strerr
, sizeof strerr
));
278 leave_pth (__FUNCTION__
);
284 pth_write_ev (int fd
, const void *buffer
, size_t size
, pth_event_t ev
)
292 pth_write (int fd
, const void * buffer
, size_t size
)
297 enter_pth (__FUNCTION__
);
298 n
= send (fd
, buffer
, size
, 0);
299 if (n
== -1 && WSAGetLastError () == WSAENOTSOCK
)
304 /* This is no real error because we first need to figure out if
305 we have a handle or a socket. */
307 n
= WriteFile ((HANDLE
)fd
, buffer
, size
, &nwrite
, NULL
);
311 fprintf (stderr
, "%s: pth_write(%d) failed in write: %s\n",
312 log_get_prefix (NULL
), fd
,
313 w32_strerror (strerr
, sizeof strerr
));
319 leave_pth (__FUNCTION__
);
325 pth_select (int nfds
, fd_set
* rfds
, fd_set
* wfds
, fd_set
* efds
,
326 const struct timeval
* timeout
)
331 enter_pth (__FUNCTION__
);
332 n
= select (nfds
, rfds
, wfds
, efds
, timeout
);
333 leave_pth (__FUNCTION__
);
339 pth_fdmode (int fd
, int mode
)
342 int ret
= PTH_FDMODE_BLOCK
;
345 /* Note: we don't do the eter/leave pth here because this is for one
346 a fast fucntion and secondly already called from inside such a
348 /* XXX: figure out original fd mode */
351 case PTH_FDMODE_NONBLOCK
:
353 if (ioctlsocket (fd
, FIONBIO
, &val
) == SOCKET_ERROR
)
354 ret
= PTH_FDMODE_ERROR
;
357 case PTH_FDMODE_BLOCK
:
359 if (ioctlsocket (fd
, FIONBIO
, &val
) == SOCKET_ERROR
)
360 ret
= PTH_FDMODE_ERROR
;
368 pth_accept (int fd
, struct sockaddr
*addr
, int *addrlen
)
373 enter_pth (__FUNCTION__
);
374 rc
= accept (fd
, addr
, addrlen
);
375 leave_pth (__FUNCTION__
);
381 pth_accept_ev (int fd
, struct sockaddr
*addr
, int *addrlen
,
382 pth_event_t ev_extra
)
390 enter_pth (__FUNCTION__
);
392 fdmode
= pth_fdmode (fd
, PTH_FDMODE_NONBLOCK
);
393 if (fdmode
== PTH_FDMODE_ERROR
)
395 leave_pth (__FUNCTION__
);
400 while ((rv
= accept (fd
, addr
, addrlen
)) == -1 &&
401 (WSAGetLastError () == WSAEINPROGRESS
||
402 WSAGetLastError () == WSAEWOULDBLOCK
))
406 ev
= do_pth_event (PTH_EVENT_FD
|PTH_UNTIL_FD_READABLE
|
407 PTH_MODE_STATIC
, &ev_key
, fd
);
410 leave_pth (__FUNCTION__
);
414 pth_event_concat (ev
, ev_extra
, NULL
);
416 /* Wait until accept has a chance. */
420 pth_event_isolate (ev
);
421 if (do_pth_event_status (ev
) != PTH_STATUS_OCCURRED
)
423 pth_fdmode (fd
, fdmode
);
424 leave_pth (__FUNCTION__
);
430 pth_fdmode (fd
, fdmode
);
431 leave_pth (__FUNCTION__
);
437 pth_connect (int fd
, struct sockaddr
*name
, int namelen
)
442 enter_pth (__FUNCTION__
);
443 rc
= connect (fd
, name
, namelen
);
444 leave_pth (__FUNCTION__
);
450 pth_mutex_release (pth_mutex_t
*mutex
)
455 enter_pth (__FUNCTION__
);
457 if (!ReleaseMutex (*mutex
))
462 fprintf (stderr
, "%s: pth_release_mutex %p failed: %s\n",
463 log_get_prefix (NULL
), *mutex
,
464 w32_strerror (strerr
, sizeof strerr
));
470 leave_pth (__FUNCTION__
);
476 pth_mutex_acquire (pth_mutex_t
*mutex
, int tryonly
, pth_event_t ev_extra
)
482 enter_pth (__FUNCTION__
);
484 /* FIXME: ev_extra is not yet supported. */
486 code
= WaitForSingleObject (*mutex
, INFINITE
);
494 fprintf (stderr
, "%s: pth_mutex_acquire for %p failed: %s\n",
495 log_get_prefix (NULL
), *mutex
,
496 w32_strerror (strerr
, sizeof strerr
));
507 fprintf (stderr
, "%s: WaitForSingleObject returned unexpected "
508 "code %d for mutex %p\n",
509 log_get_prefix (NULL
), code
, *mutex
);
514 leave_pth (__FUNCTION__
);
521 pth_mutex_init (pth_mutex_t
*mutex
)
523 SECURITY_ATTRIBUTES sa
;
526 enter_pth (__FUNCTION__
);
528 memset (&sa
, 0, sizeof sa
);
529 sa
.bInheritHandle
= TRUE
;
530 sa
.lpSecurityDescriptor
= NULL
;
531 sa
.nLength
= sizeof sa
;
532 *mutex
= CreateMutex (&sa
, FALSE
, NULL
);
537 leave_pth (__FUNCTION__
);
541 leave_pth (__FUNCTION__
);
552 hd
= calloc (1, sizeof *hd
);
558 pth_attr_destroy (pth_attr_t hd
)
571 pth_attr_set (pth_attr_t hd
, int field
, ...)
580 va_start (args
, field
);
583 case PTH_ATTR_JOINABLE
:
584 val
= va_arg (args
, int);
587 hd
->flags
|= PTH_ATTR_JOINABLE
;
589 fprintf (stderr
, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n",
590 log_get_prefix (NULL
));
594 case PTH_ATTR_STACK_SIZE
:
595 val
= va_arg (args
, int);
598 hd
->flags
|= PTH_ATTR_STACK_SIZE
;
599 hd
->stack_size
= val
;
601 fprintf (stderr
, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n",
602 log_get_prefix (NULL
), val
);
607 str
= va_arg (args
, char*);
612 hd
->name
= strdup (str
);
615 hd
->flags
|= PTH_ATTR_NAME
;
617 fprintf (stderr
, "%s: pth_attr_set: PTH_ATTR_NAME %s\n",
618 log_get_prefix (NULL
), hd
->name
);
632 do_pth_spawn (pth_attr_t hd
, void *(*func
)(void *), void *arg
)
634 SECURITY_ATTRIBUTES sa
;
637 struct thread_info_s
*ctx
;
642 memset (&sa
, 0, sizeof sa
);
643 sa
.bInheritHandle
= TRUE
;
644 sa
.lpSecurityDescriptor
= NULL
;
645 sa
.nLength
= sizeof sa
;
647 ctx
= calloc (1, sizeof *ctx
);
652 ctx
->joinable
= (hd
->flags
& PTH_ATTR_JOINABLE
);
654 /* XXX: we don't use all thread attributes. */
656 /* Note that we create the thread suspended so that we are able to
657 store the thread's handle in the context structure. We need to
658 do this to be able to close the handle from the launch helper.
660 FIXME: We should no use th W32's Thread handle directly but keep
661 our own thread control structure. CTX may be used for that. */
663 fprintf (stderr
, "%s: do_pth_spawn creating thread ...\n",
664 log_get_prefix (NULL
));
665 th
= CreateThread (&sa
, hd
->stack_size
,
666 (LPTHREAD_START_ROUTINE
)launch_thread
,
667 ctx
, CREATE_SUSPENDED
, &tid
);
670 fprintf (stderr
, "%s: do_pth_spawn created thread %p\n",
671 log_get_prefix (NULL
),th
);
681 pth_spawn (pth_attr_t hd
, void *(*func
)(void *), void *arg
)
689 enter_pth (__FUNCTION__
);
690 th
= do_pth_spawn (hd
, func
, arg
);
691 leave_pth (__FUNCTION__
);
699 return GetCurrentThread ();
703 pth_join (pth_t hd
, void **value
)
711 pth_cancel (pth_t hd
)
716 enter_pth (__FUNCTION__
);
717 WaitForSingleObject (hd
, 1000);
718 TerminateThread (hd
, 0);
719 leave_pth (__FUNCTION__
);
731 enter_pth (__FUNCTION__
);
732 TerminateThread (hd
, 0);
733 leave_pth (__FUNCTION__
);
739 pth_exit (void *value
)
742 enter_pth (__FUNCTION__
);
744 leave_pth (__FUNCTION__
);
745 exit ((int)(long)value
);
750 do_pth_waitpid (unsigned pid
, int * status
, int options
)
754 static pth_key_t ev_key
= PTH_KEY_INIT
;
757 pth_debug2("pth_waitpid: called from thread \"%s\"", pth_current
->name
);
761 /* do a non-blocking poll for the pid */
762 while ( (pid
= pth_sc(waitpid
)(wpid
, status
, options
|WNOHANG
)) < 0
766 /* if pid was found or caller requested a polling return immediately */
767 if (pid
== -1 || pid
> 0 || (pid
== 0 && (options
& WNOHANG
)))
770 /* else wait a little bit */
771 ev
= pth_event(PTH_EVENT_TIME
|PTH_MODE_STATIC
, &ev_key
,
772 pth_timeout (0,250000));
776 pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current
->name
);
783 pth_waitpid (unsigned pid
, int * status
, int options
)
788 enter_pth (__FUNCTION__
);
789 n
= do_pth_waitpid (pid
, status
, options
);
790 leave_pth (__FUNCTION__
);
796 sig_handler (DWORD signo
)
800 case CTRL_C_EVENT
: pth_signo
= SIGINT
; break;
801 case CTRL_BREAK_EVENT
: pth_signo
= SIGTERM
; break;
803 SetEvent (pth_signo_ev
);
805 fprintf (stderr
, "%s: sig_handler=%d\n", log_get_prefix (NULL
), pth_signo
);
811 do_pth_event_body (unsigned long spec
, va_list arg
)
813 SECURITY_ATTRIBUTES sa
;
818 fprintf (stderr
, "%s: pth_event spec=%lu\n", log_get_prefix (NULL
), spec
);
819 ev
= calloc (1, sizeof *ev
);
824 else if (spec
& PTH_EVENT_SIGS
)
826 ev
->u
.sig
= va_arg (arg
, struct sigset_s
*);
827 ev
->u_type
= PTH_EVENT_SIGS
;
828 ev
->val
= va_arg (arg
, int *);
829 rc
= SetConsoleCtrlHandler (sig_handler
, TRUE
);
831 fprintf (stderr
, "%s: pth_event: sigs rc=%d\n",
832 log_get_prefix (NULL
), rc
);
834 else if (spec
& PTH_EVENT_FD
)
836 if (spec
& PTH_UNTIL_FD_READABLE
)
837 ev
->flags
|= PTH_UNTIL_FD_READABLE
;
838 if (spec
& PTH_MODE_STATIC
)
839 ev
->flags
|= PTH_MODE_STATIC
;
840 ev
->u_type
= PTH_EVENT_FD
;
841 va_arg (arg
, pth_key_t
);
842 ev
->u
.fd
= va_arg (arg
, int);
844 fprintf (stderr
, "%s: pth_event: fd=%d\n",
845 log_get_prefix (NULL
), ev
->u
.fd
);
847 else if (spec
& PTH_EVENT_TIME
)
850 if (spec
& PTH_MODE_STATIC
)
851 ev
->flags
|= PTH_MODE_STATIC
;
852 va_arg (arg
, pth_key_t
);
853 t
= va_arg (arg
, pth_time_t
);
854 ev
->u_type
= PTH_EVENT_TIME
;
855 ev
->u
.tv
.tv_sec
= t
.tv_sec
;
856 ev
->u
.tv
.tv_usec
= t
.tv_usec
;
858 else if (spec
& PTH_EVENT_MUTEX
)
860 va_arg (arg
, pth_key_t
);
861 ev
->u_type
= PTH_EVENT_MUTEX
;
862 ev
->u
.mx
= va_arg (arg
, pth_mutex_t
*);
865 memset (&sa
, 0, sizeof sa
);
866 sa
.bInheritHandle
= TRUE
;
867 sa
.lpSecurityDescriptor
= NULL
;
868 sa
.nLength
= sizeof sa
;
869 ev
->hd
= CreateEvent (&sa
, FALSE
, FALSE
, NULL
);
882 do_pth_event (unsigned long spec
, ...)
887 va_start (arg
, spec
);
888 ev
= do_pth_event_body (spec
, arg
);
895 pth_event (unsigned long spec
, ...)
901 enter_pth (__FUNCTION__
);
903 va_start (arg
, spec
);
904 ev
= do_pth_event_body (spec
, arg
);
907 leave_pth (__FUNCTION__
);
913 pth_event_add (pth_event_t root
, pth_event_t node
)
917 for (n
=root
; n
->next
; n
= n
->next
)
924 pth_event_concat (pth_event_t evf
, ...)
935 while ((evn
= va_arg(ap
, pth_event_t
)) != NULL
)
936 pth_event_add (evf
, evn
);
944 wait_for_fd (int fd
, int is_read
, int nwait
)
953 FD_SET (fd
, is_read
? &r
: &w
);
960 n
= select (fd
+1, &r
, &w
, NULL
, &tv
);
962 fprintf (stderr
, "%s: wait_for_fd=%d fd %d (ec=%d)\n",
963 log_get_prefix (NULL
), n
, fd
,(int)WSAGetLastError ());
970 if (is_read
&& FD_ISSET (fd
, &r
))
972 else if (FD_ISSET (fd
, &w
))
981 launch_thread (void *arg
)
983 struct thread_info_s
*c
= arg
;
987 leave_pth (__FUNCTION__
);
989 if (!c
->joinable
&& c
->th
)
994 /* FIXME: We would badly fail if someone accesses the now
995 deallocated handle. Don't use it directly but setup proper
996 scheduling queues. */
997 enter_pth (__FUNCTION__
);
1005 /* sigemptyset (struct sigset_s * ss) */
1008 /* memset (ss->sigs, 0, sizeof ss->sigs); */
1015 /* sigaddset (struct sigset_s * ss, int signo) */
1019 /* if (ss->idx + 1 > 64) */
1021 /* ss->sigs[ss->idx] = signo; */
1028 sigpresent (struct sigset_s
* ss
, int signo
)
1031 /* for (i=0; i < ss->idx; i++) { */
1032 /* if (ss->sigs[i] == signo) */
1035 /* FIXME: See how to implement it. */
1041 do_pth_event_occurred (pth_event_t ev
)
1052 if (WaitForSingleObject (ev
->hd
, 0) == WAIT_OBJECT_0
)
1056 case PTH_EVENT_SIGS
:
1057 if (sigpresent (ev
->u
.sig
, pth_signo
) &&
1058 WaitForSingleObject (pth_signo_ev
, 0) == WAIT_OBJECT_0
)
1061 fprintf (stderr
, "%s: pth_event_occurred: sig signaled.\n",
1062 log_get_prefix (NULL
));
1063 (*ev
->val
) = pth_signo
;
1069 if (WaitForSingleObject (ev
->hd
, 0) == WAIT_OBJECT_0
)
1079 pth_event_occurred (pth_event_t ev
)
1084 enter_pth (__FUNCTION__
);
1085 ret
= do_pth_event_occurred (ev
);
1086 leave_pth (__FUNCTION__
);
1092 do_pth_event_status (pth_event_t ev
)
1096 if (do_pth_event_occurred (ev
))
1097 return PTH_STATUS_OCCURRED
;
1102 pth_event_status (pth_event_t ev
)
1106 if (pth_event_occurred (ev
))
1107 return PTH_STATUS_OCCURRED
;
1113 do_pth_event_free (pth_event_t ev
, int mode
)
1118 if (mode
== PTH_FREE_ALL
)
1120 pth_event_t cur
= ev
;
1123 pth_event_t next
= cur
->next
;
1124 CloseHandle (cur
->hd
);
1131 else if (mode
== PTH_FREE_THIS
)
1133 ev
->prev
->next
= ev
->next
;
1134 ev
->next
->prev
= ev
->prev
;
1135 CloseHandle (ev
->hd
);
1146 pth_event_free (pth_event_t ev
, int mode
)
1151 enter_pth (__FUNCTION__
);
1152 rc
= do_pth_event_free (ev
, mode
);
1153 leave_pth (__FUNCTION__
);
1159 pth_event_isolate (pth_event_t ev
)
1165 if (ev
->next
== ev
&& ev
->prev
== ev
)
1166 return NULL
; /* Only one event. */
1169 ev
->prev
->next
= ev
->next
;
1170 ev
->next
->prev
= ev
->prev
;
1178 event_count (pth_event_t ev
)
1200 spawn_helper_thread (void *(*func
)(void *), void *arg
)
1202 SECURITY_ATTRIBUTES sa
;
1206 memset (&sa
, 0, sizeof sa
);
1207 sa
.bInheritHandle
= TRUE
;
1208 sa
.lpSecurityDescriptor
= NULL
;
1209 sa
.nLength
= sizeof sa
;
1212 fprintf (stderr
, "%s: spawn_helper_thread creating thread ...\n",
1213 log_get_prefix (NULL
));
1214 th
= CreateThread (&sa
, 32*1024,
1215 (LPTHREAD_START_ROUTINE
)func
,
1218 fprintf (stderr
, "%s: spawn_helper_thread created thread %p\n",
1219 log_get_prefix (NULL
), th
);
1226 free_helper_threads (HANDLE
*waitbuf
, int *hdidx
, int n
)
1230 for (i
=0; i
< n
; i
++)
1232 CloseHandle (waitbuf
[hdidx
[i
]]);
1233 waitbuf
[hdidx
[i
]] = NULL
;
1239 wait_fd_thread (void * ctx
)
1241 pth_event_t ev
= ctx
;
1243 wait_for_fd (ev
->u
.fd
, ev
->flags
& PTH_UNTIL_FD_READABLE
, 3600);
1245 fprintf (stderr
, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL
));
1253 wait_timer_thread (void * ctx
)
1255 pth_event_t ev
= ctx
;
1256 int n
= ev
->u
.tv
.tv_sec
*1000;
1260 fprintf (stderr
, "%s: wait_timer_thread: exit.\n", log_get_prefix (NULL
));
1267 do_pth_wait (pth_event_t ev
)
1269 HANDLE waitbuf
[MAXIMUM_WAIT_OBJECTS
/2];
1270 int hdidx
[MAXIMUM_WAIT_OBJECTS
/2];
1277 n
= event_count (ev
);
1278 if (n
> MAXIMUM_WAIT_OBJECTS
/2)
1282 fprintf (stderr
, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL
), n
);
1291 waitbuf
[pos
++] = r
->hd
;
1294 case PTH_EVENT_SIGS
:
1295 waitbuf
[pos
++] = pth_signo_ev
;
1297 fprintf (stderr
, "pth_wait: add signal event.\n");
1302 fprintf (stderr
, "pth_wait: spawn event wait thread.\n");
1304 waitbuf
[pos
++] = spawn_helper_thread (wait_fd_thread
, r
);
1307 case PTH_EVENT_TIME
:
1309 fprintf (stderr
, "pth_wait: spawn event timer thread.\n");
1311 waitbuf
[pos
++] = spawn_helper_thread (wait_timer_thread
, r
);
1314 case PTH_EVENT_MUTEX
:
1316 fprintf (stderr
, "pth_wait: ignoring mutex event.\n");
1323 fprintf (stderr
, "%s: pth_wait: set %d\n", log_get_prefix (NULL
), pos
);
1324 n
= WaitForMultipleObjects (pos
, waitbuf
, FALSE
, INFINITE
);
1325 free_helper_threads (waitbuf
, hdidx
, i
);
1327 fprintf (stderr
, "%s: pth_wait: n %ld\n", log_get_prefix (NULL
), n
);
1329 if (n
!= WAIT_TIMEOUT
)
1336 pth_wait (pth_event_t ev
)
1341 enter_pth (__FUNCTION__
);
1342 rc
= do_pth_wait (ev
);
1343 leave_pth (__FUNCTION__
);
1351 static pth_key_t ev_key
= PTH_KEY_INIT
;
1355 enter_pth (__FUNCTION__
);
1359 leave_pth (__FUNCTION__
);
1363 ev
= do_pth_event (PTH_EVENT_TIME
|PTH_MODE_STATIC
, &ev_key
,
1364 pth_timeout (sec
, 0));
1367 leave_pth (__FUNCTION__
);
1371 do_pth_event_free (ev
, PTH_FREE_ALL
);
1373 leave_pth (__FUNCTION__
);
1387 void * thread (void * c
)
1391 SetEvent (((pth_event_t
)c
)->hd
);
1392 fprintf (stderr
, "\n\nhallo!.\n");
1398 int main_1 (int argc
, char ** argv
)
1405 ev
= pth_event (0, NULL
);
1406 t
= pth_attr_new ();
1407 pth_attr_set (t
, PTH_ATTR_JOINABLE
, 1);
1408 pth_attr_set (t
, PTH_ATTR_STACK_SIZE
, 4096);
1409 pth_attr_set (t
, PTH_ATTR_NAME
, "hello");
1410 hd
= pth_spawn (t
, thread
, ev
);
1413 pth_attr_destroy (t
);
1414 pth_event_free (ev
, 0);
1422 setup_signals (struct sigset_s
*sigs
, int *signo
)
1427 sigaddset (sigs
, SIGINT
);
1428 sigaddset (sigs
, SIGTERM
);
1430 ev
= pth_event (PTH_EVENT_SIGS
, sigs
, signo
);
1435 main_2 (int argc
, char ** argv
)
1438 struct sigset_s sigs
;
1442 ev
= setup_signals (&sigs
, &signo
);
1444 if (pth_event_occured (ev
) && signo
)
1445 fprintf (stderr
, "signal caught! signo %d\n", signo
);
1447 pth_event_free (ev
, PTH_FREE_ALL
);
1453 main_3 (int argc
, char ** argv
)
1455 struct sockaddr_in addr
, rem
;
1456 int fd
, n
= 0, infd
;
1458 struct sigset_s sigs
;
1462 fd
= socket (AF_INET
, SOCK_STREAM
, 0);
1464 memset (&addr
, 0, sizeof addr
);
1465 addr
.sin_addr
.s_addr
= INADDR_ANY
;
1466 addr
.sin_port
= htons (5050);
1467 addr
.sin_family
= AF_INET
;
1468 bind (fd
, (struct sockaddr
*)&addr
, sizeof addr
);
1471 ev
= setup_signals (&sigs
, &signo
);
1473 infd
= pth_accept_ev (fd
, (struct sockaddr
*)&rem
, &n
, ev
);
1474 fprintf (stderr
, "infd %d: %s:%d\n", infd
, inet_ntoa (rem
.sin_addr
),
1475 htons (rem
.sin_port
));
1478 pth_event_free (ev
, PTH_FREE_ALL
);
1484 main (int argc
, char ** argv
)
1490 /*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0));
1492 pth_event_free (ev, PTH_FREE_ALL);*/
1499 #endif /*HAVE_W32_SYSTEM*/