]> git.pond.sub.org Git - empserver/blobdiff - src/lib/empthread/ntthread.c
Update copyright notice.
[empserver] / src / lib / empthread / ntthread.c
index a5158059874226f3e985308d3cf48e3cb873785a..c734a0cd36cadea8d2c43a041ab154f3f30c46f4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -19,9 +19,9 @@
  *
  *  ---
  *
- *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- *  related information and legal notices. It is expected that any future
- *  projects/authors will amend these files as needed.
+ *  See files README, COPYING and CREDITS in the root of the source
+ *  tree for related information and legal notices.  It is expected
+ *  that future projects/authors will amend these files as needed.
  *
  *  ---
  *
@@ -30,6 +30,7 @@
  *  Known contributors to this file:
  *     Doug Hay, 1998
  *     Steve McClure, 1998
+ *     Ron Koenderink, 2004-2005
  */
 
 /*
  * WIN32 has a full pre-emptive threading environment.  But Empire can
  * not handle pre-emptive threading.  Thus, we will use the threads,
  * but limit the preemption using a Mutex semaphore.
- *
  */
 
+#include <config.h>
+
+#include <errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-#include "misc.h"
-#include "empthread.h"
-#include "prototypes.h"
-
-#if defined(_WIN32) && defined(_EMPTH_WIN32)
+#include <time.h>
 #define WIN32
 #include <winsock2.h>
 #undef NS_ALL
 #include <windows.h>
 #include <process.h>
+#include "misc.h"
+#include "empthread.h"
+#include "prototypes.h"
 
 #define loc_MIN_THREAD_STACK  16384
 
 /************************
  * loc_Thread_t
- *
- * The REAL empth_t thread structure.
- * The external world only gets a void pointer to this.
  */
