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
		Add a link
		
	
		Reference in a new issue