Used std::thread and std::condition_variable (nw)

This commit is contained in:
Miodrag Milanovic 2016-03-01 20:52:56 +01:00
parent 6d0c46eacc
commit d9510ed04d
14 changed files with 193 additions and 1164 deletions

View File

@ -96,25 +96,7 @@ project ("ocore_" .. _OPTIONS["osd"])
MAME_DIR .. "src/lib",
MAME_DIR .. "src/lib/util",
}
if _OPTIONS["targetos"]=="linux" then
BASE_TARGETOS = "unix"
SDLOS_TARGETOS = "unix"
SYNC_IMPLEMENTATION = "tc"
end
if _OPTIONS["targetos"]=="windows" then
BASE_TARGETOS = "win32"
SDLOS_TARGETOS = "win32"
SYNC_IMPLEMENTATION = "windows"
end
if _OPTIONS["targetos"]=="macosx" then
BASE_TARGETOS = "unix"
SDLOS_TARGETOS = "macosx"
SYNC_IMPLEMENTATION = "ntc"
end
files {
MAME_DIR .. "src/osd/osdnet.cpp",
MAME_DIR .. "src/osd/osdnet.h",
@ -126,5 +108,5 @@ project ("ocore_" .. _OPTIONS["osd"])
MAME_DIR .. "src/osd/osdmini/minifile.cpp",
MAME_DIR .. "src/osd/osdmini/minimisc.cpp",
MAME_DIR .. "src/osd/osdmini/minitime.cpp",
MAME_DIR .. "src/osd/modules/sync/work_mini.cpp",
MAME_DIR .. "src/osd/modules/sync/work_osd.cpp",
}

View File

