diff options
Diffstat (limited to 'jnlib/w32-pth.c')
-rw-r--r-- | jnlib/w32-pth.c | 1500 |
1 files changed, 0 insertions, 1500 deletions
diff --git a/jnlib/w32-pth.c b/jnlib/w32-pth.c deleted file mode 100644 index 0ef4d9e4e..000000000 --- a/jnlib/w32-pth.c +++ /dev/null @@ -1,1500 +0,0 @@ -/* w32-pth.c - GNU Pth emulation for W32 (MS Windows). - * Copyright (c) 1999-2003 Ralf S. Engelschall <rse@engelschall.com> - * Copyright (C) 2004, 2006 g10 Code GmbH - * - * This file is part of JNLIB. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * JNLIB is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * ------------------------------------------------------------------ - * This code is based on Ralf Engelschall's GNU Pth, a non-preemptive - * thread scheduling library which can be found at - * http://www.gnu.org/software/pth/. MS Windows (W32) specific code - * written by Timo Schulz, g10 Code. - */ - -#include <config.h> -#ifdef HAVE_W32_SYSTEM -#include <windows.h> -#include <stdio.h> -#include <stdlib.h> -#include <io.h> -#include <signal.h> - -#include "logging.h" /* For log_get_prefix () */ - -/* 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. */ -#define W32_PTH_HANDLE_INTERNAL HANDLE -#include "w32-pth.h" - - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif -#if FALSE != 0 || TRUE != 1 -#error TRUE or FALSE defined to wrong values -#endif - - -/* States whether this module has been initialized. */ -static int pth_initialized; - -/* Keeps the current debug level. Define marcos to test them. */ -static int debug_level; -#define DBG_ERROR (debug_level >= 1) -#define DBG_INFO (debug_level >= 2) -#define DBG_CALLS (debug_level >= 3) - -/* Variables to support event handling. */ -static int pth_signo; -static HANDLE pth_signo_ev; - -/* Mutex to make sure only one thread is running. */ -static CRITICAL_SECTION pth_shd; - -/* 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; - union - { - struct sigset_s * sig; - int fd; - struct timeval tv; - pth_mutex_t * mx; - } u; - int * val; - int u_type; - int flags; -}; - - -struct pth_attr_s -{ - unsigned int flags; - unsigned int stack_size; - char * name; -}; - - -/* Object to keep information about a thread. This may eventually be - used to implement a scheduler queue. */ -struct thread_info_s -{ - void *(*thread)(void *); /* The actual thread fucntion. */ - void * arg; /* The argument passed to that fucntion. */ - int joinable; /* True if this Thread is joinable. */ - HANDLE th; /* Handle of this thread. Used by non-joinable - threads to close the handle. */ -}; - - -/* Convenience macro to startup the system. */ -#define implicit_init() do { if (!pth_initialized) pth_init(); } while (0) - -/* Prototypes. */ -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); - - - - -int -pth_init (void) -{ - SECURITY_ATTRIBUTES sa; - WSADATA wsadat; - const char *s; - - if (pth_initialized) - return TRUE; - - debug_level = (s=getenv ("DEBUG_PTH"))? atoi (s):0; - if (debug_level) - fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL)); - - if (WSAStartup (0x202, &wsadat)) - return FALSE; - pth_signo = 0; - InitializeCriticalSection (&pth_shd); - if (pth_signo_ev) - CloseHandle (pth_signo_ev); - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - pth_signo_ev = CreateEvent (&sa, TRUE, FALSE, NULL); - if (!pth_signo_ev) - return FALSE; - - pth_initialized = 1; - EnterCriticalSection (&pth_shd); - return TRUE; -} - - -int -pth_kill (void) -{ - pth_signo = 0; - if (pth_signo_ev) - { - CloseHandle (pth_signo_ev); - pth_signo_ev = NULL; - } - if (pth_initialized) - DeleteCriticalSection (&pth_shd); - WSACleanup (); - pth_initialized = 0; - return TRUE; -} - - -static char * -w32_strerror (char *strerr, size_t strerrsize) -{ - if (strerrsize > 1) - FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (), - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - strerr, strerrsize, NULL); - return strerr; -} - - -static void -enter_pth (const char *function) -{ - /* Fixme: I am not sure whether the same thread my enter a critical - section twice. */ - if (DBG_CALLS) - fprintf (stderr, "%s: enter_pth (%s)\n", - log_get_prefix (NULL), function? function:""); - LeaveCriticalSection (&pth_shd); -} - - -static void -leave_pth (const char *function) -{ - EnterCriticalSection (&pth_shd); - if (DBG_CALLS) - fprintf (stderr, "%s: leave_pth (%s)\n", - log_get_prefix (NULL), function? function:""); -} - - -long -pth_ctrl (unsigned long query, ...) -{ - implicit_init (); - - switch (query) - { - case PTH_CTRL_GETAVLOAD: - case PTH_CTRL_GETPRIO: - case PTH_CTRL_GETNAME: - case PTH_CTRL_GETTHREADS_NEW: - case PTH_CTRL_GETTHREADS_READY: - case PTH_CTRL_GETTHREADS_RUNNING: - case PTH_CTRL_GETTHREADS_WAITING: - case PTH_CTRL_GETTHREADS_SUSPENDED: - case PTH_CTRL_GETTHREADS_DEAD: - case PTH_CTRL_GETTHREADS: - default: - return -1; - } - return 0; -} - - - -pth_time_t -pth_timeout (long sec, long usec) -{ - pth_time_t tvd; - - tvd.tv_sec = sec; - tvd.tv_usec = usec; - return tvd; -} - - -int -pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev) -{ - implicit_init (); - return 0; -} - - -int -pth_read (int fd, void * buffer, size_t size) -{ - int n; - - implicit_init (); - enter_pth (__FUNCTION__); - - n = recv (fd, buffer, size, 0); - if (n == -1 && WSAGetLastError () == WSAENOTSOCK) - { - DWORD nread = 0; - n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL); - if (!n) - { - char strerr[256]; - - if (DBG_ERROR) - fprintf (stderr, "%s: pth_read(%d) failed read from file: %s\n", - log_get_prefix (NULL), fd, - w32_strerror (strerr, sizeof strerr)); - n = -1; - } - else - n = (int)nread; - } - leave_pth (__FUNCTION__); - return n; -} - - -int -pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev) -{ - implicit_init (); - return 0; -} - - -int -pth_write (int fd, const void * buffer, size_t size) -{ - int n; - - implicit_init (); - enter_pth (__FUNCTION__); - n = send (fd, buffer, size, 0); - if (n == -1 && WSAGetLastError () == WSAENOTSOCK) - { - DWORD nwrite; - char strerr[256]; - - /* This is no real error because we first need to figure out if - we have a handle or a socket. */ - - n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL); - if (!n) - { - if (DBG_ERROR) - fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n", - log_get_prefix (NULL), fd, - w32_strerror (strerr, sizeof strerr)); - n = -1; - } - else - n = (int)nwrite; - } - leave_pth (__FUNCTION__); - return n; -} - - -int -pth_select (int nfds, 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); - leave_pth (__FUNCTION__); - return n; -} - - -int -pth_fdmode (int fd, int mode) -{ - unsigned long val; - int ret = PTH_FDMODE_BLOCK; - - implicit_init (); - /* Note: we don't do the eter/leave pth here because this is for one - a fast fucntion and secondly already called from inside such a - block. */ - /* XXX: figure out original fd mode */ - switch (mode) - { - case PTH_FDMODE_NONBLOCK: - val = 1; - if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) - ret = PTH_FDMODE_ERROR; - break; - - case PTH_FDMODE_BLOCK: - val = 0; - if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR) - ret = PTH_FDMODE_ERROR; - break; - } - return ret; -} - - -int -pth_accept (int fd, struct sockaddr *addr, int *addrlen) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - rc = accept (fd, addr, addrlen); - leave_pth (__FUNCTION__); - return rc; -} - - -int -pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen, - pth_event_t ev_extra) -{ - pth_key_t ev_key; - pth_event_t ev; - int rv; - int fdmode; - - implicit_init (); - enter_pth (__FUNCTION__); - - fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK); - if (fdmode == PTH_FDMODE_ERROR) - { - leave_pth (__FUNCTION__); - return -1; - } - - ev = NULL; - while ((rv = accept (fd, addr, addrlen)) == -1 && - (WSAGetLastError () == WSAEINPROGRESS || - WSAGetLastError () == WSAEWOULDBLOCK)) - { - if (!ev) - { - ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE| - PTH_MODE_STATIC, &ev_key, fd); - if (!ev) - { - leave_pth (__FUNCTION__); - return -1; - } - if (ev_extra) - pth_event_concat (ev, ev_extra, NULL); - } - /* Wait until accept has a chance. */ - do_pth_wait (ev); - if (ev_extra) - { - pth_event_isolate (ev); - if (do_pth_event_status (ev) != PTH_STATUS_OCCURRED) - { - pth_fdmode (fd, fdmode); - leave_pth (__FUNCTION__); - return -1; - } - } - } - - pth_fdmode (fd, fdmode); - leave_pth (__FUNCTION__); - return rv; -} - - -int -pth_connect (int fd, struct sockaddr *name, int namelen) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - rc = connect (fd, name, namelen); - leave_pth (__FUNCTION__); - return rc; -} - - -int -pth_mutex_release (pth_mutex_t *mutex) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - - if (!ReleaseMutex (*mutex)) - { - char strerr[256]; - - if (DBG_ERROR) - fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n", - log_get_prefix (NULL), *mutex, - w32_strerror (strerr, sizeof strerr)); - rc = FALSE; - } - else - rc = TRUE; - - leave_pth (__FUNCTION__); - return rc; -} - - -int -pth_mutex_acquire (pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra) -{ - int code; - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - - /* FIXME: ev_extra is not yet supported. */ - - code = WaitForSingleObject (*mutex, INFINITE); - switch (code) - { - case WAIT_FAILED: - { - char strerr[256]; - - if (DBG_ERROR) - fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n", - log_get_prefix (NULL), *mutex, - w32_strerror (strerr, sizeof strerr)); - } - rc = FALSE; - break; - - case WAIT_OBJECT_0: - rc = TRUE; - break; - - default: - if (DBG_ERROR) - fprintf (stderr, "%s: WaitForSingleObject returned unexpected " - "code %d for mutex %p\n", - log_get_prefix (NULL), code, *mutex); - rc = FALSE; - break; - } - - leave_pth (__FUNCTION__); - return rc; -} - - - -int -pth_mutex_init (pth_mutex_t *mutex) -{ - SECURITY_ATTRIBUTES sa; - - implicit_init (); - enter_pth (__FUNCTION__); - - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - *mutex = CreateMutex (&sa, FALSE, NULL); - if (!*mutex) - { - free (*mutex); - *mutex = NULL; - leave_pth (__FUNCTION__); - return FALSE; - } - - leave_pth (__FUNCTION__); - return TRUE; -} - - -pth_attr_t -pth_attr_new (void) -{ - pth_attr_t hd; - - implicit_init (); - hd = calloc (1, sizeof *hd); - return hd; -} - - -int -pth_attr_destroy (pth_attr_t hd) -{ - if (!hd) - return -1; - implicit_init (); - if (hd->name) - free (hd->name); - free (hd); - return TRUE; -} - - -int -pth_attr_set (pth_attr_t hd, int field, ...) -{ - va_list args; - char * str; - int val; - int rc = TRUE; - - implicit_init (); - - va_start (args, field); - switch (field) - { - case PTH_ATTR_JOINABLE: - val = va_arg (args, int); - if (val) - { - hd->flags |= PTH_ATTR_JOINABLE; - if (DBG_INFO) - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n", - log_get_prefix (NULL)); - } - break; - - case PTH_ATTR_STACK_SIZE: - val = va_arg (args, int); - if (val) - { - hd->flags |= PTH_ATTR_STACK_SIZE; - hd->stack_size = val; - if (DBG_INFO) - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n", - log_get_prefix (NULL), val); - } - break; - - case PTH_ATTR_NAME: - str = va_arg (args, char*); - if (hd->name) - free (hd->name); - if (str) - { - hd->name = strdup (str); - if (!hd->name) - return FALSE; - hd->flags |= PTH_ATTR_NAME; - if (DBG_INFO) - fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n", - log_get_prefix (NULL), hd->name); - } - break; - - default: - rc = FALSE; - break; - } - va_end (args); - return rc; -} - - -static pth_t -do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) -{ - SECURITY_ATTRIBUTES sa; - DWORD tid; - HANDLE th; - struct thread_info_s *ctx; - - if (!hd) - return NULL; - - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - - ctx = calloc (1, sizeof *ctx); - if (!ctx) - return NULL; - ctx->thread = func; - ctx->arg = arg; - ctx->joinable = (hd->flags & PTH_ATTR_JOINABLE); - - /* XXX: we don't use all thread attributes. */ - - /* Note that we create the thread suspended so that we are able to - store the thread's handle in the context structure. We need to - do this to be able to close the handle from the launch helper. - - FIXME: We should no use th W32's Thread handle directly but keep - our own thread control structure. CTX may be used for that. */ - if (DBG_INFO) - fprintf (stderr, "%s: do_pth_spawn creating thread ...\n", - log_get_prefix (NULL)); - th = CreateThread (&sa, hd->stack_size, - (LPTHREAD_START_ROUTINE)launch_thread, - ctx, CREATE_SUSPENDED, &tid); - ctx->th = th; - if (DBG_INFO) - fprintf (stderr, "%s: do_pth_spawn created thread %p\n", - log_get_prefix (NULL),th); - if (!th) - free (ctx); - else - ResumeThread (th); - - return th; -} - -pth_t -pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg) -{ - HANDLE th; - - if (!hd) - return NULL; - - implicit_init (); - enter_pth (__FUNCTION__); - th = do_pth_spawn (hd, func, arg); - leave_pth (__FUNCTION__); - return th; -} - - -pth_t -pth_self (void) -{ - return GetCurrentThread (); -} - -int -pth_join (pth_t hd, void **value) -{ - return TRUE; -} - - -/* friendly */ -int -pth_cancel (pth_t hd) -{ - if (!hd) - return -1; - implicit_init (); - enter_pth (__FUNCTION__); - WaitForSingleObject (hd, 1000); - TerminateThread (hd, 0); - leave_pth (__FUNCTION__); - return TRUE; -} - - -/* cruel */ -int -pth_abort (pth_t hd) -{ - if (!hd) - return -1; - implicit_init (); - enter_pth (__FUNCTION__); - TerminateThread (hd, 0); - leave_pth (__FUNCTION__); - return TRUE; -} - - -void -pth_exit (void *value) -{ - implicit_init (); - enter_pth (__FUNCTION__); - pth_kill (); - leave_pth (__FUNCTION__); - exit ((int)(long)value); -} - - -static unsigned int -do_pth_waitpid (unsigned pid, int * status, int options) -{ -#if 0 - pth_event_t ev; - static pth_key_t ev_key = PTH_KEY_INIT; - pid_t pid; - - pth_debug2("pth_waitpid: called from thread \"%s\"", pth_current->name); - - for (;;) - { - /* do a non-blocking poll for the pid */ - while ( (pid = pth_sc(waitpid)(wpid, status, options|WNOHANG)) < 0 - && errno == EINTR) - ; - - /* if pid was found or caller requested a polling return immediately */ - if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG))) - break; - - /* else wait a little bit */ - ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, - pth_timeout (0,250000)); - pth_wait(ev); - } - - pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name); -#endif - return 0; -} - - -unsigned int -pth_waitpid (unsigned pid, int * status, int options) -{ - unsigned int n; - - implicit_init (); - enter_pth (__FUNCTION__); - n = do_pth_waitpid (pid, status, options); - leave_pth (__FUNCTION__); - return n; -} - - -static BOOL WINAPI -sig_handler (DWORD signo) -{ - switch (signo) - { - case CTRL_C_EVENT: pth_signo = SIGINT; break; - case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break; - } - SetEvent (pth_signo_ev); - if (DBG_INFO) - fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo); - return TRUE; -} - - -static pth_event_t -do_pth_event_body (unsigned long spec, va_list arg) -{ - SECURITY_ATTRIBUTES sa; - pth_event_t ev; - int rc; - - 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; - 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 *); - rc = SetConsoleCtrlHandler (sig_handler, TRUE); - if (DBG_INFO) - fprintf (stderr, "%s: pth_event: sigs rc=%d\n", - log_get_prefix (NULL), rc); - } - else if (spec & PTH_EVENT_FD) - { - 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", - log_get_prefix (NULL), ev->u.fd); - } - 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; - ev->u.tv.tv_usec = t.tv_usec; - } - 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*); - } - - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - ev->hd = CreateEvent (&sa, FALSE, FALSE, NULL); - if (!ev->hd) - { - free (ev); - return NULL; - } - ev->next = ev; - ev->prev = ev; - - return ev; -} - -static pth_event_t -do_pth_event (unsigned long spec, ...) -{ - va_list arg; - pth_event_t ev; - - va_start (arg, spec); - ev = do_pth_event_body (spec, arg); - va_end (arg); - - return ev; -} - -pth_event_t -pth_event (unsigned long spec, ...) -{ - va_list arg; - pth_event_t ev; - - implicit_init (); - enter_pth (__FUNCTION__); - - va_start (arg, spec); - ev = do_pth_event_body (spec, arg); - va_end (arg); - - leave_pth (__FUNCTION__); - return ev; -} - - -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_t evn; - va_list ap; - - if (!evf) - return NULL; - - implicit_init (); - - va_start (ap, evf); - while ((evn = va_arg(ap, pth_event_t)) != NULL) - pth_event_add (evf, evn); - va_end (ap); - - return evf; -} - - -static int -wait_for_fd (int fd, int is_read, int nwait) -{ - struct timeval tv; - fd_set r; - fd_set w; - int n; - - FD_ZERO (&r); - FD_ZERO (&w); - FD_SET (fd, is_read ? &r : &w); - - tv.tv_sec = nwait; - tv.tv_usec = 0; - - while (1) - { - n = select (fd+1, &r, &w, NULL, &tv); - if (DBG_INFO) - fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n", - log_get_prefix (NULL), n, fd,(int)WSAGetLastError ()); - if (n == -1) - break; - if (!n) - continue; - if (n == 1) - { - if (is_read && FD_ISSET (fd, &r)) - break; - else if (FD_ISSET (fd, &w)) - break; - } - } - return 0; -} - - -static void * -launch_thread (void *arg) -{ - struct thread_info_s *c = arg; - - if (c) - { - leave_pth (__FUNCTION__); - c->thread (c->arg); - if (!c->joinable && c->th) - { - CloseHandle (c->th); - c->th = NULL; - } - /* FIXME: We would badly fail if someone accesses the now - deallocated handle. Don't use it directly but setup proper - scheduling queues. */ - enter_pth (__FUNCTION__); - free (c); - } - ExitThread (0); - return NULL; -} - -/* void */ -/* sigemptyset (struct sigset_s * ss) */ -/* { */ -/* if (ss) { */ -/* memset (ss->sigs, 0, sizeof ss->sigs); */ -/* ss->idx = 0; */ -/* } */ -/* } */ - - -/* int */ -/* sigaddset (struct sigset_s * ss, int signo) */ -/* { */ -/* if (!ss) */ -/* return -1; */ -/* if (ss->idx + 1 > 64) */ -/* return -1; */ -/* ss->sigs[ss->idx] = signo; */ -/* ss->idx++; */ -/* return 0; */ -/* } */ - - -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; -} - - -static int -do_pth_event_occurred (pth_event_t ev) -{ - 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); - 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) -{ - if (!ev) - return 0; - if (pth_event_occurred (ev)) - return PTH_STATUS_OCCURRED; - return 0; -} - - -static int -do_pth_event_free (pth_event_t ev, int mode) -{ - if (!ev) - return FALSE; - - if (mode == PTH_FREE_ALL) - { - pth_event_t cur = ev; - do - { - pth_event_t next = cur->next; - CloseHandle (cur->hd); - cur->hd = NULL; - free (cur); - cur = next; - } - while (cur != ev); - } - else if (mode == PTH_FREE_THIS) - { - ev->prev->next = ev->next; - ev->next->prev = ev->prev; - CloseHandle (ev->hd); - ev->hd = NULL; - free (ev); - } - else - return FALSE; - - return TRUE; -} - -int -pth_event_free (pth_event_t ev, int mode) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - rc = do_pth_event_free (ev, mode); - leave_pth (__FUNCTION__); - return rc; -} - - -pth_event_t -pth_event_isolate (pth_event_t ev) -{ - pth_event_t ring; - - if (!ev) - return NULL; - if (ev->next == ev && ev->prev == ev) - return NULL; /* Only one event. */ - - ring = ev->next; - ev->prev->next = ev->next; - ev->next->prev = ev->prev; - ev->prev = ev; - ev->next = ev; - return ring; -} - - -static int -event_count (pth_event_t ev) -{ - pth_event_t r; - int cnt = 0; - - if (ev) - { - r = ev; - do - { - cnt++; - r = r->next; - } - while (r != ev); - } - - return cnt; -} - - - -static pth_t -spawn_helper_thread (void *(*func)(void *), void *arg) -{ - SECURITY_ATTRIBUTES sa; - DWORD tid; - HANDLE th; - - memset (&sa, 0, sizeof sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - sa.nLength = sizeof sa; - - if (DBG_INFO) - fprintf (stderr, "%s: spawn_helper_thread creating thread ...\n", - log_get_prefix (NULL)); - th = CreateThread (&sa, 32*1024, - (LPTHREAD_START_ROUTINE)func, - arg, 0, &tid); - if (DBG_INFO) - fprintf (stderr, "%s: spawn_helper_thread created thread %p\n", - log_get_prefix (NULL), th); - - return th; -} - - -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) -{ - pth_event_t ev = ctx; - - wait_for_fd (ev->u.fd, ev->flags & PTH_UNTIL_FD_READABLE, 3600); - if (DBG_INFO) - fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL)); - SetEvent (ev->hd); - ExitThread (0); - return NULL; -} - - -static void * -wait_timer_thread (void * ctx) -{ - pth_event_t ev = ctx; - int n = ev->u.tv.tv_sec*1000; - Sleep (n); - SetEvent (ev->hd); - if (DBG_INFO) - fprintf (stderr, "%s: wait_timer_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; - - if (!ev) - return 0; - - n = event_count (ev); - if (n > MAXIMUM_WAIT_OBJECTS/2) - return -1; - - if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n); - if (ev) - { - pth_event_t r = ev; - do - { - 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_MUTEX: - if (DBG_INFO) - fprintf (stderr, "pth_wait: ignoring mutex event.\n"); - break; - } - } - while ( r != ev ); - } - if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: set %d\n", log_get_prefix (NULL), pos); - n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE); - free_helper_threads (waitbuf, hdidx, i); - if (DBG_INFO) - fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n); - - if (n != WAIT_TIMEOUT) - return 1; - - return 0; -} - -int -pth_wait (pth_event_t ev) -{ - int rc; - - implicit_init (); - enter_pth (__FUNCTION__); - rc = do_pth_wait (ev); - leave_pth (__FUNCTION__); - return rc; -} - - -int -pth_sleep (int sec) -{ - static pth_key_t ev_key = PTH_KEY_INIT; - pth_event_t ev; - - implicit_init (); - enter_pth (__FUNCTION__); - - if (sec == 0) - { - leave_pth (__FUNCTION__); - return 0; - } - - ev = do_pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, - pth_timeout (sec, 0)); - if (ev == NULL) - { - leave_pth (__FUNCTION__); - return -1; - } - do_pth_wait (ev); - do_pth_event_free (ev, PTH_FREE_ALL); - - leave_pth (__FUNCTION__); - return 0; -} - - - - - -/* - Some simple tests. - */ -#ifdef TEST -#include <stdio.h> - -void * thread (void * c) -{ - - Sleep (2000); - SetEvent (((pth_event_t)c)->hd); - fprintf (stderr, "\n\nhallo!.\n"); - pth_exit (NULL); - return NULL; -} - - -int main_1 (int argc, char ** argv) -{ - pth_attr_t t; - pth_t hd; - pth_event_t ev; - - pth_init (); - ev = pth_event (0, NULL); - t = pth_attr_new (); - pth_attr_set (t, PTH_ATTR_JOINABLE, 1); - pth_attr_set (t, PTH_ATTR_STACK_SIZE, 4096); - pth_attr_set (t, PTH_ATTR_NAME, "hello"); - hd = pth_spawn (t, thread, ev); - - pth_wait (ev); - pth_attr_destroy (t); - pth_event_free (ev, 0); - pth_kill (); - - return 0; -} - - -static pth_event_t -setup_signals (struct sigset_s *sigs, int *signo) -{ - pth_event_t ev; - - sigemptyset (sigs); - sigaddset (sigs, SIGINT); - sigaddset (sigs, SIGTERM); - - ev = pth_event (PTH_EVENT_SIGS, sigs, signo); - return ev; -} - -int -main_2 (int argc, char ** argv) -{ - pth_event_t ev; - struct sigset_s sigs; - int signo = 0; - - pth_init (); - ev = setup_signals (&sigs, &signo); - pth_wait (ev); - if (pth_event_occured (ev) && signo) - fprintf (stderr, "signal caught! signo %d\n", signo); - - pth_event_free (ev, PTH_FREE_ALL); - pth_kill (); - return 0; -} - -int -main_3 (int argc, char ** argv) -{ - struct sockaddr_in addr, rem; - int fd, n = 0, infd; - int signo = 0; - struct sigset_s sigs; - pth_event_t ev; - - pth_init (); - fd = socket (AF_INET, SOCK_STREAM, 0); - - memset (&addr, 0, sizeof addr); - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons (5050); - addr.sin_family = AF_INET; - bind (fd, (struct sockaddr*)&addr, sizeof addr); - listen (fd, 5); - - ev = setup_signals (&sigs, &signo); - n = sizeof addr; - infd = pth_accept_ev (fd, (struct sockaddr *)&rem, &n, ev); - fprintf (stderr, "infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr), - htons (rem.sin_port)); - - closesocket (infd); - pth_event_free (ev, PTH_FREE_ALL); - pth_kill (); - return 0; -} - -int -main (int argc, char ** argv) -{ - pth_event_t ev; - pth_key_t ev_key; - - pth_init (); - /*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0)); - pth_wait (ev); - pth_event_free (ev, PTH_FREE_ALL);*/ - pth_sleep (5); - pth_kill (); - return 0; -} -#endif - -#endif /*HAVE_W32_SYSTEM*/ - |