Ruby31: add support for Darwin ppc/ppc64 (#5927)
* add coroutines for ppc & ppc64 * fix universal coroutine to include ppc & ppc64 * add powerpc*-darwin to configure.ac * fix thread_pthread for older systems
This commit is contained in:
parent
84257244cd
commit
539459abda
Notes:
git
2022-05-22 12:02:28 +09:00
Merged-By: ioquatix <samuel@codeotaku.com>
@ -1866,7 +1866,7 @@ AS_IF([test $rb_cv_stack_end_address != no], [
|
|||||||
dnl Checks for library functions.
|
dnl Checks for library functions.
|
||||||
AC_TYPE_GETGROUPS
|
AC_TYPE_GETGROUPS
|
||||||
AS_CASE(["${target_cpu}-${target_os}:${target_archs}"],
|
AS_CASE(["${target_cpu}-${target_os}:${target_archs}"],
|
||||||
[powerpc-darwin*], [
|
[powerpc*-darwin*], [
|
||||||
AC_LIBSOURCES(alloca.c)
|
AC_LIBSOURCES(alloca.c)
|
||||||
AC_SUBST([ALLOCA], [\${LIBOBJDIR}alloca.${ac_objext}])
|
AC_SUBST([ALLOCA], [\${LIBOBJDIR}alloca.${ac_objext}])
|
||||||
AC_DEFINE(C_ALLOCA)
|
AC_DEFINE(C_ALLOCA)
|
||||||
@ -2546,6 +2546,12 @@ AS_CASE([$coroutine_type], [yes|''], [
|
|||||||
[arm64-darwin*], [
|
[arm64-darwin*], [
|
||||||
coroutine_type=arm64
|
coroutine_type=arm64
|
||||||
],
|
],
|
||||||
|
[powerpc-darwin*], [
|
||||||
|
coroutine_type=ppc
|
||||||
|
],
|
||||||
|
[powerpc64-darwin*], [
|
||||||
|
coroutine_type=ppc64
|
||||||
|
],
|
||||||
[x*64-linux*], [
|
[x*64-linux*], [
|
||||||
AS_CASE(["$ac_cv_sizeof_voidp"],
|
AS_CASE(["$ac_cv_sizeof_voidp"],
|
||||||
[8], [ coroutine_type=amd64 ],
|
[8], [ coroutine_type=amd64 ],
|
||||||
|
73
coroutine/ppc/Context.S
Normal file
73
coroutine/ppc/Context.S
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#define TOKEN_PASTE(x,y) x##y
|
||||||
|
#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 2
|
||||||
|
|
||||||
|
.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
|
||||||
|
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
|
||||||
|
# Make space on the stack for caller registers
|
||||||
|
addi r1,r1,-80
|
||||||
|
|
||||||
|
# Save caller registers
|
||||||
|
stw r13,0(r1)
|
||||||
|
stw r14,4(r1)
|
||||||
|
stw r15,8(r1)
|
||||||
|
stw r16,12(r1)
|
||||||
|
stw r17,16(r1)
|
||||||
|
stw r18,20(r1)
|
||||||
|
stw r19,24(r1)
|
||||||
|
stw r20,28(r1)
|
||||||
|
stw r21,32(r1)
|
||||||
|
stw r22,36(r1)
|
||||||
|
stw r23,40(r1)
|
||||||
|
stw r24,44(r1)
|
||||||
|
stw r25,48(r1)
|
||||||
|
stw r26,52(r1)
|
||||||
|
stw r27,56(r1)
|
||||||
|
stw r28,60(r1)
|
||||||
|
stw r29,64(r1)
|
||||||
|
stw r30,68(r1)
|
||||||
|
stw r31,72(r1)
|
||||||
|
|
||||||
|
# Save return address
|
||||||
|
mflr r0
|
||||||
|
stw r0,76(r1)
|
||||||
|
|
||||||
|
# Save stack pointer to first argument
|
||||||
|
stw r1,0(r3)
|
||||||
|
|
||||||
|
# Load stack pointer from second argument
|
||||||
|
lwz r1,0(r4)
|
||||||
|
|
||||||
|
# Restore caller registers
|
||||||
|
lwz r13,0(r1)
|
||||||
|
lwz r14,4(r1)
|
||||||
|
lwz r15,8(r1)
|
||||||
|
lwz r16,12(r1)
|
||||||
|
lwz r17,16(r1)
|
||||||
|
lwz r18,20(r1)
|
||||||
|
lwz r19,24(r1)
|
||||||
|
lwz r20,28(r1)
|
||||||
|
lwz r21,32(r1)
|
||||||
|
lwz r22,36(r1)
|
||||||
|
lwz r23,40(r1)
|
||||||
|
lwz r24,44(r1)
|
||||||
|
lwz r25,48(r1)
|
||||||
|
lwz r26,52(r1)
|
||||||
|
lwz r27,56(r1)
|
||||||
|
lwz r28,60(r1)
|
||||||
|
lwz r29,64(r1)
|
||||||
|
lwz r30,68(r1)
|
||||||
|
lwz r31,72(r1)
|
||||||
|
|
||||||
|
# Load return address
|
||||||
|
lwz r0,76(r1)
|
||||||
|
mtlr r0
|
||||||
|
|
||||||
|
# Pop stack frame
|
||||||
|
addi r1,r1,80
|
||||||
|
|
||||||
|
# Jump to return address
|
||||||
|
blr
|
||||||
|
|
57
coroutine/ppc/Context.h
Normal file
57
coroutine/ppc/Context.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef COROUTINE_PPC_CONTEXT_H
|
||||||
|
#define COROUTINE_PPC_CONTEXT_H 1
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define COROUTINE __attribute__((noreturn)) void
|
||||||
|
|
||||||
|
enum {
|
||||||
|
COROUTINE_REGISTERS =
|
||||||
|
20 /* 19 general purpose registers (r13–r31) and 1 return address */
|
||||||
|
+ 4 /* space for fiber_entry() to store the link register */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct coroutine_context
|
||||||
|
{
|
||||||
|
void **stack_pointer;
|
||||||
|
void *argument;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
|
||||||
|
|
||||||
|
static inline void coroutine_initialize_main(struct coroutine_context * context) {
|
||||||
|
context->stack_pointer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void coroutine_initialize(
|
||||||
|
struct coroutine_context *context,
|
||||||
|
coroutine_start start,
|
||||||
|
void *stack,
|
||||||
|
size_t size
|
||||||
|
) {
|
||||||
|
assert(start && stack && size >= 1024);
|
||||||
|
|
||||||
|
// Stack grows down. Force 16-byte alignment.
|
||||||
|
char * top = (char*)stack + size;
|
||||||
|
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
|
||||||
|
|
||||||
|
context->stack_pointer -= COROUTINE_REGISTERS;
|
||||||
|
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
|
||||||
|
|
||||||
|
/* Skip a global prologue that sets the TOC register */
|
||||||
|
context->stack_pointer[19] = ((char*)start) + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
|
||||||
|
|
||||||
|
static inline void coroutine_destroy(struct coroutine_context * context)
|
||||||
|
{
|
||||||
|
context->stack_pointer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* COROUTINE_PPC_CONTEXT_H */
|
70
coroutine/ppc64/Context.S
Normal file
70
coroutine/ppc64/Context.S
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#define TOKEN_PASTE(x,y) x##y
|
||||||
|
#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 3
|
||||||
|
|
||||||
|
.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
|
||||||
|
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
|
||||||
|
# Make space on the stack for caller registers
|
||||||
|
addi r1,r1,-152
|
||||||
|
|
||||||
|
# Save caller registers
|
||||||
|
std r14,0(r1)
|
||||||
|
std r15,8(r1)
|
||||||
|
std r16,16(r1)
|
||||||
|
std r17,24(r1)
|
||||||
|
std r18,32(r1)
|
||||||
|
std r19,40(r1)
|
||||||
|
std r20,48(r1)
|
||||||
|
std r21,56(r1)
|
||||||
|
std r22,64(r1)
|
||||||
|
std r23,72(r1)
|
||||||
|
std r24,80(r1)
|
||||||
|
std r25,88(r1)
|
||||||
|
std r26,96(r1)
|
||||||
|
std r27,104(r1)
|
||||||
|
std r28,112(r1)
|
||||||
|
std r29,120(r1)
|
||||||
|
std r30,128(r1)
|
||||||
|
std r31,136(r1)
|
||||||
|
|
||||||
|
# Save return address
|
||||||
|
mflr r0
|
||||||
|
std r0,144(r1)
|
||||||
|
|
||||||
|
# Save stack pointer to first argument
|
||||||
|
std r1,0(r3)
|
||||||
|
|
||||||
|
# Load stack pointer from second argument
|
||||||
|
ld r1,0(r4)
|
||||||
|
|
||||||
|
# Restore caller registers
|
||||||
|
ld r14,0(r1)
|
||||||
|
ld r15,8(r1)
|
||||||
|
ld r16,16(r1)
|
||||||
|
ld r17,24(r1)
|
||||||
|
ld r18,32(r1)
|
||||||
|
ld r19,40(r1)
|
||||||
|
ld r20,48(r1)
|
||||||
|
ld r21,56(r1)
|
||||||
|
ld r22,64(r1)
|
||||||
|
ld r23,72(r1)
|
||||||
|
ld r24,80(r1)
|
||||||
|
ld r25,88(r1)
|
||||||
|
ld r26,96(r1)
|
||||||
|
ld r27,104(r1)
|
||||||
|
ld r28,112(r1)
|
||||||
|
ld r29,120(r1)
|
||||||
|
ld r30,128(r1)
|
||||||
|
ld r31,136(r1)
|
||||||
|
|
||||||
|
# Load return address
|
||||||
|
ld r0,144(r1)
|
||||||
|
mtlr r0
|
||||||
|
|
||||||
|
# Pop stack frame
|
||||||
|
addi r1,r1,152
|
||||||
|
|
||||||
|
# Jump to return address
|
||||||
|
blr
|
57
coroutine/ppc64/Context.h
Normal file
57
coroutine/ppc64/Context.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef COROUTINE_PPC64_CONTEXT_H
|
||||||
|
#define COROUTINE_PPC64_CONTEXT_H 1
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define COROUTINE __attribute__((noreturn)) void
|
||||||
|
|
||||||
|
enum {
|
||||||
|
COROUTINE_REGISTERS =
|
||||||
|
19 /* 18 general purpose registers (r14–r31) and 1 return address */
|
||||||
|
+ 4 /* space for fiber_entry() to store the link register */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct coroutine_context
|
||||||
|
{
|
||||||
|
void **stack_pointer;
|
||||||
|
void *argument;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
|
||||||
|
|
||||||
|
static inline void coroutine_initialize_main(struct coroutine_context * context) {
|
||||||
|
context->stack_pointer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void coroutine_initialize(
|
||||||
|
struct coroutine_context *context,
|
||||||
|
coroutine_start start,
|
||||||
|
void *stack,
|
||||||
|
size_t size
|
||||||
|
) {
|
||||||
|
assert(start && stack && size >= 1024);
|
||||||
|
|
||||||
|
// Stack grows down. Force 16-byte alignment.
|
||||||
|
char * top = (char*)stack + size;
|
||||||
|
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
|
||||||
|
|
||||||
|
context->stack_pointer -= COROUTINE_REGISTERS;
|
||||||
|
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
|
||||||
|
|
||||||
|
/* Skip a global prologue that sets the TOC register */
|
||||||
|
context->stack_pointer[18] = ((char*)start) + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
|
||||||
|
|
||||||
|
static inline void coroutine_destroy(struct coroutine_context * context)
|
||||||
|
{
|
||||||
|
context->stack_pointer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* COROUTINE_PPC64_CONTEXT_H */
|
@ -3,7 +3,11 @@
|
|||||||
# include "coroutine/amd64/Context.S"
|
# include "coroutine/amd64/Context.S"
|
||||||
#elif defined __i386__
|
#elif defined __i386__
|
||||||
# include "coroutine/x86/Context.S"
|
# include "coroutine/x86/Context.S"
|
||||||
#elif defined __ppc64__
|
#elif defined __ppc__
|
||||||
|
# include "coroutine/ppc/Context.S"
|
||||||
|
#elif defined __ppc64__ && defined(WORDS_BIGENDIAN)
|
||||||
|
# include "coroutine/ppc64/Context.S"
|
||||||
|
#elif defined __ppc64__ && !defined(WORDS_BIGENDIAN)
|
||||||
# include "coroutine/ppc64le/Context.S"
|
# include "coroutine/ppc64le/Context.S"
|
||||||
#elif defined __arm64__
|
#elif defined __arm64__
|
||||||
# include "coroutine/arm64/Context.S"
|
# include "coroutine/arm64/Context.S"
|
||||||
|
@ -6,7 +6,11 @@
|
|||||||
# include "coroutine/amd64/Context.h"
|
# include "coroutine/amd64/Context.h"
|
||||||
#elif defined __i386__
|
#elif defined __i386__
|
||||||
# include "coroutine/x86/Context.h"
|
# include "coroutine/x86/Context.h"
|
||||||
#elif defined __ppc64__
|
#elif defined __ppc__
|
||||||
|
# include "coroutine/ppc/Context.h"
|
||||||
|
#elif defined __ppc64__ && defined(WORDS_BIGENDIAN)
|
||||||
|
# include "coroutine/ppc64/Context.h"
|
||||||
|
#elif defined __ppc64__ && !defined(WORDS_BIGENDIAN)
|
||||||
# include "coroutine/ppc64le/Context.h"
|
# include "coroutine/ppc64le/Context.h"
|
||||||
#elif defined __arm64__
|
#elif defined __arm64__
|
||||||
# include "coroutine/arm64/Context.h"
|
# include "coroutine/arm64/Context.h"
|
||||||
|
@ -1765,10 +1765,23 @@ native_thread_native_thread_id(rb_thread_t *target_th)
|
|||||||
if (tid == 0) return Qnil;
|
if (tid == 0) return Qnil;
|
||||||
return INT2FIX(tid);
|
return INT2FIX(tid);
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
|
||||||
uint64_t tid;
|
uint64_t tid;
|
||||||
int e = pthread_threadid_np(target_th->nt->thread_id, &tid);
|
tid = pthread_mach_thread_np(pthread_self());
|
||||||
if (e != 0) rb_syserr_fail(e, "pthread_threadid_np");
|
#elif MAC_OS_X_VERSION_MIN_REQUIRED < 1060
|
||||||
|
uint64_t tid;
|
||||||
|
if (&pthread_threadid_np) {
|
||||||
|
int error = pthread_threadid_np(target_th->thread_id, &tid);
|
||||||
|
if (error != 0) rb_syserr_fail(error, "pthread_threadid_np");
|
||||||
|
} else {
|
||||||
|
uint64_t tid;
|
||||||
|
tid = pthread_mach_thread_np(pthread_self());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int error = pthread_threadid_np(target_th->thread_id, &tid);
|
||||||
|
if (error != 0) rb_syserr_fail(error, "pthread_threadid_np");
|
||||||
return ULL2NUM((unsigned long long)tid);
|
return ULL2NUM((unsigned long long)tid);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
# define USE_NATIVE_THREAD_NATIVE_THREAD_ID 1
|
# define USE_NATIVE_THREAD_NATIVE_THREAD_ID 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user