@ -222,27 +222,20 @@ end
BASE_TARGETOS = "unix"
SDLOS_TARGETOS = "unix"
SYNC_IMPLEMENTATION = "tc"
SDL_NETWORK = ""
if _OPTIONS["targetos"]=="linux" then
SDL_NETWORK = "taptun"
elseif _OPTIONS["targetos"]=="openbsd" then
SYNC_IMPLEMENTATION = "ntc"
elseif _OPTIONS["targetos"]=="netbsd" then
SYNC_IMPLEMENTATION = "ntc"
SDL_NETWORK = "pcap"
elseif _OPTIONS["targetos"]=="haiku" then
SYNC_IMPLEMENTATION = "ntc"
elseif _OPTIONS["targetos"]=="asmjs" then
SYNC_IMPLEMENTATION = "mini"
elseif _OPTIONS["targetos"]=="windows" then
BASE_TARGETOS = "win32"
SDLOS_TARGETOS = "win32"
SYNC_IMPLEMENTATION = "windows"
SDL_NETWORK = "pcap"
elseif _OPTIONS["targetos"]=="macosx" then
SDLOS_TARGETOS = "macosx"
SYNC_IMPLEMENTATION = "ntc"
SDL_NETWORK = "pcap"
end
@ -476,20 +469,11 @@ project ("ocore_" .. _OPTIONS["osd"])
MAME_DIR .. "src/osd/modules/osdmodule.h",
MAME_DIR .. "src/osd/modules/lib/osdlib_" .. SDLOS_TARGETOS .. ".cpp",
MAME_DIR .. "src/osd/modules/lib/osdlib.h",
MAME_DIR .. "src/osd/modules/sync/sync_" .. SYNC_IMPLEMENTATION .. ".cpp",
MAME_DIR .. "src/osd/modules/sync/osdsync.cpp",
MAME_DIR .. "src/osd/modules/sync/osdsync.h",
MAME_DIR .. "src/osd/modules/sync/work_osd.cpp",
}
if _OPTIONS["NOASM"]=="1" then
files {
MAME_DIR .. "src/osd/modules/sync/work_mini.cpp",
}
else
files {
MAME_DIR .. "src/osd/modules/sync/work_osd.cpp",
}
end
if _OPTIONS["targetos"]=="macosx" then
files {
MAME_DIR .. "src/osd/sdl/osxutils.h",

View File

@ -67,7 +67,6 @@ end
defines {
"OSD_SDL",
"SYNC_IMPLEMENTATION=" .. SYNC_IMPLEMENTATION,
}
if BASE_TARGETOS=="unix" then

View File

@ -224,7 +224,6 @@ project ("ocore_" .. _OPTIONS["osd"])
BASE_TARGETOS = "win32"
SDLOS_TARGETOS = "win32"
SYNC_IMPLEMENTATION = "windows"
includedirs {
MAME_DIR .. "src/osd/windows",
@ -245,7 +244,7 @@ project ("ocore_" .. _OPTIONS["osd"])
MAME_DIR .. "src/osd/windows/main.cpp",
MAME_DIR .. "src/osd/windows/windir.cpp",
MAME_DIR .. "src/osd/windows/winfile.cpp",
MAME_DIR .. "src/osd/modules/sync/sync_windows.cpp",
MAME_DIR .. "src/osd/modules/sync/osdsync.cpp",
MAME_DIR .. "src/osd/modules/sync/osdsync.h",
MAME_DIR .. "src/osd/windows/winutf8.cpp",
MAME_DIR .. "src/osd/windows/winutf8.h",
@ -258,18 +257,9 @@ project ("ocore_" .. _OPTIONS["osd"])
MAME_DIR .. "src/osd/modules/osdmodule.cpp",
MAME_DIR .. "src/osd/modules/osdmodule.h",
MAME_DIR .. "src/osd/modules/lib/osdlib_win32.cpp",
MAME_DIR .. "src/osd/modules/sync/work_osd.cpp",
}
if _OPTIONS["NOASM"] == "1" then
files {
MAME_DIR .. "src/osd/modules/sync/work_mini.cpp",
}
else
files {
MAME_DIR .. "src/osd/modules/sync/work_osd.cpp",
}
end
--------------------------------------------------
-- ledutil

View File

@ -0,0 +1,131 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles,Miodrag Milanovic
//============================================================
//
// osdsync.cpp -OSD core synchronization functions
//
//============================================================
// MAME headers
#include "osdcore.h"
#include "osdsync.h"
// C++ headers
#include <mutex>
#include <atomic>
#include <condition_variable>
//============================================================
// TYPE DEFINITIONS
//============================================================
struct osd_event {
std::mutex *mutex;
std::condition_variable *cond;
std::atomic<INT32> autoreset;
std::atomic<INT32> signalled;
};
//============================================================
// osd_event_alloc
//============================================================
osd_event *osd_event_alloc(int manualreset, int initialstate)
{
osd_event *ev;
ev = (osd_event *)calloc(1, sizeof(osd_event));
if (ev == nullptr)
return nullptr;
ev->mutex = new std::mutex();
ev->cond = new std::condition_variable();
ev->signalled = initialstate;
ev->autoreset = !manualreset;
return ev;
}
//============================================================
// osd_event_free
//============================================================
void osd_event_free(osd_event *event)
{
delete event->mutex;
delete event->cond;
free(event);
}
//============================================================
// osd_event_set
//============================================================
void osd_event_set(osd_event *event)
{
event->mutex->lock();
if (event->signalled == FALSE)
{
event->signalled = TRUE;
if (event->autoreset)
event->cond->notify_one();
else
event->cond->notify_all();
}
event->mutex->unlock();
}
//============================================================
// osd_event_reset
//============================================================
void osd_event_reset(osd_event *event)
{
event->mutex->lock();
event->signalled = FALSE;
event->mutex->unlock();
}
//============================================================
// osd_event_wait
//============================================================
int osd_event_wait(osd_event *event, osd_ticks_t timeout)
{
if (timeout == OSD_EVENT_WAIT_INFINITE)
timeout = osd_ticks_per_second() * (osd_ticks_t)10000;
std::unique_lock<std::mutex> lock(*event->mutex);
if (!timeout)
{
if (!event->signalled)
{
return FALSE;
}
}
else
{
if (!event->signalled)
{
UINT64 msec = timeout * 1000 / osd_ticks_per_second();
do {
if (event->cond->wait_for(lock, std::chrono::milliseconds(msec)) == std::cv_status::timeout)
{
if (!event->signalled)
{
return FALSE;
}
else
break;
} else
break;
} while (TRUE);
}
}
if (event->autoreset)
event->signalled = 0;
return TRUE;
}

View File

@ -103,75 +103,4 @@ void osd_event_set(osd_event *event);
-----------------------------------------------------------------------------*/
void osd_event_free(osd_event *event);
/***************************************************************************
SYNCHRONIZATION INTERFACES - Threads
***************************************************************************/
/* osd_thread is an opaque type which represents a thread */
struct osd_thread;
/* osd_thread_callback is a callback function that will be called from the thread */
typedef void *(*osd_thread_callback)(void *param);
/*-----------------------------------------------------------------------------
osd_thread_create: create a new thread
Parameters:
callback - The callback function to be called once the thread is up
cbparam - The parameter to pass to the callback function.
Return value:
A pointer to the created thread.
-----------------------------------------------------------------------------*/
osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam);
/*-----------------------------------------------------------------------------
osd_thread_adjust_priority: adjust priority of a thread
Parameters:
thread - A pointer to a previously created thread.
adjust - signed integer to add to the thread priority
Return value:
TRUE on success, FALSE on failure
-----------------------------------------------------------------------------*/
int osd_thread_adjust_priority(osd_thread *thread, int adjust);
/*-----------------------------------------------------------------------------
osd_thread_cpu_affinity: change cpu affinity of a thread
Parameters:
thread - A pointer to a previously created thread
or NULL for main thread
mask - bitmask to which cpus to bind
i.e. 0x01 1st cpu, 0x02, 2nd cpu, 0x04 3rd cpu
Return value:
TRUE on success, FALSE on failure
-----------------------------------------------------------------------------*/
int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask);
/*-----------------------------------------------------------------------------
osd_thread_wait_free: wait for thread to finish and free resources
Parameters:
thread - A pointer to a previously created thread.
Return value:
None.
-----------------------------------------------------------------------------*/
void osd_thread_wait_free(osd_thread *thread);
#endif /* __OSDSYNC__ */

