|
From: kosmirror <kos...@us...> - 2025-11-21 04:43:10
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "A pseudo Operating System for the Dreamcast.".
The branch, master has been updated
via b4ba51022014b5ba860e2ba9015209ef0cdfc28f (commit)
via 3ad0d86cae562d2c728521667ce5639752381126 (commit)
via 51fdde63310d2cbe82728593b321a65e60c9593f (commit)
via 124794dc82fa0f0f9b8f7ad03815b37a53f9b478 (commit)
via fdf5089fe6064cc35624cd441ba9b7aab84cf332 (commit)
via 1495e8dee3cd50ec793c91492d61c5b188f2a8e5 (commit)
via 700c8423cb3db2a292401b7cb1217b25fac6f95d (commit)
via a4e246b012a5ea60009dcb856452b93c7d78580d (commit)
via 6ca1c196e89e76c202704b446695cd957c2d47b0 (commit)
via c1f398025b8618b2c7356ffcbeb91fe7d29f87c3 (commit)
via ab9074edbb9342459d7789a9c16a3437a7cc6534 (commit)
via 0fc163f313112c105bd9921d234319644c070982 (commit)
from 0ef0a6e931f9d973637d5908b68337a8c276e699 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit b4ba51022014b5ba860e2ba9015209ef0cdfc28f
Author: Paul Cercueil <pa...@cr...>
Date: Thu Sep 25 19:54:47 2025 +0200
mutex: Handle recursive/errcheck after trying to get lock
Speed up mutex locking for regular mutexes by handling
recursive/errcheck mutexes after the atomic compare-and-swap.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 3ad0d86cae562d2c728521667ce5639752381126
Author: Paul Cercueil <pa...@cr...>
Date: Thu Sep 25 15:32:21 2025 +0200
mutex: Replace runtime checks by assert() calls
Allow applications to disable these runtime checks, by converting them
to assert() calls.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 51fdde63310d2cbe82728593b321a65e60c9593f
Author: Paul Cercueil <pa...@cr...>
Date: Thu Sep 25 14:13:41 2025 +0200
mutex: Don't check interrupt context twice in mutex_lock()
In mutex_lock_timed() and mutex_lock(), we are already guaranteed (by an
assert()) to not be inside an interrupt context.
By reworking the code a little, we can ensure that the interrupt context
check is only done once.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 124794dc82fa0f0f9b8f7ad03815b37a53f9b478
Author: Paul Cercueil <pa...@cr...>
Date: Thu Sep 25 21:31:45 2025 +0200
mutex: Make mutex_lock() a static inline
mutex_lock() is just a tiny wrapper around mutex_lock_timed() with just
an extra parameter.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit fdf5089fe6064cc35624cd441ba9b7aab84cf332
Author: Paul Cercueil <pa...@cr...>
Date: Thu Sep 25 14:11:08 2025 +0200
mutex: Make timeout parameter to mutex_lock_timed() unsigned
By making this parameter unsigned, we do not have to handle the case
where it is negative.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 1495e8dee3cd50ec793c91492d61c5b188f2a8e5
Author: Paul Cercueil <pa...@cr...>
Date: Thu Sep 25 14:07:58 2025 +0200
c11: Handle negative timeout in mtx_timedlock()
Don't bother to call mutex_lock_timed() with a negative timeout, since
we know that it will fail.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 700c8423cb3db2a292401b7cb1217b25fac6f95d
Author: Paul Cercueil <pa...@cr...>
Date: Thu Sep 25 15:48:01 2025 +0200
genwait: Replace runtime check with assert() call
Allow applications to disable this runtime check, by converting it to an
assert() call.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit a4e246b012a5ea60009dcb856452b93c7d78580d
Author: Paul Cercueil <pa...@cr...>
Date: Thu Sep 25 15:43:56 2025 +0200
genwait: Make timeout parameter to genwait_wait() unsigned
Negative timeout values are handled the same as a zero value, which
means that the parameter can be unsigned.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 6ca1c196e89e76c202704b446695cd957c2d47b0
Author: Paul Cercueil <pa...@cr...>
Date: Thu Sep 25 15:57:57 2025 +0200
net: Factorize code using mutex_lock_irqsafe()
The net_{tcp,udp}_getpeername() function were basically inlining
mutex_lock_irqsafe().
Signed-off-by: Paul Cercueil <pa...@cr...>
commit c1f398025b8618b2c7356ffcbeb91fe7d29f87c3
Author: Paul Cercueil <pa...@cr...>
Date: Mon Sep 29 11:15:47 2025 +0200
pthread: Implement errcheck mutexes with recursive mutexes
Instead of using KallistiOS' "errcheck" mutexes, which will be gone
soon, implement the errcheck mutexes using recursive mutexes and extra
checks.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit ab9074edbb9342459d7789a9c16a3437a7cc6534
Author: Paul Cercueil <pa...@cr...>
Date: Sun Sep 28 22:51:52 2025 +0200
pthread: Use new <kos/errno.h> macros
Use the errno_save_scoped() macro which allows to automatically save the
'errno' variable when it's called, and restore it right before exiting
the current functional block.
Use the errno_if_nonzero() macro to factorize the code further.
Signed-off-by: Paul Cercueil <pa...@cr...>
commit 0fc163f313112c105bd9921d234319644c070982
Author: Paul Cercueil <pa...@cr...>
Date: Sun Sep 28 23:00:03 2025 +0200
kos: Add <kos/errno.h> header to simplify errno handling
This new header contains functions and macros related to the 'errno'
variable.
Notably, it contains the errno_save_scoped() macro which will keep a
copy of the current value of the errno variable, and will restore it
once the execution exits the functional block in which the macro was
called.
It also contains the simple macro errno_if_nonzero(), which will return
the value of the 'errno' variable if the input value is non-zero, and
will otherwise return zero.
Signed-off-by: Paul Cercueil <pa...@cr...>
-----------------------------------------------------------------------
Summary of changes:
addons/libpthread/pthread-internal.h | 1 +
addons/libpthread/pthread_attr_setname_np.c | 13 ++----
addons/libpthread/pthread_cond_broadcast.c | 11 ++---
addons/libpthread/pthread_cond_destroy.c | 11 ++---
addons/libpthread/pthread_cond_init.c | 12 +++---
addons/libpthread/pthread_cond_signal.c | 11 ++---
addons/libpthread/pthread_cond_timedwait.c | 11 ++---
addons/libpthread/pthread_cond_wait.c | 11 ++---
addons/libpthread/pthread_mutex_destroy.c | 11 ++---
addons/libpthread/pthread_mutex_init.c | 17 +++-----
addons/libpthread/pthread_mutex_lock.c | 17 +++++---
addons/libpthread/pthread_mutex_timedlock.c | 18 +++++---
addons/libpthread/pthread_mutex_trylock.c | 17 +++++---
addons/libpthread/pthread_mutex_unlock.c | 14 +++---
addons/libpthread/pthread_rwlock_destroy.c | 13 ++----
addons/libpthread/pthread_rwlock_init.c | 13 ++----
addons/libpthread/pthread_rwlock_rdlock.c | 13 ++----
addons/libpthread/pthread_rwlock_timedrdlock.c | 11 ++---
addons/libpthread/pthread_rwlock_timedwrlock.c | 11 ++---
addons/libpthread/pthread_rwlock_tryrdlock.c | 13 ++----
addons/libpthread/pthread_rwlock_trywrlock.c | 13 ++----
addons/libpthread/pthread_rwlock_unlock.c | 13 ++----
addons/libpthread/pthread_rwlock_wrlock.c | 13 ++----
include/kos/errno.h | 53 +++++++++++++++++++++++
include/kos/genwait.h | 3 +-
include/kos/mutex.h | 44 ++++++++++---------
kernel/exports.txt | 1 -
kernel/libc/c11/mtx_timedlock.c | 3 ++
kernel/net/net_tcp.c | 12 ++----
kernel/net/net_udp.c | 10 ++---
kernel/thread/genwait.c | 9 ++--
kernel/thread/mutex.c | 59 ++++++++++++--------------
utils/dc-chain/patches/gcc/gthr-kos.h | 9 ++--
33 files changed, 221 insertions(+), 270 deletions(-)
create mode 100644 include/kos/errno.h
diff --git a/addons/libpthread/pthread-internal.h b/addons/libpthread/pthread-internal.h
index c0b457cb..2ccf5bf5 100644
--- a/addons/libpthread/pthread-internal.h
+++ b/addons/libpthread/pthread-internal.h
@@ -47,6 +47,7 @@ typedef union pthread_attr_t {
typedef union pthread_mutex_t {
mutex_t mutex;
+ unsigned int type;
unsigned char __data[__PTHREAD_MUTEX_SIZE];
long int __align;
} pthread_mutex_t;
diff --git a/addons/libpthread/pthread_attr_setname_np.c b/addons/libpthread/pthread_attr_setname_np.c
index f972841e..a4e8f783 100644
--- a/addons/libpthread/pthread_attr_setname_np.c
+++ b/addons/libpthread/pthread_attr_setname_np.c
@@ -6,14 +6,12 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
#include <string.h>
+#include <kos/errno.h>
#include <kos/thread.h>
int pthread_attr_setname_np(pthread_attr_t *__RESTRICT attr,
const char *__RESTRICT name) {
- int old, rv;
-
if(!attr)
return EINVAL;
@@ -23,13 +21,10 @@ int pthread_attr_setname_np(pthread_attr_t *__RESTRICT attr,
if(strlen(name) >= KTHREAD_LABEL_SIZE)
return EINVAL;
- old = errno;
+ errno_save_scoped();
- if(!(attr->attr.label = strdup(name))) {
- rv = errno;
- errno = old;
- return rv;
- }
+ if(!(attr->attr.label = strdup(name)))
+ return errno;
return 0;
}
diff --git a/addons/libpthread/pthread_cond_broadcast.c b/addons/libpthread/pthread_cond_broadcast.c
index df5d9f8b..32339aef 100644
--- a/addons/libpthread/pthread_cond_broadcast.c
+++ b/addons/libpthread/pthread_cond_broadcast.c
@@ -7,16 +7,11 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
+#include <kos/errno.h>
#include <kos/cond.h>
int pthread_cond_broadcast(pthread_cond_t *cond) {
- int old, rv = 0;
+ errno_save_scoped();
- old = errno;
- if(cond_broadcast(&cond->cond))
- rv = errno;
-
- errno = old;
- return rv;
+ return errno_if_nonzero(cond_broadcast(&cond->cond));
}
diff --git a/addons/libpthread/pthread_cond_destroy.c b/addons/libpthread/pthread_cond_destroy.c
index 30db2242..9c668d0b 100644
--- a/addons/libpthread/pthread_cond_destroy.c
+++ b/addons/libpthread/pthread_cond_destroy.c
@@ -7,16 +7,11 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
+#include <kos/errno.h>
#include <kos/cond.h>
int pthread_cond_destroy(pthread_cond_t *cond) {
- int old, rv = 0;
+ errno_save_scoped();
- old = errno;
- if(cond_destroy(&cond->cond))
- rv = errno;
-
- errno = old;
- return rv;
+ return errno_if_nonzero(cond_destroy(&cond->cond));
}
diff --git a/addons/libpthread/pthread_cond_init.c b/addons/libpthread/pthread_cond_init.c
index e5c95332..f32aa7a1 100644
--- a/addons/libpthread/pthread_cond_init.c
+++ b/addons/libpthread/pthread_cond_init.c
@@ -7,19 +7,18 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
+#include <kos/errno.h>
#include <kos/cond.h>
int pthread_cond_init(pthread_cond_t *__RESTRICT cond,
const pthread_condattr_t *__RESTRICT attr) {
- int old, rv = 0;
-
if(!cond)
return EFAULT;
- old = errno;
+ errno_save_scoped();
+
if(cond_init(&cond->cond))
- rv = errno;
+ return errno;
/* Copy attributes over into the condition variable. */
if(attr)
@@ -27,6 +26,5 @@ int pthread_cond_init(pthread_cond_t *__RESTRICT cond,
else
cond->clock_id = CLOCK_REALTIME;
- errno = old;
- return rv;
+ return 0;
}
diff --git a/addons/libpthread/pthread_cond_signal.c b/addons/libpthread/pthread_cond_signal.c
index a64681b7..2f35030c 100644
--- a/addons/libpthread/pthread_cond_signal.c
+++ b/addons/libpthread/pthread_cond_signal.c
@@ -7,16 +7,11 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
#include <kos/cond.h>
+#include <kos/errno.h>
int pthread_cond_signal(pthread_cond_t *cond) {
- int old, rv = 0;
+ errno_save_scoped();
- old = errno;
- if(cond_signal(&cond->cond))
- rv = errno;
-
- errno = old;
- return rv;
+ return errno_if_nonzero(cond_signal(&cond->cond));
}
diff --git a/addons/libpthread/pthread_cond_timedwait.c b/addons/libpthread/pthread_cond_timedwait.c
index 2627e987..bfd4b6c4 100644
--- a/addons/libpthread/pthread_cond_timedwait.c
+++ b/addons/libpthread/pthread_cond_timedwait.c
@@ -9,14 +9,13 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
#include <sys/time.h>
#include <kos/cond.h>
+#include <kos/errno.h>
int pthread_cond_timedwait(pthread_cond_t *__RESTRICT cond,
pthread_mutex_t *__RESTRICT mutex,
const struct timespec *__RESTRICT abstime) {
- int old, rv = 0;
int tmo;
struct timespec ctv;
@@ -26,7 +25,7 @@ int pthread_cond_timedwait(pthread_cond_t *__RESTRICT cond,
if(abstime->tv_nsec < 0 || abstime->tv_nsec > 1000000000L)
return EINVAL;
- old = errno;
+ errno_save_scoped();
/* Figure out the timeout we need to provide in milliseconds. */
clock_gettime(cond->clock_id, &ctv);
@@ -37,9 +36,5 @@ int pthread_cond_timedwait(pthread_cond_t *__RESTRICT cond,
if(tmo <= 0)
return ETIMEDOUT;
- if(cond_wait_timed(&cond->cond, &mutex->mutex, tmo))
- rv = errno;
-
- errno = old;
- return rv;
+ return errno_if_nonzero(cond_wait_timed(&cond->cond, &mutex->mutex, tmo));
}
diff --git a/addons/libpthread/pthread_cond_wait.c b/addons/libpthread/pthread_cond_wait.c
index 67d50183..d057a7b9 100644
--- a/addons/libpthread/pthread_cond_wait.c
+++ b/addons/libpthread/pthread_cond_wait.c
@@ -7,17 +7,12 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
#include <kos/cond.h>
+#include <kos/errno.h>
int pthread_cond_wait(pthread_cond_t *__RESTRICT cond,
pthread_mutex_t *__RESTRICT mutex) {
- int old, rv = 0;
+ errno_save_scoped();
- old = errno;
- if(cond_wait(&cond->cond, &mutex->mutex))
- rv = errno;
-
- errno = old;
- return rv;
+ return errno_if_nonzero(cond_wait(&cond->cond, &mutex->mutex));
}
diff --git a/addons/libpthread/pthread_mutex_destroy.c b/addons/libpthread/pthread_mutex_destroy.c
index cf7b53d1..07877726 100644
--- a/addons/libpthread/pthread_mutex_destroy.c
+++ b/addons/libpthread/pthread_mutex_destroy.c
@@ -7,16 +7,11 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
+#include <kos/errno.h>
#include <kos/mutex.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex) {
- int old, rv = 0;
+ errno_save_scoped();
- old = errno;
- if(mutex_destroy(&mutex->mutex))
- rv = errno;
-
- errno = old;
- return rv;
+ return errno_if_nonzero(mutex_destroy(&mutex->mutex));
}
diff --git a/addons/libpthread/pthread_mutex_init.c b/addons/libpthread/pthread_mutex_init.c
index 572d3d5b..57f6795e 100644
--- a/addons/libpthread/pthread_mutex_init.c
+++ b/addons/libpthread/pthread_mutex_init.c
@@ -7,13 +7,12 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
+#include <kos/errno.h>
#include <kos/mutex.h>
int pthread_mutex_init(pthread_mutex_t *__RESTRICT mutex,
const pthread_mutexattr_t *__RESTRICT attr) {
unsigned int type = MUTEX_TYPE_NORMAL;
- int old, rv = 0;
if(attr) {
switch(attr->mtype) {
@@ -22,9 +21,6 @@ int pthread_mutex_init(pthread_mutex_t *__RESTRICT mutex,
break;
case PTHREAD_MUTEX_ERRORCHECK:
- type = MUTEX_TYPE_ERRORCHECK;
- break;
-
case PTHREAD_MUTEX_RECURSIVE:
type = MUTEX_TYPE_RECURSIVE;
break;
@@ -32,12 +28,13 @@ int pthread_mutex_init(pthread_mutex_t *__RESTRICT mutex,
default:
return EINVAL;
}
+
+ mutex->type = attr->mtype;
+ } else {
+ mutex->type = PTHREAD_MUTEX_NORMAL;
}
- old = errno;
- if(mutex_init(&mutex->mutex, type))
- rv = errno;
+ errno_save_scoped();
- errno = old;
- return rv;
+ return errno_if_nonzero(mutex_init(&mutex->mutex, type));
}
diff --git a/addons/libpthread/pthread_mutex_lock.c b/addons/libpthread/pthread_mutex_lock.c
index 89ea42ba..09eaf65d 100644
--- a/addons/libpthread/pthread_mutex_lock.c
+++ b/addons/libpthread/pthread_mutex_lock.c
@@ -7,19 +7,22 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
+#include <kos/errno.h>
#include <kos/mutex.h>
int pthread_mutex_lock(pthread_mutex_t *mutex) {
- int old, rv = 0;
-
if(mutex->mutex.type > MUTEX_TYPE_RECURSIVE)
return EINVAL;
- old = errno;
+ errno_save_scoped();
+
if(mutex_lock(&mutex->mutex))
- rv = errno;
+ return errno;
+
+ if(mutex->type == PTHREAD_MUTEX_ERRORCHECK && mutex->mutex.count > 1) {
+ mutex_unlock(&mutex->mutex);
+ return EDEADLK;
+ }
- errno = old;
- return rv;
+ return 0;
}
diff --git a/addons/libpthread/pthread_mutex_timedlock.c b/addons/libpthread/pthread_mutex_timedlock.c
index b1ee3561..b7831a9c 100644
--- a/addons/libpthread/pthread_mutex_timedlock.c
+++ b/addons/libpthread/pthread_mutex_timedlock.c
@@ -8,13 +8,12 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
#include <sys/time.h>
+#include <kos/errno.h>
#include <kos/mutex.h>
int pthread_mutex_timedlock(pthread_mutex_t *__RESTRICT mutex,
const struct timespec *__RESTRICT abstime) {
- int old, rv = 0;
int tmo;
struct timespec ctv;
@@ -31,10 +30,10 @@ int pthread_mutex_timedlock(pthread_mutex_t *__RESTRICT mutex,
the timing... POSIX says that if the lock can be acquired immediately
then this function should never return a timeout, regardless of what
abstime says. */
- old = errno;
+ errno_save_scoped();
if(!mutex_trylock(&mutex->mutex))
- return 0;
+ goto out_check_err;
/* Figure out the timeout we need to provide in milliseconds. */
clock_gettime(CLOCK_REALTIME, &ctv);
@@ -46,8 +45,13 @@ int pthread_mutex_timedlock(pthread_mutex_t *__RESTRICT mutex,
return ETIMEDOUT;
if(mutex_lock_timed(&mutex->mutex, tmo))
- rv = errno;
+ return errno;
- errno = old;
- return rv;
+out_check_err:
+ if(mutex->type == PTHREAD_MUTEX_ERRORCHECK && mutex->mutex.count > 1) {
+ mutex_unlock(&mutex->mutex);
+ return EDEADLK;
+ }
+
+ return 0;
}
diff --git a/addons/libpthread/pthread_mutex_trylock.c b/addons/libpthread/pthread_mutex_trylock.c
index 4271483f..585f8493 100644
--- a/addons/libpthread/pthread_mutex_trylock.c
+++ b/addons/libpthread/pthread_mutex_trylock.c
@@ -7,19 +7,22 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
+#include <kos/errno.h>
#include <kos/mutex.h>
int pthread_mutex_trylock(pthread_mutex_t *mutex) {
- int old, rv = 0;
-
if(mutex->mutex.type > MUTEX_TYPE_RECURSIVE)
return EINVAL;
- old = errno;
+ errno_save_scoped();
+
if(mutex_trylock(&mutex->mutex))
- rv = errno;
+ return errno;
+
+ if(mutex->type == PTHREAD_MUTEX_ERRORCHECK && mutex->mutex.count > 1) {
+ mutex_unlock(&mutex->mutex);
+ return EDEADLK;
+ }
- errno = old;
- return rv;
+ return 0;
}
diff --git a/addons/libpthread/pthread_mutex_unlock.c b/addons/libpthread/pthread_mutex_unlock.c
index a5d1b0c3..0d38820e 100644
--- a/addons/libpthread/pthread_mutex_unlock.c
+++ b/addons/libpthread/pthread_mutex_unlock.c
@@ -7,16 +7,16 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
+#include <kos/errno.h>
#include <kos/mutex.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex) {
- int old, rv = 0;
+ if(mutex->type == PTHREAD_MUTEX_ERRORCHECK &&
+ (mutex->mutex.count == 0 || mutex->mutex.holder != thd_get_current())) {
+ return EFAULT;
+ }
- old = errno;
- if(mutex_unlock(&mutex->mutex))
- rv = errno;
+ errno_save_scoped();
- errno = old;
- return rv;
+ return errno_if_nonzero(mutex_unlock(&mutex->mutex));
}
diff --git a/addons/libpthread/pthread_rwlock_destroy.c b/addons/libpthread/pthread_rwlock_destroy.c
index e98940d4..298fb51e 100644
--- a/addons/libpthread/pthread_rwlock_destroy.c
+++ b/addons/libpthread/pthread_rwlock_destroy.c
@@ -7,21 +7,14 @@
#include "pthread-internal.h"
#include <pthread.h>
-#include <errno.h>
+#include <kos/errno.h>
#include <kos/rwsem.h>
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) {
- int old, rv = 0;
-
if(!rwlock)
return EFAULT;
- old = errno;
-
- if(rwsem_destroy(&rwlock->rwsem)) {
- rv = errno;
- errno = old;
- }
+ errno_save_scoped();
- return rv;
+ return errno_if_nonzero(rwsem_destroy(&rwlock->rwsem));
}
diff --git a/addons/libpthread/pthread_rwlock_init.c b/addons/libpthread/pthread_rwlock_init.c
index 13b8aebf..7e891f9e 100644
--- a/addons/libpthread/pthread_rwlock_init.c
+++ b/addons/libpthread/pthread_rwlock_init.c
@@ -7,24 +7,17 @@
#include "pthread-internal.h"
#include <pthread.h>
...<truncated>...
hooks/post-receive
--
A pseudo Operating System for the Dreamcast.
|