Skip to content

Commit

Permalink
gthr_aux: Unify thread implementation
Browse files Browse the repository at this point in the history
Reference: #270
Signed-off-by: LIU Hao <lh_mouse@126.com>
  • Loading branch information
lhmouse committed Nov 26, 2024
1 parent 478cab4 commit fb3f1a5
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 160 deletions.
10 changes: 0 additions & 10 deletions mcfgthread/c11.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,6 @@
#include "c11.h"
#include "clock.h"

__MCF_DLLEXPORT
void
__MCF_c11_thread_thunk_v2(_MCF_thread* thrd)
{
__MCF_c11_thread_record* rec = _MCF_thread_get_data(thrd);

/* Invoke the user-defined procedure and save its result in the record. */
rec->__result = (*(rec->__proc)) (rec->__arg);
}

__MCF_DLLEXPORT
int
__MCF_c11_thrd_sleep(const __MCF_timespec* dur, __MCF_timespec* rem_opt)
Expand Down
56 changes: 7 additions & 49 deletions mcfgthread/c11.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,6 @@ typedef _MCF_once once_flag;
typedef _MCF_cond cnd_t;
typedef __MCF_c11_mutex mtx_t;

/* This is the actual thread function for a C11 thread. */
__MCF_C11_IMPORT
void
__MCF_c11_thread_thunk_v2(_MCF_thread* __thrd) __MCF_noexcept;