View File

@ -1,105 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
//============================================================
//
// sdlsync_mini.c - Minimal core synchronization functions
//
//============================================================
#include "osdcore.h"
#include "osdsync.h"
struct _osd_event
{
void * ptr;
};
struct _osd_thread {
void * ptr;
};
//============================================================
// osd_event_alloc
//============================================================
osd_event *osd_event_alloc(int manualreset, int initialstate)
{
return nullptr;
}
//============================================================
// osd_event_free
//============================================================
void osd_event_free(osd_event *event)
{
}
//============================================================
// osd_event_set
//============================================================
void osd_event_set(osd_event *event)
{
}
//============================================================
// osd_event_reset
//============================================================
void osd_event_reset(osd_event *event)
{
}
//============================================================
// osd_event_wait
//============================================================
int osd_event_wait(osd_event *event, osd_ticks_t timeout)
{
return TRUE;
}
//============================================================
// osd_thread_create
//============================================================
osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
{
return nullptr;
}
//============================================================
// osd_thread_adjust_priority
//============================================================
int osd_thread_adjust_priority(osd_thread *thread, int adjust)
{
return FALSE;
}
//============================================================
// osd_thread_cpu_affinity
//============================================================
int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
{
return TRUE;
}
//============================================================
// osd_thread_wait_free
//============================================================
void osd_thread_wait_free(osd_thread *thread)
{
}

View File

@ -1,248 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert, R. Belmont
//============================================================
//
// sdlsync.c - SDL core synchronization functions
//
// SDLMAME by Olivier Galibert and R. Belmont
//
//============================================================
#ifndef _GNU_SOURCE
#define _GNU_SOURCE // for PTHREAD_MUTEX_RECURSIVE; needs to be here before other glibc headers are included
#endif
#include "sdlinc.h"
#ifdef SDLMAME_MACOSX
#include <mach/mach.h>
#include <signal.h>
#endif
#if defined(SDLMAME_NETBSD) || defined(SDLMAME_OPENBSD)
/* for SIGKILL */
#include <signal.h>
#endif
// standard C headers
#include <math.h>
#include <unistd.h>
// MAME headers
#include "osdcore.h"
#include "osdsync.h"
#include "eminline.h"
#include <pthread.h>
#include <errno.h>
#include <sys/time.h>
struct osd_event {
pthread_mutex_t mutex;
pthread_cond_t cond;
volatile INT32 autoreset;
volatile INT32 signalled;
// Fill a 64-byte cache line (a bit more padding with smaller pointers)
INT8 padding[(sizeof(void *) >= 8) ? 40 : 48];
};
//============================================================
// TYPE DEFINITIONS
//============================================================
struct osd_thread {
pthread_t thread;
};
//============================================================
// osd_event_alloc
//============================================================
osd_event *osd_event_alloc(int manualreset, int initialstate)
{
osd_event *ev;
pthread_mutexattr_t mtxattr;
ev = (osd_event *)calloc(1, sizeof(osd_event));
if (ev == NULL)
return NULL;
pthread_mutexattr_init(&mtxattr);
pthread_mutex_init(&ev->mutex, &mtxattr);
pthread_cond_init(&ev->cond, NULL);
ev->signalled = initialstate;
ev->autoreset = !manualreset;
return ev;
}
//============================================================
// osd_event_free
//============================================================
void osd_event_free(osd_event *event)
{
pthread_mutex_destroy(&event->mutex);
pthread_cond_destroy(&event->cond);
free(event);
}
//============================================================
// osd_event_set
//============================================================
void osd_event_set(osd_event *event)
{
pthread_mutex_lock(&event->mutex);
if (event->signalled == FALSE)
{
event->signalled = TRUE;
if (event->autoreset)
pthread_cond_signal(&event->cond);
else
pthread_cond_broadcast(&event->cond);
}
pthread_mutex_unlock(&event->mutex);
}
//============================================================
// osd_event_reset
//============================================================
void osd_event_reset(osd_event *event)
{
pthread_mutex_lock(&event->mutex);
event->signalled = FALSE;
pthread_mutex_unlock(&event->mutex);
}
//============================================================
// osd_event_wait
//============================================================
int osd_event_wait(osd_event *event, osd_ticks_t timeout)
{
if (timeout == OSD_EVENT_WAIT_INFINITE)
timeout = osd_ticks_per_second() * (osd_ticks_t)10000;
pthread_mutex_lock(&event->mutex);
if (!timeout)
{
if (!event->signalled)
{
pthread_mutex_unlock(&event->mutex);
return FALSE;
}
}
else
{
if (!event->signalled)
{
struct timespec ts;
struct timeval tp;
UINT64 msec = timeout * 1000 / osd_ticks_per_second();
UINT64 nsec;
gettimeofday(&tp, NULL);
ts.tv_sec = tp.tv_sec;
nsec = (UINT64) tp.tv_usec * (UINT64) 1000 + (msec * (UINT64) 1000000);
ts.tv_nsec = nsec % (UINT64) 1000000000;
ts.tv_sec += nsec / (UINT64) 1000000000;
do {
int ret = pthread_cond_timedwait(&event->cond, &event->mutex, &ts);
if ( ret == ETIMEDOUT )
{
if (!event->signalled)
{
pthread_mutex_unlock(&event->mutex);
return FALSE;
}
else
break;
}
if (ret == 0)
break;
if ( ret != EINTR)
{
printf("Error %d while waiting for pthread_cond_timedwait: %s\n", ret, strerror(ret));
}
} while (TRUE);
}
}
if (event->autoreset)
event->signalled = 0;
pthread_mutex_unlock(&event->mutex);
return TRUE;
}
//============================================================
// osd_thread_create
//============================================================
osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
{
osd_thread *thread;
pthread_attr_t attr;
thread = (osd_thread *)calloc(1, sizeof(osd_thread));
if (thread == NULL)
return NULL;
pthread_attr_init(&attr);
#ifndef SDLMAME_HAIKU
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
#endif
if ( pthread_create(&thread->thread, &attr, callback, cbparam) != 0 )
{
free(thread);
return NULL;
}
return thread;
}
//============================================================
// osd_thread_adjust_priority
//============================================================
int osd_thread_adjust_priority(osd_thread *thread, int adjust)
{
struct sched_param sched;
int policy;
if ( pthread_getschedparam( thread->thread, &policy, &sched ) == 0 )
{
sched.sched_priority += adjust;
if ( pthread_setschedparam(thread->thread, policy, &sched ) == 0)
return TRUE;
else
return FALSE;
}
else
return FALSE;
}
//============================================================
// osd_thread_cpu_affinity
//============================================================
int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
{
return TRUE;
}
//============================================================
// osd_thread_wait_free
//============================================================
void osd_thread_wait_free(osd_thread *thread)
{
pthread_join(thread->thread, NULL);
free(thread);
}

