]> git.pond.sub.org Git - empserver/blobdiff - src/lib/empthread/ntthread.c
Update copyright notice
[empserver] / src / lib / empthread / ntthread.c
index 68bd3ffb1945e5403ce457cd9d41c72500b92d55..73868dad1056e4053ce9e50f216129cdc6b6774a 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
- *                           Ken Stevens, Steve McClure
+ *  Copyright (C) 1986-2017, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *                Ken Stevens, Steve McClure, Markus Armbruster
  *
- *  This program is free software; you can redistribute it and/or modify
+ *  Empire is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
+ *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU 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
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  ---
  *
@@ -30,7 +29,7 @@
  *  Known contributors to this file:
  *     Doug Hay, 1998
  *     Steve McClure, 1998
- *     Ron Koenderink, 2004-2008
+ *     Ron Koenderink, 2004-2009
  */
 
 /*
 #include <stdarg.h>
 #include <sys/types.h>
 #include <time.h>
-#include <winsock2.h>
-#undef NS_ALL
 #include <windows.h>
 #include <process.h>
-/* Note: unistd.h(posixio.c) is not thread-safe.
- * It may be used *only* while holding hThreadMutex.
- */
-#include "unistd.h"
 #include "misc.h"
 #include "empthread.h"
+#include "file.h"
 #include "prototypes.h"
 #include "server.h"
+#include "sys/socket.h"
 
 #define loc_MIN_THREAD_STACK  16384
 
@@ -81,9 +76,6 @@ struct loc_Thread {
     /* The user data passed in at create time. */
     void *pvUserData;
 
-    /* True if this thread has been killed. */
-    BOOL bKilled;
-
     /* The entry function for the thread. */
     void (*pfnEntry) (void *);
 
@@ -105,7 +97,7 @@ struct loc_Thread {
  * any state:
  *     nwrite >= 0
  *     nread >= 0
-
+ *
  * if unlocked:
  *     can_read set
  *     can_write set
@@ -226,7 +218,6 @@ loc_FreeThreadInfo(empth_t *pThread)
            CloseHandle(pThread->hThreadEvent);
        if (pThread->szName != NULL)
            free(pThread->szName);
-       memset(pThread, 0, sizeof(*pThread));
        free(pThread);
     }
 }
@@ -245,14 +236,6 @@ loc_RunThisThread(HANDLE hWaitObject)
 
     empth_t *pThread = TlsGetValue(dwTLSIndex);
 
-    if (pThread->bKilled) {
-       if (!pThread->bMainThread) {
-           TlsSetValue(dwTLSIndex, NULL);
-           loc_FreeThreadInfo(pThread);
-           _endthread();
-       }
-    }
-
     hWaitObjects[0] = hThreadMutex;
     hWaitObjects[1] = hWaitObject;
 
@@ -305,15 +288,15 @@ static BOOL WINAPI
 loc_Exit_Handler(DWORD fdwCtrlType)
 {
     switch (fdwCtrlType) {
-        case CTRL_C_EVENT:
-        case CTRL_CLOSE_EVENT:
-        case CTRL_BREAK_EVENT:
-        case CTRL_LOGOFF_EVENT:
-        case CTRL_SHUTDOWN_EVENT:
-           empth_request_shutdown();
-            return TRUE;
-        default:
-            return FALSE;
+    case CTRL_C_EVENT:
+    case CTRL_CLOSE_EVENT:
+    case CTRL_BREAK_EVENT:
+    case CTRL_LOGOFF_EVENT:
+    case CTRL_SHUTDOWN_EVENT:
+       empth_request_shutdown();
+       return TRUE;
+    default:
+       return FALSE;
     }
 }
 
@@ -392,7 +375,7 @@ empth_init(void **ctx_ptr, int flags)
     /* Manual reset */
     hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
     if (!hShutdownEvent) {
-        logerror("Failed to create shutdown event %lu", GetLastError());
+       logerror("Failed to create shutdown event %lu", GetLastError());
        return 0;
     }
     SetConsoleCtrlHandler(loc_Exit_Handler, TRUE);
@@ -414,7 +397,6 @@ empth_init(void **ctx_ptr, int flags)
     /* Make this the running thread. */
     loc_RunThisThread(NULL);
 