-typedef struct loc_Thread_t {
+struct loc_Thread_t {
 
     /* The thread name, passed in at create time. */
     char szName[17];
@@ -91,16 +89,13 @@ typedef struct loc_Thread_t {
 
     /* An Event sem that the thread will wait/sleep on. */
     HANDLE hThreadEvent;
-} loc_Thread_t;
+};
 
 
 /************************
  * loc_Sem_t
- *
- * The REAL empth_sem_t structure.
- * The external world only gets a void pointer to this.
  */
-typedef struct loc_Sem_t {
+struct loc_Sem_t {
 
     char szName[17];
 
@@ -111,39 +106,37 @@ typedef struct loc_Sem_t {
     HANDLE hEvent;
     /* The count variable */
     int count;
-} loc_Sem_t;
+};
 
-static struct {
-    /* This is the thread exclusion/non-premption mutex. */
-    /* The running thread has this MUTEX, and all others are */
-    /* either blocked on it, or waiting for some OS response. */
-    HANDLE hThreadMutex;
+/* This is the thread exclusion/non-premption mutex. */
+/* The running thread has this MUTEX, and all others are */
+/* either blocked on it, or waiting for some OS response. */
+static HANDLE hThreadMutex;
 
-    /* This is the thread startup event sem. */
-    /* We use this to lockstep when we are starting up threads. */
-    HANDLE hThreadStartEvent;
+/* This is the thread startup event sem. */
+/* We use this to lockstep when we are starting up threads. */
+static HANDLE hThreadStartEvent;
 
-    /* This is an event used to wakeup the main thread */
-    /* to start the shutdown sequence. */
-    HANDLE hShutdownEvent;
+/* This is an event used to wakeup the main thread */
+/* to start the shutdown sequence. */
+static HANDLE hShutdownEvent;
 
-    /* The Thread Local Storage index.  We store the pThread pointer */
-    /* for each thread at this index. */
-    DWORD dwTLSIndex;
+/* The Thread Local Storage index.  We store the pThread pointer */
+/* for each thread at this index. */
+static DWORD dwTLSIndex;
 
-    /* The current running thread. */
-    loc_Thread_t *pCurThread;
+/* The current running thread. */
+static empth_t *pCurThread;
 
-    /* Ticks at start */
-    unsigned long ulTickAtStart;
+/* Ticks at start */
+static unsigned long ulTickAtStart;
 
-    /* Pointer out to global context.  "player". */
-    /* From empth_init parameter. */
-    void **ppvUserData;
+/* Pointer out to global context.  "player". */
+/* From empth_init parameter. */
+static void **ppvUserData;
 
-    /* Global flags.  From empth_init parameter. */
-    int flags;
-} loc_GVAR;
+/* Global flags.  From empth_init parameter. */
+static int global_flags;
 
 
 /************************
@@ -158,16 +151,15 @@ loc_debug(const char *pszFmt, ...)
     unsigned long ulCurTick;
     unsigned long ulRunTick;
     unsigned long ulMs, ulSec, ulMin, ulHr;
-    loc_Thread_t *pThread =
-       (loc_Thread_t *)TlsGetValue(loc_GVAR.dwTLSIndex);
+    empth_t *pThread = TlsGetValue(dwTLSIndex);
     char buf[1024];
 
-    if ((loc_GVAR.flags & EMPTH_PRINT) != 0) {
+    if ((global_flags & EMPTH_PRINT) != 0) {
 
        /* Ticks are in milliseconds */
        ulCurTick = GetTickCount();
 
-       ulRunTick = ulCurTick - loc_GVAR.ulTickAtStart;
+       ulRunTick = ulCurTick - ulTickAtStart;
        ulMs = ulRunTick % 1000L;
        ulSec = (ulRunTick / 1000L) % 60L;
        ulMin = (ulRunTick / (60L * 1000L)) % 60L;
@@ -190,10 +182,9 @@ loc_debug(const char *pszFmt, ...)
 
 /************************
  * loc_FreeThreadInfo
- *
  */
 static void
-loc_FreeThreadInfo(loc_Thread_t *pThread)
+loc_FreeThreadInfo(empth_t *pThread)
 {
     if (pThread) {
        if (pThread->hThreadEvent)
@@ -211,27 +202,26 @@ loc_FreeThreadInfo(loc_Thread_t *pThread)
  * info, and the thread owns the MUTEX sem.
  */
 static void
-loc_RunThisThread()
+loc_RunThisThread(void)
 {
-    loc_Thread_t *pThread =
-       (loc_Thread_t *)TlsGetValue(loc_GVAR.dwTLSIndex);
+    empth_t *pThread = TlsGetValue(dwTLSIndex);
 
     if (pThread->bKilled) {
        if (!pThread->bMainThread) {
-           TlsSetValue(loc_GVAR.dwTLSIndex, NULL);
+           TlsSetValue(dwTLSIndex, NULL);
            loc_FreeThreadInfo(pThread);
            _endthread();
        }
     }
 
     /* Get the MUTEX semaphore, wait forever. */
-    WaitForSingleObject(loc_GVAR.hThreadMutex, INFINITE);
+    WaitForSingleObject(hThreadMutex, INFINITE);
 
-    if (!loc_GVAR.pCurThread) {
+    if (!pCurThread) {
        /* Set the globals to this thread. */
-       *loc_GVAR.ppvUserData = pThread->pvUserData;
+       *ppvUserData = pThread->pvUserData;
 
-       loc_GVAR.pCurThread = pThread;
+       pCurThread = pThread;
     } else {
        /* Hmm, a problem, eh? */
        logerror("RunThisThread, someone already running.");
@@ -244,19 +234,18 @@ loc_RunThisThread()
  * This thread was running.  It no longer wants to.
  */
 static void
-loc_BlockThisThread()
+loc_BlockThisThread(void)
 {
-    loc_Thread_t *pThread =
-       (loc_Thread_t *)TlsGetValue(loc_GVAR.dwTLSIndex);
+    empth_t *pThread = TlsGetValue(dwTLSIndex);
 
-    if (loc_GVAR.pCurThread == pThread) {
+    if (pCurThread == pThread) {
        /* Reset the globals back to original */
 
-       loc_GVAR.pCurThread = NULL;
-       *loc_GVAR.ppvUserData = NULL;
+       pCurThread = NULL;
+       *ppvUserData = NULL;
 
        /* Release the MUTEX */
-       ReleaseMutex(loc_GVAR.hThreadMutex);
+       ReleaseMutex(hThreadMutex);
     } else {
        /* Hmm, this thread was not the running one. */
        logerror("BlockThisThread, not running.");
@@ -273,8 +262,7 @@ loc_BlockThisThread()
 static BOOL
 loc_Exit_Handler(DWORD fdwCtrlType)
 {
-    switch (fdwCtrlType) 
-    { 
+    switch (fdwCtrlType) { 
         case CTRL_C_EVENT:
         case CTRL_CLOSE_EVENT:
         case CTRL_BREAK_EVENT: 
@@ -287,60 +275,35 @@ loc_Exit_Handler(DWORD fdwCtrlType)
     }
 }
 
-/************************
- * empth_request_shutdown
- *
- * This wakes up the main thread so shutdown can proceed.
- * This is done by signalling hShutdownEvent.
- */
-void
-empth_request_shutdown(void)
-{
-    SetEvent(loc_GVAR.hShutdownEvent);
-}
-
-/************************
- * loc_BlockMainThread
- *
- * This blocks up the main thread.  loc_WakeupMainThread() is used
- * wakeup the main so shutdown can proceed.
- */
-static void
-loc_BlockMainThread(void)
-{
-    /* Get the MUTEX semaphore, wait the number of MS */
-    WaitForSingleObject(loc_GVAR.hShutdownEvent, INFINITE);
-}
-
 /************************
  * empth_threadMain
  *
  * This is the main line of each thread.
  * This is really a static local func....
  */
-void
+static void
 empth_threadMain(void *pvData)
 {
     time_t now;
 
-    loc_Thread_t *pThread = (loc_Thread_t *)pvData;
+    empth_t *pThread = pvData;
 
     /* Out of here... */
     if (!pvData)
        return;
 
     /* Store pThread on this thread. */
-    TlsSetValue(loc_GVAR.dwTLSIndex, pvData);
+    TlsSetValue(dwTLSIndex, pvData);
 
     /* Get the ID of the thread. */
     pThread->ulThreadID = GetCurrentThreadId();
 
     /* Signal that the thread has started. */
-    SetEvent(loc_GVAR.hThreadStartEvent);
+    SetEvent(hThreadStartEvent);
 
     /* seed the rand() function */
     time(&now);
-    srand(now ^ (unsigned int)pThread);
+    srand(now ^ (unsigned)pThread);
 
     /* Switch to this thread context */
     loc_RunThisThread();
@@ -363,34 +326,34 @@ empth_threadMain(void *pvData)
 int
 empth_init(void **ctx_ptr, int flags)
 {
-    loc_Thread_t *pThread = NULL;
+    empth_t *pThread = NULL;
 
-    loc_GVAR.ulTickAtStart = GetTickCount();
-    loc_GVAR.ppvUserData = ctx_ptr;
-    loc_GVAR.flags = flags;
-    loc_GVAR.dwTLSIndex = TlsAlloc();
+    ulTickAtStart = GetTickCount();
+    ppvUserData = ctx_ptr;
+    global_flags = flags;
+    dwTLSIndex = TlsAlloc();
 
     /* Create the thread mutex sem. */
     /* Initally unowned. */
-    loc_GVAR.hThreadMutex = CreateMutex(NULL, FALSE, NULL);
-    if (!loc_GVAR.hThreadMutex) {
-       logerror("Failed to create mutex %d", GetLastError());
+    hThreadMutex = CreateMutex(NULL, FALSE, NULL);
+    if (!hThreadMutex) {
+       logerror("Failed to create mutex %lu", GetLastError());
        return 0;
     }
 
     /* Create the thread start event sem. */
     /* Automatic state reset. */
-    loc_GVAR.hThreadStartEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (!loc_GVAR.hThreadStartEvent) {
-       logerror("Failed to create start event %d", GetLastError());
+    hThreadStartEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (!hThreadStartEvent) {
+       logerror("Failed to create start event %lu", GetLastError());
        return 0;
     }
 
     /* Create the shutdown event for the main thread. */
     /* Manual reset */
-    loc_GVAR.hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-    if (!loc_GVAR.hShutdownEvent) {
-        logerror("Failed to create shutdown event %d", GetLastError());
+    hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    if (!hShutdownEvent) {
+        logerror("Failed to create shutdown event %lu", GetLastError());
        return 0;
     }
     SetConsoleCtrlHandler((PHANDLER_ROUTINE)loc_Exit_Handler, TRUE);
@@ -409,7 +372,7 @@ empth_init(void **ctx_ptr, int flags)
     pThread->ulThreadID = GetCurrentThreadId();
     pThread->bMainThread = TRUE;
 
-    TlsSetValue(loc_GVAR.dwTLSIndex, pThread);
+    TlsSetValue(dwTLSIndex, pThread);
 
     /* Make this the running thread. */
     loc_RunThisThread();
@@ -439,14 +402,14 @@ empth_t *
 empth_create(int prio, void (*entry)(void *), int size, int flags,
             char *name, char *desc, void *ud)
 {
-    loc_Thread_t *pThread = NULL;
+    empth_t *pThread = NULL;
 
     loc_debug("creating new thread %s:%s", name, desc);
 
     pThread = malloc(sizeof(*pThread));
     if (!pThread) {
-       logerror("not enough memory to create thread: %s (%s)", name,
-                desc);
+       logerror("not enough memory to create thread: %s (%s)",
+                name, desc);
        return NULL;
     }
     memset(pThread, 0, sizeof(*pThread));
@@ -465,12 +428,13 @@ empth_create(int prio, void (*entry)(void *), int size, int flags,
 
     pThread->ulThreadID = _beginthread(empth_threadMain, size, pThread);
     if (pThread->ulThreadID == -1) {
-       logerror("can not create thread: %s (%s): %s", name, desc,
-                strerror(errno));
+       logerror("can not create thread: %s (%s): %s",
+                name, desc, strerror(errno));
        goto bad;
     }
 
     loc_debug("new thread id is %ld", pThread->ulThreadID);
+    empth_yield();
     return pThread;
 
   bad:
@@ -487,8 +451,7 @@ empth_create(int prio, void (*entry)(void *), int size, int flags,
 empth_t *
 empth_self(void)
 {
-    loc_Thread_t *pThread =
-       (loc_Thread_t *)TlsGetValue(loc_GVAR.dwTLSIndex);
+    empth_t *pThread = TlsGetValue(dwTLSIndex);
 
     return pThread;
 }
@@ -499,22 +462,14 @@ empth_self(void)
 void
 empth_exit(void)
 {
-    loc_Thread_t *pThread =
-       (loc_Thread_t *)TlsGetValue(loc_GVAR.dwTLSIndex);
-
-    loc_BlockThisThread();
+    empth_t *pThread = TlsGetValue(dwTLSIndex);
 
     loc_debug("empth_exit");
+    loc_BlockThisThread();
 
-    if (pThread->bMainThread) {
-       loc_BlockMainThread();
-       loc_RunThisThread();
-       shutdwn(0);
-    } else {
-       TlsSetValue(loc_GVAR.dwTLSIndex, NULL);
-       loc_FreeThreadInfo(pThread);
-       _endthread();
-    }
+    TlsSetValue(dwTLSIndex, NULL);
+    loc_FreeThreadInfo(pThread);
+    _endthread();
 }
 
 /************************
@@ -535,10 +490,8 @@ empth_yield(void)
  * Kill off the thread.
  */
 void
-empth_terminate(empth_t *a)
+empth_terminate(empth_t *pThread)
 {
-    loc_Thread_t *pThread = (loc_Thread_t *)a;
-
     loc_debug("killing thread %s", pThread->szName);
     pThread->bKilled = TRUE;
 
@@ -557,8 +510,7 @@ void
 empth_select(int fd, int flags)
 {
     WSAEVENT hEventObject[2];
-    loc_Thread_t *pThread =
-       (loc_Thread_t *)TlsGetValue(loc_GVAR.dwTLSIndex);
+    empth_t *pThread = TlsGetValue(dwTLSIndex);
 
     loc_debug("%s select on %d",
              flags == EMPTH_FD_READ ? "read" : "write", fd);
@@ -585,31 +537,14 @@ empth_select(int fd, int flags)
     loc_RunThisThread();
 }
 
-/************************
- * empth_alarm
- */
-void
-empth_alarm(int sig)
-{
-    loc_Thread_t *pThread =
-       (loc_Thread_t *)TlsGetValue(loc_GVAR.dwTLSIndex);
-
-    loc_debug("got alarm signal  %d", sig);
-
-    /* Let it run if it is blocked like... */
-    SetEvent(pThread->hThreadEvent);
-}
-
 /************************
  * empth_wakeup
  *
  * Wake up the specified thread.
  */
 void
-empth_wakeup(empth_t *a)
+empth_wakeup(empth_t *pThread)
 {
-    loc_Thread_t *pThread = (loc_Thread_t *)a;
-
     loc_debug("waking up thread %s", pThread->szName);
 
     /* Let it run if it is blocked... */
@@ -638,6 +573,29 @@ empth_sleep(time_t until)
     loc_RunThisThread();
 }
 
+/************************
+ * empth_request_shutdown
+ *
+ * This wakes up empth_wait_for_signal() so shutdown can proceed.
+ * This is done by signalling hShutdownEvent.
+ */
+void
+empth_request_shutdown(void)
+{
+    SetEvent(hShutdownEvent);
+}
+
+int
+empth_wait_for_signal(void)
+{
+    loc_BlockThisThread();
+
+    /* Get the MUTEX semaphore, wait the number of MS */
+    WaitForSingleObject(hShutdownEvent, INFINITE);
+
+    loc_RunThisThread();
+    return 0;
+}
 
 /************************
  * empth_sem_create
@@ -647,7 +605,7 @@ empth_sleep(time_t until)
 empth_sem_t *
 empth_sem_create(char *name, int cnt)
 {
-    loc_Sem_t *pSem;
+    empth_sem_t *pSem;
 
     pSem = malloc(sizeof(*pSem));
     if (!pSem) {
@@ -671,10 +629,8 @@ empth_sem_create(char *name, int cnt)
  * Hit/signal the specified semaphore.
  */
 void
-empth_sem_signal(empth_sem_t *sm)
+empth_sem_signal(empth_sem_t *pSem)
 {
-    loc_Sem_t *pSem = sm;
-
     loc_debug("signal on semaphore %s:%d", pSem->szName, pSem->count);
 
     /* Wait for the Semaphore */
@@ -693,11 +649,9 @@ empth_sem_signal(empth_sem_t *sm)
  * Wait for the specified signal semaphore to be signaled.
  */
 void
-empth_sem_wait(empth_sem_t *sm)
+empth_sem_wait(empth_sem_t *pSem)
 {
-    loc_Thread_t *pThread =
-       (loc_Thread_t *)TlsGetValue(loc_GVAR.dwTLSIndex);
-    loc_Sem_t *pSem = sm;
+    empth_t *pThread = TlsGetValue(dwTLSIndex);
 
     loc_debug("wait on semaphore %s:%d", pSem->szName, pSem->count);
 
@@ -718,5 +672,3 @@ empth_sem_wait(empth_sem_t *sm)
 
     loc_RunThisThread();
 }
-
-#endif /* _WIN32 */