View File

@ -1,227 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert, R. Belmont
//============================================================
//
// sdlsync.c - SDL core synchronization functions
//
// SDLMAME by Olivier Galibert and R. Belmont
//
//============================================================
#include "sdlinc.h"
// standard C headers
#include <cstdint>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
// MAME headers
#include "osdcore.h"
#include "osdsync.h"
#include "eminline.h"
#define VERBOSE (0)
#if VERBOSE
#define LOG( x ) do { printf x; printf("\n"); } while (0)
#else
#define LOG( x )
#endif
struct hidden_mutex_t {
SDL_mutex * id;
volatile INT32 locked;
volatile INT32 threadid;
};
struct osd_event {
SDL_mutex * mutex;
SDL_cond * cond;
volatile INT32 autoreset;
volatile INT32 signalled;
};
//============================================================
// TYPE DEFINITIONS
//============================================================
struct osd_thread {
SDL_Thread * thread;
osd_thread_callback callback;
void *param;
};
//============================================================
// osd_event_alloc
//============================================================
osd_event *osd_event_alloc(int manualreset, int initialstate)
{
osd_event *ev;
ev = (osd_event *)calloc(1, sizeof(osd_event));
if (ev == NULL)
return NULL;
ev->mutex = SDL_CreateMutex();
ev->cond = SDL_CreateCond();
ev->signalled = initialstate;
ev->autoreset = !manualreset;
return ev;
}
//============================================================
// osd_event_free
//============================================================
void osd_event_free(osd_event *event)
{
SDL_DestroyMutex(event->mutex);
SDL_DestroyCond(event->cond);
free(event);
}
//============================================================
// osd_event_set
//============================================================
void osd_event_set(osd_event *event)
{
LOG(("osd_event_set"));
SDL_mutexP(event->mutex);
if (event->signalled == FALSE)
{
event->signalled = TRUE;
if (event->autoreset)
SDL_CondSignal(event->cond);
else
SDL_CondBroadcast(event->cond);
}
SDL_mutexV(event->mutex);
}
//============================================================
// osd_event_reset
//============================================================
void osd_event_reset(osd_event *event)
{
LOG(("osd_event_reset"));
SDL_mutexP(event->mutex);
event->signalled = FALSE;
SDL_mutexV(event->mutex);
}
//============================================================
// osd_event_wait
//============================================================
int osd_event_wait(osd_event *event, osd_ticks_t timeout)
{
LOG(("osd_event_wait"));
if (timeout == OSD_EVENT_WAIT_INFINITE)
timeout = osd_ticks_per_second() * (osd_ticks_t)10000;
SDL_mutexP(event->mutex);
if (!timeout)
{
if (!event->signalled)
{
SDL_mutexV(event->mutex);
return FALSE;
}
}
else
{
if (!event->signalled)
{
UINT64 msec = (timeout * 1000) / osd_ticks_per_second();
do {
int ret = SDL_CondWaitTimeout(event->cond, event->mutex, msec);
if ( ret == SDL_MUTEX_TIMEDOUT )
{
if (!event->signalled)
{
SDL_mutexV(event->mutex);
return FALSE;
}
else
break;
}
if (ret == 0)
break;
printf("Error %d while waiting for pthread_cond_timedwait: %s\n", ret, strerror(ret));
} while (TRUE);
}
}
if (event->autoreset)
event->signalled = 0;
SDL_mutexV(event->mutex);
return TRUE;
}
//============================================================
// osd_thread_create
//============================================================
static int worker_thread_entry(void *param)
{
osd_thread *thread = (osd_thread *) param;
void *res;
res = thread->callback(thread->param);
return int(intptr_t(res));
}
osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
{
osd_thread *thread;
thread = (osd_thread *)calloc(1, sizeof(osd_thread));
if (thread == NULL)
return NULL;
thread->callback = callback;
thread->param = cbparam;
thread->thread = SDL_CreateThread(worker_thread_entry, "Thread", thread);
if ( thread->thread == NULL )
{
free(thread);
return NULL;
}
return thread;
}
//============================================================
// osd_thread_adjust_priority
//============================================================
int osd_thread_adjust_priority(osd_thread *thread, int adjust)
{
return TRUE;
}
//============================================================
// osd_thread_cpu_affinity
//============================================================
int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
{
return TRUE;
}
//============================================================
// osd_thread_wait_free
//============================================================
void osd_thread_wait_free(osd_thread *thread)
{
int status;
SDL_WaitThread(thread->thread, &status);
free(thread);
}