-    logerror("NT pthreads initialized");
     return 0;
 }
 
@@ -440,6 +422,7 @@ empth_create(void (*entry)(void *), int size, int flags,
     empth_t *pThread = NULL;
 
     loc_debug("creating new thread %s", name);
+    ef_make_stale();
 
     pThread = malloc(sizeof(*pThread));
     if (!pThread) {
@@ -469,7 +452,7 @@ empth_create(void (*entry)(void *), int size, int flags,
     empth_yield();
     return pThread;
 
-  bad:
+bad:
     if (pThread) {
        loc_FreeThreadInfo(pThread);
     }
@@ -483,9 +466,7 @@ empth_create(void (*entry)(void *), int size, int flags,
 empth_t *
 empth_self(void)
 {
-    empth_t *pThread = TlsGetValue(dwTLSIndex);
-
-    return pThread;
+    return ppvUserData ? TlsGetValue(dwTLSIndex) : NULL;
 }
 
 /************************
@@ -518,6 +499,7 @@ empth_exit(void)
     empth_t *pThread = TlsGetValue(dwTLSIndex);
 
     loc_debug("empth_exit");
+    ef_make_stale();
     loc_BlockThisThread();
 
     TlsSetValue(dwTLSIndex, NULL);
@@ -533,25 +515,12 @@ empth_exit(void)
 void
 empth_yield(void)
 {
+    ef_make_stale();
     loc_BlockThisThread();
     Sleep(0);
     loc_RunThisThread(NULL);
 }
 
-/************************
- * empth_terminate
- *
- * Kill off the thread.
- */
-void
-empth_terminate(empth_t *pThread)
-{
-    loc_debug("killing thread %s", pThread->szName);
-    pThread->bKilled = TRUE;
-
-    SetEvent(pThread->hThreadEvent);
-}
-
 /************************
  * empth_select
  *
@@ -560,39 +529,64 @@ empth_terminate(empth_t *pThread)
  *
  * This would be one of the main functions used within gen\io.c
  */
-void
-empth_select(int fd, int flags)
+int
+empth_select(int fd, int flags, struct timeval *timeout)
 {
-    int handle;
+    SOCKET sock;
     WSAEVENT hEventObject[2];
+    long events;
+    DWORD result, msec;
     empth_t *pThread = TlsGetValue(dwTLSIndex);
+    int res;
 
     loc_debug("%s select on %d",
              flags == EMPTH_FD_READ ? "read" : "write", fd);
+    ef_make_stale();
     loc_BlockThisThread();
 
     hEventObject[0] = WSACreateEvent();
     hEventObject[1] = pThread->hThreadEvent;
 
-    handle = posix_fd2socket(fd);
-    CANT_HAPPEN(handle < 0);
-
-    if (flags == EMPTH_FD_READ)
-       WSAEventSelect(handle, hEventObject[0], FD_READ | FD_ACCEPT | FD_CLOSE);
-    else if (flags == EMPTH_FD_WRITE)
-       WSAEventSelect(handle, hEventObject[0], FD_WRITE | FD_CLOSE);
-    else {
-       logerror("bad flag %d passed to empth_select", flags);
-       empth_exit();
+    sock = w32_fd2socket(fd);
+    CANT_HAPPEN(sock == (SOCKET)-1);
+
+    events = 0;
+    if (flags & EMPTH_FD_READ)
+       events |= FD_READ | FD_ACCEPT | FD_CLOSE;
+    if (flags & EMPTH_FD_WRITE)
+       events |= FD_WRITE | FD_CLOSE;
+    WSAEventSelect(sock, hEventObject[0], events);
+
+    if (timeout)
+       msec = timeout->tv_sec * 1000L + timeout->tv_usec / 1000L;
+    else
+       msec = WSA_INFINITE;
+    result = WSAWaitForMultipleEvents(2, hEventObject, FALSE, msec, FALSE);
+
+    switch (result) {
+    case WSA_WAIT_EVENT_0:
+       res = 1;
+       break;
+    case WSA_WAIT_EVENT_0 + 1:
+    case WSA_WAIT_TIMEOUT:
+       res = 0;
+       break;
+    case WSA_WAIT_FAILED:
+       w32_set_winsock_errno();
+       res = -1;
+       break;
+    default:
+       CANT_REACH();
+       errno = EINVAL;
+       res = -1;
     }
 
-    WSAWaitForMultipleEvents(2, hEventObject, FALSE, WSA_INFINITE, FALSE);
-
-    WSAEventSelect(handle, hEventObject[0], 0);
+    WSAEventSelect(sock, hEventObject[0], 0);
 
     WSACloseEvent(hEventObject[0]);
 
     loc_RunThisThread(NULL);
+    return res;
 }
 
 /************************
@@ -617,23 +611,25 @@ empth_wakeup(empth_t *pThread)
 int
 empth_sleep(time_t until)
 {
-    long lSec = until - time(0) > 0 ? until - time(0) : 0;
+    time_t now;
+    long lSec;
     empth_t *pThread = TlsGetValue(dwTLSIndex);
-    int iReturn = 0;
+    DWORD result;
+
+    ef_make_stale();
+    loc_BlockThisThread();
 
     do {
-       loc_BlockThisThread();
+       now = time(NULL);
+       lSec = until >= now ? until - now : 0;
        loc_debug("going to sleep %ld sec", lSec);
+       result = WaitForSingleObject(pThread->hThreadEvent, lSec * 1000L);
+    } while (result != WAIT_TIMEOUT && result != WAIT_OBJECT_0);
 
-       if (WaitForSingleObject(pThread->hThreadEvent, lSec * 1000L) !=
-           WAIT_TIMEOUT)
-           iReturn = -1;
-
-       loc_debug("sleep done. Waiting to run.");
-       loc_RunThisThread(NULL);
-    } while (!iReturn && ((lSec = until - time(0)) > 0));
+    loc_debug("sleep done. Waiting to run.");
+    loc_RunThisThread(NULL);
 
-    return iReturn;
+    return result == WAIT_TIMEOUT ? 0 : -1;
 }
 
 /************************
@@ -651,6 +647,7 @@ empth_request_shutdown(void)
 int
 empth_wait_for_signal(void)
 {
+    ef_make_stale();
     loc_BlockThisThread();
     loc_RunThisThread(hShutdownEvent);
     return SIGTERM;
@@ -670,7 +667,7 @@ empth_rwlock_create(char *name)
 
     if ((rwlock->can_read = CreateEvent(NULL, TRUE, TRUE, NULL)) == NULL) {
        logerror("rwlock_create: failed to create reader event %s at %s:%d",
-           name, __FILE__, __LINE__);
+                name, __FILE__, __LINE__);
        free(rwlock->name);
        free(rwlock);
        return NULL;
@@ -678,7 +675,7 @@ empth_rwlock_create(char *name)
 
     if ((rwlock->can_write = CreateEvent(NULL, FALSE, TRUE, NULL)) == NULL) {
        logerror("rwlock_create: failed to create writer event %s at %s:%d",
-           name, __FILE__, __LINE__);
+                name, __FILE__, __LINE__);
        free(rwlock->name);
        CloseHandle(rwlock->can_read);
        free(rwlock);
@@ -702,6 +699,7 @@ empth_rwlock_destroy(empth_rwlock_t *rwlock)
 void
 empth_rwlock_wrlock(empth_rwlock_t *rwlock)
 {
+    ef_make_stale();
     /* block any new readers */
     ResetEvent(rwlock->can_read);
     rwlock->nwrite++;
@@ -713,6 +711,7 @@ empth_rwlock_wrlock(empth_rwlock_t *rwlock)
 void
 empth_rwlock_rdlock(empth_rwlock_t *rwlock)
 {
+    ef_make_stale();
     loc_BlockThisThread();
     loc_RunThisThread(rwlock->can_read);
     ResetEvent(rwlock->can_write);
@@ -724,7 +723,7 @@ empth_rwlock_unlock(empth_rwlock_t *rwlock)
 {
     if (CANT_HAPPEN(!rwlock->nread && !rwlock->nwrite))
        return;
-   if (rwlock->nread) { /* holding read lock */
+    if (rwlock->nread) {       /* holding read lock */
        rwlock->nread--;
        if (rwlock->nread == 0)
            SetEvent(rwlock->can_write);