/* Define enumeration constants. */
enum __MCF_mtx_type
{
Expand Down Expand Up @@ -510,16 +505,8 @@ __MCF_C11_INLINE
int
__MCF_c11_thrd_create(thrd_t* __thrdp, thrd_start_t __proc, void* __arg) __MCF_noexcept
{
__MCF_c11_thread_record __rec[1] = __MCF_0_INIT;
_MCF_thread* __thrd;

__rec->__proc = __proc;
__rec->__arg = __arg;
__rec->__joinable[0] = 1;

__thrd = _MCF_thread_new(__MCF_c11_thread_thunk_v2, __rec, sizeof(*__rec));
*__thrdp = __thrd;
return (__thrd == __MCF_nullptr) ? thrd_nomem : thrd_success;
*__thrdp = __MCF_gthr_thread_create_v3(__MCF_CAST_PTR(__MCF_gthr_thread_procedure, __proc), __arg);
return (*__thrdp == __MCF_nullptr) ? thrd_nomem : thrd_success;
}

__MCF_C11_INLINE __MCF_FN_CONST
Expand All @@ -533,15 +520,6 @@ __MCF_C11_INLINE
int
__MCF_c11_thrd_detach(thrd_t __thrd) __MCF_noexcept
{
__MCF_c11_thread_record* __rec = __MCF_nullptr;
if(__thrd->__proc == __MCF_c11_thread_thunk_v2)
__rec = (__MCF_c11_thread_record*) _MCF_thread_get_data(__thrd);

/* Clear the joinable state. If the thread is not joinable, fail. */
if(__rec && (_MCF_atomic_xchg_8_rlx(__rec->__joinable, 0) == 0))
return thrd_error;

/* Free the thread. */
_MCF_thread_drop_ref(__thrd);
return thrd_success;
}
Expand All @@ -557,37 +535,17 @@ __MCF_C11_INLINE __MCF_NEVER_RETURN
void
__MCF_c11_thrd_exit(int __result) __MCF_noexcept
{
_MCF_thread* __self = _MCF_thread_self();
int* __resp = __MCF_nullptr;
if(__self->__proc == __MCF_c11_thread_thunk_v2)
__resp = &(((__MCF_c11_thread_record*) _MCF_thread_get_data(__self))->__result);

/* Set the exit status and exit. Unlike `ExitThread()`, if the last
* thread exits, the current process exits with zero. */
__MCF_SET_IF(__resp, __result);
_MCF_thread_exit();
__MCF_gthr_thread_exit_v3((void*)(intptr_t) __result);
}

__MCF_C11_INLINE
int
__MCF_c11_thrd_join(thrd_t __thrd, int* __resp_opt) __MCF_noexcept
{
__MCF_c11_thread_record* __rec = __MCF_nullptr;
if(__thrd->__proc == __MCF_c11_thread_thunk_v2)
__rec = (__MCF_c11_thread_record*) _MCF_thread_get_data(__thrd);

if(__thrd->__tid == _MCF_thread_self_tid())
return thrd_error;

/* Clear the joinable state. If the thread is not joinable, fail. */
if(__rec && (_MCF_atomic_xchg_8_rlx(__rec->__joinable, 0) == 0))
return thrd_error;

/* Wait for the thread to terminate. */
_MCF_thread_wait(__thrd, __MCF_nullptr);
__MCF_SET_IF(__resp_opt, __rec ? __rec->__result : 0);
_MCF_thread_drop_ref(__thrd);
return 0;
void* __resp;
__MCF_gthr_thread_join_v3(__thrd, &__resp);
__MCF_SET_IF(__resp_opt, (int)(intptr_t) __resp);
return thrd_success;
}

__MCF_C11_INLINE
Expand Down
61 changes: 15 additions & 46 deletions mcfgthread/gthr.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,31 +305,31 @@ __MCF_FNA(__MCF_gthr_cond_broadcast, __gthread_cond_broadcast);
/* Creates a thread, like `pthread_create()`. */
__MCF_GTHR_IMPORT
int
__MCF_gthr_create_v2(__gthread_t* __thrdp, __MCF_gthr_thread_procedure* __proc, void* __arg) __MCF_noexcept;
__MCF_gthr_create_v3(__gthread_t* __thrdp, __MCF_gthr_thread_procedure* __proc, void* __arg) __MCF_noexcept;

#ifndef __MCF_GTHR_NO_ALIASES
__MCF_FNA(__MCF_gthr_create_v2, __gthread_create);
# define __MCF_gthr_create_v2 __gthread_create
__MCF_FNA(__MCF_gthr_create_v3, __gthread_create);
# define __MCF_gthr_create_v3 __gthread_create
#endif

/* Awaits a thread to terminate and gets its result, like `pthread_join()`. */
__MCF_GTHR_IMPORT
int
__MCF_gthr_join_v2(__gthread_t __thrd, void** __resp_opt) __MCF_noexcept;
__MCF_gthr_join_v3(__gthread_t __thrd, void** __resp_opt) __MCF_noexcept;

#ifndef __MCF_GTHR_NO_ALIASES
__MCF_FNA(__MCF_gthr_join_v2, __gthread_join);
# define __MCF_gthr_join_v2 __gthread_join
__MCF_FNA(__MCF_gthr_join_v3, __gthread_join);
# define __MCF_gthr_join_v3 __gthread_join
#endif

/* Detaches a thread, like `pthread_detach()` */
__MCF_GTHR_IMPORT
int
__MCF_gthr_detach_v2(__gthread_t __thrd) __MCF_noexcept;
__MCF_gthr_detach(__gthread_t __thrd) __MCF_noexcept;

#ifndef __MCF_GTHR_NO_ALIASES
__MCF_FNA(__MCF_gthr_detach_v2, __gthread_detach);
# define __MCF_gthr_detach_v2 __gthread_detach
__MCF_FNA(__MCF_gthr_detach, __gthread_detach);
# define __MCF_gthr_detach __gthread_detach
#endif

/* Gets a thread itself, like `pthread_self()`.
Expand Down Expand Up @@ -593,55 +593,24 @@ __MCF_gthr_cond_broadcast(__gthread_cond_t* __cond) __MCF_noexcept

__MCF_GTHR_INLINE
int
__MCF_gthr_create_v2(__gthread_t* __thrdp, __MCF_gthr_thread_procedure* __proc, void* __arg) __MCF_noexcept
__MCF_gthr_create_v3(__gthread_t* __thrdp, __MCF_gthr_thread_procedure* __proc, void* __arg) __MCF_noexcept
{
__MCF_gthr_thread_record __rec[1] = __MCF_0_INIT;
_MCF_thread* __thrd;

__rec->__proc = __proc;
__rec->__arg = __arg;
__rec->__joinable[0] = 1;

__thrd = _MCF_thread_new(__MCF_gthr_thread_thunk_v2, __rec, sizeof(*__rec));
*__thrdp = __thrd;
return (__thrd == __MCF_nullptr) ? EAGAIN : 0;
*__thrdp = __MCF_gthr_thread_create_v3(__proc, __arg);
return (*__thrdp == __MCF_nullptr) ? EAGAIN : 0;
}

__MCF_GTHR_INLINE
int
__MCF_gthr_join_v2(__gthread_t __thrd, void** __resp_opt) __MCF_noexcept
__MCF_gthr_join_v3(__gthread_t __thrd, void** __resp_opt) __MCF_noexcept
{
__MCF_gthr_thread_record* __rec = __MCF_nullptr;
if(__thrd->__proc == __MCF_gthr_thread_thunk_v2)
__rec = (__MCF_gthr_thread_record*) _MCF_thread_get_data(__thrd);

if(__thrd->__tid == _MCF_thread_self_tid())
return EDEADLK;

/* Clear the joinable state. If the thread is not joinable, fail. */
if(__rec && (_MCF_atomic_xchg_8_rlx(__rec->__joinable, 0) == 0))
return EINVAL;

/* Wait for the thread to terminate. */
_MCF_thread_wait(__thrd, __MCF_nullptr);
__MCF_SET_IF(__resp_opt, __rec ? __rec->__result : __MCF_nullptr);
_MCF_thread_drop_ref(__thrd);
__MCF_gthr_thread_join_v3(__thrd, __resp_opt);
return 0;
}