View File

@ -1,270 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert, R. Belmont
//============================================================
//
// sdlsync.c - SDL core synchronization functions
//
// SDLMAME by Olivier Galibert and R. Belmont
//
//============================================================
#ifndef _GNU_SOURCE
#define _GNU_SOURCE // for PTHREAD_MUTEX_RECURSIVE; needs to be here before other glibc headers are included
#endif
#include "sdlinc.h"
#ifdef SDLMAME_MACOSX
#include <mach/mach.h>
#endif
// standard C headers
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
// MAME headers
#include "osdcomm.h"
#include "osdcore.h"
#include "osdsync.h"
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
struct hidden_mutex_t {
pthread_mutex_t id;
};
struct osd_event {
pthread_mutex_t mutex;
pthread_cond_t cond;
volatile INT32 autoreset;
volatile INT32 signalled;
// Fill a 64-byte cache line (a bit more padding with smaller pointers)
INT8 padding[(sizeof(void *) >= 8) ? 40 : 48];
};
//============================================================
// TYPE DEFINITIONS
//============================================================
struct osd_thread {
pthread_t thread;
};
//============================================================
// osd_event_alloc
//============================================================
osd_event *osd_event_alloc(int manualreset, int initialstate)
{
osd_event *ev;
pthread_mutexattr_t mtxattr;
ev = (osd_event *)calloc(1, sizeof(osd_event));
if (ev == NULL)
return NULL;
pthread_mutexattr_init(&mtxattr);
pthread_mutex_init(&ev->mutex, &mtxattr);
pthread_cond_init(&ev->cond, NULL);
ev->signalled = initialstate;
ev->autoreset = !manualreset;
return ev;
}
//============================================================
// osd_event_free
//============================================================
void osd_event_free(osd_event *event)
{
pthread_mutex_destroy(&event->mutex);
pthread_cond_destroy(&event->cond);
free(event);
}
//============================================================
// osd_event_set
//============================================================
void osd_event_set(osd_event *event)
{
pthread_mutex_lock(&event->mutex);
if (event->signalled == FALSE)
{
event->signalled = TRUE;
if (event->autoreset)
pthread_cond_signal(&event->cond);
else
pthread_cond_broadcast(&event->cond);
}
pthread_mutex_unlock(&event->mutex);
}
//============================================================
// osd_event_reset
//============================================================
void osd_event_reset(osd_event *event)
{
pthread_mutex_lock(&event->mutex);
event->signalled = FALSE;
pthread_mutex_unlock(&event->mutex);
}
//============================================================
// osd_event_wait
//============================================================
int osd_event_wait(osd_event *event, osd_ticks_t timeout)
{
if (timeout == OSD_EVENT_WAIT_INFINITE)
timeout = osd_ticks_per_second() * (osd_ticks_t)10000;
pthread_mutex_lock(&event->mutex);
if (!timeout)
{
if (!event->signalled)
{
pthread_mutex_unlock(&event->mutex);
return FALSE;
}
}
else
{
if (!event->signalled)
{
struct timespec ts;
struct timeval tp;
UINT64 msec = timeout * 1000 / osd_ticks_per_second();
UINT64 nsec;
gettimeofday(&tp, NULL);
ts.tv_sec = tp.tv_sec;
nsec = (UINT64) tp.tv_usec * (UINT64) 1000 + (msec * (UINT64) 1000000);
ts.tv_nsec = nsec % (UINT64) 1000000000;
ts.tv_sec += nsec / (UINT64) 1000000000;
do {
int ret = pthread_cond_timedwait(&event->cond, &event->mutex, &ts);
if ( ret == ETIMEDOUT )
{
if (!event->signalled)
{
pthread_mutex_unlock(&event->mutex);
return FALSE;
}
else
break;
}
if (ret == 0)
break;
if ( ret != EINTR)
{
printf("Error %d while waiting for pthread_cond_timedwait: %s\n", ret, strerror(ret));
}
} while (TRUE);
}
}
if (event->autoreset)
event->signalled = 0;
pthread_mutex_unlock(&event->mutex);
return TRUE;
}
//============================================================
// osd_thread_create
//============================================================
osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
{
osd_thread *thread;
pthread_attr_t attr;
thread = (osd_thread *)calloc(1, sizeof(osd_thread));
if (thread == NULL)
return NULL;
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
if ( pthread_create(&thread->thread, &attr, callback, cbparam) != 0 )
{
free(thread);
return NULL;
}
return thread;
}
//============================================================
// osd_thread_adjust_priority
//============================================================
int osd_thread_adjust_priority(osd_thread *thread, int adjust)
{
struct sched_param sched;
int policy;
if ( pthread_getschedparam( thread->thread, &policy, &sched ) == 0 )
{
sched.sched_priority += adjust;
if ( pthread_setschedparam(thread->thread, policy, &sched ) == 0)
return TRUE;
else
return FALSE;
}
else
return FALSE;
}
//============================================================
// osd_thread_cpu_affinity
//============================================================
int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
{
#if !defined(NO_AFFINITY_NP)
cpu_set_t cmask;
pthread_t lthread;
int bitnum;
CPU_ZERO(&cmask);
for (bitnum=0; bitnum<32; bitnum++)
if (mask & (1<<bitnum))
CPU_SET(bitnum, &cmask);
if (thread == NULL)
lthread = pthread_self();
else
lthread = thread->thread;
if (pthread_setaffinity_np(lthread, sizeof(cmask), &cmask) <0)
{
/* Not available during link in all targets */
fprintf(stderr, "error %d setting cpu affinity to mask %08x", errno, mask);
return FALSE;
}
else
return TRUE;
#else
return TRUE;
#endif
}
//============================================================
// osd_thread_wait_free
//============================================================
void osd_thread_wait_free(osd_thread *thread)
{
pthread_join(thread->thread, NULL);
free(thread);
}

