Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] -netthread fixes and implementation for linux #569

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rehlds/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ void setupToolchain(NativeBinarySpec b) {
cfg.linkerOptions.args '-Wl,--version-script=../version_script.lds', '-Wl,--gc-sections'

cfg.projectLibpath(project, '/lib/linux32')
cfg.extraLibs 'rt', 'dl', 'm', 'steam_api', 'aelf32'
cfg.extraLibs 'rt', 'dl', 'm', 'steam_api', 'aelf32', 'pthread'
}

if (unitTestExecutable) {
Expand Down
92 changes: 81 additions & 11 deletions rehlds/engine/net_ws.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ net_messages_t *normalqueue;
HANDLE hNetThread;
DWORD dwNetThreadId;
CRITICAL_SECTION net_cs;
#else
pthread_mutex_t net_mutex;
pthread_t hNetThread;
#endif

#ifdef REHLDS_FIXES
volatile bool net_thread_terminated;
#endif

cvar_t net_address = { "net_address", "", 0, 0.0f, NULL };
Expand Down Expand Up @@ -100,22 +107,26 @@ cvar_t net_graphpos = { "net_graphpos", "1", FCVAR_ARCHIVE, 0.0f, NULL };

void NET_ThreadLock()
{
#ifdef _WIN32
if (use_thread && net_thread_initialized)
{
#ifdef _WIN32
EnterCriticalSection(&net_cs);
}
#else
pthread_mutex_lock(&net_mutex);
#endif // _WIN32
}
}

void NET_ThreadUnlock()
{
#ifdef _WIN32
if (use_thread && net_thread_initialized)
{
#ifdef _WIN32
LeaveCriticalSection(&net_cs);
}
#else
pthread_mutex_unlock(&net_mutex);
#endif // _WIN32
}
}

unsigned short Q_ntohs(unsigned short netshort)
Expand Down Expand Up @@ -1112,14 +1123,20 @@ int NET_Sleep()
}

tv.tv_sec = 0;
#ifdef REHLDS_FIXES
tv.tv_usec = 0.25 * 1000000;
#else
tv.tv_usec = 20 * 1000;
#endif

return select((int)(number + 1), &fdset, NULL, NULL, net_sleepforever == 0 ? &tv : NULL);
}

#ifdef _WIN32

DWORD WINAPI NET_ThreadMain(LPVOID lpThreadParameter)
#else
void* NET_ThreadMain(void*)
#endif // _WIN32
{
while (true)
{
Expand All @@ -1130,6 +1147,14 @@ DWORD WINAPI NET_ThreadMain(LPVOID lpThreadParameter)
{
NET_ThreadLock();

#ifdef REHLDS_FIXES
if (net_thread_terminated)
{
NET_ThreadUnlock();
return 0;
}
#endif

bret = NET_QueuePacket((netsrc_t)sock);
if (bret)
{
Expand Down Expand Up @@ -1161,33 +1186,45 @@ DWORD WINAPI NET_ThreadMain(LPVOID lpThreadParameter)
break;
}

#ifndef REHLDS_FIXES
Sys_Sleep(1);
#endif
}

return 0;
}

#endif // _WIN32

void NET_StartThread()
{
if (use_thread)
{
if (!net_thread_initialized)
{
net_thread_initialized = TRUE;
#ifdef REHLDS_FIXES
net_thread_terminated = false;
#endif

#ifdef _WIN32
InitializeCriticalSection(&net_cs);
hNetThread = CreateThread(0, 0, NET_ThreadMain, 0, 0, &dwNetThreadId);
if (!hNetThread)
{
DeleteCriticalSection(&net_cs);
#else
// In-line: There are several cases where mutex can go recursive in one thread.
pthread_mutexattr_t net_mutex_attr;
pthread_mutexattr_init(&net_mutex_attr);
pthread_mutexattr_settype(&net_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&net_mutex, &net_mutex_attr);
if (pthread_create(&hNetThread, nullptr, &NET_ThreadMain, nullptr) != 0)
{
pthread_mutex_destroy(&net_mutex);
#endif
net_thread_initialized = FALSE;
use_thread = FALSE;
Sys_Error("%s: Couldn't initialize network thread, run without -netthread\n", __func__);
}
#endif // _WIN32
Con_Printf("Network thread was initialized\n");
}
}
}
Expand All @@ -1198,11 +1235,38 @@ void NET_StopThread()
{
if (net_thread_initialized)
{
#ifdef REHLDS_FIXES // Safe thread stopping.
NET_ThreadLock();
net_thread_terminated = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need lock here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@theAsmodai what's the reason? x86?

NET_ThreadUnlock();
#endif // REHLDS_FIXES

#ifdef _WIN32
TerminateThread(hNetThread, 0);

#ifdef REHLDS_FIXES
if (WaitForSingleObject(hNetThread, 0.5 * 1000) != WAIT_OBJECT_0) // Wait 0.5 second for thread to finish
#endif // REHLDS_FIXES
{
TerminateThread(hNetThread, 0); // Kill unresponsive thread.
}
DeleteCriticalSection(&net_cs);

#else // _WIN32
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
Sys_Error("%s: CLOCK_REALTIME ERROR: %s", __func__, NET_ErrorString(NET_GetLastError()));
}
ts.tv_nsec += 0.5 * 1000000000; // Wait 0.5 second for thread to finish

if (pthread_timedjoin_np(hNetThread, nullptr, &ts) != 0)
{
pthread_cancel(hNetThread); // Kill unresponsive thread.
pthread_join(hNetThread, nullptr);
}
pthread_mutex_destroy(&net_mutex);
#endif // _WIN32
net_thread_initialized = FALSE;
Con_Printf("Network thread was terminated\n");
}
}
}
Expand Down Expand Up @@ -2013,9 +2077,15 @@ void NET_Init()
Cvar_RegisterVariable(&net_graphpos);

if (COM_CheckParm("-netthread"))
#if defined(REHLDS_FIXES) || defined(_WIN32) // -netthread will work either on windows or on fixed linux build.
use_thread = TRUE;
#else
use_thread = FALSE;
#endif

if (COM_CheckParm("-netsleep"))
#ifndef REHLDS_FIXES
if (COM_CheckParm("-netsleep")) // Sleeping forever is useless.
#endif
net_sleepforever = 0;

#ifdef _WIN32
Expand Down
1 change: 1 addition & 0 deletions rehlds/public/rehlds/osconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include <pthread.h>
#endif // _WIN32

#include <string>
Expand Down