__MCF_GTHR_INLINE
int
__MCF_gthr_detach_v2(__gthread_t __thrd) __MCF_noexcept
__MCF_gthr_detach(__gthread_t __thrd) __MCF_noexcept
{
__MCF_gthr_thread_record* __rec = __MCF_nullptr;
if(__thrd->__proc == __MCF_gthr_thread_thunk_v2)
__rec = (__MCF_gthr_thread_record*) _MCF_thread_get_data(__thrd);

/* Clear the joinable state. If the thread is not joinable, fail. */
if(__rec && (_MCF_atomic_xchg_8_rlx(__rec->__joinable, 0) == 0))
return EINVAL;

/* Free the thread. */
_MCF_thread_drop_ref(__thrd);
return 0;
}
Expand Down
72 changes: 68 additions & 4 deletions mcfgthread/gthr_aux.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,76 @@ __MCF_gthr_cond_recursive_mutex_wait(_MCF_cond* cond, __MCF_gthr_rc_mutex* rmtx,
(intptr_t) rmtx, timeout_opt);
}

__MCF_DLLEXPORT
static __MCF_ALIGNED(16)
const GUID gthread_guid = __MCF_GUID(9FB2D15C,C5F2,4AE7,868D,2769591B8E92);

static
void
__MCF_gthr_thread_thunk_v2(_MCF_thread* thrd)
do_gthr_thread_thunk_v3(_MCF_thread* thrd)
{
__MCF_gthr_thread_record* rec = _MCF_thread_get_data(thrd);
rec->__arg_or_result = (*(rec->__proc)) (rec->__arg_or_result);
}

static inline
__MCF_gthr_thread_record*
do_gthr_get_thread_record(_MCF_thread* thrd)
{
__MCF_gthr_thread_record* rec = _MCF_thread_get_data(thrd);
if(!rec)
return __MCF_nullptr;

/* Check the GUID. As user-defined data are aligned to 16-byte boundaries,
* there must be at least 16 bytes available. */
if(__builtin_memcmp(rec->__magic_guid, &gthread_guid, 16) != 0)
return __MCF_nullptr;

/* Assume so. `do_gthr_thread_thunk_v3()` is not shared across modules,
* so we should not check it for uniqueness. */
return rec;
}

__MCF_DLLEXPORT
_MCF_thread*
__MCF_gthr_thread_create_v3(__MCF_gthr_thread_procedure* proc, void* arg)
{
__MCF_ALIGNED(16) __MCF_gthr_thread_record record;
__builtin_memcpy(record.__magic_guid, &gthread_guid, 16);
record.__proc = proc;
record.__arg_or_result = arg;
return _MCF_thread_new(do_gthr_thread_thunk_v3, &record, sizeof(record));
}