View File

@ -1,164 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
//============================================================
//
// winsync.c - Win32 OSD core synchronization functions
//
//============================================================
// standard windows headers
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <process.h>
// MAME headers
#include "osdcore.h"
#include "eminline.h"
#include "osdsync.h"
// C++ headers
#include <cstdint>
//============================================================
// DEBUGGING
//============================================================
#define DEBUG_SLOW_LOCKS 0
//============================================================
// TYPE DEFINITIONS
//============================================================
typedef BOOL (WINAPI *try_enter_critical_section_ptr)(LPCRITICAL_SECTION lpCriticalSection);
struct osd_event
{
void * ptr;
};
struct osd_thread {
HANDLE handle;
osd_thread_callback callback;
void *param;
};
//============================================================
// osd_event_alloc
//============================================================
osd_event *osd_event_alloc(int manualreset, int initialstate)
{
return (osd_event *) CreateEvent(nullptr, manualreset, initialstate, nullptr);
}
//============================================================
// osd_event_free
//============================================================
void osd_event_free(osd_event *event)
{
CloseHandle((HANDLE) event);
}
//============================================================
// osd_event_set
//============================================================
void osd_event_set(osd_event *event)
{
SetEvent((HANDLE) event);
}
//============================================================
// osd_event_reset
//============================================================
void osd_event_reset(osd_event *event)
{
ResetEvent((HANDLE) event);
}
//============================================================
// osd_event_wait
//============================================================
int osd_event_wait(osd_event *event, osd_ticks_t timeout)
{
DWORD timeout_param;
if (timeout == OSD_EVENT_WAIT_INFINITE)
timeout_param = INFINITE;
else
timeout_param = timeout * 1000 / osd_ticks_per_second();
int ret = WaitForSingleObject((HANDLE) event, timeout_param);
return (ret == WAIT_OBJECT_0);
}
//============================================================
// osd_thread_create
//============================================================
static unsigned __stdcall worker_thread_entry(void *param)
{
osd_thread *thread = (osd_thread *) param;
void *res;
res = thread->callback(thread->param);
return unsigned(uintptr_t(res));
}
osd_thread *osd_thread_create(osd_thread_callback callback, void *cbparam)
{
osd_thread *thread;
uintptr_t handle;
thread = (osd_thread *)calloc(1, sizeof(osd_thread));
if (thread == nullptr)
return nullptr;
thread->callback = callback;
thread->param = cbparam;
handle = _beginthreadex(nullptr, 0, worker_thread_entry, thread, 0, nullptr);
if (handle == 0)
{
free(thread);
return nullptr;
}
thread->handle = (HANDLE) handle;
return thread;
}
//============================================================
// osd_thread_wait_free
//============================================================
void osd_thread_wait_free(osd_thread *thread)
{
WaitForSingleObject(thread->handle, INFINITE);
CloseHandle(thread->handle);
free(thread);
}
//============================================================
// osd_thread_adjust_priority
//============================================================
int osd_thread_adjust_priority(osd_thread *thread, int adjust)
{
if (adjust)
SetThreadPriority(thread->handle, THREAD_PRIORITY_ABOVE_NORMAL);
else
SetThreadPriority(thread->handle, GetThreadPriority(GetCurrentThread()));
return TRUE;
}
//============================================================
// osd_thread_cpu_affinity
//============================================================
int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask)
{
return TRUE;
}

