Revise for LP64.
Encapsulate previously copied code sections into macros.
This commit is contained in:
parent
032dc727f7
commit
a228aa3de2
|
@ -0,0 +1,189 @@
|
|||
/* $NetBSD: _context_u.S,v 1.1 2006/07/08 05:09:44 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Allen Briggs for Wasabi Systems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
#include "assym.h"
|
||||
|
||||
/*
|
||||
* Define:
|
||||
* int _getcontext_u(ucontext_t *ctx)
|
||||
* Store the current context in the provided ctx structure.
|
||||
* [only store the callee-saved registers]
|
||||
* int _setcontext_u(const ucontext_t *ctx)
|
||||
* Restore the current context from the provided ctx structure.
|
||||
* int _swapcontext_u(ucontext_t *from_ctx, const ucontext_t *to_ctx)
|
||||
* First, store the current context into from_ctx and then
|
||||
* restore the current context from the to_ctx.
|
||||
*/
|
||||
|
||||
/*
|
||||
* According to the SVR4 ABI for PPC, r1, r14-r31, LR, and portions of the
|
||||
* CR are non-volatile. I.e., they need to be preserved across the function
|
||||
* call.
|
||||
*
|
||||
* If _getcontext_u is called, set the UC_USER_BIT in the UC_FLAGS. If
|
||||
* _setcontext_u sees that bit, then it will just restore this part of the
|
||||
* context, otherwise, it will call through to setcontext(2).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Arrange to not include FP save/restore on a soft-float
|
||||
* build. Thread switching shouldn't consume 40 system traps.
|
||||
*/
|
||||
#ifdef _SOFT_FLOAT
|
||||
#define FPUFLAG 0
|
||||
#define GETFP(reg)
|
||||
#define SETFP
|
||||
#else
|
||||
#define FPUFLAG _UC_FPU
|
||||
#define GETFP(reg) \
|
||||
mffs %r0 ; \
|
||||
stfd %r0, (_REG_FPSCR - 4)(reg) ; \
|
||||
stfd %r14, (_REG_FP0 + 14*8)(reg) ; \
|
||||
stfd %r15, (_REG_FP0 + 15*8)(reg) ; \
|
||||
stfd %r16, (_REG_FP0 + 16*8)(reg) ; \
|
||||
stfd %r17, (_REG_FP0 + 17*8)(reg) ; \
|
||||
stfd %r18, (_REG_FP0 + 18*8)(reg) ; \
|
||||
stfd %r19, (_REG_FP0 + 19*8)(reg) ; \
|
||||
stfd %r20, (_REG_FP0 + 20*8)(reg) ; \
|
||||
stfd %r21, (_REG_FP0 + 21*8)(reg) ; \
|
||||
stfd %r22, (_REG_FP0 + 22*8)(reg) ; \
|
||||
stfd %r23, (_REG_FP0 + 23*8)(reg) ; \
|
||||
stfd %r24, (_REG_FP0 + 24*8)(reg) ; \
|
||||
stfd %r25, (_REG_FP0 + 25*8)(reg) ; \
|
||||
stfd %r26, (_REG_FP0 + 26*8)(reg) ; \
|
||||
stfd %r27, (_REG_FP0 + 27*8)(reg) ; \
|
||||
stfd %r28, (_REG_FP0 + 28*8)(reg) ; \
|
||||
stfd %r29, (_REG_FP0 + 29*8)(reg) ; \
|
||||
stfd %r30, (_REG_FP0 + 30*8)(reg) ; \
|
||||
stfd %r31, (_REG_FP0 + 31*8)(reg)
|
||||
|
||||
#define SETFP \
|
||||
andi. %r5, %r3, _UC_FPU ; \
|
||||
beq 1f ; \
|
||||
; \
|
||||
lwz %r5, (_UC_FPVALID)(%r4) ; \
|
||||
or. %r5, %r5, %r5 ; \
|
||||
beq 1f ; \
|
||||
; \
|
||||
lfd %r14, (_REG_FP0 + 14*8)(%r4) ; \
|
||||
lfd %r15, (_REG_FP0 + 15*8)(%r4) ; \
|
||||
lfd %r16, (_REG_FP0 + 16*8)(%r4) ; \
|
||||
lfd %r17, (_REG_FP0 + 17*8)(%r4) ; \
|
||||
lfd %r18, (_REG_FP0 + 18*8)(%r4) ; \
|
||||
lfd %r19, (_REG_FP0 + 19*8)(%r4) ; \
|
||||
lfd %r20, (_REG_FP0 + 20*8)(%r4) ; \
|
||||
lfd %r21, (_REG_FP0 + 21*8)(%r4) ; \
|
||||
lfd %r22, (_REG_FP0 + 22*8)(%r4) ; \
|
||||
lfd %r23, (_REG_FP0 + 23*8)(%r4) ; \
|
||||
lfd %r24, (_REG_FP0 + 24*8)(%r4) ; \
|
||||
lfd %r25, (_REG_FP0 + 25*8)(%r4) ; \
|
||||
lfd %r26, (_REG_FP0 + 26*8)(%r4) ; \
|
||||
lfd %r27, (_REG_FP0 + 27*8)(%r4) ; \
|
||||
lfd %r28, (_REG_FP0 + 28*8)(%r4) ; \
|
||||
lfd %r29, (_REG_FP0 + 29*8)(%r4) ; \
|
||||
lfd %r30, (_REG_FP0 + 30*8)(%r4) ; \
|
||||
lfd %r31, (_REG_FP0 + 31*8)(%r4) ; \
|
||||
lfd %r0, (_REG_FPSCR - 4)(%r4) ; \
|
||||
mtfsf 0xff, %r0 ; \
|
||||
1:
|
||||
#endif
|
||||
|
||||
|
||||
#define GETC(reg) \
|
||||
std %r1, (_REG_R0 + 1*8)(reg) ; \
|
||||
i = 0 ; \
|
||||
.rept 31-14+1 ; \
|
||||
std 14+i,[_REG_R0+[[14+i]*8]](reg) ; \
|
||||
i = i+1 ; \
|
||||
.endr ; \
|
||||
mfcr %r0 ; \
|
||||
std %r0, _REG_CR(reg) ; \
|
||||
mflr %r0 ; \
|
||||
std %r0, _REG_LR(reg) ; \
|
||||
std %r0, _REG_PC(reg) ; \
|
||||
; \
|
||||
GETFP(reg) ; \
|
||||
; \
|
||||
li %r8, 1 ; \
|
||||
stw %r8, (_UC_FPVALID)(reg) ; \
|
||||
slwi %r9, %r8, _UC_USER_BIT ; \
|
||||
ori %r9, %r9, (_UC_CPU | FPUFLAG) ; \
|
||||
stw %r9, (UC_FLAGS)(reg)
|
||||
|
||||
#define SETC \
|
||||
li %r9, 1 ; \
|
||||
slwi %r9, %r9, _UC_USER_BIT ; \
|
||||
lwz %r3, (UC_FLAGS)(%r4) ; \
|
||||
and. %r9, %r3, %r9 ; \
|
||||
beq 2f ; \
|
||||
; \
|
||||
lwz %r1, (_REG_R0 + 1*4)(%r4) ; \
|
||||
/* lmw %r14, (_REG_R0 + 14*4)(%r4) */ ; \
|
||||
i = 0 ; \
|
||||
.rept 31-14+1 ; \
|
||||
ld 14+i,[_REG_R0+[[14+i]*8]](%r4) ;\
|
||||
i = i+1 ; \
|
||||
.endr ; \
|
||||
lwz %r0, _REG_LR(%r4) ; \
|
||||
mtlr %r0 ; \
|
||||
lwz %r0, _REG_PC(%r4) ; \
|
||||
mtctr %r0 ; \
|
||||
; \
|
||||
SETFP ; \
|
||||
; \
|
||||
lwz %r0, _REG_CR(%r4) ; \
|
||||
mtcr %r0 ; \
|
||||
bctr ; \
|
||||
2: ; \
|
||||
mr %r3, %r4 ; \
|
||||
b .setcontext ; \
|
||||
nop ; \
|
||||
/* NOTREACHED */
|
||||
|
||||
ENTRY(_getcontext_u)
|
||||
GETC(%r3)
|
||||
xor %r3,%r3,%r3
|
||||
blr
|
||||
|
||||
ENTRY(_setcontext_u)
|
||||
mr %r4,%r3
|
||||
SETC
|
||||
|
||||
ENTRY(_swapcontext_u)
|
||||
GETC(%r3)
|
||||
SETC
|
|
@ -0,0 +1,72 @@
|
|||
# $NetBSD: genassym.cf,v 1.1 2006/07/08 05:09:44 ross Exp $
|
||||
|
||||
# Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Written by Allen Briggs for Wasabi Systems, Inc.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed for the NetBSD Project by
|
||||
# Wasabi Systems, Inc.
|
||||
# 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
# or promote products derived from this software without specific prior
|
||||
# written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include <ucontext.h>
|
||||
include <sys/queue.h>
|
||||
include "pthread.h"
|
||||
include "pthread_int.h"
|
||||
include "pthread_md.h"
|
||||
|
||||
# for _context_u.S
|
||||
define UC_FLAGS offsetof(ucontext_t, uc_flags)
|
||||
define _UC_FPVALID offsetof(ucontext_t, uc_mcontext.__fpregs.__fpu_valid)
|
||||
define _REG_R0 offsetof(ucontext_t, uc_mcontext.__gregs[_REG_R0])
|
||||
define _REG_CR offsetof(ucontext_t, uc_mcontext.__gregs[_REG_CR])
|
||||
define _REG_LR offsetof(ucontext_t, uc_mcontext.__gregs[_REG_LR])
|
||||
define _REG_PC offsetof(ucontext_t, uc_mcontext.__gregs[_REG_PC])
|
||||
define _REG_MSR offsetof(ucontext_t, uc_mcontext.__gregs[_REG_MSR])
|
||||
define _REG_CTR offsetof(ucontext_t, uc_mcontext.__gregs[_REG_CTR])
|
||||
define _REG_XER offsetof(ucontext_t, uc_mcontext.__gregs[_REG_XER])
|
||||
define _REG_FP0 offsetof(ucontext_t, uc_mcontext.__fpregs.__fpu_regs[0])
|
||||
define _REG_FPSCR offsetof(ucontext_t, uc_mcontext.__fpregs.__fpu_fpscr)
|
||||
|
||||
# uc_flags
|
||||
define _UC_CPU _UC_CPU
|
||||
define _UC_FPU _UC_FPU
|
||||
define _UC_USER_BIT _UC_USER_BIT
|
||||
|
||||
#========================================================================
|
||||
# for pthread_switch.S
|
||||
define PT_UC offsetof(struct __pthread_st, pt_uc)
|
||||
define PT_TRAPUC offsetof(struct __pthread_st, pt_trapuc)
|
||||
define PT_NEXT offsetof(struct __pthread_st, pt_next)
|
||||
define PT_SPINLOCKS offsetof(struct __pthread_st, pt_spinlocks)
|
||||
define PT_SWITCHTO offsetof(struct __pthread_st, pt_switchto)
|
||||
define PT_SWITCHTOUC offsetof(struct __pthread_st, pt_switchtouc)
|
||||
define PT_HELDLOCK offsetof(struct __pthread_st, pt_heldlock)
|
||||
|
||||
define CONTEXTSIZE sizeof(ucontext_t)
|
||||
define STACKSPACE STACKSPACE
|
|
@ -0,0 +1,125 @@
|
|||
/* $NetBSD: pthread_md.h,v 1.1 2006/07/08 05:09:44 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Allen Briggs for Wasabi Systems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LIB_PTHREAD_POWERPC_MD_H
|
||||
#define _LIB_PTHREAD_POWERPC_MD_H
|
||||
|
||||
static inline long
|
||||
pthread__sp(void)
|
||||
{
|
||||
long ret;
|
||||
|
||||
__asm("mr %0,1" : "=r" (ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[1])
|
||||
#define pthread__uc_pc(ucp) ((ucp)->uc_mcontext.__gregs[34])
|
||||
|
||||
/*
|
||||
* Set initial, sane values for registers whose values aren't just
|
||||
* "don't care".
|
||||
* 0xd032 is PSL_USERSET from arch/powerpc/include/psl.h
|
||||
*/
|
||||
#define _INITCONTEXT_U_MD(ucp) \
|
||||
(ucp)->uc_mcontext.__gregs[_REG_MSR] = 0xd032;
|
||||
|
||||
/*
|
||||
* Usable stack space below the ucontext_t.
|
||||
* For a good time, see comments in pthread_switch.S and
|
||||
* ../i386/pthread_switch.S about STACK_SWITCH.
|
||||
*/
|
||||
#define STACKSPACE 16 /* room for 4 integer values */
|
||||
|
||||
/*
|
||||
* Conversions between struct reg and struct mcontext. Used by
|
||||
* libpthread_dbg.
|
||||
*/
|
||||
|
||||
#define PTHREAD_UCONTEXT_TO_REG(reg, uc) do { \
|
||||
memcpy((reg)->fixreg, (uc)->uc_mcontext.__gregs, 32 * 4); \
|
||||
(reg)->cr = (uc)->uc_mcontext.__gregs[_REG_CR]; \
|
||||
(reg)->lr = (uc)->uc_mcontext.__gregs[_REG_LR]; \
|
||||
(reg)->pc = (uc)->uc_mcontext.__gregs[_REG_PC]; \
|
||||
(reg)->ctr = (uc)->uc_mcontext.__gregs[_REG_CTR]; \
|
||||
(reg)->xer = (uc)->uc_mcontext.__gregs[_REG_XER]; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define PTHREAD_REG_TO_UCONTEXT(uc, reg) do { \
|
||||
memcpy((uc)->uc_mcontext.__gregs, (reg)->fixreg, 32 * 4); \
|
||||
(uc)->uc_mcontext.__gregs[_REG_CR] = (reg)->cr; \
|
||||
(uc)->uc_mcontext.__gregs[_REG_LR] = (reg)->lr; \
|
||||
(uc)->uc_mcontext.__gregs[_REG_PC] = (reg)->pc; \
|
||||
(uc)->uc_mcontext.__gregs[_REG_CTR] = (reg)->ctr; \
|
||||
(uc)->uc_mcontext.__gregs[_REG_XER] = (reg)->xer; \
|
||||
(uc)->uc_flags = ((uc)->uc_flags | _UC_CPU) & ~_UC_USER; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define PTHREAD_UCONTEXT_TO_FPREG(freg, uc) do { \
|
||||
memcpy((freg)->fpreg, (uc)->uc_mcontext.__fpregs.__fpu_regs, \
|
||||
32 * 4); \
|
||||
(freg)->fpscr = (uc)->uc_mcontext.__fpregs.__fpu_fpscr; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define PTHREAD_FPREG_TO_UCONTEXT(uc, freg) do { \
|
||||
memcpy((uc)->uc_mcontext.__fpregs.__fpu_regs, (freg)->fpreg, \
|
||||
32 * 4); \
|
||||
(uc)->uc_mcontext.__fpregs.__fpu_fpscr = (freg)->fpscr; \
|
||||
(uc)->uc_flags = ((uc)->uc_flags | _UC_FPU) & ~_UC_USER; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define PTHREAD_UCONTEXT_XREG_FLAG _UC_POWERPC_VEC
|
||||
|
||||
#define PTHREAD_UCONTEXT_TO_XREG(xreg, uc) do { \
|
||||
memcpy(((struct vreg *)(xreg))->vreg, \
|
||||
(uc)->uc_mcontext.__vrf.__vrs, \
|
||||
16 * _NVR); \
|
||||
((struct vreg *)(xreg))->vscr = (uc)->uc_mcontext.__vrf.__vscr; \
|
||||
((struct vreg *)(xreg))->vrsave = (uc)->uc_mcontext.__vrf.__vrsave; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define PTHREAD_XREG_TO_UCONTEXT(uc, xreg) do { \
|
||||
memcpy((uc)->uc_mcontext.__vrf.__vrs, \
|
||||
((struct vreg *)(xreg))->vreg, \
|
||||
16 * _NVR); \
|
||||
(uc)->uc_mcontext.__vrf.__vscr = ((struct vreg *)(xreg))->vscr; \
|
||||
(uc)->uc_mcontext.__vrf.__vrsave = ((struct vreg *)(xreg))->vrsave; \
|
||||
(uc)->uc_flags = ((uc)->uc_flags | _UC_POWERPC_VEC) & ~_UC_USER; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#endif /* _LIB_PTHREAD_POWERPC_MD_H */
|
|
@ -0,0 +1,310 @@
|
|||
/* $NetBSD: pthread_switch.S,v 1.1 2006/07/08 05:09:44 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Allen Briggs for Wasabi Systems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
#include "assym.h"
|
||||
|
||||
#define NOTREACHED
|
||||
|
||||
/*
|
||||
* PowerPC ABI says stack pointer must be 16-byte aligned.
|
||||
*/
|
||||
#define RND_CTXSIZE ((CONTEXTSIZE + 15) & 0xfffffff0)
|
||||
|
||||
/*
|
||||
* Define:
|
||||
* void pthread__switch(pthread_t self, pthread_t next)
|
||||
* void pthread__upcall_switch(pthread_t self, pthread_t next)
|
||||
* void pthread__locked_switch(pthread_t self, pthread_t next,
|
||||
* pt_spin_t *lock)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Evil STACK_SWITCH()
|
||||
* See comments in ../i386/pthread_switch.S.
|
||||
*/
|
||||
#define STACK_SWITCH(pt,tmp,z) \
|
||||
ld tmp, PT_TRAPUC(pt) ; \
|
||||
or. tmp, tmp, tmp ; \
|
||||
bne 1f ; \
|
||||
ld tmp, PT_UC(pt) ; \
|
||||
1: la %r1, -STACKSPACE(tmp) ; \
|
||||
li z, 0 ; \
|
||||
std z, PT_TRAPUC(pt)
|
||||
|
||||
/*
|
||||
* void
|
||||
* pthread__switch(pthread_t self (%r3), pthread_t next (%r4))
|
||||
*
|
||||
* Plain switch that doesn't do any special checking or handle spin-
|
||||
* preemption. It isn't used much by normal code, actually; its main
|
||||
* purpose is to be a basic switch engine when the MI code is already
|
||||
* dealing with spin-preemption or other gunk.
|
||||
*
|
||||
* What we do here is allocate the ucontext for the 'self' thread on its
|
||||
* stack, saving the pointer in self's pthread structure, then swapping
|
||||
* context to 'next', effectively deallocating next's context on the way
|
||||
* out.
|
||||
*
|
||||
* Stack:
|
||||
* ------------------------------------------------------------------
|
||||
* highest addresses
|
||||
* saved r31 8 (offset is framesize - 8)
|
||||
* pad 8 pad r31 space up to 16
|
||||
* pad to round ucontext_t up to a 16 byte boundary
|
||||
* ucontext_t (offset is SF_SZ )
|
||||
* other elf stack frame (SF_PARAM_SZ )
|
||||
* elf stack frame header (SF_HEADER_SZ )
|
||||
* lowest addresses
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
ENTRY(pthread__switch)
|
||||
frameSize = SF_SZ + RND_CTXSIZE + 16 # need +8 for r31, & align
|
||||
saved31 = frameSize - 8
|
||||
.macro init_frame
|
||||
stdu %r1, -frameSize(%r1) /* alloc stack space */
|
||||
mflr %r0
|
||||
std %r31,saved31(%r1)
|
||||
std %r3, SF_PARAM+0(%r1) /* self */
|
||||
std %r4, SF_PARAM+8(%r1) /* next */
|
||||
std %r5, SF_PARAM+16(%r1) /* lock, for locked_switch */
|
||||
std %r0, frameSize+SF_LR(%r1) /* Save return address */
|
||||
la %r31, SF_SZ(%r1) /* %r31 = ucontext */
|
||||
.endm
|
||||
init_frame
|
||||
|
||||
.macro switch_context
|
||||
/* Get the current context */
|
||||
mr %r3, %r31
|
||||
CALL(_getcontext_u)
|
||||
ld %r3, SF_PARAM+0(%r1)
|
||||
ld %r4, SF_PARAM+8(%r1)
|
||||
ld %r5, SF_PARAM+16(%r1)
|
||||
/*
|
||||
* Edit the context to make it continue at switch_return instead of
|
||||
* here.
|
||||
*/
|
||||
ld %r6, pthread__common_return@got(%r2)
|
||||
std %r6, SF_SZ+_REG_PC(%r1)
|
||||
std %r31, PT_UC(%r3)
|
||||
|
||||
STACK_SWITCH(%r4, %r7, %r6)
|
||||
.endm
|
||||
switch_context
|
||||
|
||||
.macro set_context
|
||||
mr %r3, %r7
|
||||
b ._setcontext_u
|
||||
.endm
|
||||
set_context
|
||||
NOTREACHED
|
||||
|
||||
|
||||
|
||||
pthread__switch_away:
|
||||
STACK_SWITCH(%r4, %r6, %r7)
|
||||
|
||||
or. %r5, %r5, %r5
|
||||
beq 1f
|
||||
lwz %r7, PT_SPINLOCKS(%r3) # w OK
|
||||
addi %r7, %r7, -1
|
||||
stw %r7, PT_SPINLOCKS(%r3) # w OK
|
||||
|
||||
1: mr %r3, %r6
|
||||
b ._setcontext_u
|
||||
NOTREACHED
|
||||
|
||||
/*
|
||||
* void
|
||||
* pthread__upcall_switch(pthread_t self (%r3), pthread_t next (%r4))
|
||||
*/
|
||||
ENTRY(pthread__upcall_switch)
|
||||
lwz %r6, PT_SPINLOCKS(%r4) # w OK
|
||||
addi %r6, %r6, 1
|
||||
stw %r6, PT_SPINLOCKS(%r4) # w OK
|
||||
|
||||
STACK_SWITCH(%r4, %r5, %r6)
|
||||
|
||||
ld %r7, PT_NEXT(%r3)
|
||||
or. %r7, %r7, %r7
|
||||
beq 1f
|
||||
|
||||
std %r5, PT_SWITCHTOUC(%r3)
|
||||
std %r4, PT_SWITCHTO(%r3)
|
||||
mr %r3, %r4
|
||||
mr %r4, %r7
|
||||
li %r5, 1
|
||||
b pthread__switch_away
|
||||
NOTREACHED
|
||||
|
||||
1: mr %r14, %r3
|
||||
mr %r15, %r4
|
||||
mr %r16, %r5
|
||||
CALL(pthread__sa_recycle)
|
||||
mr %r3, %r14
|
||||
mr %r4, %r15
|
||||
mr %r5, %r16
|
||||
|
||||
lwz %r6, PT_SPINLOCKS(%r4) # w OK
|
||||
addi %r6, %r6, -1
|
||||
stw %r6, PT_SPINLOCKS(%r4) # w OK
|
||||
|
||||
ld %r7, PT_NEXT(%r4)
|
||||
or. %r7, %r7, %r7
|
||||
beq 2f
|
||||
|
||||
std %r5, PT_SWITCHTOUC(%r4)
|
||||
std %r4, PT_SWITCHTO(%r4)
|
||||
mr %r3, %r4
|
||||
mr %r4, %r7
|
||||
li %r5, 0
|
||||
b pthread__switch_away
|
||||
NOTREACHED
|
||||
|
||||
2: mr %r3, %r16
|
||||
b ._setcontext_u
|
||||
NOTREACHED
|
||||
|
||||
/*
|
||||
* void
|
||||
* pthread__locked_switch(pthread_t self (%r3), pthread_t next (%r4),
|
||||
* pt_spin_t *lock (%r5))
|
||||
*
|
||||
* THIS STACK FRAME APPLIES ONLY TO THE ORIGINAL ILP32 CODE
|
||||
*
|
||||
* Stack is:
|
||||
* high addr -- return addr ( 4 bytes)
|
||||
* %r1@call caller saved %r1 ( 4 bytes)
|
||||
* any padding to make %r1 a multiple of 16 ... *
|
||||
* saved %r31 ( 4 bytes) *
|
||||
* saved %r9 ( 4 bytes) *
|
||||
* saved %r5 ( 4 bytes) *
|
||||
* saved %r4 ( 4 bytes) *
|
||||
* saved %r3 ( 4 bytes) *
|
||||
* context (RND_CTXSIZE bytes) *
|
||||
* padding to 16 bytes ( 20 bytes) *
|
||||
* space for callee ra ( 4 bytes) *
|
||||
* low addr p__l_s saved %r1 ( 4 bytes) *
|
||||
*
|
||||
* STACKSPACE is the space between the bottom of the stack and
|
||||
* the ucontext on the stack. i.e., 8, but we want to keep the stack
|
||||
* rounded to a multiple of 16, so it's really 16.
|
||||
*/
|
||||
|
||||
.type locked_return,@function
|
||||
|
||||
ENTRY(pthread__locked_switch)
|
||||
|
||||
init_frame
|
||||
|
||||
/* increment spinlock to make sure that next gets continued */
|
||||
lwz %r6, PT_SPINLOCKS(%r4) # w OK
|
||||
addi %r6, %r6, 1
|
||||
stw %r6, PT_SPINLOCKS(%r4) # w OK
|
||||
|
||||
switch_context
|
||||
|
||||
/* Check if the switcher was preempted and continued to here. */
|
||||
ld %r8, PT_NEXT(%r3)
|
||||
or. %r8, %r8, %r8
|
||||
beq 1f
|
||||
|
||||
/*
|
||||
* Yes, it was. Stash the thread we were going to switch to,
|
||||
* the lock the original thread was holding, and switch to the
|
||||
* next thread in the continuation chain. Mark the fact that
|
||||
* this was a locked switch, and so the thread does not need to
|
||||
* be put on a run queue.
|
||||
* Don't release the lock. It's possible that if we do so,
|
||||
* PT_SWITCHTO will be stomped by another switch_lock and preemption.
|
||||
*/
|
||||
std %r5, PT_HELDLOCK(%r3)
|
||||
std %r7, PT_SWITCHTOUC(%r3)
|
||||
std %r4, PT_SWITCHTO(%r3)
|
||||
lwz %r6, PT_SPINLOCKS(%r3) # w OK
|
||||
addi %r6, %r6, -1
|
||||
stw %r6, PT_SPINLOCKS(%r3) # w OK
|
||||
|
||||
mr %r3, %r4
|
||||
mr %r4, %r8
|
||||
li %r5, 1
|
||||
b pthread__switch_away
|
||||
NOTREACHED
|
||||
|
||||
/* No locked old-preemption */
|
||||
1: /*
|
||||
* We've moved to the new stack, and the old context has been
|
||||
* saved. The queue lock can be released.
|
||||
*/
|
||||
/* Reduce the lock count... */
|
||||
lwz %r6, PT_SPINLOCKS(%r3) # w OK
|
||||
addi %r6, %r6, -1
|
||||
stw %r6, PT_SPINLOCKS(%r3) # w OK
|
||||
/* ... actually release the lock ... */
|
||||
sync
|
||||
xor %r9,%r9,%r9
|
||||
std %r9, 0(%r5)
|
||||
/* ... and remove the fake lock */
|
||||
lwz %r6, PT_SPINLOCKS(%r4) # w OK
|
||||
addi %r6, %r6, -1
|
||||
stw %r6, PT_SPINLOCKS(%r4) # w OK
|
||||
|
||||
/* Check to see if we were preempted while holding the fake lock */
|
||||
ld %r8, PT_NEXT(%r4)
|
||||
or. %r8, %r8, %r8
|
||||
beq 2f
|
||||
|
||||
/* Yes, we were. Go to the next element in the chain. */
|
||||
std %r7, PT_SWITCHTOUC(%r4)
|
||||
std %r4, PT_SWITCHTO(%r4)
|
||||
mr %r3, %r4
|
||||
mr %r4, %r8
|
||||
li %r5, 0
|
||||
b pthread__switch_away
|
||||
NOTREACHED
|
||||
|
||||
2: set_context
|
||||
NOTREACHED
|
||||
|
||||
|
||||
ENTRY(pthread__common_return)
|
||||
ld %r31, saved31(%r1)
|
||||
ld %r0, frameSize+SF_LR(%r1)
|
||||
la %r1, frameSize(%r1)
|
||||
mtlr %r0
|
||||
blr
|
Loading…
Reference in New Issue