Add alpha support to libpthread. It compiles but hasn't been tested;
there is still some missing kernel support. Reviewed by: marcel
This commit is contained in:
parent
ad2238f4b4
commit
a99e26741c
@ -2,4 +2,4 @@
|
||||
|
||||
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
|
||||
|
||||
SRCS+= ksd.c thr_enter_uts.S thr_getcontext.S thr_switch.S
|
||||
SRCS+= enter_uts.S context.S pthread_md.c
|
||||
|
353
lib/libpthread/arch/alpha/alpha/context.S
Normal file
353
lib/libpthread/arch/alpha/alpha/context.S
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright (c) 2001,3 Daniel Eischen <deischen@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994, 1995 Carnegie-Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Chris G. Demetriou
|
||||
*
|
||||
* Permission to use, copy, modify and distribute this software and
|
||||
* its documentation is hereby granted, provided that both the copyright
|
||||
* notice and this permission notice appear in all copies of the
|
||||
* software, derivative works or modified versions, and any portions
|
||||
* thereof, and that both notices appear in supporting documentation.
|
||||
*
|
||||
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
||||
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
|
||||
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
||||
*
|
||||
* Carnegie Mellon requests users of this software to return to
|
||||
*
|
||||
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
||||
* School of Computer Science
|
||||
* Carnegie Mellon University
|
||||
* Pittsburgh PA 15213-3890
|
||||
*
|
||||
* any improvements or extensions that they make and grant Carnegie the
|
||||
* rights to redistribute these changes.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/* #include <machine/frame.h> */
|
||||
#define FRAME_V0 0
|
||||
#define FRAME_T0 1
|
||||
#define FRAME_T1 2
|
||||
#define FRAME_T2 3
|
||||
#define FRAME_T3 4
|
||||
#define FRAME_T4 5
|
||||
#define FRAME_T5 6
|
||||
#define FRAME_T6 7
|
||||
#define FRAME_T7 8
|
||||
#define FRAME_S0 9
|
||||
#define FRAME_S1 10
|
||||
#define FRAME_S2 11
|
||||
#define FRAME_S3 12
|
||||
#define FRAME_S4 13
|
||||
#define FRAME_S5 14
|
||||
#define FRAME_S6 15
|
||||
#define FRAME_A3 16
|
||||
#define FRAME_A4 17
|
||||
#define FRAME_A5 18
|
||||
#define FRAME_RA 23
|
||||
#define FRAME_T12 24
|
||||
#define FRAME_AT 25
|
||||
#define FRAME_SP 26
|
||||
#define FRAME_TRAPARG_A0 28
|
||||
#define FRAME_TRAPARG_A1 29
|
||||
#define FRAME_TRAPARG_A2 30
|
||||
#define FRAME_PC (FRAME_TRAPARG_A2 + 1 + 1)
|
||||
|
||||
/* #include <machine/reg.h> */
|
||||
#define R_V0 0
|
||||
#define R_T0 1
|
||||
#define R_T1 2
|
||||
#define R_T2 3
|
||||
#define R_T3 4
|
||||
#define R_T4 5
|
||||
#define R_T5 6
|
||||
#define R_T6 7
|
||||
#define R_T7 8
|
||||
#define R_S0 9
|
||||
#define R_S1 10
|
||||
#define R_S2 11
|
||||
#define R_S3 12
|
||||
#define R_S4 13
|
||||
#define R_S5 14
|
||||
#define R_S6 15
|
||||
#define R_A0 16
|
||||
#define R_A1 17
|
||||
#define R_A2 18
|
||||
#define R_A3 19
|
||||
#define R_A4 20
|
||||
#define R_A5 21
|
||||
#define R_T8 22
|
||||
#define R_T9 23
|
||||
#define R_T10 24
|
||||
#define R_T11 25
|
||||
#define R_RA 26
|
||||
#define R_T12 27
|
||||
#define R_SP 30
|
||||
#define R_ZERO 31
|
||||
|
||||
/*
|
||||
* XXX - The rev id's are defined in <machine/ucontext.h>
|
||||
*/
|
||||
#define MC_FMT_OFFSET 73*8 /* offset to format from mcontext */
|
||||
#define REV0_SIGFRAME 0x0001 /* rev R0 sigcontext format */
|
||||
#define REV0_TRAPFRAME 0x0002 /* rev R0 trapframe format */
|
||||
|
||||
/*
|
||||
* int _alpha_restore_context(const mcontext_t *mcp,
|
||||
* intptr_t val, intptr_t *loc);
|
||||
*
|
||||
* The format of the context is verified at the beginning.
|
||||
* Returns -1 if invalid format.
|
||||
*/
|
||||
.set noreorder
|
||||
LEAF(_alpha_restore_context, 3)
|
||||
LDGP(pv)
|
||||
bne a0, Lsc1 /* argument null? */
|
||||
Lscbad: ldiq v0, -1 /* return -1 */
|
||||
br Lscend
|
||||
Lsc1: ldq t1, MC_FMT_OFFSET(a0) /* is mcontext valid format? */
|
||||
ldiq t0, REV0_TRAPFRAME
|
||||
cmpeq t0, t1, t0 /* is it trapframe format? */
|
||||
bne t0, Lsc_fp /* if so, check fp state */
|
||||
ldiq t0, REV0_SIGFRAME
|
||||
cmpeq t0, t1, t0 /* is it sigcontext format? */
|
||||
beq t0, Lscbad
|
||||
/* supposedly sigcontext format, check magic number */
|
||||
ldiq t0, 0xACEDBADE /* check magic number */
|
||||
ldq t1, ((R_ZERO + 1) * 8)(a0) /* magic in mc_regs[R_ZERO] */
|
||||
cmpeq t0, t1, t0
|
||||
beq t0, Lscbad
|
||||
/* restore floating point regs first */
|
||||
Lsc_fp: ldq t0, ((71 + 1) * 8)(a0) /* if FP regs not saved, */
|
||||
beq t0, Lsc2 /* skip setting FP regs */
|
||||
ldt $f0, ((37 + 1) * 8)(a0) /* restore FP regs using */
|
||||
ldt $f1, ((38 + 1) * 8)(a0) /* hw name */
|
||||
ldt $f2, ((39 + 1) * 8)(a0)
|
||||
ldt $f3, ((40 + 1) * 8)(a0)
|
||||
ldt $f4, ((41 + 1) * 8)(a0)
|
||||
ldt $f5, ((42 + 1) * 8)(a0)
|
||||
ldt $f6, ((43 + 1) * 8)(a0)
|
||||
ldt $f7, ((44 + 1) * 8)(a0)
|
||||
ldt $f8, ((45 + 1) * 8)(a0)
|
||||
ldt $f9, ((46 + 1) * 8)(a0)
|
||||
ldt $f10, ((47 + 1) * 8)(a0)
|
||||
ldt $f11, ((48 + 1) * 8)(a0)
|
||||
ldt $f12, ((49 + 1) * 8)(a0)
|
||||
ldt $f13, ((50 + 1) * 8)(a0)
|
||||
ldt $f14, ((51 + 1) * 8)(a0)
|
||||
ldt $f15, ((52 + 1) * 8)(a0)
|
||||
ldt $f16, ((53 + 1) * 8)(a0)
|
||||
ldt $f17, ((54 + 1) * 8)(a0)
|
||||
ldt $f18, ((55 + 1) * 8)(a0)
|
||||
ldt $f19, ((56 + 1) * 8)(a0)
|
||||
ldt $f20, ((57 + 1) * 8)(a0)
|
||||
ldt $f21, ((58 + 1) * 8)(a0)
|
||||
ldt $f22, ((59 + 1) * 8)(a0)
|
||||
ldt $f23, ((60 + 1) * 8)(a0)
|
||||
ldt $f24, ((61 + 1) * 8)(a0)
|
||||
ldt $f25, ((62 + 1) * 8)(a0)
|
||||
ldt $f26, ((63 + 1) * 8)(a0)
|
||||
ldt $f27, ((64 + 1) * 8)(a0)
|
||||
.set noat
|
||||
ldt $f28, ((65 + 1) * 8)(a0)
|
||||
.set at
|
||||
ldt $f29, ((66 + 1) * 8)(a0)
|
||||
ldt $f30, ((67 + 1) * 8)(a0)
|
||||
/* $f31 is hardwired zero */
|
||||
ldt ft0, ((69 + 1) * 8)(a0) /* restore FP control reg */
|
||||
mt_fpcr ft0
|
||||
Lsc2: ldiq t0, REV0_SIGFRAME /* check the context format */
|
||||
ldq t1, MC_FMT_OFFSET(a0) /* again. */
|
||||
cmpeq t0, t1, t0 /* is it sigcontext format? */
|
||||
bne t0, Lsc_sc
|
||||
/* trapframe format */
|
||||
ldq v0, ((FRAME_V0 + 1) * 8)(a0) /* restore v0 */
|
||||
ldq t0, ((FRAME_T0 + 1) * 8)(a0) /* restore t0-t7 */
|
||||
ldq t1, ((FRAME_T1 + 1) * 8)(a0)
|
||||
ldq t2, ((FRAME_T2 + 1) * 8)(a0)
|
||||
ldq t3, ((FRAME_T3 + 1) * 8)(a0)
|
||||
ldq t4, ((FRAME_T4 + 1) * 8)(a0)
|
||||
ldq t5, ((FRAME_T5 + 1) * 8)(a0)
|
||||
ldq t6, ((FRAME_T6 + 1) * 8)(a0)
|
||||
ldq t7, ((FRAME_T7 + 1) * 8)(a0)
|
||||
ldq s0, ((FRAME_S0 + 1) * 8)(a0) /* restore s0-s6 */
|
||||
ldq s1, ((FRAME_S1 + 1) * 8)(a0)
|
||||
ldq s2, ((FRAME_S2 + 1) * 8)(a0)
|
||||
ldq s3, ((FRAME_S3 + 1) * 8)(a0)
|
||||
ldq s4, ((FRAME_S4 + 1) * 8)(a0)
|
||||
ldq s5, ((FRAME_S5 + 1) * 8)(a0)
|
||||
ldq s6, ((FRAME_S6 + 1) * 8)(a0)
|
||||
ldq a4, ((FRAME_A4 + 1) * 8)(a0) /* restore a4, a5 */
|
||||
ldq a5, ((FRAME_A5 + 1) * 8)(a0)
|
||||
ldq ra, ((FRAME_RA + 1) * 8)(a0)
|
||||
ldq sp, ((FRAME_SP + 1) * 8)(a0)
|
||||
subq sp, 16, sp /* save room on stack */
|
||||
ldq a3, ((FRAME_TRAPARG_A1 + 1) * 8)(a0)
|
||||
stq a3, 0(a0) /* save a1 on stack */
|
||||
ldq a3, ((FRAME_TRAPARG_A2 + 1) * 8)(a0)
|
||||
stq a3, 8(a0) /* save a2 on stack */
|
||||
.set noat
|
||||
ldq at_reg, ((FRAME_PC + 1) * 8)(a0) /* PC at time of trap? */
|
||||
.set at
|
||||
ldq a3, ((FRAME_A3 + 1) * 8)(a0) /* restore a3 */
|
||||
ldq a0, ((FRAME_TRAPARG_A0 + 1) * 8)(a0) /* restore a0 */
|
||||
br Lsc3
|
||||
Lsc_sc: /* sigcontext format */
|
||||
ldq v0, ((R_V0 + 1) * 8)(a0) /* restore v0 */
|
||||
ldq t0, ((R_T0 + 1) * 8)(a0) /* restore t0-t7 */
|
||||
ldq t1, ((R_T1 + 1) * 8)(a0)
|
||||
ldq t2, ((R_T2 + 1) * 8)(a0)
|
||||
ldq t3, ((R_T3 + 1) * 8)(a0)
|
||||
ldq t4, ((R_T4 + 1) * 8)(a0)
|
||||
ldq t5, ((R_T5 + 1) * 8)(a0)
|
||||
ldq t6, ((R_T6 + 1) * 8)(a0)
|
||||
ldq t7, ((R_T7 + 1) * 8)(a0)
|
||||
ldq s0, ((R_S0 + 1) * 8)(a0) /* restore s0-s6 */
|
||||
ldq s1, ((R_S1 + 1) * 8)(a0)
|
||||
ldq s2, ((R_S2 + 1) * 8)(a0)
|
||||
ldq s3, ((R_S3 + 1) * 8)(a0)
|
||||
ldq s4, ((R_S4 + 1) * 8)(a0)
|
||||
ldq s5, ((R_S5 + 1) * 8)(a0)
|
||||
ldq s6, ((R_S6 + 1) * 8)(a0)
|
||||
ldq a4, ((R_A4 + 1) * 8)(a0) /* restore a4, a5 */
|
||||
ldq a5, ((R_A5 + 1) * 8)(a0)
|
||||
ldq ra, ((R_RA + 1) * 8)(a0)
|
||||
ldq sp, ((R_SP + 1) * 8)(a0)
|
||||
subq sp, 16, sp /* save room on stack */
|
||||
ldq a3, ((R_A1 + 1) * 8)(a0) /* get a1 */
|
||||
stq a3, 0(a0) /* save a1 on stack */
|
||||
ldq a3, ((R_A2 + 1) * 8)(a0) /* get a2 */
|
||||
stq a3, 8(a0) /* save a2 on stack */
|
||||
ldq a3, ((R_A3 + 1) * 8)(a0) /* restore a3 */
|
||||
ldq a0, ((R_A0 + 1) * 8)(a0) /* restore a0 */
|
||||
Lsc3: bne a2, Lsc4
|
||||
stq a1, 0(a2)
|
||||
Lsc4: ldq a1, 0(sp) /* restore a1, a2 */
|
||||
ldq a2, 8(sp)
|
||||
addq sp, 16, sp /* restore stack */
|
||||
Lscend: RET
|
||||
END(_alpha_restore_context)
|
||||
|
||||
|
||||
/*
|
||||
* int _alpha_save_context(mcontext_t *);
|
||||
*
|
||||
* Always save in trapframe format. Floating point registers are
|
||||
* saved but may be optimized away later (see comments below).
|
||||
*/
|
||||
LEAF(_alpha_save_context, 1)
|
||||
LDGP(pv)
|
||||
bne a0, Lgc1 /* argument null? */
|
||||
ldiq v0, -1 /* return -1 */
|
||||
br Lgcend
|
||||
Lgc1: ldiq v0, 1 /* save_context returns 1, */
|
||||
stq v0, ((FRAME_V0 + 1) * 8)(a0) /* so save 1 in v0 */
|
||||
stq t0, ((FRAME_T0 + 1) * 8)(a0) /* save t0-t7 */
|
||||
stq t1, ((FRAME_T1 + 1) * 8)(a0)
|
||||
stq t2, ((FRAME_T2 + 1) * 8)(a0)
|
||||
stq t3, ((FRAME_T3 + 1) * 8)(a0)
|
||||
stq t4, ((FRAME_T4 + 1) * 8)(a0)
|
||||
stq t5, ((FRAME_T5 + 1) * 8)(a0)
|
||||
stq t6, ((FRAME_T6 + 1) * 8)(a0)
|
||||
stq t7, ((FRAME_T7 + 1) * 8)(a0)
|
||||
stq s0, ((FRAME_S0 + 1) * 8)(a0) /* save s0-s6 */
|
||||
stq s1, ((FRAME_S1 + 1) * 8)(a0)
|
||||
stq s2, ((FRAME_S2 + 1) * 8)(a0)
|
||||
stq s3, ((FRAME_S3 + 1) * 8)(a0)
|
||||
stq s4, ((FRAME_S4 + 1) * 8)(a0)
|
||||
stq s5, ((FRAME_S5 + 1) * 8)(a0)
|
||||
stq s6, ((FRAME_S6 + 1) * 8)(a0)
|
||||
stq a0, ((FRAME_TRAPARG_A0 + 1) * 8)(a0) /* save a0-a5 */
|
||||
stq a1, ((FRAME_TRAPARG_A1 + 1) * 8)(a0)
|
||||
stq a2, ((FRAME_TRAPARG_A2 + 1) * 8)(a0)
|
||||
stq a3, ((FRAME_A3 + 1) * 8)(a0)
|
||||
stq a4, ((FRAME_A4 + 1) * 8)(a0)
|
||||
stq a5, ((FRAME_A5 + 1) * 8)(a0)
|
||||
stq ra, ((FRAME_RA + 1) * 8)(a0)
|
||||
stq sp, ((FRAME_SP + 1) * 8)(a0)
|
||||
ldiq t0, REV0_TRAPFRAME /* store trapframe format in */
|
||||
stq t0, MC_FMT_OFFSET(a0) /* ucp->uc-rev */
|
||||
/*
|
||||
* XXX - Do we really need to save floating point registers?
|
||||
*
|
||||
* This is an explicit call to get the current context, so
|
||||
* shouldn't the caller be done with the floating point registers?
|
||||
* Contexts formed by involuntary switches, such as signal delivery,
|
||||
* should have floating point registers saved by the kernel.
|
||||
*/
|
||||
#if 1
|
||||
stq zero, ((71 + 1) * 8)(a0) /* FP regs are not saved */
|
||||
#else
|
||||
ldiq t0, 1 /* say we've used FP, */
|
||||
stq t0, ((71 + 1) * 8)(a0) /* mc_ownedfp = 1 */
|
||||
stt $f0, ((37 + 1) * 8)(a0) /* save first register, using */
|
||||
stt $f1, ((38 + 1) * 8)(a0) /* hw name etc. */
|
||||
stt $f2, ((39 + 1) * 8)(a0)
|
||||
stt $f3, ((40 + 1) * 8)(a0)
|
||||
stt $f4, ((41 + 1) * 8)(a0)
|
||||
stt $f5, ((42 + 1) * 8)(a0)
|
||||
stt $f6, ((43 + 1) * 8)(a0)
|
||||
stt $f7, ((44 + 1) * 8)(a0)
|
||||
stt $f8, ((45 + 1) * 8)(a0)
|
||||
stt $f9, ((46 + 1) * 8)(a0)
|
||||
stt $f10, ((47 + 1) * 8)(a0)
|
||||
stt $f11, ((48 + 1) * 8)(a0)
|
||||
stt $f12, ((49 + 1) * 8)(a0)
|
||||
stt $f13, ((50 + 1) * 8)(a0)
|
||||
stt $f14, ((51 + 1) * 8)(a0)
|
||||
stt $f15, ((52 + 1) * 8)(a0)
|
||||
stt $f16, ((53 + 1) * 8)(a0)
|
||||
stt $f17, ((54 + 1) * 8)(a0)
|
||||
stt $f18, ((55 + 1) * 8)(a0)
|
||||
stt $f19, ((56 + 1) * 8)(a0)
|
||||
stt $f20, ((57 + 1) * 8)(a0)
|
||||
stt $f21, ((58 + 1) * 8)(a0)
|
||||
stt $f22, ((59 + 1) * 8)(a0)
|
||||
stt $f23, ((60 + 1) * 8)(a0)
|
||||
stt $f24, ((61 + 1) * 8)(a0)
|
||||
stt $f25, ((62 + 1) * 8)(a0)
|
||||
stt $f26, ((63 + 1) * 8)(a0)
|
||||
stt $f27, ((64 + 1) * 8)(a0)
|
||||
.set noat
|
||||
stt $f28, ((65 + 1) * 8)(a0)
|
||||
.set at
|
||||
stt $f29, ((66 + 1) * 8)(a0)
|
||||
stt $f30, ((67 + 1) * 8)(a0)
|
||||
/* $f31 is hardwired zero */
|
||||
#endif
|
||||
mf_fpcr ft0 /* get FP control reg */
|
||||
stt ft0, ((69 + 1) * 8)(a0) /* and store it in mc_fpcr */
|
||||
stq zero, ((70 + 1) * 8)(a0) /* FP software control XXX */
|
||||
mov zero, v0 /* return zero */
|
||||
Lgcend: RET
|
||||
END(_alpha_save_context)
|
43
lib/libpthread/arch/alpha/alpha/enter_uts.S
Normal file
43
lib/libpthread/arch/alpha/alpha/enter_uts.S
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* _alpha_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack,
|
||||
* long stacksz);
|
||||
*/
|
||||
LEAF(_alpha_enter_uts, 4)
|
||||
addq a2, a3, a2
|
||||
ldiq a3, ~0xf
|
||||
and a2, a3, a2
|
||||
mov a2, sp
|
||||
mov a1, ra
|
||||
mov a1, t12
|
||||
RET
|
76
lib/libpthread/arch/alpha/alpha/pthread_md.c
Normal file
76
lib/libpthread/arch/alpha/alpha/pthread_md.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include "pthread_md.h"
|
||||
|
||||
/*
|
||||
* The constructors.
|
||||
*/
|
||||
struct tcb *
|
||||
_tcb_ctor(struct pthread *thread)
|
||||
{
|
||||
struct tcb *tcb;
|
||||
|
||||
if ((tcb = malloc(sizeof(struct tcb))) != NULL) {
|
||||
bzero(tcb, sizeof(struct tcb));
|
||||
tcb->tcb_thread = thread;
|
||||
/* Allocate TDV */
|
||||
}
|
||||
return (tcb);
|
||||
}
|
||||
|
||||
void
|
||||
_tcb_dtor(struct tcb *tcb)
|
||||
{
|
||||
/* Free TDV */
|
||||
free(tcb);
|
||||
}
|
||||
|
||||
struct kcb *
|
||||
_kcb_ctor(struct kse *kse)
|
||||
{
|
||||
struct kcb *kcb;
|
||||
|
||||
if ((kcb = malloc(sizeof(struct kcb))) != NULL) {
|
||||
bzero(kcb, sizeof(struct kcb));
|
||||
kcb->kcb_faketcb.tcb_isfake = 1;
|
||||
kcb->kcb_faketcb.tcb_tmbx.tm_flags = TMF_NOUPCALL;
|
||||
kcb->kcb_curtcb = &kcb->kcb_faketcb;
|
||||
kcb->kcb_kse = kse;
|
||||
}
|
||||
return (kcb);
|
||||
}
|
||||
|
||||
void
|
||||
_kcb_dtor(struct kcb *kcb)
|
||||
{
|
||||
free(kcb);
|
||||
}
|
56
lib/libpthread/arch/alpha/include/atomic_ops.h
Normal file
56
lib/libpthread/arch/alpha/include/atomic_ops.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Daniel Eischen <deischen@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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. Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _ATOMIC_OPS_H_
|
||||
#define _ATOMIC_OPS_H_
|
||||
|
||||
/*
|
||||
* Atomic swap:
|
||||
* Atomic (tmp = *dst, *dst = val), then *res = tmp
|
||||
*
|
||||
* void atomic_swap_long(long *dst, long val, long *res);
|
||||
*/
|
||||
static inline void
|
||||
atomic_swap_long(long *dst, long val, long *res)
|
||||
{
|
||||
/* $1 and $2 are t0 and t1 respectively. */
|
||||
__asm ( " ldq $1, %1\n" /* get cache line before lock */
|
||||
"1: ldq_l $1, %1\n" /* load *dst asserting lock */
|
||||
" mov %2, $2\n" /* save value to be swapped */
|
||||
" stq_c $2, %1\n" /* attempt the store; $2 clobbered */
|
||||
" beq $2, 1b\n" /* it didn't work, loop */
|
||||
" stq $1, %0\n" /* save value of *dst in *res */
|
||||
: "+m"(*res)
|
||||
: "m"(*dst), "r"(val)
|
||||
: "memory", "$1", "$2"); /* clobber t0 and t1 */
|
||||
}
|
||||
|
||||
#define atomic_swap_ptr(d, v, r) \
|
||||
atomic_swap_long((long *)(d), (long)(v), (long *)(r))
|
||||
|
||||
#endif
|
232
lib/libpthread/arch/alpha/include/pthread_md.h
Normal file
232
lib/libpthread/arch/alpha/include/pthread_md.h
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Marcel Moolenaar
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _PTHREAD_MD_H_
|
||||
#define _PTHREAD_MD_H_
|
||||
|
||||
#include <sys/kse.h>
|
||||
#include <stddef.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define THR_GETCONTEXT(ucp) _alpha_save_context(&(ucp)->uc_mcontext)
|
||||
#define THR_SETCONTEXT(ucp) _alpha_restore_context(&(ucp)->uc_mcontext, \
|
||||
0, NULL)
|
||||
|
||||
#define PER_THREAD
|
||||
|
||||
struct kcb;
|
||||
struct kse;
|
||||
struct pthread;
|
||||
struct tcb;
|
||||
struct tdv; /* We don't know what this is yet? */
|
||||
|
||||
/*
|
||||
* tp points to one of these. We define the static TLS as an array
|
||||
* of long double to enforce 16-byte alignment of the TLS memory,
|
||||
* struct ia64_tp, struct tcb and also struct kcb. Both static and
|
||||
* dynamic allocation of any of these structures will result in a
|
||||
* valid, well-aligned thread pointer.
|
||||
*/
|
||||
struct ia64_tp {
|
||||
struct tdv *tp_tdv; /* dynamic TLS */
|
||||
uint64_t _reserved_;
|
||||
long double tp_tls[0]; /* static TLS */
|
||||
};
|
||||
|
||||
struct tcb {
|
||||
struct kse_thr_mailbox tcb_tmbx;
|
||||
struct pthread *tcb_thread;
|
||||
struct kcb *tcb_curkcb;
|
||||
long tcb_isfake;
|
||||
struct ia64_tp tcb_tp;
|
||||
};
|
||||
|
||||
struct kcb {
|
||||
struct kse_mailbox kcb_kmbx;
|
||||
struct tcb kcb_faketcb;
|
||||
struct tcb *kcb_curtcb;
|
||||
struct kse *kcb_kse;
|
||||
};
|
||||
|
||||
#define _tp __builtin_thread_pointer()
|
||||
#define _tcb ((struct tcb*)((char*)(_tp) - offsetof(struct tcb, tcb_tp)))
|
||||
|
||||
/*
|
||||
* The kcb and tcb constructors.
|
||||
*/
|
||||
struct tcb *_tcb_ctor(struct pthread *);
|
||||
void _tcb_dtor(struct tcb *);
|
||||
struct kcb *_kcb_ctor(struct kse *kse);
|
||||
void _kcb_dtor(struct kcb *);
|
||||
|
||||
/* Called from the KSE to set its private data. */
|
||||
static __inline void
|
||||
_kcb_set(struct kcb *kcb)
|
||||
{
|
||||
/* There is no thread yet; use the fake tcb. */
|
||||
__builtin_set_thread_pointer(&kcb->kcb_faketcb.tcb_tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current kcb.
|
||||
*
|
||||
* This can only be called while in a critical region; don't
|
||||
* worry about having the kcb changed out from under us.
|
||||
*/
|
||||
static __inline struct kcb *
|
||||
_kcb_get(void)
|
||||
{
|
||||
return (_tcb->tcb_curkcb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter a critical region.
|
||||
*
|
||||
* Read and clear km_curthread in the kse mailbox.
|
||||
*/
|
||||
static __inline struct kse_thr_mailbox *
|
||||
_kcb_critical_enter(void)
|
||||
{
|
||||
struct kse_thr_mailbox *crit;
|
||||
uint32_t flags;
|
||||
|
||||
if (_tcb->tcb_isfake != 0) {
|
||||
/*
|
||||
* We already are in a critical region since
|
||||
* there is no current thread.
|
||||
*/
|
||||
crit = NULL;
|
||||
} else {
|
||||
flags = _tcb->tcb_tmbx.tm_flags;
|
||||
_tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL;
|
||||
crit = _tcb->tcb_curkcb->kcb_kmbx.km_curthread;
|
||||
_tcb->tcb_curkcb->kcb_kmbx.km_curthread = NULL;
|
||||
_tcb->tcb_tmbx.tm_flags = flags;
|
||||
}
|
||||
return (crit);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
_kcb_critical_leave(struct kse_thr_mailbox *crit)
|
||||
{
|
||||
/* No need to do anything if this is a fake tcb. */
|
||||
if (_tcb->tcb_isfake == 0)
|
||||
_tcb->tcb_curkcb->kcb_kmbx.km_curthread = crit;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
_kcb_in_critical(void)
|
||||
{
|
||||
uint32_t flags;
|
||||
int ret;
|
||||
|
||||
if (_tcb->tcb_isfake != 0) {
|
||||
/*
|
||||
* We are in a critical region since there is no
|
||||
* current thread.
|
||||
*/
|
||||
ret = 1;
|
||||
} else {
|
||||
flags = _tcb->tcb_tmbx.tm_flags;
|
||||
_tcb->tcb_tmbx.tm_flags |= TMF_NOUPCALL;
|
||||
ret = (_tcb->tcb_curkcb->kcb_kmbx.km_curthread == NULL);
|
||||
_tcb->tcb_tmbx.tm_flags = flags;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
_tcb_set(struct kcb *kcb, struct tcb *tcb)
|
||||
{
|
||||
if (tcb == NULL)
|
||||
tcb = &kcb->kcb_faketcb;
|
||||
kcb->kcb_curtcb = tcb;
|
||||
tcb->tcb_curkcb = kcb;
|
||||
__builtin_set_thread_pointer(&tcb->tcb_tp);
|
||||
}
|
||||
|
||||
static __inline struct tcb *
|
||||
_tcb_get(void)
|
||||
{
|
||||
return (_tcb);
|
||||
}
|
||||
|
||||
static __inline struct pthread *
|
||||
_get_curthread(void)
|
||||
{
|
||||
return (_tcb->tcb_thread);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current kse.
|
||||
*
|
||||
* Like _kcb_get(), this can only be called while in a critical region.
|
||||
*/
|
||||
static __inline struct kse *
|
||||
_get_curkse(void)
|
||||
{
|
||||
return (_tcb->tcb_curkcb->kcb_kse);
|
||||
}
|
||||
|
||||
void _alpha_enter_uts(struct kse_mailbox *km, kse_func_t uts, void *stack,
|
||||
size_t stacksz);
|
||||
int _alpha_restore_context(mcontext_t *mc, intptr_t val, intptr_t *loc);
|
||||
int _alpha_save_context(mcontext_t *mc);
|
||||
|
||||
static __inline int
|
||||
_thread_enter_uts(struct tcb *tcb, struct kcb *kcb)
|
||||
{
|
||||
if (_alpha_save_context(&tcb->tcb_tmbx.tm_context.uc_mcontext) == 0) {
|
||||
/* Make the fake tcb the current thread. */
|
||||
kcb->kcb_curtcb = &kcb->kcb_faketcb;
|
||||
__builtin_set_thread_pointer(&kcb->kcb_faketcb.tcb_tp);
|
||||
_alpha_enter_uts(&kcb->kcb_kmbx, kcb->kcb_kmbx.km_func,
|
||||
kcb->kcb_kmbx.km_stack.ss_sp,
|
||||
kcb->kcb_kmbx.km_stack.ss_size);
|
||||
/* We should not reach here. */
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox)
|
||||
{
|
||||
_tcb_set(kcb, tcb);
|
||||
if (setmbox != 0)
|
||||
_alpha_restore_context(&tcb->tcb_tmbx.tm_context.uc_mcontext,
|
||||
(intptr_t)&tcb->tcb_tmbx,
|
||||
(intptr_t *)&kcb->kcb_kmbx.km_curthread);
|
||||
else
|
||||
_alpha_restore_context(&tcb->tcb_tmbx.tm_context.uc_mcontext,
|
||||
0, NULL);
|
||||
/* We should not reach here. */
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#endif /* _PTHREAD_MD_H_ */
|
Loading…
Reference in New Issue
Block a user