Update threading code

This commit is contained in:
twinaphex 2014-06-18 22:10:07 +02:00
parent a4020fd1d9
commit 76e8a0d95f
12 changed files with 396 additions and 200 deletions

View File

@ -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
View 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

View File

@ -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)

View File

@ -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);
}

View File

@ -200,7 +200,7 @@
RelativePath="..\..\..\scrc32.cpp">
</File>
<File
RelativePath="..\..\..\stubs.cpp">
RelativePath="..\..\..\thread.c">
</File>
<Filter
Name="mednafen"

View File

@ -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>

View File

@ -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">

View File

@ -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>

View File

@ -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">

View File

@ -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

View File

@ -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

View File

@ -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);