[svn] w32pth - r4 - trunk
svn author wk
cvs at cvs.gnupg.org
Fri Jun 29 20:38:29 CEST 2007
Author: wk
Date: 2007-06-29 20:38:00 +0200 (Fri, 29 Jun 2007)
New Revision: 4
Modified:
trunk/ChangeLog
trunk/README
trunk/autogen.sh
trunk/w32-pth.c
Log:
Rewrote most of the event stuff.
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2007-06-12 13:40:50 UTC (rev 3)
+++ trunk/ChangeLog 2007-06-29 18:38:00 UTC (rev 4)
@@ -1,3 +1,31 @@
+2007-06-29 Werner Koch <wk at g10code.com>
+
+ * w32-pth.c (pth_event_add): Remove.
+ (pth_event_concat): Correctly implement as a ring.
+ (do_pth_wait): Fixed bug which let us wait only on the first
+ event. More or less rewrote it.
+ (do_pth_event_occurred): removed and repalced by direct call to
+ theSTATUS field of the event.
+ (pth_event_status): Changed implementation to accommodate the
+ changed do_pth_wait.
+ (pth_event_status): Ditto.
+
+2007-06-28 Werner Koch <wk at g10code.com>
+
+ * w32-pth.c (sig_handler): Ignore the logoff and close event.
+ (do_pth_event_body): Properly ignore the static mode.
+ (do_pth_event_body): Implement PTH_EVENT_SELECT.
+ (wait_select_thread): New.
+ (pth_select_ev): Support ev_extra.
+
+2007-06-25 Werner Koch <wk at g10code.com>
+
+ * w32-pth.c (pth_mutex_init): Remove superfluous free.
+
+2007-06-15 Werner Koch <wk at g10code.com>
+
+ * autogen.sh: Use = and not == in test to be POSIXly correct.
+
2007-05-30 Werner Koch <wk at g10code.com>
Package created.
Modified: trunk/README
===================================================================
--- trunk/README 2007-06-12 13:40:50 UTC (rev 3)
+++ trunk/README 2007-06-29 18:38:00 UTC (rev 4)
@@ -10,7 +10,16 @@
It is currently limited to what GnuPG 2.0 requires.
-Thisng we need to implement:
+Thing we need to implement:
pth_select_ev - EV is currently ignored.
+
+Missing stuff:
+
+ PTH_MODE_STATIC is known but ignored.
+ PTH_MODE_REUSE
+ PTH_MODE_CHAIN
+
+ as well as many more things.
+
Modified: trunk/autogen.sh
===================================================================
--- trunk/autogen.sh 2007-06-12 13:40:50 UTC (rev 3)
+++ trunk/autogen.sh 2007-06-29 18:38:00 UTC (rev 4)
@@ -30,7 +30,7 @@
DIE=no
FORCE=
-if test "$1" == "--force"; then
+if test x"$1" = x"--force"; then
FORCE=" --force"
shift
fi
@@ -76,7 +76,7 @@
fi
./configure --enable-maintainer-mode --prefix=${w32root} \
- --host=${host} --build=${build}
+ --host=${host} --build=${build} "$@"
exit $?
fi
Modified: trunk/w32-pth.c
===================================================================
--- trunk/w32-pth.c 2007-06-12 13:40:50 UTC (rev 3)
+++ trunk/w32-pth.c 2007-06-29 18:38:00 UTC (rev 4)
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <io.h>
#include <signal.h>
+#include <errno.h>
/* We don't want to have any Windows specific code in the header, thus
we use a macro which defaults to a compatible type in w32-pth.h. */
@@ -70,27 +71,42 @@
/* Events are store in a double linked event ring. */
struct pth_event_s
{
- struct pth_event_s * next;
- struct pth_event_s * prev;
- HANDLE hd;
+ struct pth_event_s *next;
+ struct pth_event_s *prev;
+ HANDLE hd; /* The event object. */
+ int u_type; /* The type of the event. */
union
{
- struct sigset_s * sig;
- int fd;
- struct timeval tv;
- pth_mutex_t * mx;
+ int fd; /* Used for PTH_EVENT_FD. */
+ struct
+ {
+ int *rc;
+ int nfd;
+ fd_set *rfds;
+ fd_set *wfds;
+ fd_set *efds;
+ } sel; /* Used for PTH_EVENT_SELECT. */
+ struct
+ {
+ struct sigset_s *set;
+ int *signo;
+ } sig; /* Used for PTH_EVENT_SIGS. */
+ struct timeval tv; /* Used for PTH_EVENT_TIME. */
+ pth_mutex_t *mx; /* Used for PTH_EVENT_MUTEX. */
} u;
- int * val;
- int u_type;
- int flags;
+ unsigned int flags; /* Flags used to further describe an event.
+ This is the bit wise combination of
+ PTH_MODE_* or PTH_UNTIL_*. */
+ pth_status_t status; /* Current status of the event. */
};
+/* Attribute object for threads. */
struct pth_attr_s
{
unsigned int flags;
unsigned int stack_size;
- char * name;
+ char *name;
};
@@ -113,8 +129,8 @@
static pth_event_t do_pth_event (unsigned long spec, ...);
static unsigned int do_pth_waitpid (unsigned pid, int * status, int options);
static int do_pth_wait (pth_event_t ev);
-static int do_pth_event_status (pth_event_t ev);
static void *launch_thread (void * ctx);
+static int do_pth_event_free (pth_event_t ev, int mode);
@@ -323,7 +339,6 @@
}
else if (n == -1)
{
- DWORD nwrite;
char strerr[256];
if (DBG_ERROR)
@@ -338,30 +353,90 @@
int
-pth_select (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds,
+pth_select (int nfd, fd_set * rfds, fd_set * wfds, fd_set * efds,
const struct timeval * timeout)
{
int n;
implicit_init ();
enter_pth (__FUNCTION__);
- n = select (nfds, rfds, wfds, efds, timeout);
+ n = select (nfd, rfds, wfds, efds, timeout);
leave_pth (__FUNCTION__);
return n;
}
int
-pth_select_ev (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds,
- const struct timeval * timeout, pth_event_t ev_extra)
+pth_select_ev (int nfd, fd_set *rfds, fd_set *wfds, fd_set *efds,
+ const struct timeval *timeout, pth_event_t ev_extra)
{
- int n;
+ int rc;
+ pth_event_t ev;
+ pth_event_t ev_time = NULL;
+ int selected;
implicit_init ();
enter_pth (__FUNCTION__);
- n = select (nfds, rfds, wfds, efds, timeout);
+
+ ev = do_pth_event (PTH_EVENT_SELECT, &rc, nfd, rfds, wfds, efds);
+ if (!ev)
+ {
+ leave_pth (__FUNCTION__);
+ return -1;
+ }
+ if (timeout)
+ {
+ ev_time = do_pth_event (PTH_EVENT_TIME,
+ pth_timeout (timeout->tv_sec, timeout->tv_usec));
+ if (!ev_time)
+ {
+ rc = -1;
+ goto leave;
+ }
+ pth_event_concat (ev, ev_time, NULL);
+ }
+ if (ev_extra)
+ pth_event_concat (ev, ev_extra, NULL);
+
+ do
+ {
+ rc = do_pth_wait (ev);
+ if (rc < 0)
+ goto leave;
+ }
+ while (!rc);
+
+ if (ev_extra)
+ pth_event_isolate (ev_extra);
+ if (timeout)
+ pth_event_isolate (ev_time);
+
+ /* Fixme: We should check whether select failed and return EBADF in
+ this case. */
+ selected = (ev && ev->status == PTH_STATUS_OCCURRED);
+ if (timeout && (ev_time && ev_time->status == PTH_STATUS_OCCURRED))
+ {
+ selected = 1;
+ if (rfds)
+ FD_ZERO(rfds);
+ if (wfds)
+ FD_ZERO(wfds);
+ if (efds)
+ FD_ZERO(efds);
+ rc = 0;
+ }
+ if (ev_extra && !selected)
+ {
+ rc = -1;
+ errno = EINTR;
+ }
+
+ leave:
+ do_pth_event_free (ev, PTH_FREE_THIS);
+ do_pth_event_free (ev_time, PTH_FREE_THIS);
+
leave_pth (__FUNCTION__);
- return n;
+ return rc;
}
@@ -448,7 +523,7 @@
if (ev_extra)
{
pth_event_isolate (ev);
- if (do_pth_event_status (ev) != PTH_STATUS_OCCURRED)
+ if (ev && ev->status != PTH_STATUS_OCCURRED)
{
pth_fdmode (fd, fdmode);
leave_pth (__FUNCTION__);
@@ -562,8 +637,6 @@
*mutex = CreateMutex (&sa, FALSE, NULL);
if (!*mutex)
{
- free (*mutex);
- *mutex = NULL;
leave_pth (__FUNCTION__);
return FALSE;
}
@@ -829,7 +902,10 @@
{
case CTRL_C_EVENT: pth_signo = SIGINT; break;
case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break;
+ default:
+ return FALSE;
}
+ /* Fixme: We can keep only track of one signal at a time. */
SetEvent (pth_signo_ev);
if (DBG_INFO)
fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo);
@@ -844,18 +920,38 @@
pth_event_t ev;
int rc;
+ if ((spec & (PTH_MODE_CHAIN|PTH_MODE_REUSE)))
+ {
+ if (DBG_ERROR)
+ fprintf (stderr, "%s: pth_event spec=%lu - not supported\n",
+ log_get_prefix (NULL), spec);
+ return NULL; /* Not supported. */
+ }
+
if (DBG_INFO)
fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec);
+
ev = calloc (1, sizeof *ev);
if (!ev)
return NULL;
+
+ /* We don't support static yet but we need to consume the
+ argument. */
+ if ( (spec & PTH_MODE_STATIC) )
+ {
+ ev->flags |= PTH_MODE_STATIC;
+ va_arg (arg, pth_key_t);
+ }
+
+ ev->status = PTH_STATUS_PENDING;
+
if (spec == 0)
;
else if (spec & PTH_EVENT_SIGS)
{
- ev->u.sig = va_arg (arg, struct sigset_s *);
ev->u_type = PTH_EVENT_SIGS;
- ev->val = va_arg (arg, int *);
+ ev->u.sig.set = va_arg (arg, struct sigset_s *);
+ ev->u.sig.signo = va_arg (arg, int *);
rc = SetConsoleCtrlHandler (sig_handler, TRUE);
if (DBG_INFO)
fprintf (stderr, "%s: pth_event: sigs rc=%d\n",
@@ -865,10 +961,7 @@
{
if (spec & PTH_UNTIL_FD_READABLE)
ev->flags |= PTH_UNTIL_FD_READABLE;
- if (spec & PTH_MODE_STATIC)
- ev->flags |= PTH_MODE_STATIC;
ev->u_type = PTH_EVENT_FD;
- va_arg (arg, pth_key_t);
ev->u.fd = va_arg (arg, int);
if (DBG_INFO)
fprintf (stderr, "%s: pth_event: fd=%d\n",
@@ -877,9 +970,6 @@
else if (spec & PTH_EVENT_TIME)
{
pth_time_t t;
- if (spec & PTH_MODE_STATIC)
- ev->flags |= PTH_MODE_STATIC;
- va_arg (arg, pth_key_t);
t = va_arg (arg, pth_time_t);
ev->u_type = PTH_EVENT_TIME;
ev->u.tv.tv_sec = t.tv_sec;
@@ -887,16 +977,25 @@
}
else if (spec & PTH_EVENT_MUTEX)
{
- va_arg (arg, pth_key_t);
ev->u_type = PTH_EVENT_MUTEX;
ev->u.mx = va_arg (arg, pth_mutex_t*);
}
-
+ else if (spec & PTH_EVENT_SELECT)
+ {
+ ev->u_type = PTH_EVENT_SELECT;
+ ev->u.sel.rc = va_arg (arg, int *);
+ ev->u.sel.nfd = va_arg (arg, int);
+ ev->u.sel.rfds = va_arg (arg, fd_set *);
+ ev->u.sel.wfds = va_arg (arg, fd_set *);
+ ev->u.sel.efds = va_arg (arg, fd_set *);
+ }
+
+ /* Create an Event which needs to be manually reset. */
memset (&sa, 0, sizeof sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof sa;
- ev->hd = CreateEvent (&sa, FALSE, FALSE, NULL);
+ ev->hd = CreateEvent (&sa, TRUE, FALSE, NULL);
if (!ev->hd)
{
free (ev);
@@ -939,34 +1038,33 @@
}
-static void
-pth_event_add (pth_event_t root, pth_event_t node)
-{
- pth_event_t n;
-
- for (n=root; n->next; n = n->next)
- ;
- n->next = node;
-}
-
-
pth_event_t
-pth_event_concat (pth_event_t evf, ...)
+pth_event_concat (pth_event_t head, ...)
{
- pth_event_t evn;
+ pth_event_t ev, next, last, tmp;
va_list ap;
- if (!evf)
+ if (!head)
return NULL;
implicit_init ();
- va_start (ap, evf);
- while ((evn = va_arg(ap, pth_event_t)) != NULL)
- pth_event_add (evf, evn);
+ ev = head;
+ last = head->next;
+ va_start (ap, head);
+ while ( (next = va_arg (ap, pth_event_t)))
+ {
+ ev->next = next;
+ tmp = next->prev;
+ next->prev = ev;
+ ev = tmp;
+ }
va_end (ap);
- return evf;
+ ev->next = last;
+ last->prev = ev;
+
+ return head;
}
@@ -1054,91 +1152,43 @@
/* } */
-static int
-sigpresent (struct sigset_s * ss, int signo)
-{
+/* static int */
+/* sigpresent (struct sigset_s * ss, int signo) */
+/* { */
/* int i; */
/* for (i=0; i < ss->idx; i++) { */
/* if (ss->sigs[i] == signo) */
/* return 1; */
/* } */
/* FIXME: See how to implement it. */
- return 0;
-}
+/* return 0; */
+/* } */
-static int
-do_pth_event_occurred (pth_event_t ev)
+
+int
+pth_event_status (pth_event_t ev)
{
- int ret;
+ int ret;
if (!ev)
return 0;
-
- ret = 0;
- switch (ev->u_type)
- {
- case 0:
- if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
- ret = 1;
- break;
-
- case PTH_EVENT_SIGS:
- if (sigpresent (ev->u.sig, pth_signo) &&
- WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0)
- {
- if (DBG_INFO)
- fprintf (stderr, "%s: pth_event_occurred: sig signaled.\n",
- log_get_prefix (NULL));
- (*ev->val) = pth_signo;
- ret = 1;
- }
- break;
-
- case PTH_EVENT_FD:
- if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
- ret = 1;
- break;
- }
-
- return ret;
-}
-
-
-int
-pth_event_occurred (pth_event_t ev)
-{
- int ret;
-
implicit_init ();
enter_pth (__FUNCTION__);
- ret = do_pth_event_occurred (ev);
+ ret = ev? ev->status : 0;;
leave_pth (__FUNCTION__);
return ret;
}
-static int
-do_pth_event_status (pth_event_t ev)
-{
- if (!ev)
- return 0;
- if (do_pth_event_occurred (ev))
- return PTH_STATUS_OCCURRED;
- return 0;
-}
-
int
-pth_event_status (pth_event_t ev)
+pth_event_occurred (pth_event_t ev)
{
- if (!ev)
- return 0;
- if (pth_event_occurred (ev))
- return PTH_STATUS_OCCURRED;
- return 0;
+ return pth_event_status (ev) == PTH_STATUS_OCCURRED;
}
+
static int
do_pth_event_free (pth_event_t ev, int mode)
{
@@ -1252,19 +1302,7 @@
}
-static void
-free_helper_threads (HANDLE *waitbuf, int *hdidx, int n)
-{
- int i;
- for (i=0; i < n; i++)
- {
- CloseHandle (waitbuf[hdidx[i]]);
- waitbuf[hdidx[i]] = NULL;
- }
-}
-
-
static void *
wait_fd_thread (void * ctx)
{
@@ -1293,13 +1331,30 @@
}
+static void *
+wait_select_thread (void * ctx)
+{
+ pth_event_t ev = ctx;
+
+ *ev->u.sel.rc = select (ev->u.sel.nfd,
+ ev->u.sel.rfds, ev->u.sel.wfds, ev->u.sel.efds,NULL);
+ SetEvent (ev->hd);
+ if (DBG_INFO)
+ fprintf (stderr, "%s: wait_select_thread: exit.\n", log_get_prefix (NULL));
+ ExitThread (0);
+ return NULL;
+}
+
+
static int
do_pth_wait (pth_event_t ev)
{
HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2];
- int hdidx[MAXIMUM_WAIT_OBJECTS/2];
- DWORD n = 0;
- int pos=0, i=0;
+ pth_event_t evarray[MAXIMUM_WAIT_OBJECTS/2];
+ HANDLE threadlist[MAXIMUM_WAIT_OBJECTS/2];
+ DWORD n;
+ int pos, idx, threadlistidx, i;
+ pth_event_t r;
if (!ev)
return 0;
@@ -1310,58 +1365,105 @@
if (DBG_INFO)
fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n);
- if (ev)
+
+ /* Set all events to pending. */
+ r = ev;
+ do
{
- pth_event_t r = ev;
- do
+ r->status = PTH_STATUS_PENDING;
+ r = r->next;
+ }
+ while ( r != ev);
+
+ /* Prepare all events which requires to launch helper threads for
+ some types. This creates an array of handles which are lates
+ passed to WFMO. */
+ pos = threadlistidx = 0;
+ r = ev;
+ do
+ {
+ switch (r->u_type)
{
- switch (r->u_type)
- {
- case 0:
- waitbuf[pos++] = r->hd;
- break;
-
- case PTH_EVENT_SIGS:
- waitbuf[pos++] = pth_signo_ev;
- if (DBG_INFO)
- fprintf (stderr, "pth_wait: add signal event.\n");
- break;
-
- case PTH_EVENT_FD:
- if (DBG_INFO)
- fprintf (stderr, "pth_wait: spawn event wait thread.\n");
- hdidx[i++] = pos;
- waitbuf[pos++] = spawn_helper_thread (wait_fd_thread, r);
- break;
-
- case PTH_EVENT_TIME:
- if (DBG_INFO)
- fprintf (stderr, "pth_wait: spawn event timer thread.\n");
- hdidx[i++] = pos;
- waitbuf[pos++] = spawn_helper_thread (wait_timer_thread, r);
- break;
+ case PTH_EVENT_SIGS:
+ if (DBG_INFO)
+ fprintf (stderr, "pth_wait: add signal event\n");
+ /* Register the global signal event. */
+ evarray[pos] = ev;
+ waitbuf[pos++] = pth_signo_ev;
+ break;
- case PTH_EVENT_MUTEX:
- if (DBG_INFO)
- fprintf (stderr, "pth_wait: ignoring mutex event.\n");
- break;
- }
+ case PTH_EVENT_FD:
+ if (DBG_INFO)
+ fprintf (stderr, "pth_wait: spawn wait_fd_thread\n");
+ evarray[pos] = ev;
+ waitbuf[pos] = spawn_helper_thread (wait_fd_thread, r);
+ threadlist[threadlistidx++] = waitbuf[pos];
+ pos++;
+ break;
+
+ case PTH_EVENT_TIME:
+ if (DBG_INFO)
+ fprintf (stderr, "pth_wait: spawn wait_timer_thread\n");
+ evarray[pos] = ev;
+ waitbuf[pos] = spawn_helper_thread (wait_timer_thread, r);
+ threadlist[threadlistidx++] = waitbuf[pos];
+ pos++;
+ break;
+
+ case PTH_EVENT_SELECT:
+ if (DBG_INFO)
+ fprintf (stderr, "pth_wait: spawn wait_select_thread.\n");
+ evarray[pos] = ev;
+ waitbuf[pos] = spawn_helper_thread (wait_select_thread, r);
+ threadlist[threadlistidx++] = waitbuf[pos];
+ pos++;
+ break;
+
+ case PTH_EVENT_MUTEX:
+ if (DBG_ERROR)
+ fprintf (stderr, "pth_wait: ignoring mutex event.\n");
+ break;
}
- while ( r != ev );
+ r = r->next;
}
+ while ( r != ev );
+
if (DBG_INFO)
- fprintf (stderr, "%s: pth_wait: set %d\n", log_get_prefix (NULL), pos);
+ fprintf (stderr, "%s: pth_wait: WFMO n=%d\n", log_get_prefix (NULL), pos);
n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE);
- free_helper_threads (waitbuf, hdidx, i);
+ for (i=0; i < threadlistidx; i++)
+ CloseHandle (threadlist[i]);
if (DBG_INFO)
- fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n);
+ fprintf (stderr, "%s: pth_wait: WFMO returned %ld\n",
+ log_get_prefix (NULL), n);
- if (n != WAIT_TIMEOUT)
- return 1;
-
- return 0;
+ if (n >= 0 && n < pos)
+ {
+ int count;
+ /* At least one object has been signaled. Walk over all events
+ with an assigned handle and update the status. We start at N
+ which indicates the lowest signaled event. */
+ for (count = 0, idx = n; idx < pos; idx++)
+ if (idx == n || WaitForSingleObject (waitbuf[idx], 0) == WAIT_OBJECT_0)
+ {
+ ResetEvent (evarray[idx]->hd);
+ evarray[idx]->status = PTH_STATUS_OCCURRED;
+ count++;
+ if (evarray[idx]->u_type == PTH_EVENT_SIGS)
+ *(evarray[idx]->u.sig.signo) = pth_signo;
+ }
+ if (DBG_INFO)
+ fprintf (stderr, "%s: pth_wait: %d events have been signalled\n",
+ log_get_prefix (NULL), count);
+ return count;
+ }
+ else if (n == WAIT_TIMEOUT)
+ return 0;
+ else
+ return -1;
}
+
int
pth_wait (pth_event_t ev)
{
More information about the Gnupg-commits
mailing list