2004-12-07 11:21:40 +00:00
|
|
|
|
/* w32-pth.c - GNU Pth emulation for W32 (MS Windows).
|
2004-12-13 09:05:31 +00:00
|
|
|
|
* Copyright (c) 1999-2003 Ralf S. Engelschall <rse@engelschall.com>
|
2004-12-07 11:21:40 +00:00
|
|
|
|
* Copyright (C) 2004 g10 Code GmbH
|
|
|
|
|
*
|
|
|
|
|
* This file is part of GnuPG.
|
|
|
|
|
*
|
2004-12-14 11:25:04 +00:00
|
|
|
|
* GnuPG 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.
|
2004-12-07 11:21:40 +00:00
|
|
|
|
*
|
2004-12-14 11:25:04 +00:00
|
|
|
|
* GnuPG 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.
|
2004-12-07 11:21:40 +00:00
|
|
|
|
*
|
2004-12-14 11:25:04 +00:00
|
|
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
2004-12-13 09:05:31 +00:00
|
|
|
|
*
|
|
|
|
|
* ------------------------------------------------------------------
|
|
|
|
|
* 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.
|
2004-12-07 11:21:40 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#ifdef HAVE_W32_SYSTEM
|
|
|
|
|
#include <windows.h>
|
2004-12-13 18:00:35 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2004-12-07 11:21:40 +00:00
|
|
|
|
#include <io.h>
|
2004-12-13 09:05:31 +00:00
|
|
|
|
#include <signal.h>
|
2004-12-07 11:21:40 +00:00
|
|
|
|
|
2004-12-18 18:53:32 +00:00
|
|
|
|
#include "logging.h" /* For log_get_prefix () */
|
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
/* 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
|
2004-12-07 11:21:40 +00:00
|
|
|
|
#include "w32-pth.h"
|
|
|
|
|
|
2004-12-19 13:38:24 +00:00
|
|
|
|
|
2004-12-18 18:53:32 +00:00
|
|
|
|
#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
|
|
|
|
|
|
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
/* States whether this module has been initialized. */
|
2004-12-19 13:38:24 +00:00
|
|
|
|
static int pth_initialized;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
/* 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)
|
2004-12-13 18:00:35 +00:00
|
|
|
|
|
|
|
|
|
/* Variables to support event handling. */
|
2004-12-19 13:38:24 +00:00
|
|
|
|
static int pth_signo;
|
|
|
|
|
static HANDLE pth_signo_ev;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
/* Mutex to make sure only one thread is running. */
|
|
|
|
|
static CRITICAL_SECTION pth_shd;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
/* Events are store in a double linked event ring. */
|
2004-12-13 18:00:35 +00:00
|
|
|
|
struct pth_event_s
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct pth_attr_s
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
unsigned int flags;
|
|
|
|
|
unsigned int stack_size;
|
|
|
|
|
char * name;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 19:20:36 +00:00
|
|
|
|
/* Object to keep information about a thread. This may eventually be
|
|
|
|
|
used to implement a scheduler queue. */
|
|
|
|
|
struct thread_info_s
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
2004-12-14 19:20:36 +00:00
|
|
|
|
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. */
|
2004-12-13 09:05:31 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 19:20:36 +00:00
|
|
|
|
/* Convenience macro to startup the system. */
|
|
|
|
|
#define implicit_init() do { if (!pth_initialized) pth_init(); } while (0)
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
/* 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);
|
2004-12-14 19:20:36 +00:00
|
|
|
|
static void *launch_thread (void * ctx);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_init (void)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
|
WSADATA wsadat;
|
2004-12-20 11:36:46 +00:00
|
|
|
|
const char *s;
|
2004-12-14 11:25:04 +00:00
|
|
|
|
|
2004-12-18 18:53:32 +00:00
|
|
|
|
if (pth_initialized)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
debug_level = (s=getenv ("DEBUG_PTH"))? atoi (s):0;
|
|
|
|
|
if (debug_level)
|
|
|
|
|
fprintf (stderr, "%s: pth_init: called.\n", log_get_prefix (NULL));
|
2004-12-19 13:38:24 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (WSAStartup (0x202, &wsadat))
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return FALSE;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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)
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
pth_initialized = 1;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
EnterCriticalSection (&pth_shd);
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return TRUE;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_kill (void)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_signo = 0;
|
|
|
|
|
if (pth_signo_ev)
|
2004-12-14 17:47:12 +00:00
|
|
|
|
{
|
|
|
|
|
CloseHandle (pth_signo_ev);
|
|
|
|
|
pth_signo_ev = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (pth_initialized)
|
|
|
|
|
DeleteCriticalSection (&pth_shd);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
WSACleanup ();
|
|
|
|
|
pth_initialized = 0;
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return TRUE;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 19:20:36 +00:00
|
|
|
|
static char *
|
|
|
|
|
w32_strerror (char *strerr, size_t strerrsize)
|
2004-12-14 17:47:12 +00:00
|
|
|
|
{
|
2004-12-14 19:20:36 +00:00
|
|
|
|
if (strerrsize > 1)
|
|
|
|
|
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, (int)GetLastError (),
|
|
|
|
|
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
|
strerr, strerrsize, NULL);
|
2004-12-14 17:47:12 +00:00
|
|
|
|
return strerr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
static void
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (const char *function)
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
2004-12-14 11:25:04 +00:00
|
|
|
|
/* Fixme: I am not sure whether the same thread my enter a critical
|
|
|
|
|
section twice. */
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_CALLS)
|
2004-12-19 13:38:24 +00:00
|
|
|
|
fprintf (stderr, "%s: enter_pth (%s)\n",
|
|
|
|
|
log_get_prefix (NULL), function? function:"");
|
2004-12-14 11:25:04 +00:00
|
|
|
|
LeaveCriticalSection (&pth_shd);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (const char *function)
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
2004-12-14 11:25:04 +00:00
|
|
|
|
EnterCriticalSection (&pth_shd);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_CALLS)
|
2004-12-19 13:38:24 +00:00
|
|
|
|
fprintf (stderr, "%s: leave_pth (%s)\n",
|
|
|
|
|
log_get_prefix (NULL), function? function:"");
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long
|
|
|
|
|
pth_ctrl (unsigned long query, ...)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
switch (query)
|
|
|
|
|
{
|
2004-12-13 09:05:31 +00:00
|
|
|
|
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:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
case PTH_CTRL_GETTHREADS:
|
2004-12-13 09:05:31 +00:00
|
|
|
|
default:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return -1;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return 0;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pth_time_t
|
|
|
|
|
pth_timeout (long sec, long usec)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_time_t tvd;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
tvd.tv_sec = sec;
|
|
|
|
|
tvd.tv_usec = usec;
|
|
|
|
|
return tvd;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_read_ev (int fd, void *buffer, size_t size, pth_event_t ev)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
|
|
|
|
return 0;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_read (int fd, void * buffer, size_t size)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
n = recv (fd, buffer, size, 0);
|
|
|
|
|
if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
|
|
|
|
|
{
|
|
|
|
|
DWORD nread = 0;
|
|
|
|
|
n = ReadFile ((HANDLE)fd, buffer, size, &nread, NULL);
|
|
|
|
|
if (!n)
|
2004-12-14 17:47:12 +00:00
|
|
|
|
{
|
2004-12-14 19:20:36 +00:00
|
|
|
|
char strerr[256];
|
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
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));
|
2004-12-14 17:47:12 +00:00
|
|
|
|
n = -1;
|
|
|
|
|
}
|
2004-12-14 11:25:04 +00:00
|
|
|
|
else
|
|
|
|
|
n = (int)nread;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return n;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_write_ev (int fd, const void *buffer, size_t size, pth_event_t ev)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
|
|
|
|
return 0;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_write (int fd, const void * buffer, size_t size)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
n = send (fd, buffer, size, 0);
|
|
|
|
|
if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
|
|
|
|
|
{
|
|
|
|
|
DWORD nwrite;
|
2004-12-14 19:20:36 +00:00
|
|
|
|
char strerr[256];
|
2004-12-14 17:47:12 +00:00
|
|
|
|
|
2004-12-14 19:20:36 +00:00
|
|
|
|
/* This is no real error because we first need to figure out if
|
|
|
|
|
we have a handle or a socket. */
|
2004-12-14 17:47:12 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
n = WriteFile ((HANDLE)fd, buffer, size, &nwrite, NULL);
|
|
|
|
|
if (!n)
|
2004-12-14 11:25:04 +00:00
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_ERROR)
|
|
|
|
|
fprintf (stderr, "%s: pth_write(%d) failed in write: %s\n",
|
|
|
|
|
log_get_prefix (NULL), fd,
|
|
|
|
|
w32_strerror (strerr, sizeof strerr));
|
2004-12-14 11:25:04 +00:00
|
|
|
|
n = -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
n = (int)nwrite;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return n;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_select (int nfds, fd_set * rfds, fd_set * wfds, fd_set * efds,
|
|
|
|
|
const struct timeval * timeout)
|
2004-12-07 11:21:40 +00:00
|
|
|
|
{
|
2004-12-14 11:25:04 +00:00
|
|
|
|
int n;
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
|
|
|
|
n = select (nfds, rfds, wfds, efds, timeout);
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
return n;
|
2004-12-07 11:21:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_fdmode (int fd, int mode)
|
2004-12-07 11:21:40 +00:00
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
unsigned long val;
|
2004-12-14 11:25:04 +00:00
|
|
|
|
int ret = PTH_FDMODE_BLOCK;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
/* 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. */
|
2004-12-13 18:00:35 +00:00
|
|
|
|
/* XXX: figure out original fd mode */
|
|
|
|
|
switch (mode)
|
|
|
|
|
{
|
2004-12-13 09:05:31 +00:00
|
|
|
|
case PTH_FDMODE_NONBLOCK:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
val = 1;
|
|
|
|
|
if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR)
|
2004-12-14 11:25:04 +00:00
|
|
|
|
ret = PTH_FDMODE_ERROR;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
case PTH_FDMODE_BLOCK:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
val = 0;
|
|
|
|
|
if (ioctlsocket (fd, FIONBIO, &val) == SOCKET_ERROR)
|
2004-12-14 11:25:04 +00:00
|
|
|
|
ret = PTH_FDMODE_ERROR;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-14 11:25:04 +00:00
|
|
|
|
return ret;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_accept (int fd, struct sockaddr *addr, int *addrlen)
|
|
|
|
|
{
|
2004-12-14 11:25:04 +00:00
|
|
|
|
int rc;
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
|
|
|
|
rc = accept (fd, addr, addrlen);
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
return rc;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_accept_ev (int fd, struct sockaddr *addr, int *addrlen,
|
|
|
|
|
pth_event_t ev_extra)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_key_t ev_key;
|
|
|
|
|
pth_event_t ev;
|
|
|
|
|
int rv;
|
|
|
|
|
int fdmode;
|
|
|
|
|
|
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
|
|
|
|
|
fdmode = pth_fdmode (fd, PTH_FDMODE_NONBLOCK);
|
|
|
|
|
if (fdmode == PTH_FDMODE_ERROR)
|
2004-12-14 11:25:04 +00:00
|
|
|
|
{
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
|
|
|
|
|
ev = NULL;
|
|
|
|
|
while ((rv = accept (fd, addr, addrlen)) == -1 &&
|
|
|
|
|
(WSAGetLastError () == WSAEINPROGRESS ||
|
|
|
|
|
WSAGetLastError () == WSAEWOULDBLOCK))
|
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (!ev)
|
2004-12-14 17:47:12 +00:00
|
|
|
|
{
|
|
|
|
|
ev = do_pth_event (PTH_EVENT_FD|PTH_UNTIL_FD_READABLE|
|
|
|
|
|
PTH_MODE_STATIC, &ev_key, fd);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (!ev)
|
2004-12-14 17:47:12 +00:00
|
|
|
|
{
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (ev_extra)
|
2004-12-14 17:47:12 +00:00
|
|
|
|
pth_event_concat (ev, ev_extra, NULL);
|
|
|
|
|
}
|
2004-12-14 11:25:04 +00:00
|
|
|
|
/* Wait until accept has a chance. */
|
|
|
|
|
do_pth_wait (ev);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (ev_extra)
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
|
|
|
|
pth_event_isolate (ev);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
if (do_pth_event_status (ev) != PTH_STATUS_OCCURRED)
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
|
|
|
|
pth_fdmode (fd, fdmode);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return -1;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_fdmode (fd, fdmode);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return rv;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_connect (int fd, struct sockaddr *name, int namelen)
|
|
|
|
|
{
|
2004-12-14 11:25:04 +00:00
|
|
|
|
int rc;
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
|
|
|
|
rc = connect (fd, name, namelen);
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
return rc;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2004-12-19 17:44:20 +00:00
|
|
|
|
pth_mutex_release (pth_mutex_t *mutex)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-19 17:44:20 +00:00
|
|
|
|
int rc;
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
2004-12-19 17:44:20 +00:00
|
|
|
|
|
|
|
|
|
if (!ReleaseMutex (*mutex))
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
2004-12-19 17:44:20 +00:00
|
|
|
|
char strerr[256];
|
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_ERROR)
|
|
|
|
|
fprintf (stderr, "%s: pth_release_mutex %p failed: %s\n",
|
|
|
|
|
log_get_prefix (NULL), *mutex,
|
|
|
|
|
w32_strerror (strerr, sizeof strerr));
|
2004-12-19 17:44:20 +00:00
|
|
|
|
rc = FALSE;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-19 17:44:20 +00:00
|
|
|
|
else
|
|
|
|
|
rc = TRUE;
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-19 17:44:20 +00:00
|
|
|
|
return rc;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2004-12-19 17:44:20 +00:00
|
|
|
|
pth_mutex_acquire (pth_mutex_t *mutex, int tryonly, pth_event_t ev_extra)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-19 17:44:20 +00:00
|
|
|
|
int code;
|
|
|
|
|
int rc;
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-19 17:44:20 +00:00
|
|
|
|
/* FIXME: ev_extra is not yet supported. */
|
|
|
|
|
|
|
|
|
|
code = WaitForSingleObject (*mutex, INFINITE);
|
|
|
|
|
switch (code)
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
2004-12-19 17:44:20 +00:00
|
|
|
|
case WAIT_FAILED:
|
2004-12-14 17:47:12 +00:00
|
|
|
|
{
|
2004-12-19 17:44:20 +00:00
|
|
|
|
char strerr[256];
|
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_ERROR)
|
|
|
|
|
fprintf (stderr, "%s: pth_mutex_acquire for %p failed: %s\n",
|
|
|
|
|
log_get_prefix (NULL), *mutex,
|
|
|
|
|
w32_strerror (strerr, sizeof strerr));
|
2004-12-14 17:47:12 +00:00
|
|
|
|
}
|
2004-12-19 17:44:20 +00:00
|
|
|
|
rc = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case WAIT_OBJECT_0:
|
|
|
|
|
rc = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_ERROR)
|
|
|
|
|
fprintf (stderr, "%s: WaitForSingleObject returned unexpected "
|
|
|
|
|
"code %d for mutex %p\n",
|
|
|
|
|
log_get_prefix (NULL), code, *mutex);
|
2004-12-19 17:44:20 +00:00
|
|
|
|
rc = FALSE;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-19 17:44:20 +00:00
|
|
|
|
return rc;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-19 17:44:20 +00:00
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
int
|
2004-12-19 17:44:20 +00:00
|
|
|
|
pth_mutex_init (pth_mutex_t *mutex)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
|
|
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
memset (&sa, 0, sizeof sa);
|
|
|
|
|
sa.bInheritHandle = TRUE;
|
|
|
|
|
sa.lpSecurityDescriptor = NULL;
|
|
|
|
|
sa.nLength = sizeof sa;
|
2004-12-19 17:44:20 +00:00
|
|
|
|
*mutex = CreateMutex (&sa, FALSE, NULL);
|
|
|
|
|
if (!*mutex)
|
|
|
|
|
{
|
|
|
|
|
free (*mutex);
|
|
|
|
|
*mutex = NULL;
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return TRUE;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pth_attr_t
|
|
|
|
|
pth_attr_new (void)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_attr_t hd;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
|
|
|
|
hd = calloc (1, sizeof *hd);
|
|
|
|
|
return hd;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_attr_destroy (pth_attr_t hd)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (!hd)
|
|
|
|
|
return -1;
|
|
|
|
|
implicit_init ();
|
|
|
|
|
if (hd->name)
|
|
|
|
|
free (hd->name);
|
|
|
|
|
free (hd);
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return TRUE;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_attr_set (pth_attr_t hd, int field, ...)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
va_list args;
|
|
|
|
|
char * str;
|
|
|
|
|
int val;
|
2004-12-18 18:53:32 +00:00
|
|
|
|
int rc = TRUE;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
|
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
va_start (args, field);
|
|
|
|
|
switch (field)
|
|
|
|
|
{
|
2004-12-13 09:05:31 +00:00
|
|
|
|
case PTH_ATTR_JOINABLE:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
val = va_arg (args, int);
|
|
|
|
|
if (val)
|
|
|
|
|
{
|
|
|
|
|
hd->flags |= PTH_ATTR_JOINABLE;
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_JOINABLE\n",
|
|
|
|
|
log_get_prefix (NULL));
|
2004-12-13 18:00:35 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
case PTH_ATTR_STACK_SIZE:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
val = va_arg (args, int);
|
|
|
|
|
if (val)
|
|
|
|
|
{
|
|
|
|
|
hd->flags |= PTH_ATTR_STACK_SIZE;
|
|
|
|
|
hd->stack_size = val;
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_STACK_SIZE %d\n",
|
|
|
|
|
log_get_prefix (NULL), val);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
case PTH_ATTR_NAME:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
str = va_arg (args, char*);
|
|
|
|
|
if (hd->name)
|
|
|
|
|
free (hd->name);
|
|
|
|
|
if (str)
|
|
|
|
|
{
|
|
|
|
|
hd->name = strdup (str);
|
|
|
|
|
if (!hd->name)
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return FALSE;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
hd->flags |= PTH_ATTR_NAME;
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_attr_set: PTH_ATTR_NAME %s\n",
|
|
|
|
|
log_get_prefix (NULL), hd->name);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
default:
|
2004-12-18 18:53:32 +00:00
|
|
|
|
rc = FALSE;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
va_end (args);
|
|
|
|
|
return rc;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 14:49:21 +00:00
|
|
|
|
static pth_t
|
|
|
|
|
do_pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
|
DWORD tid;
|
|
|
|
|
HANDLE th;
|
2004-12-14 19:20:36 +00:00
|
|
|
|
struct thread_info_s *ctx;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (!hd)
|
|
|
|
|
return NULL;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
memset (&sa, 0, sizeof sa);
|
|
|
|
|
sa.bInheritHandle = TRUE;
|
|
|
|
|
sa.lpSecurityDescriptor = NULL;
|
|
|
|
|
sa.nLength = sizeof sa;
|
|
|
|
|
|
2004-12-14 19:20:36 +00:00
|
|
|
|
ctx = calloc (1, sizeof *ctx);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
if (!ctx)
|
2004-12-14 14:49:21 +00:00
|
|
|
|
return NULL;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
ctx->thread = func;
|
|
|
|
|
ctx->arg = arg;
|
2004-12-14 19:20:36 +00:00
|
|
|
|
ctx->joinable = (hd->flags & PTH_ATTR_JOINABLE);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
|
|
|
|
|
/* XXX: we don't use all thread attributes. */
|
2004-12-14 11:25:04 +00:00
|
|
|
|
|
2004-12-14 19:20:36 +00:00
|
|
|
|
/* 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. */
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: do_pth_spawn creating thread ...\n",
|
|
|
|
|
log_get_prefix (NULL));
|
2004-12-13 18:00:35 +00:00
|
|
|
|
th = CreateThread (&sa, hd->stack_size,
|
2004-12-14 19:20:36 +00:00
|
|
|
|
(LPTHREAD_START_ROUTINE)launch_thread,
|
|
|
|
|
ctx, CREATE_SUSPENDED, &tid);
|
|
|
|
|
ctx->th = th;
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: do_pth_spawn created thread %p\n",
|
|
|
|
|
log_get_prefix (NULL),th);
|
2004-12-14 19:20:36 +00:00
|
|
|
|
if (!th)
|
|
|
|
|
free (ctx);
|
|
|
|
|
else
|
|
|
|
|
ResumeThread (th);
|
|
|
|
|
|
2004-12-14 14:49:21 +00:00
|
|
|
|
return th;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pth_t
|
|
|
|
|
pth_spawn (pth_attr_t hd, void *(*func)(void *), void *arg)
|
|
|
|
|
{
|
|
|
|
|
HANDLE th;
|
|
|
|
|
|
|
|
|
|
if (!hd)
|
|
|
|
|
return NULL;
|
2004-12-14 11:25:04 +00:00
|
|
|
|
|
2004-12-14 14:49:21 +00:00
|
|
|
|
implicit_init ();
|
|
|
|
|
enter_pth (__FUNCTION__);
|
|
|
|
|
th = do_pth_spawn (hd, func, arg);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return th;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-19 17:44:20 +00:00
|
|
|
|
pth_t
|
|
|
|
|
pth_self (void)
|
|
|
|
|
{
|
|
|
|
|
return GetCurrentThread ();
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
int
|
|
|
|
|
pth_join (pth_t hd, void **value)
|
|
|
|
|
{
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return TRUE;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* friendly */
|
|
|
|
|
int
|
|
|
|
|
pth_cancel (pth_t hd)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (!hd)
|
|
|
|
|
return -1;
|
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
WaitForSingleObject (hd, 1000);
|
|
|
|
|
TerminateThread (hd, 0);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return TRUE;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* cruel */
|
|
|
|
|
int
|
|
|
|
|
pth_abort (pth_t hd)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (!hd)
|
|
|
|
|
return -1;
|
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
TerminateThread (hd, 0);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return TRUE;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
pth_exit (void *value)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_kill ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
exit ((int)(long)value);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
static unsigned int
|
|
|
|
|
do_pth_waitpid (unsigned pid, int * status, int options)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
|
|
|
|
#if 0
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
#endif
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return 0;
|
2004-12-07 11:21:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
static BOOL WINAPI
|
|
|
|
|
sig_handler (DWORD signo)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
switch (signo)
|
|
|
|
|
{
|
2004-12-13 09:05:31 +00:00
|
|
|
|
case CTRL_C_EVENT: pth_signo = SIGINT; break;
|
|
|
|
|
case CTRL_BREAK_EVENT: pth_signo = SIGTERM; break;
|
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
SetEvent (pth_signo_ev);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: sig_handler=%d\n", log_get_prefix (NULL), pth_signo);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return TRUE;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
static pth_event_t
|
|
|
|
|
do_pth_event_body (unsigned long spec, va_list arg)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
|
pth_event_t ev;
|
|
|
|
|
int rc;
|
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_event spec=%lu\n", log_get_prefix (NULL), spec);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_event: sigs rc=%d\n",
|
|
|
|
|
log_get_prefix (NULL), rc);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_event: fd=%d\n",
|
|
|
|
|
log_get_prefix (NULL), ev->u.fd);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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*);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-20 11:36:46 +00:00
|
|
|
|
ev->next = ev;
|
|
|
|
|
ev->prev = ev;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return ev;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
pth_event_add (pth_event_t root, pth_event_t node)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_event_t n;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
for (n=root; n->next; n = n->next)
|
|
|
|
|
;
|
|
|
|
|
n->next = node;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pth_event_t
|
|
|
|
|
pth_event_concat (pth_event_t evf, ...)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_event_t evn;
|
|
|
|
|
va_list ap;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (!evf)
|
|
|
|
|
return NULL;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
va_start (ap, evf);
|
|
|
|
|
while ((evn = va_arg(ap, pth_event_t)) != NULL)
|
|
|
|
|
pth_event_add (evf, evn);
|
|
|
|
|
va_end (ap);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return evf;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
wait_for_fd (int fd, int is_read, int nwait)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: wait_for_fd=%d fd %d (ec=%d)\n",
|
|
|
|
|
log_get_prefix (NULL), n, fd,(int)WSAGetLastError ());
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void *
|
2004-12-14 19:20:36 +00:00
|
|
|
|
launch_thread (void *arg)
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
2004-12-14 19:20:36 +00:00
|
|
|
|
struct thread_info_s *c = arg;
|
2004-12-14 17:47:12 +00:00
|
|
|
|
|
|
|
|
|
if (c)
|
|
|
|
|
{
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
c->thread (c->arg);
|
2004-12-14 19:20:36 +00:00
|
|
|
|
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. */
|
2004-12-14 17:47:12 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
|
|
|
|
free (c);
|
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
ExitThread (0);
|
|
|
|
|
return NULL;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
static int
|
|
|
|
|
do_pth_event_occurred (pth_event_t ev)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-14 11:25:04 +00:00
|
|
|
|
int ret;
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (!ev)
|
|
|
|
|
return 0;
|
2004-12-14 11:25:04 +00:00
|
|
|
|
|
|
|
|
|
ret = 0;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
switch (ev->u_type)
|
|
|
|
|
{
|
2004-12-13 09:05:31 +00:00
|
|
|
|
case 0:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
|
2004-12-14 11:25:04 +00:00
|
|
|
|
ret = 1;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
case PTH_EVENT_SIGS:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (sigpresent (ev->u.sig, pth_signo) &&
|
|
|
|
|
WaitForSingleObject (pth_signo_ev, 0) == WAIT_OBJECT_0)
|
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_event_occurred: sig signaled.\n",
|
|
|
|
|
log_get_prefix (NULL));
|
2004-12-13 18:00:35 +00:00
|
|
|
|
(*ev->val) = pth_signo;
|
2004-12-14 11:25:04 +00:00
|
|
|
|
ret = 1;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
case PTH_EVENT_FD:
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (WaitForSingleObject (ev->hd, 0) == WAIT_OBJECT_0)
|
2004-12-14 11:25:04 +00:00
|
|
|
|
ret = 1;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
break;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
return ret;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
int
|
|
|
|
|
pth_event_status (pth_event_t ev)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (!ev)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
return 0;
|
2004-12-14 11:25:04 +00:00
|
|
|
|
if (pth_event_occurred (ev))
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return PTH_STATUS_OCCURRED;
|
|
|
|
|
return 0;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
static int
|
|
|
|
|
do_pth_event_free (pth_event_t ev, int mode)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (!ev)
|
|
|
|
|
return FALSE;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
|
|
|
|
|
if (mode == PTH_FREE_ALL)
|
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
pth_event_t cur = ev;
|
|
|
|
|
do
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
pth_event_t next = cur->next;
|
|
|
|
|
CloseHandle (cur->hd);
|
|
|
|
|
cur->hd = NULL;
|
|
|
|
|
free (cur);
|
|
|
|
|
cur = next;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
}
|
2004-12-20 11:36:46 +00:00
|
|
|
|
while (cur != ev);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
else if (mode == PTH_FREE_THIS)
|
|
|
|
|
{
|
|
|
|
|
ev->prev->next = ev->next;
|
|
|
|
|
ev->next->prev = ev->prev;
|
2004-12-14 17:47:12 +00:00
|
|
|
|
CloseHandle (ev->hd);
|
|
|
|
|
ev->hd = NULL;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
free (ev);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-20 11:36:46 +00:00
|
|
|
|
else
|
|
|
|
|
return FALSE;
|
2004-12-14 11:25:04 +00:00
|
|
|
|
|
2004-12-18 18:53:32 +00:00
|
|
|
|
return TRUE;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
pth_event_t
|
|
|
|
|
pth_event_isolate (pth_event_t ev)
|
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
pth_event_t ring;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (!ev)
|
|
|
|
|
return NULL;
|
2004-12-20 11:36:46 +00:00
|
|
|
|
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;
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return ring;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2004-12-20 11:36:46 +00:00
|
|
|
|
event_count (pth_event_t ev)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
pth_event_t r;
|
|
|
|
|
int cnt = 0;
|
|
|
|
|
|
|
|
|
|
if (ev)
|
|
|
|
|
{
|
|
|
|
|
r = ev;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
cnt++;
|
|
|
|
|
r = r->next;
|
|
|
|
|
}
|
|
|
|
|
while (r != ev);
|
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
|
|
|
|
|
return cnt;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 14:49:21 +00:00
|
|
|
|
|
|
|
|
|
static pth_t
|
2004-12-14 19:20:36 +00:00
|
|
|
|
spawn_helper_thread (void *(*func)(void *), void *arg)
|
2004-12-14 14:49:21 +00:00
|
|
|
|
{
|
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
|
DWORD tid;
|
|
|
|
|
HANDLE th;
|
|
|
|
|
|
|
|
|
|
memset (&sa, 0, sizeof sa);
|
|
|
|
|
sa.bInheritHandle = TRUE;
|
|
|
|
|
sa.lpSecurityDescriptor = NULL;
|
|
|
|
|
sa.nLength = sizeof sa;
|
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: spawn_helper_thread creating thread ...\n",
|
|
|
|
|
log_get_prefix (NULL));
|
2004-12-14 19:20:36 +00:00
|
|
|
|
th = CreateThread (&sa, 32*1024,
|
2004-12-14 14:49:21 +00:00
|
|
|
|
(LPTHREAD_START_ROUTINE)func,
|
|
|
|
|
arg, 0, &tid);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: spawn_helper_thread created thread %p\n",
|
|
|
|
|
log_get_prefix (NULL), th);
|
2004-12-14 14:49:21 +00:00
|
|
|
|
|
|
|
|
|
return th;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_helper_threads (HANDLE *waitbuf, int *hdidx, int n)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i=0; i < n; i++)
|
2004-12-14 17:47:12 +00:00
|
|
|
|
{
|
|
|
|
|
CloseHandle (waitbuf[hdidx[i]]);
|
|
|
|
|
waitbuf[hdidx[i]] = NULL;
|
|
|
|
|
}
|
2004-12-14 14:49:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: wait_fd_thread: exit.\n", log_get_prefix (NULL));
|
2004-12-14 14:49:21 +00:00
|
|
|
|
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);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: wait_timer_thread: exit.\n", log_get_prefix (NULL));
|
2004-12-14 14:49:21 +00:00
|
|
|
|
ExitThread (0);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
static int
|
|
|
|
|
do_pth_wait (pth_event_t ev)
|
2004-12-13 09:05:31 +00:00
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS/2];
|
|
|
|
|
int hdidx[MAXIMUM_WAIT_OBJECTS/2];
|
|
|
|
|
DWORD n = 0;
|
|
|
|
|
int pos=0, i=0;
|
|
|
|
|
|
|
|
|
|
if (!ev)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
n = event_count (ev);
|
2004-12-14 17:47:12 +00:00
|
|
|
|
if (n > MAXIMUM_WAIT_OBJECTS/2)
|
|
|
|
|
return -1;
|
|
|
|
|
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_wait: cnt %lu\n", log_get_prefix (NULL), n);
|
|
|
|
|
if (ev)
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
pth_event_t r = ev;
|
|
|
|
|
do
|
2004-12-13 18:00:35 +00:00
|
|
|
|
{
|
2004-12-20 11:36:46 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2004-12-13 18:00:35 +00:00
|
|
|
|
}
|
2004-12-20 11:36:46 +00:00
|
|
|
|
while ( r != ev );
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_wait: set %d\n", log_get_prefix (NULL), pos);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
n = WaitForMultipleObjects (pos, waitbuf, FALSE, INFINITE);
|
2004-12-14 14:49:21 +00:00
|
|
|
|
free_helper_threads (waitbuf, hdidx, i);
|
2004-12-20 11:36:46 +00:00
|
|
|
|
if (DBG_INFO)
|
|
|
|
|
fprintf (stderr, "%s: pth_wait: n %ld\n", log_get_prefix (NULL), n);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (n != WAIT_TIMEOUT)
|
|
|
|
|
return 1;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return 0;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-12-14 11:25:04 +00:00
|
|
|
|
int
|
|
|
|
|
pth_wait (pth_event_t ev)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
implicit_init ();
|
|
|
|
|
enter_pth (__FUNCTION__);
|
|
|
|
|
rc = do_pth_wait (ev);
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
pth_sleep (int sec)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
static pth_key_t ev_key = PTH_KEY_INIT;
|
|
|
|
|
pth_event_t ev;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
implicit_init ();
|
2004-12-14 11:25:04 +00:00
|
|
|
|
enter_pth (__FUNCTION__);
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (sec == 0)
|
2004-12-14 11:25:04 +00:00
|
|
|
|
{
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ev = do_pth_event (PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key,
|
|
|
|
|
pth_timeout (sec, 0));
|
2004-12-13 18:00:35 +00:00
|
|
|
|
if (ev == NULL)
|
2004-12-14 11:25:04 +00:00
|
|
|
|
{
|
|
|
|
|
leave_pth (__FUNCTION__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
do_pth_wait (ev);
|
|
|
|
|
do_pth_event_free (ev, PTH_FREE_ALL);
|
|
|
|
|
|
|
|
|
|
leave_pth (__FUNCTION__);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
return 0;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Some simple tests.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef TEST
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
void * thread (void * c)
|
|
|
|
|
{
|
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
Sleep (2000);
|
|
|
|
|
SetEvent (((pth_event_t)c)->hd);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
fprintf (stderr, "\n\nhallo!.\n");
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_exit (NULL);
|
|
|
|
|
return NULL;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int main_1 (int argc, char ** argv)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static pth_event_t
|
|
|
|
|
setup_signals (struct sigset_s *sigs, int *signo)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_event_t ev;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
sigemptyset (sigs);
|
|
|
|
|
sigaddset (sigs, SIGINT);
|
|
|
|
|
sigaddset (sigs, SIGTERM);
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
ev = pth_event (PTH_EVENT_SIGS, sigs, signo);
|
|
|
|
|
return ev;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
main_2 (int argc, char ** argv)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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)
|
2004-12-14 11:25:04 +00:00
|
|
|
|
fprintf (stderr, "signal caught! signo %d\n", signo);
|
2004-12-13 18:00:35 +00:00
|
|
|
|
|
|
|
|
|
pth_event_free (ev, PTH_FREE_ALL);
|
|
|
|
|
pth_kill ();
|
|
|
|
|
return 0;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
main_3 (int argc, char ** argv)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
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);
|
2004-12-14 11:25:04 +00:00
|
|
|
|
fprintf (stderr, "infd %d: %s:%d\n", infd, inet_ntoa (rem.sin_addr),
|
2004-12-13 18:00:35 +00:00
|
|
|
|
htons (rem.sin_port));
|
|
|
|
|
|
|
|
|
|
closesocket (infd);
|
|
|
|
|
pth_event_free (ev, PTH_FREE_ALL);
|
|
|
|
|
pth_kill ();
|
|
|
|
|
return 0;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
main (int argc, char ** argv)
|
|
|
|
|
{
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_event_t ev;
|
|
|
|
|
pth_key_t ev_key;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_init ();
|
|
|
|
|
/*ev = pth_event (PTH_EVENT_TIME, &ev_key, pth_timeout (5, 0));
|
2004-12-13 09:05:31 +00:00
|
|
|
|
pth_wait (ev);
|
|
|
|
|
pth_event_free (ev, PTH_FREE_ALL);*/
|
2004-12-13 18:00:35 +00:00
|
|
|
|
pth_sleep (5);
|
|
|
|
|
pth_kill ();
|
|
|
|
|
return 0;
|
2004-12-13 09:05:31 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-07 11:21:40 +00:00
|
|
|
|
#endif /*HAVE_W32_SYSTEM*/
|
2004-12-13 09:05:31 +00:00
|
|
|
|
|