Skip to content

Commit ee44112

Browse files
committed
Add support for C++ std::thread and derivatives
Implements dkp's gthread interface using LWP functions. With this, std::{thread,mutex,recursive_mutex,condition_variable} are now supported.
1 parent efb0217 commit ee44112

File tree

3 files changed

+181
-1
lines changed

3 files changed

+181
-1
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ INCLUDES += -I$(BASEDIR)/cube
100100
endif
101101

102102
CFLAGS := $(FALSE_POSITIVES) -g -O2 -fno-strict-aliasing -Wall $(MACHDEP) $(INCLUDES)
103+
CXXFLAGS := $(CFLAGS) -std=gnu++17 -fno-exceptions -fno-rtti
103104
ASFLAGS := $(MACHDEP) -mregnames -D_LANGUAGE_ASSEMBLY $(INCLUDES)
104105

105106
#---------------------------------------------------------------------------------
@@ -149,7 +150,7 @@ OGCOBJ := \
149150
console_font_8x16.o timesupp.o lock_supp.o usbgecko.o usbmouse.o \
150151
sbrk.o malloc_lock.o kprintf.o stm.o aes.o sha.o ios.o es.o isfs.o usb.o network_common.o \
151152
sdgecko_io.o sdgecko_buf.o gcsd.o argv.o network_wii.o wiisd.o conf.o usbstorage.o \
152-
texconv.o wiilaunch.o sys_report.o
153+
texconv.o wiilaunch.o sys_report.o ogc_gthread.o
153154

154155
#---------------------------------------------------------------------------------
155156
MODOBJ := freqtab.o mixer.o modplay.o semitonetab.o gcmodplay.o

