mirror of
https://github.com/libretro/beetle-pce-fast-libretro.git
synced 2024-11-23 07:50:03 +00:00
Update threading code
This commit is contained in:
parent
a4020fd1d9
commit
76e8a0d95f
6
Makefile
6
Makefile
@ -2,7 +2,6 @@ DEBUG = 0
|
||||
FRONTEND_SUPPORTS_RGB565 = 1
|
||||
|
||||
MEDNAFEN_DIR := mednafen
|
||||
MEDNAFEN_LIBRETRO_DIR := mednafen-libretro
|
||||
NEED_TREMOR = 0
|
||||
LIBRETRO_SOURCES :=
|
||||
|
||||
@ -241,6 +240,7 @@ endif
|
||||
|
||||
ifeq ($(NEED_THREADING), 1)
|
||||
FLAGS += -DWANT_THREADING
|
||||
THREAD_SOURCES += thread.c
|
||||
endif
|
||||
|
||||
ifeq ($(NEED_CRC32), 1)
|
||||
@ -301,12 +301,12 @@ MEDNAFEN_SOURCES := $(MEDNAFEN_DIR)/mednafen.cpp \
|
||||
$(MEDNAFEN_DIR)/md5.cpp
|
||||
|
||||
|
||||
LIBRETRO_SOURCES += libretro.cpp stubs.cpp $(THREAD_STUBS)
|
||||
LIBRETRO_SOURCES += libretro.cpp
|
||||
|
||||
TRIO_SOURCES += $(MEDNAFEN_DIR)/trio/trio.c \
|
||||
$(MEDNAFEN_DIR)/trio/triostr.c $(MEDNAFEN_DIR)/cputest/cputest.c
|
||||
|
||||
SOURCES_C := $(TREMOR_SRC) $(LIBRETRO_SOURCES_C) $(TRIO_SOURCES)
|
||||
SOURCES_C := $(TREMOR_SRC) $(LIBRETRO_SOURCES_C) $(TRIO_SOURCES) $(THREAD_SOURCES)
|
||||
|
||||
SOURCES := $(LIBRETRO_SOURCES) $(CORE_SOURCES) $(MEDNAFEN_SOURCES) $(HW_CPU_SOURCES) $(HW_MISC_SOURCES) $(HW_SOUND_SOURCES) $(HW_VIDEO_SOURCES)
|
||||
|
||||
|
33
boolean.h
Normal file
33
boolean.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __RARCH_BOOLEAN_H
|
||||
#define __RARCH_BOOLEAN_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#if defined(_MSC_VER) && !defined(SN_TARGET_PS3)
|
||||
/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */
|
||||
#define bool unsigned char
|
||||
#define true 1
|
||||
#define false 0
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -67,6 +67,7 @@ CORE_INCDIR := $(CORE_DIR)
|
||||
|
||||
ifeq ($(NEED_THREADING), 1)
|
||||
FLAGS += -DWANT_THREADING
|
||||
THREAD_SOURCES += $(MEDNAFEN_LIBRETRO_DIR)/thread.c
|
||||
endif
|
||||
|
||||
ifeq ($(NEED_CRC32), 1)
|
||||
@ -116,9 +117,9 @@ MEDNAFEN_SOURCES := $(MEDNAFEN_DIR)/mednafen.cpp \
|
||||
$(MEDNAFEN_DIR)/md5.cpp
|
||||
|
||||
|
||||
LIBRETRO_SOURCES := $(MEDNAFEN_LIBRETRO_DIR)/libretro.cpp $(MEDNAFEN_LIBRETRO_DIR)/stubs.cpp $(THREAD_STUBS)
|
||||
LIBRETRO_SOURCES := $(MEDNAFEN_LIBRETRO_DIR)/libretro.cpp
|
||||
|
||||
SOURCES_C := $(TREMOR_SRC) $(LIBRETRO_SOURCES_C) $(MEDNAFEN_DIR)/trio/trio.c $(MEDNAFEN_DIR)/trio/triostr.c
|
||||
SOURCES_C := $(TREMOR_SRC) $(LIBRETRO_SOURCES_C) $(MEDNAFEN_DIR)/trio/trio.c $(MEDNAFEN_DIR)/trio/triostr.c $(THREAD_SOURCES)
|
||||
|
||||
LOCAL_SRC_FILES += $(LIBRETRO_SOURCES) $(CORE_SOURCES) $(MEDNAFEN_SOURCES) $(CDROM_SOURCES) $(SCSI_CD_SOURCES) $(HW_CPU_SOURCES) $(HW_MISC_SOURCES) $(HW_SOUND_SOURCES) $(HW_VIDEO_SOURCES) $(SOURCES_C) $(CORE_CD_SOURCES)
|
||||
|
||||
|
120
libretro.cpp
120
libretro.cpp
@ -7,6 +7,7 @@
|
||||
#include "mednafen/video/Deinterlacer.h"
|
||||
#endif
|
||||
#include "libretro.h"
|
||||
#include "thread.h"
|
||||
|
||||
static MDFNGI *game;
|
||||
|
||||
@ -622,3 +623,122 @@ void retro_cheat_reset(void)
|
||||
|
||||
void retro_cheat_set(unsigned, bool, const char *)
|
||||
{}
|
||||
|
||||
MDFN_Thread *MDFND_CreateThread(int (*fn)(void *), void *data)
|
||||
{
|
||||
return (MDFN_Thread*)sthread_create((void (*)(void*))fn, data);
|
||||
}
|
||||
|
||||
void MDFND_WaitThread(MDFN_Thread *thr, int *val)
|
||||
{
|
||||
sthread_join((sthread_t*)thr);
|
||||
|
||||
if (val)
|
||||
{
|
||||
*val = 0;
|
||||
fprintf(stderr, "WaitThread relies on return value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MDFND_KillThread(MDFN_Thread *)
|
||||
{
|
||||
fprintf(stderr, "Killing a thread is a BAD IDEA!\n");
|
||||
}
|
||||
|
||||
MDFN_Mutex *MDFND_CreateMutex()
|
||||
{
|
||||
return (MDFN_Mutex*)slock_new();
|
||||
}
|
||||
|
||||
void MDFND_DestroyMutex(MDFN_Mutex *lock)
|
||||
{
|
||||
slock_free((slock_t*)lock);
|
||||
}
|
||||
|
||||
int MDFND_LockMutex(MDFN_Mutex *lock)
|
||||
{
|
||||
slock_lock((slock_t*)lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MDFND_UnlockMutex(MDFN_Mutex *lock)
|
||||
{
|
||||
slock_unlock((slock_t*)lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void sanitize_path(std::string &path)
|
||||
{
|
||||
size_t size = path.size();
|
||||
for (size_t i = 0; i < size; i++)
|
||||
if (path[i] == '/')
|
||||
path[i] = '\\';
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use a simpler approach to make sure that things go right for libretro.
|
||||
std::string MDFN_MakeFName(MakeFName_Type type, int id1, const char *cd1)
|
||||
{
|
||||
char slash;
|
||||
#ifdef _WIN32
|
||||
slash = '\\';
|
||||
#else
|
||||
slash = '/';
|
||||
#endif
|
||||
std::string ret;
|
||||
switch (type)
|
||||
{
|
||||
case MDFNMKF_SAV:
|
||||
ret = retro_save_directory +slash + retro_base_name +
|
||||
std::string(".") +
|
||||
#ifndef _XBOX
|
||||
md5_context::asciistr(MDFNGameInfo->MD5, 0) + std::string(".") +
|
||||
#endif
|
||||
std::string(cd1);
|
||||
break;
|
||||
case MDFNMKF_FIRMWARE:
|
||||
ret = retro_base_directory + slash + std::string(cd1);
|
||||
#ifdef _WIN32
|
||||
sanitize_path(ret); // Because Windows path handling is mongoloid.
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_INFO, "MDFN_MakeFName: %s\n", ret.c_str());
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MDFND_DispMessage(unsigned char *str)
|
||||
{
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_INFO, "%s\n", str);
|
||||
}
|
||||
|
||||
void MDFND_Message(const char *str)
|
||||
{
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_INFO, "%s\n", str);
|
||||
}
|
||||
|
||||
void MDFND_MidSync(const EmulateSpecStruct *)
|
||||
{}
|
||||
|
||||
void MDFN_MidLineUpdate(EmulateSpecStruct *espec, int y)
|
||||
{
|
||||
//MDFND_MidLineUpdate(espec, y);
|
||||
}
|
||||
|
||||
void MDFND_PrintError(const char* err)
|
||||
{
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_ERROR, "%s\n", err);
|
||||
}
|
||||
|
||||
void MDFND_Sleep(unsigned int time)
|
||||
{
|
||||
retro_sleep(time);
|
||||
}
|
||||
|
@ -200,7 +200,7 @@
|
||||
RelativePath="..\..\..\scrc32.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\stubs.cpp">
|
||||
RelativePath="..\..\..\thread.c">
|
||||
</File>
|
||||
<Filter
|
||||
Name="mednafen"
|
||||
|
@ -219,7 +219,7 @@
|
||||
<ClCompile Include="..\..\..\mednafen\video\Deinterlacer.cpp" />
|
||||
<ClCompile Include="..\..\..\mednafen\video\surface.cpp" />
|
||||
<ClCompile Include="..\..\..\scrc32.cpp" />
|
||||
<ClCompile Include="..\..\..\stubs.cpp" />
|
||||
<ClCompile Include="..\..\..\thread.c" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{38462FE9-E3FC-4336-B241-50F5599C537B}</ProjectGuid>
|
||||
|
@ -107,7 +107,7 @@
|
||||
<ClCompile Include="..\..\..\mednafen\sound\Blip_Buffer.cpp">
|
||||
<Filter>Source Files\mednafen\sound</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\stubs.cpp">
|
||||
<ClCompile Include="..\..\..\thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\libretro.cpp">
|
||||
|
@ -134,7 +134,7 @@
|
||||
<ClCompile Include="..\..\..\mednafen\video\Deinterlacer.cpp" />
|
||||
<ClCompile Include="..\..\..\mednafen\video\surface.cpp" />
|
||||
<ClCompile Include="..\..\..\scrc32.cpp" />
|
||||
<ClCompile Include="..\..\..\stubs.cpp" />
|
||||
<ClCompile Include="..\..\..\thread.c" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{38462FE9-E3FC-4336-B241-50F5599C537B}</ProjectGuid>
|
||||
|
@ -107,7 +107,7 @@
|
||||
<ClCompile Include="..\..\..\mednafen\sound\Blip_Buffer.cpp">
|
||||
<Filter>Source Files\mednafen\sound</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\stubs.cpp">
|
||||
<ClCompile Include="..\..\..\thread.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\libretro.cpp">
|
||||
|
@ -1,130 +1,29 @@
|
||||
#include "mednafen/mednafen-types.h"
|
||||
#include "mednafen/mednafen.h"
|
||||
#include "mednafen/md5.h"
|
||||
#include "mednafen/git.h"
|
||||
#include "mednafen/general.h"
|
||||
#include "mednafen/mednafen-driver.h"
|
||||
|
||||
#include "libretro.h"
|
||||
|
||||
extern retro_log_printf_t log_cb;
|
||||
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#include <sys/timer.h>
|
||||
#include <ppu_intrinsics.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#ifdef _XBOX
|
||||
#include <xtl.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// Stubs
|
||||
|
||||
extern std::string retro_base_directory;
|
||||
extern std::string retro_base_name;
|
||||
extern std::string retro_save_directory;
|
||||
|
||||
#ifdef _WIN32
|
||||
static void sanitize_path(std::string &path)
|
||||
{
|
||||
size_t size = path.size();
|
||||
for (size_t i = 0; i < size; i++)
|
||||
if (path[i] == '/')
|
||||
path[i] = '\\';
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use a simpler approach to make sure that things go right for libretro.
|
||||
std::string MDFN_MakeFName(MakeFName_Type type, int id1, const char *cd1)
|
||||
{
|
||||
char slash;
|
||||
#ifdef _WIN32
|
||||
slash = '\\';
|
||||
#else
|
||||
slash = '/';
|
||||
#endif
|
||||
std::string ret;
|
||||
switch (type)
|
||||
{
|
||||
case MDFNMKF_SAV:
|
||||
ret = retro_save_directory +slash + retro_base_name +
|
||||
std::string(".") +
|
||||
#ifndef _XBOX
|
||||
md5_context::asciistr(MDFNGameInfo->MD5, 0) + std::string(".") +
|
||||
#endif
|
||||
std::string(cd1);
|
||||
break;
|
||||
case MDFNMKF_FIRMWARE:
|
||||
ret = retro_base_directory + slash + std::string(cd1);
|
||||
#ifdef _WIN32
|
||||
sanitize_path(ret); // Because Windows path handling is mongoloid.
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_INFO, "MDFN_MakeFName: %s\n", ret.c_str());
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MDFND_DispMessage(unsigned char *str)
|
||||
{
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_INFO, "%s\n", str);
|
||||
}
|
||||
|
||||
void MDFND_Message(const char *str)
|
||||
{
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_INFO, "%s\n", str);
|
||||
}
|
||||
|
||||
void MDFND_MidSync(const EmulateSpecStruct *)
|
||||
{}
|
||||
|
||||
void MDFN_MidLineUpdate(EmulateSpecStruct *espec, int y)
|
||||
{
|
||||
//MDFND_MidLineUpdate(espec, y);
|
||||
}
|
||||
|
||||
void MDFND_PrintError(const char* err)
|
||||
{
|
||||
if (log_cb)
|
||||
log_cb(RETRO_LOG_ERROR, "%s\n", err);
|
||||
}
|
||||
|
||||
void MDFND_Sleep(unsigned int time)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
Sleep(time);
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
sys_timer_usleep(time * 1000);
|
||||
#else
|
||||
usleep(time * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WANT_THREADING
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2014 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "thread.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
#if defined(_WIN32)
|
||||
#ifdef _XBOX
|
||||
#include <xtl.h>
|
||||
#else
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#elif defined(_XBOX)
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
#elif defined(GEKKO)
|
||||
#include "thread/gx_pthread.h"
|
||||
#else
|
||||
@ -185,6 +84,13 @@ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata)
|
||||
return thread;
|
||||
}
|
||||
|
||||
int sthread_detach(sthread_t *thread)
|
||||
{
|
||||
CloseHandle(thread->thread);
|
||||
free(thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sthread_join(sthread_t *thread)
|
||||
{
|
||||
WaitForSingleObject(thread->thread, INFINITE);
|
||||
@ -194,7 +100,7 @@ void sthread_join(sthread_t *thread)
|
||||
|
||||
struct slock
|
||||
{
|
||||
CRITICAL_SECTION lock;
|
||||
HANDLE lock;
|
||||
};
|
||||
|
||||
slock_t *slock_new(void)
|
||||
@ -203,24 +109,29 @@ slock_t *slock_new(void)
|
||||
if (!lock)
|
||||
return NULL;
|
||||
|
||||
InitializeCriticalSection(&lock->lock);
|
||||
lock->lock = CreateMutex(NULL, FALSE, "");
|
||||
if (!lock->lock)
|
||||
{
|
||||
free(lock);
|
||||
return NULL;
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
|
||||
void slock_free(slock_t *lock)
|
||||
{
|
||||
DeleteCriticalSection(&lock->lock);
|
||||
CloseHandle(lock->lock);
|
||||
free(lock);
|
||||
}
|
||||
|
||||
void slock_lock(slock_t *lock)
|
||||
{
|
||||
EnterCriticalSection(&lock->lock);
|
||||
WaitForSingleObject(lock->lock, INFINITE);
|
||||
}
|
||||
|
||||
void slock_unlock(slock_t *lock)
|
||||
{
|
||||
LeaveCriticalSection(&lock->lock);
|
||||
ReleaseMutex(lock->lock);
|
||||
}
|
||||
|
||||
struct scond
|
||||
@ -247,19 +158,17 @@ scond_t *scond_new(void)
|
||||
void scond_wait(scond_t *cond, slock_t *lock)
|
||||
{
|
||||
WaitForSingleObject(cond->event, 0);
|
||||
slock_unlock(lock);
|
||||
|
||||
WaitForSingleObject(cond->event, INFINITE);
|
||||
SignalObjectAndWait(lock->lock, cond->event, INFINITE, FALSE);
|
||||
|
||||
slock_lock(lock);
|
||||
}
|
||||
|
||||
int scond_wait_timeout(scond_t *cond, slock_t *lock, unsigned timeout_ms)
|
||||
bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us)
|
||||
{
|
||||
WaitForSingleObject(cond->event, 0);
|
||||
slock_unlock(lock);
|
||||
|
||||
DWORD res = WaitForSingleObject(cond->event, timeout_ms);
|
||||
DWORD res = SignalObjectAndWait(lock->lock, cond->event, (DWORD)(timeout_us) / 1000, FALSE);
|
||||
|
||||
slock_lock(lock);
|
||||
return res == WAIT_OBJECT_0;
|
||||
@ -270,6 +179,13 @@ void scond_signal(scond_t *cond)
|
||||
SetEvent(cond->event);
|
||||
}
|
||||
|
||||
/* FIXME - check how this function should differ from scond_signal implementation */
|
||||
int scond_broadcast(scond_t *cond)
|
||||
{
|
||||
SetEvent(cond->event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void scond_free(scond_t *cond)
|
||||
{
|
||||
CloseHandle(cond->event);
|
||||
@ -317,6 +233,11 @@ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata)
|
||||
return thr;
|
||||
}
|
||||
|
||||
int sthread_detach(sthread_t *thread)
|
||||
{
|
||||
return pthread_detach(thread->id);
|
||||
}
|
||||
|
||||
void sthread_join(sthread_t *thread)
|
||||
{
|
||||
pthread_join(thread->id, NULL);
|
||||
@ -390,6 +311,48 @@ void scond_wait(scond_t *cond, slock_t *lock)
|
||||
pthread_cond_wait(&cond->cond, &lock->lock);
|
||||
}
|
||||
|
||||
int scond_broadcast(scond_t *cond)
|
||||
{
|
||||
return pthread_cond_broadcast(&cond->cond);
|
||||
}
|
||||
|
||||
bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us)
|
||||
{
|
||||
struct timespec now = {0};
|
||||
|
||||
#ifdef __MACH__ // OSX doesn't have clock_gettime ... :(
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
||||
clock_get_time(cclock, &mts);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
now.tv_sec = mts.tv_sec;
|
||||
now.tv_nsec = mts.tv_nsec;
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
sys_time_sec_t s;
|
||||
sys_time_nsec_t n;
|
||||
sys_time_get_current_time(&s, &n);
|
||||
now.tv_sec = s;
|
||||
now.tv_nsec = n;
|
||||
#elif defined(__mips__)
|
||||
struct timeval tm;
|
||||
gettimeofday(&tm, NULL);
|
||||
now.tv_sec = tm.tv_sec;
|
||||
now.tv_nsec = tm.tv_usec * 1000;
|
||||
#elif !defined(GEKKO) // timeout on libogc is duration, not end time
|
||||
clock_gettime(CLOCK_REALTIME, &now);
|
||||
#endif
|
||||
|
||||
now.tv_sec += timeout_us / 1000000LL;
|
||||
now.tv_nsec += timeout_us * 1000LL;
|
||||
|
||||
now.tv_sec += now.tv_nsec / 1000000000LL;
|
||||
now.tv_nsec = now.tv_nsec % 1000000000LL;
|
||||
|
||||
int ret = pthread_cond_timedwait(&cond->cond, &lock->lock, &now);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
void scond_signal(scond_t *cond)
|
||||
{
|
||||
pthread_cond_signal(&cond->cond);
|
||||
@ -397,47 +360,3 @@ void scond_signal(scond_t *cond)
|
||||
|
||||
#endif
|
||||
|
||||
MDFN_Thread *MDFND_CreateThread(int (*fn)(void *), void *data)
|
||||
{
|
||||
return (MDFN_Thread*)sthread_create((void (*)(void*))fn, data);
|
||||
}
|
||||
|
||||
void MDFND_WaitThread(MDFN_Thread *thr, int *val)
|
||||
{
|
||||
sthread_join((sthread_t*)thr);
|
||||
|
||||
if (val)
|
||||
{
|
||||
*val = 0;
|
||||
fprintf(stderr, "WaitThread relies on return value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MDFND_KillThread(MDFN_Thread *)
|
||||
{
|
||||
fprintf(stderr, "Killing a thread is a BAD IDEA!\n");
|
||||
}
|
||||
|
||||
MDFN_Mutex *MDFND_CreateMutex()
|
||||
{
|
||||
return (MDFN_Mutex*)slock_new();
|
||||
}
|
||||
|
||||
void MDFND_DestroyMutex(MDFN_Mutex *lock)
|
||||
{
|
||||
slock_free((slock_t*)lock);
|
||||
}
|
||||
|
||||
int MDFND_LockMutex(MDFN_Mutex *lock)
|
||||
{
|
||||
slock_lock((slock_t*)lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MDFND_UnlockMutex(MDFN_Mutex *lock)
|
||||
{
|
||||
slock_unlock((slock_t*)lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
53
thread.h
53
thread.h
@ -1,5 +1,6 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2014 - Daniel de Matteis
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
@ -16,12 +17,20 @@
|
||||
#ifndef THREAD_H__
|
||||
#define THREAD_H__
|
||||
|
||||
#include "boolean.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Implements the bare minimum needed for RetroArch. :)
|
||||
|
||||
typedef struct sthread sthread_t;
|
||||
|
||||
// Threading
|
||||
sthread_t *sthread_create(void (*thread_func)(void*), void *userdata);
|
||||
int sthread_detach(sthread_t *thread);
|
||||
void sthread_join(sthread_t *thread);
|
||||
|
||||
// Mutexes
|
||||
@ -40,7 +49,49 @@ scond_t *scond_new(void);
|
||||
void scond_free(scond_t *cond);
|
||||
|
||||
void scond_wait(scond_t *cond, slock_t *lock);
|
||||
#ifndef RARCH_CONSOLE
|
||||
bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us);
|
||||
int scond_broadcast(scond_t *cond);
|
||||
#endif
|
||||
void scond_signal(scond_t *cond);
|
||||
|
||||
#ifndef RARCH_INTERNAL
|
||||
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
#include <sys/timer.h>
|
||||
#elif defined(XENON)
|
||||
#include <time/time.h>
|
||||
#elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__)
|
||||
#include <unistd.h>
|
||||
#elif defined(PSP)
|
||||
#include <pspthreadman.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
static inline void retro_sleep(unsigned msec)
|
||||
{
|
||||
#if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)
|
||||
sys_timer_usleep(1000 * msec);
|
||||
#elif defined(PSP)
|
||||
sceKernelDelayThread(1000 * msec);
|
||||
#elif defined(_WIN32)
|
||||
Sleep(msec);
|
||||
#elif defined(XENON)
|
||||
udelay(1000 * msec);
|
||||
#elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__)
|
||||
usleep(1000 * msec);
|
||||
#else
|
||||
struct timespec tv = {0};
|
||||
tv.tv_sec = msec / 1000;
|
||||
tv.tv_nsec = (msec % 1000) * 1000000;
|
||||
nanosleep(&tv, NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2012 - Daniel De Matteis
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2014 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch 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 Found-
|
||||
@ -21,9 +21,65 @@
|
||||
#include <gccore.h>
|
||||
#include <ogc/cond.h>
|
||||
|
||||
#ifndef OSThread
|
||||
#define OSThread lwp_t
|
||||
#endif
|
||||
|
||||
#ifndef OSCond
|
||||
#define OSCond lwpq_t
|
||||
#endif
|
||||
|
||||
#ifndef OSThreadQueue
|
||||
#define OSThreadQueue lwpq_t
|
||||
#endif
|
||||
|
||||
#ifndef OSInitMutex
|
||||
#define OSInitMutex(mutex) LWP_MutexInit(mutex, 0)
|
||||
#endif
|
||||
|
||||
#ifndef OSLockMutex
|
||||
#define OSLockMutex(mutex) LWP_MutexLock(mutex)
|
||||
#endif
|
||||
|
||||
#ifndef OSUnlockMutex
|
||||
#define OSUnlockMutex(mutex) LWP_MutexUnlock(mutex)
|
||||
#endif
|
||||
|
||||
#ifndef OSTryLockMutex
|
||||
#define OSTryLockMutex(mutex) LWP_MutexTryLock(mutex)
|
||||
#endif
|
||||
|
||||
#ifndef OSInitCond
|
||||
#define OSInitCond(cond) LWP_CondInit(cond)
|
||||
#endif
|
||||
|
||||
#ifndef OSSignalCond
|
||||
#define OSSignalCond(cond) LWP_ThreadSignal(cond)
|
||||
#endif
|
||||
|
||||
#ifndef OSWaitCond
|
||||
#define OSWaitCond(cond, mutex) LWP_CondWait(cond, mutex)
|
||||
#endif
|
||||
|
||||
#ifndef OSInitThreadQueue
|
||||
#define OSInitThreadQueue(queue) LWP_InitQueue(queue)
|
||||
#endif
|
||||
|
||||
#ifndef OSSleepThread
|
||||
#define OSSleepThread(queue) LWP_ThreadSleep(queue)
|
||||
#endif
|
||||
|
||||
#ifndef OSJoinThread
|
||||
#define OSJoinThread(thread, val) LWP_JoinThread(thread, val)
|
||||
#endif
|
||||
|
||||
#ifndef OSCreateThread
|
||||
#define OSCreateThread(thread, func, intarg, ptrarg, stackbase, stacksize, priority, attrs) LWP_CreateThread(thread, func, ptrarg, stackbase, stacksize, priority)
|
||||
#endif
|
||||
|
||||
#define STACKSIZE (8 * 1024)
|
||||
|
||||
typedef lwp_t pthread_t;
|
||||
typedef OSThread pthread_t;
|
||||
typedef mutex_t pthread_mutex_t;
|
||||
typedef void* pthread_mutexattr_t;
|
||||
typedef int pthread_attr_t;
|
||||
@ -33,12 +89,12 @@ typedef cond_t pthread_condattr_t;
|
||||
static inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)
|
||||
{
|
||||
*thread = 0;
|
||||
return LWP_CreateThread(thread, start_routine, arg, 0, STACKSIZE, 64);
|
||||
return OSCreateThread(thread, start_routine, 0 /* unused */, arg, 0, STACKSIZE, 64, 0 /* unused */);
|
||||
}
|
||||
|
||||
static inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
|
||||
{
|
||||
return LWP_MutexInit(mutex, 0);
|
||||
return OSInitMutex(mutex);
|
||||
}
|
||||
|
||||
static inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
|
||||
@ -48,39 +104,50 @@ static inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
|
||||
|
||||
static inline int pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||
{
|
||||
return LWP_MutexLock(*mutex);
|
||||
return OSLockMutex(*mutex);
|
||||
}
|
||||
|
||||
static inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
||||
{
|
||||
return LWP_MutexUnlock(*mutex);
|
||||
return OSUnlockMutex(*mutex);
|
||||
}
|
||||
|
||||
static inline void pthread_exit(void *retval)
|
||||
{
|
||||
/* FIXME: No LWP equivalent for this? */
|
||||
(void)retval;
|
||||
}
|
||||
|
||||
static inline int pthread_detach(pthread_t thread)
|
||||
{
|
||||
/* FIXME: pthread_detach equivalent missing? */
|
||||
(void)thread;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int pthread_join(pthread_t thread, void **retval)
|
||||
{
|
||||
// FIXME: Shouldn't the second arg to LWP_JoinThread take retval?
|
||||
(void)retval;
|
||||
return LWP_JoinThread(thread, NULL);
|
||||
return OSJoinThread(thread, retval);
|
||||
}
|
||||
|
||||
static inline int pthread_mutex_trylock(pthread_mutex_t *mutex)
|
||||
{
|
||||
return LWP_MutexTryLock(*mutex);
|
||||
return OSTryLockMutex(*mutex);
|
||||
}
|
||||
|
||||
static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
|
||||
{
|
||||
return LWP_CondWait(*cond, *mutex);
|
||||
return OSWaitCond(*cond, *mutex);
|
||||
}
|
||||
|
||||
static inline int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
|
||||
{
|
||||
return LWP_CondWait(*cond, *mutex);
|
||||
return LWP_CondTimedWait(*cond, *mutex, abstime);
|
||||
}
|
||||
|
||||
static inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
|
||||
{
|
||||
return LWP_CondInit(cond);
|
||||
return OSInitCond(cond);
|
||||
}
|
||||
|
||||
static inline int pthread_cond_signal(pthread_cond_t *cond)
|
||||
@ -88,6 +155,11 @@ static inline int pthread_cond_signal(pthread_cond_t *cond)
|
||||
return LWP_CondSignal(*cond);
|
||||
}
|
||||
|
||||
static inline int pthread_cond_broadcast(pthread_cond_t *cond)
|
||||
{
|
||||
return LWP_CondBroadcast(*cond);
|
||||
}
|
||||
|
||||
static inline int pthread_cond_destroy(pthread_cond_t *cond)
|
||||
{
|
||||
return LWP_CondDestroy(*cond);
|
||||
|
Loading…
Reference in New Issue
Block a user