__MCF_DLLEXPORT
void
__MCF_gthr_thread_join_v3(_MCF_thread* thrd, void** resp_opt)
{
/* Wait for the thread to terminate. */
__MCF_ASSERT(thrd->__tid != _MCF_thread_self_tid());
_MCF_thread_wait(thrd, __MCF_nullptr);

if(resp_opt) {
*resp_opt = __MCF_nullptr;

/* Get the exit code. */
__MCF_gthr_thread_record* rec = do_gthr_get_thread_record(thrd);
if(rec)
*resp_opt = rec->__arg_or_result;
}

/* Free the thread. */
_MCF_thread_drop_ref(thrd);
}

__MCF_DLLEXPORT
void
__MCF_gthr_thread_exit_v3(void* resp)
{
/* Set the exit code. */
__MCF_gthr_thread_record* rec = do_gthr_get_thread_record(_MCF_thread_self());
if(rec)
rec->__arg_or_result = resp;

/* Invoke the user-defined procedure and save its result in the record. */
rec->__result = (*(rec->__proc)) (rec->__arg);
/* Terminate the current thread. */
_MCF_thread_exit();
}
19 changes: 12 additions & 7 deletions mcfgthread/gthr_aux.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,9 @@ struct __MCF_gthr_rc_mutex

struct __MCF_gthr_thread_record
{
void* __result;
uint8_t __magic_guid[16];
__MCF_gthr_thread_procedure* __proc;
void* __arg;
uint8_t __joinable[1];
uintptr_t __reserved_low;
uintptr_t __reserved_high;
void* __arg_or_result;
};

/* These functions implement `__gthread_once()`. If `__once_fn` initiates stack
Expand Down Expand Up @@ -135,10 +132,18 @@ __MCF_GTHR_AUX_IMPORT
int
__MCF_gthr_cond_recursive_mutex_wait(_MCF_cond* __cond, __MCF_gthr_rc_mutex* __rmtx, int64_t* __timeout_opt) __MCF_noexcept;

/* This is the actual thread function for a gthread. */
/* These are auxiliary functions for threads. */
__MCF_GTHR_AUX_IMPORT
_MCF_thread*
__MCF_gthr_thread_create_v3(__MCF_gthr_thread_procedure* __proc, void* __arg) __MCF_noexcept;

__MCF_GTHR_AUX_IMPORT
void
__MCF_gthr_thread_join_v3(_MCF_thread* __thrd, void** __resp_opt) __MCF_noexcept;

__MCF_GTHR_AUX_IMPORT __MCF_NEVER_RETURN
void
__MCF_gthr_thread_thunk_v2(_MCF_thread* __thrd) __MCF_noexcept;
__MCF_gthr_thread_exit_v3(void* __resp) __MCF_noexcept;

/* Define inline functions after all declarations.
* We would like to keep them away from declarations for conciseness, which also
Expand Down
11 changes: 3 additions & 8 deletions mcfgthread/gthr_libobjc.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,19 +352,14 @@ __MCF_GTHR_LIBOBJC_INLINE
objc_thread_t
__MCF_gthr_objc_thread_detach(__MCF_gthr_thread_procedure* __proc, void* __arg) __MCF_noexcept
{
__MCF_gthr_thread_record __rec[1] = __MCF_0_INIT;
_MCF_thread* __thrd;
uint32_t __tid;

__rec->__proc = __proc;
__rec->__arg = __arg;

__thrd = _MCF_thread_new(__MCF_gthr_thread_thunk_v2, __rec, sizeof(*__rec));
uint32_t __tid = 0;
_MCF_thread* __thrd = __MCF_gthr_thread_create_v3(__proc, __arg);
if(!__thrd)
return __MCF_nullptr;

__tid = __thrd->__tid;
_MCF_thread_drop_ref_nonnull(__thrd);

return (objc_thread_t)(uintptr_t) __tid;
}

Expand Down
Loading

0 comments on commit fb3f1a5

Please sign in to comment.