diff options
| author | ross <ross@NetBSD.org> | 2006-07-08 05:09:44 +0000 |
|---|---|---|
| committer | ross <ross@NetBSD.org> | 2006-07-08 05:09:44 +0000 |
| commit | a228aa3de265fe7643cbbb3a4577825599146812 (patch) | |
| tree | d0b5d48010df3e7823637ff4300d310757f53cee /lib/libpthread | |
| parent | 032dc727f738be733b24466c6bb62111ff34e90f (diff) | |
Revise for LP64.
Encapsulate previously copied code sections into macros.
Diffstat (limited to 'lib/libpthread')
| -rw-r--r-- | lib/libpthread/arch/powerpc64/_context_u.S | 189 | ||||
| -rw-r--r-- | lib/libpthread/arch/powerpc64/genassym.cf | 72 | ||||
| -rw-r--r-- | lib/libpthread/arch/powerpc64/pthread_md.h | 125 | ||||
| -rw-r--r-- | lib/libpthread/arch/powerpc64/pthread_switch.S | 310 |
4 files changed, 696 insertions, 0 deletions
diff --git a/lib/libpthread/arch/powerpc64/_context_u.S b/lib/libpthread/arch/powerpc64/_context_u.S new file mode 100644 index 00000000000..58faf20aae7 --- /dev/null +++ b/lib/libpthread/arch/powerpc64/_context_u.S @@ -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 diff --git a/lib/libpthread/arch/powerpc64/genassym.cf b/lib/libpthread/arch/powerpc64/genassym.cf new file mode 100644 index 00000000000..827552bad4b --- /dev/null +++ b/lib/libpthread/arch/powerpc64/genassym.cf @@ -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 diff --git a/lib/libpthread/arch/powerpc64/pthread_md.h b/lib/libpthread/arch/powerpc64/pthread_md.h new file mode 100644 index 00000000000..5e33899aaf2 --- /dev/null +++ b/lib/libpthread/arch/powerpc64/pthread_md.h @@ -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 */ diff --git a/lib/libpthread/arch/powerpc64/pthread_switch.S b/lib/libpthread/arch/powerpc64/pthread_switch.S new file mode 100644 index 00000000000..99442f3e91a --- /dev/null +++ b/lib/libpthread/arch/powerpc64/pthread_switch.S @@ -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 |