View File

@ -6,7 +6,7 @@
//
//============================================================
#if defined(OSD_WINDOWS)
#if defined(OSD_WINDOWS) || (SDLMAME_WIN32)
// standard windows headers
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -20,6 +20,7 @@
#endif
#include <mutex>
#include <atomic>
#include <thread>
// MAME headers
#include "osdcore.h"
@ -32,7 +33,9 @@
#if defined(SDLMAME_MACOSX)
#include "osxutils.h"
#endif
#if defined(SDLMAME_LINUX) || defined(SDLMAME_BSD) || defined(SDLMAME_HAIKU) || defined(SDLMAME_EMSCRIPTEN) || defined(SDLMAME_MACOSX)
#include <pthread.h>
#endif
#if defined(OSD_SDL)
typedef void *PVOID;
#endif
@ -95,7 +98,7 @@ static void spin_while_not(const volatile _AtomType * volatile atom, const _Main
struct work_thread_info
{
osd_work_queue * queue; // pointer back to the queue
osd_thread * handle; // handle to the thread
std::thread * handle; // handle to the thread
osd_event * wakeevent; // wake event for the thread
std::atomic<INT32> active; // are we actively processing work?
@ -160,6 +163,33 @@ static void * worker_thread_entry(void *param);
static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread);
static bool queue_has_list_items(osd_work_queue *queue);
//============================================================
// osd_thread_adjust_priority
//============================================================
int thread_adjust_priority(std::thread *thread, int adjust)
{
#if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32)
if (adjust)
SetThreadPriority((HANDLE)thread->native_handle(), THREAD_PRIORITY_ABOVE_NORMAL);
else
SetThreadPriority((HANDLE)thread->native_handle(), GetThreadPriority(GetCurrentThread()));
#endif
#if defined(SDLMAME_LINUX) || defined(SDLMAME_BSD) || defined(SDLMAME_HAIKU) || defined(SDLMAME_EMSCRIPTEN) || defined(SDLMAME_DARWIN)
struct sched_param sched;
int policy;
if (pthread_getschedparam(thread->native_handle(), &policy, &sched) == 0)
{
sched.sched_priority += adjust;
if (pthread_setschedparam(thread->native_handle(), policy, &sched) == 0)
return TRUE;
else
return FALSE;
}
#endif
return TRUE;
}
//============================================================
// osd_work_queue_alloc
@ -237,16 +267,16 @@ osd_work_queue *osd_work_queue_alloc(int flags)
goto error;
// create the thread
thread->handle = osd_thread_create(worker_thread_entry, thread);
if (thread->handle == NULL)
thread->handle = new std::thread(worker_thread_entry, thread);
if (thread->handle == nullptr)
goto error;
// set its priority: I/O threads get high priority because they are assumed to be
// blocked most of the time; other threads just match the creator's priority
if (flags & WORK_QUEUE_FLAG_IO)
osd_thread_adjust_priority(thread->handle, 1);
thread_adjust_priority(thread->handle, 1);
else
osd_thread_adjust_priority(thread->handle, 0);
thread_adjust_priority(thread->handle, 0);
}
// start a timer going for "waittime" on the main thread
@ -357,7 +387,8 @@ void osd_work_queue_free(osd_work_queue *queue)
// block on the thread going away, then close the handle
if (thread->handle != NULL)
{
osd_thread_wait_free(thread->handle);
thread->handle->join();
delete thread->handle;
}
// clean up the wake event
@ -446,12 +477,11 @@ osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_call
// first allocate a new work item; try the free list first
{
queue->lock->lock();
std::lock_guard<std::mutex> lock(*queue->lock);
do
{
item = (osd_work_item *)queue->free;
} while (item != NULL && !queue->free.compare_exchange_weak(item, item->next, std::memory_order_release, std::memory_order_relaxed));
queue->lock->unlock();
} while (item != NULL && !queue->free.compare_exchange_weak(item, item->next, std::memory_order_release, std::memory_order_relaxed));
}
// if nothing, allocate something new
@ -486,10 +516,9 @@ osd_work_item *osd_work_item_queue_multiple(osd_work_queue *queue, osd_work_call
// enqueue the whole thing within the critical section
{
queue->lock->lock();
std::lock_guard<std::mutex> lock(*queue->lock);
*queue->tailptr = itemlist;
queue->tailptr = item_tailptr;
queue->lock->unlock();
queue->tailptr = item_tailptr;
}
// increment the number of items in the queue
@ -544,9 +573,8 @@ int osd_work_item_wait(osd_work_item *item, osd_ticks_t timeout)
// if we don't have an event, create one
if (item->event == NULL)
{
item->queue->lock->lock();
item->event = osd_event_alloc(TRUE, FALSE); // manual reset, not signalled
item->queue->lock->unlock();
std::lock_guard<std::mutex> lock(*item->queue->lock);
item->event = osd_event_alloc(TRUE, FALSE); // manual reset, not signalled
}
else
osd_event_reset(item->event);
@ -589,13 +617,12 @@ void osd_work_item_release(osd_work_item *item)
osd_work_item_wait(item, 100 * osd_ticks_per_second());
// add us to the free list on our queue
item->queue->lock->lock();
std::lock_guard<std::mutex> lock(*item->queue->lock);
do
{
next = (osd_work_item *)item->queue->free;
item->next = next;
} while (!item->queue->free.compare_exchange_weak(next, item, std::memory_order_release, std::memory_order_relaxed));
item->queue->lock->unlock();
}
@ -716,7 +743,8 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
// use a critical section to synchronize the removal of items
{
queue->lock->lock();
std::lock_guard<std::mutex> lock(*queue->lock);
if (queue->list.load() == nullptr)
{
end_loop = true;
@ -732,7 +760,6 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
queue->tailptr = (osd_work_item **)&queue->list;
}
}
queue->lock->unlock();
}
if (end_loop)
@ -758,13 +785,13 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
// set the result and signal the event
else
{
queue->lock->lock();
std::lock_guard<std::mutex> lock(*queue->lock);
if (item->event != NULL)
{
osd_event_set(item->event);
add_to_stat(item->queue->setevents, 1);
}
queue->lock->unlock();
}
// if we removed an item and there's still work to do, bump the stats
@ -785,8 +812,7 @@ static void worker_thread_process(osd_work_queue *queue, work_thread_info *threa
bool queue_has_list_items(osd_work_queue *queue)
{
queue->lock->lock();
std::lock_guard<std::mutex> lock(*queue->lock);
bool has_list_items = (queue->list.load() != nullptr);
queue->lock->unlock();
return has_list_items;
}

View File

@ -45,7 +45,7 @@ watchdog::watchdog(void)
{
m_do_exit = 0;
m_event = osd_event_alloc(1, 0);
m_thread = osd_thread_create(watchdog_thread, this);
m_thread = new std::thread(watchdog_thread, this);
m_timeout = 60 * osd_ticks_per_second();
}
@ -53,7 +53,8 @@ watchdog::~watchdog(void)
{
m_do_exit = 1;
osd_event_set(m_event);
osd_thread_wait_free(m_thread);
m_thread->join();
delete m_thread;
osd_event_free(m_event);
}

View File

@ -12,6 +12,7 @@
#include "modules/sync/osdsync.h"
#include <atomic>
#include <thread>
class watchdog
{
@ -27,7 +28,7 @@ public:
void setTimeout(int timeout);
private:
osd_event * m_event;
osd_thread * m_thread;
std::thread* m_thread;
std::atomic<INT32> m_do_exit;
osd_ticks_t m_timeout;