libogc/ogc_gthread.cpp

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#include <bits/gthr-default.h>
2+
#include <errno.h>
3+
#include <stdlib.h>
4+
#include <malloc.h>
5+
6+
#include "lwp.h"
7+
#include "mutex.h"
8+
#include "cond.h"
9+
10+
#define __OGC_GTHR_BASE_PRIO (64)
11+
12+
extern "C" {
13+
14+
typedef struct {
15+
lwpq_t queue;
16+
lwp_t thread;
17+
} gthr_thread_t;
18+
19+
int __gthr_impl_active(void)
20+
{
21+
return 1;
22+
}
23+
24+
int __gthr_impl_create(__gthread_t *__threadid, void *(*__func) (void*), void *__args)
25+
{
26+
gthr_thread_t *th = (gthr_thread_t*)malloc(sizeof(gthr_thread_t));
27+
28+
if (!th) {
29+
return ENOMEM;
30+
}
31+
32+
if (LWP_InitQueue(&th->queue) != LWP_SUCCESSFUL) {
33+
free(th);
34+
return EINVAL;
35+
}
36+
37+
if (LWP_CreateThread(&th->thread, __func, __args, NULL, 0, __OGC_GTHR_BASE_PRIO) != LWP_SUCCESSFUL) {
38+
LWP_CloseQueue(th->queue);
39+
free(th);
40+
return EINVAL;
41+
}
42+
43+
*__threadid = (__gthread_t)th;
44+
return 0;
45+
}
46+
47+
int __gthr_impl_join(__gthread_t __threadid, void **__value_ptr)
48+
{
49+
gthr_thread_t *th = (gthr_thread_t*)__threadid;
50+
51+
int res = LWP_JoinThread(th->thread, __value_ptr);
52+
if (res != LWP_SUCCESSFUL) {
53+
return -1;
54+
}
55+
56+
/* Clean up thread data */
57+
LWP_CloseQueue(th->queue);
58+
free(th);
59+
60+
return 0;
61+
}
62+
63+
int __gthr_impl_detach(__gthread_t __threadid)
64+
{
65+
/* Not supported */
66+
return -1;
67+
}
68+
69+
int __gthr_impl_equal(__gthread_t __t1, __gthread_t __t2)
70+
{
71+
return (gthr_thread_t*)__t1 == (gthr_thread_t*)__t2;
72+
}
73+
74+
__gthread_t __gthr_impl_self(void)
75+
{
76+
/*
77+
HACK: __gthread_self() is only used for std::thread::get_id(), so returning
78+
LWP_GetSelf() works as a unique id even though it's technically not a thread
79+
*/
80+
return (__gthread_t)LWP_GetSelf();
81+
}
82+
83+
int __gthr_impl_yield(void)
84+
{
85+
LWP_YieldThread();
86+
return 0;
87+
}
88+
89+
void __gthr_impl_mutex_init_function(__gthread_mutex_t *mutex)
90+
{
91+
LWP_MutexInit(((mutex_t*)mutex), false);
92+
}
93+
94+
int __gthr_impl_mutex_lock(__gthread_mutex_t *mutex)
95+
{
96+
return LWP_MutexLock(*((mutex_t*)mutex));
97+
}
98+
99+
int __gthr_impl_mutex_trylock(__gthread_mutex_t *mutex)
100+
{
101+
return LWP_MutexTryLock(*((mutex_t*)mutex));
102+
}
103+
104+
int __gthr_impl_mutex_unlock(__gthread_mutex_t *mutex)
105+
{
106+
return LWP_MutexUnlock(*((mutex_t*)mutex));
107+
}
108+
109+
int __gthr_impl_mutex_destroy(__gthread_mutex_t *mutex)
110+
{
111+
return LWP_MutexDestroy(*((mutex_t*)mutex));
112+
}
113+
114+
int __gthr_impl_recursive_mutex_init_function(__gthread_recursive_mutex_t *mutex)
115+
{
116+
return LWP_MutexInit(((mutex_t *)mutex), true);
117+
}
118+
119+
int __gthr_impl_recursive_mutex_lock(__gthread_recursive_mutex_t *mutex)
120+
{
121+
return LWP_MutexLock(*((mutex_t*)mutex));
122+
}
123+
124+
int __gthr_impl_recursive_mutex_trylock(__gthread_recursive_mutex_t *mutex)
125+
{
126+
return LWP_MutexTryLock(*((mutex_t*)mutex));
127+
}
128+
129+
int __gthr_impl_recursive_mutex_unlock(__gthread_recursive_mutex_t *mutex)
130+
{
131+
return LWP_MutexUnlock(*((mutex_t*)mutex));
132+
}
133+
134+
int __gthr_impl_recursive_mutex_destroy(__gthread_recursive_mutex_t *mutex)
135+
{
136+
return LWP_MutexDestroy(*((mutex_t*)mutex));
137+
}
138+
139+
void __gthr_impl_cond_init_function(__gthread_cond_t *__cond)
140+
{
141+
LWP_CondInit((cond_t*)__cond);
142+
}
143+
144+
int __gthr_impl_cond_broadcast(__gthread_cond_t *__cond)
145+
{
146+
return LWP_CondBroadcast(*(cond_t*)__cond);
147+
}
148+
149+
int __gthr_impl_cond_signal(__gthread_cond_t *__cond)
150+
{
151+
return LWP_CondSignal(*(cond_t*)__cond);
152+
}
153+
154+
int __gthr_impl_cond_wait(__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
155+
{
156+
return LWP_CondWait(*(cond_t*)__cond, *(mutex_t*)__mutex);
157+
}
158+
159+
int __gthr_impl_cond_timedwait(__gthread_cond_t *__cond, __gthread_mutex_t *__mutex, const __gthread_time_t *__abs_timeout)
160+
{
161+
return LWP_CondTimedWait(*(cond_t*)__cond, *(mutex_t*)__mutex, __abs_timeout);
162+
}
163+
164+
int __gthr_impl_cond_wait_recursive(__gthread_cond_t *__cond, __gthread_recursive_mutex_t *__mutex)
165+
{
166+
return LWP_CondWait(*(cond_t*)__cond, *(mutex_t*)__mutex);
167+
}
168+
169+
int __gthr_impl_cond_destroy(__gthread_cond_t* __cond)
170+
{
171+
return LWP_CondDestroy(*(cond_t*)__cond);
172+
}
173+
174+
/* Dummy function required so that the linker doesn't strip this module */
175+
void __ogc_gthread_init() {}
176+
}

libogc/system.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ extern int __libogc_nanosleep(const struct timespec *tb, struct timespec *rem);
215215
extern u64 gettime(void);
216216
extern void settime(u64);
217217

218+
extern void __ogc_gthread_init();
219+
218220
extern u8 __gxregs[];
219221
extern u8 __text_start[];
220222
extern u8 __isIPL[];
@@ -1097,6 +1099,7 @@ void SYS_Init(void)
10971099
IRQ_Request(IRQ_PI_RSW,__RSWHandler,NULL);
10981100
__MaskIrq(IRQMASK(IRQ_PI_RSW));
10991101
#endif
1102+
__ogc_gthread_init();
11001103
__lwp_thread_startmultitasking();
11011104
_CPU_ISR_Restore(level);
11021105
}

0 commit comments

Comments
 (0)