mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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>
8 changed files with 291 additions and 7 deletions
|
@ -1866,7 +1866,7 @@ AS_IF([test $rb_cv_stack_end_address != no], [
|
|||
dnl Checks for library functions.
|
||||
AC_TYPE_GETGROUPS
|
||||
AS_CASE(["${target_cpu}-${target_os}:${target_archs}"],
|
||||
[powerpc-darwin*], [
|
||||
[powerpc*-darwin*], [
|
||||
AC_LIBSOURCES(alloca.c)
|
||||
AC_SUBST([ALLOCA], [\${LIBOBJDIR}alloca.${ac_objext}])
|
||||
AC_DEFINE(C_ALLOCA)
|
||||
|
@ -2546,6 +2546,12 @@ AS_CASE([$coroutine_type], [yes|''], [
|
|||
[arm64-darwin*], [
|
||||
coroutine_type=arm64
|
||||
],
|
||||
[powerpc-darwin*], [
|
||||
coroutine_type=ppc
|
||||
],
|
||||
[powerpc64-darwin*], [
|
||||
coroutine_type=ppc64
|
||||
],
|
||||
[x*64-linux*], [
|
||||
AS_CASE(["$ac_cv_sizeof_voidp"],
|
||||
[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"
|
||||
#elif defined __i386__
|
||||
# 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"
|
||||
#elif defined __arm64__
|
||||
# include "coroutine/arm64/Context.S"
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
# include "coroutine/amd64/Context.h"
|
||||
#elif defined __i386__
|
||||
# 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"
|
||||
#elif defined __arm64__
|
||||
# include "coroutine/arm64/Context.h"
|
||||
|
|
|
@ -1765,10 +1765,23 @@ native_thread_native_thread_id(rb_thread_t *target_th)
|
|||
if (tid == 0) return Qnil;
|
||||
return INT2FIX(tid);
|
||||
#elif defined(__APPLE__)
|
||||
uint64_t tid;
|
||||
int e = pthread_threadid_np(target_th->nt->thread_id, &tid);
|
||||
if (e != 0) rb_syserr_fail(e, "pthread_threadid_np");
|
||||
return ULL2NUM((unsigned long long)tid);
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
|
||||
uint64_t tid;
|
||||
tid = pthread_mach_thread_np(pthread_self());
|
||||
#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);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
# define USE_NATIVE_THREAD_NATIVE_THREAD_ID 1
|
||||
|
|
Loading…
Add table
Reference in a new issue