Add preliminary sparc64 support to libpthread. This does not

yet work, but hopefully someone familiar with the sparc64
port can pick up the reins.

Submitted by:	jake
With mods by:	deischen
This commit is contained in:
Daniel Eischen 2003-10-09 02:32:28 +00:00
parent 981152552a
commit 203a51090b
12 changed files with 1018 additions and 0 deletions

View File

@ -0,0 +1,5 @@
# $FreeBSD$
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
SRCS+= pthread_md.c thr_getcontext.S

View File

@ -0,0 +1,75 @@
/*-
* Copyright (c) 2003 Jake Burkholder <jake@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_
#include <machine/atomic.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)
{
long tmp;
long r;
tmp = *dst;
for (;;) {
r = atomic_cas_64(dst, tmp, val);
if (r == tmp)
break;
tmp = r;
}
*res = tmp;
}
static __inline void
atomic_swap_int(int *dst, int val, int *res)
{
int tmp;
int r;
tmp = *dst;
for (;;) {
r = atomic_cas_32(dst, tmp, val);
if (r == tmp)
break;
tmp = r;
}
*res = tmp;
}
#define atomic_swap_ptr(dst, val, res) \
atomic_swap_long((long *)dst, (long)val, (long *)res)
#endif

View File

@ -0,0 +1,243 @@
/*-
* Copyright (c) 2003 Jake Burkholder <jake@freebsd.org>.
* 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$
*/
/*
* Machine-dependent thread prototypes/definitions for the thread kernel.
*/
#ifndef _PTHREAD_MD_H_
#define _PTHREAD_MD_H_
#include <sys/kse.h>
#include <stddef.h>
#include <ucontext.h>
#define KSE_STACKSIZE 16384
int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *);
int _thr_getcontext(mcontext_t *);
#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext)
#define THR_SETCONTEXT(ucp) _thr_setcontext(&(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? */
/*
* %g6 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.
*
* XXX - Both static and dynamic allocation of any of these structures
* will result in a valid, well-aligned thread pointer???
*/
struct sparc64_tp {
struct tdv *tp_tdv; /* dynamic TLS */
uint64_t _reserved_;
long double tp_tls[0]; /* static TLS */
};
struct tcb {
struct pthread *tcb_thread;
void *tcb_addr; /* allocated tcb address */
struct kcb *tcb_curkcb;
uint64_t tcb_isfake;
uint64_t tcb_spare[4];
struct kse_thr_mailbox tcb_tmbx; /* needs 64-byte alignment */
struct sparc64_tp tcb_tp;
} __aligned(64);
struct kcb {
struct kse_mailbox kcb_kmbx;
struct tcb kcb_faketcb;
struct tcb *kcb_curtcb;
struct kse *kcb_kse;
};
register struct sparc64_tp *_tp __asm("%g6");
#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. */
_tp = &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;
_tp = &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 _sparc64_enter_uts(kse_func_t uts, struct kse_mailbox *km, void *stack,
size_t stacksz);
static __inline int
_thread_enter_uts(struct tcb *tcb, struct kcb *kcb)
{
if (_thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext) == 0) {
/* Make the fake tcb the current thread. */
kcb->kcb_curtcb = &kcb->kcb_faketcb;
_tp = &kcb->kcb_faketcb.tcb_tp;
_sparc64_enter_uts(kcb->kcb_kmbx.km_func, &kcb->kcb_kmbx,
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)
{
mcontext_t *mc;
_tcb_set(kcb, tcb);
mc = &tcb->tcb_tmbx.tm_context.uc_mcontext;
if (setmbox)
_thr_setcontext(mc, (intptr_t)&tcb->tcb_tmbx,
(intptr_t *)&kcb->kcb_kmbx.km_curthread);
else
_thr_setcontext(mc, 0, NULL);
/* We should not reach here. */
return (-1);
}
#endif /* _PTHREAD_MD_H_ */

View File

@ -0,0 +1,13 @@
/*
* Offsets into structures used from asm. Must be kept in sync with
* appropriate headers.
*
* $FreeBSD$
*/
#define UC_MCONTEXT 0x40
#define MC_GLOBAL 0x0
#define MC_OUT 0x40
#define MC_TPC 0xc8
#define MC_TNPC 0xc0

View File

@ -0,0 +1,88 @@
/*-
* Copyright (C) 2003 Jake Burkholder <jake@freebsd.org>
* Copyright (C) 2003 David Xu <davidxu@freebsd.org>
* Copyright (c) 2001,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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include "pthread_md.h"
struct tcb *
_tcb_ctor(struct pthread *thread)
{
struct tcb *tcb;
void *addr;
addr = malloc(sizeof(struct tcb) + 63);
if (addr == NULL)
tcb = NULL;
else {
tcb = (struct tcb *)(((uintptr_t)(addr) + 63) & ~63);
bzero(tcb, sizeof(struct tcb));
tcb->tcb_addr = addr;
tcb->tcb_thread = thread;
/* XXX - Allocate tdv/tls */
}
return (tcb);
}
void
_tcb_dtor(struct tcb *tcb)
{
void *addr;
addr = tcb->tcb_addr;
tcb->tcb_addr = NULL;
free(addr);
}
struct kcb *
_kcb_ctor(struct kse *kse)
{
struct kcb *kcb;
kcb = malloc(sizeof(struct kcb));
if (kcb != NULL) {
bzero(kcb, sizeof(struct kcb));
kcb->kcb_kse = kse;
}
return (kcb);
}
void
_kcb_dtor(struct kcb *kcb)
{
free(kcb);
}

View File

@ -0,0 +1,85 @@
/*-
* Copyright (C) 2003 Jake Burkholder <jake@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.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include "assym.s"
.weak CNAME(_thr_getcontext)
.set CNAME(_thr_getcontext),CNAME(__thr_getcontext)
ENTRY(__thr_getcontext)
add %o7, 8, %o1
add %o1, 4, %o2
stx %sp, [%o0 + MC_OUT + (6 * 8)]
stx %o1, [%o0 + MC_TPC]
stx %o2, [%o0 + MC_TNPC]
mov 1, %l0 # Validate the context.
stx %l0, [%o0 + MC_GLOBAL]
retl
nop
END(__thr_getcontext)
.weak CNAME(_thr_setcontext)
.set CNAME(_thr_setcontext),CNAME(__thr_setcontext)
ENTRY(__thr_setcontext)
save %sp, -CCFSZ, %sp
flushw
mov %i0, %l0
mov %i1, %l1
mov %i2, %l2
ldx [%l0 + MC_GLOBAL + (1 * 8)], %g1
ldx [%l0 + MC_GLOBAL + (2 * 8)], %g2
ldx [%l0 + MC_GLOBAL + (3 * 8)], %g3
ldx [%l0 + MC_GLOBAL + (4 * 8)], %g4
ldx [%l0 + MC_GLOBAL + (5 * 8)], %g5
ldx [%l0 + MC_GLOBAL + (6 * 8)], %g6
ldx [%l0 + MC_GLOBAL + (7 * 8)], %g7
ldx [%l0 + MC_OUT + (0 * 8)], %i0
ldx [%l0 + MC_OUT + (1 * 8)], %i1
ldx [%l0 + MC_OUT + (2 * 8)], %i2
ldx [%l0 + MC_OUT + (3 * 8)], %i3
ldx [%l0 + MC_OUT + (4 * 8)], %i4
ldx [%l0 + MC_OUT + (5 * 8)], %i5
ldx [%l0 + MC_OUT + (6 * 8)], %i6
ldx [%l0 + MC_OUT + (7 * 8)], %i7
ldx [%l0 + MC_TPC], %l4
ldx [%l0 + MC_TNPC], %l3
brz %l2, 1f
nop
stx %l1, [%l2]
1: jmpl %l3, %g0
return %l4
END(__thr_setcontext)
ENTRY(_sparc64_enter_uts)
save %sp, -CCFSZ, %sp
flushw
add %i2, %i3, %i2
sub %i2, SPOFF + CCFSZ, %sp
jmpl %i1, %g0
mov %i0, %o0
END(_sparc64_enter_uts)

View File

@ -0,0 +1,5 @@
# $FreeBSD$
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/${MACHINE_ARCH}
SRCS+= pthread_md.c thr_getcontext.S

View File

@ -0,0 +1,75 @@
/*-
* Copyright (c) 2003 Jake Burkholder <jake@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_
#include <machine/atomic.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)
{
long tmp;
long r;
tmp = *dst;
for (;;) {
r = atomic_cas_64(dst, tmp, val);
if (r == tmp)
break;
tmp = r;
}
*res = tmp;
}
static __inline void
atomic_swap_int(int *dst, int val, int *res)
{
int tmp;
int r;
tmp = *dst;
for (;;) {
r = atomic_cas_32(dst, tmp, val);
if (r == tmp)
break;
tmp = r;
}
*res = tmp;
}
#define atomic_swap_ptr(dst, val, res) \
atomic_swap_long((long *)dst, (long)val, (long *)res)
#endif

View File

@ -0,0 +1,243 @@
/*-
* Copyright (c) 2003 Jake Burkholder <jake@freebsd.org>.
* 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$
*/
/*
* Machine-dependent thread prototypes/definitions for the thread kernel.
*/
#ifndef _PTHREAD_MD_H_
#define _PTHREAD_MD_H_
#include <sys/kse.h>
#include <stddef.h>
#include <ucontext.h>
#define KSE_STACKSIZE 16384
int _thr_setcontext(mcontext_t *, intptr_t, intptr_t *);
int _thr_getcontext(mcontext_t *);
#define THR_GETCONTEXT(ucp) _thr_getcontext(&(ucp)->uc_mcontext)
#define THR_SETCONTEXT(ucp) _thr_setcontext(&(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? */
/*
* %g6 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.
*
* XXX - Both static and dynamic allocation of any of these structures
* will result in a valid, well-aligned thread pointer???
*/
struct sparc64_tp {
struct tdv *tp_tdv; /* dynamic TLS */
uint64_t _reserved_;
long double tp_tls[0]; /* static TLS */
};
struct tcb {
struct pthread *tcb_thread;
void *tcb_addr; /* allocated tcb address */
struct kcb *tcb_curkcb;
uint64_t tcb_isfake;
uint64_t tcb_spare[4];
struct kse_thr_mailbox tcb_tmbx; /* needs 64-byte alignment */
struct sparc64_tp tcb_tp;
} __aligned(64);
struct kcb {
struct kse_mailbox kcb_kmbx;
struct tcb kcb_faketcb;
struct tcb *kcb_curtcb;
struct kse *kcb_kse;
};
register struct sparc64_tp *_tp __asm("%g6");
#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. */
_tp = &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;
_tp = &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 _sparc64_enter_uts(kse_func_t uts, struct kse_mailbox *km, void *stack,
size_t stacksz);
static __inline int
_thread_enter_uts(struct tcb *tcb, struct kcb *kcb)
{
if (_thr_getcontext(&tcb->tcb_tmbx.tm_context.uc_mcontext) == 0) {
/* Make the fake tcb the current thread. */
kcb->kcb_curtcb = &kcb->kcb_faketcb;
_tp = &kcb->kcb_faketcb.tcb_tp;
_sparc64_enter_uts(kcb->kcb_kmbx.km_func, &kcb->kcb_kmbx,
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)
{
mcontext_t *mc;
_tcb_set(kcb, tcb);
mc = &tcb->tcb_tmbx.tm_context.uc_mcontext;
if (setmbox)
_thr_setcontext(mc, (intptr_t)&tcb->tcb_tmbx,
(intptr_t *)&kcb->kcb_kmbx.km_curthread);
else
_thr_setcontext(mc, 0, NULL);
/* We should not reach here. */
return (-1);
}
#endif /* _PTHREAD_MD_H_ */

View File

@ -0,0 +1,13 @@
/*
* Offsets into structures used from asm. Must be kept in sync with
* appropriate headers.
*
* $FreeBSD$
*/
#define UC_MCONTEXT 0x40
#define MC_GLOBAL 0x0
#define MC_OUT 0x40
#define MC_TPC 0xc8
#define MC_TNPC 0xc0

View File

@ -0,0 +1,88 @@
/*-
* Copyright (C) 2003 Jake Burkholder <jake@freebsd.org>
* Copyright (C) 2003 David Xu <davidxu@freebsd.org>
* Copyright (c) 2001,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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include "pthread_md.h"
struct tcb *
_tcb_ctor(struct pthread *thread)
{
struct tcb *tcb;
void *addr;
addr = malloc(sizeof(struct tcb) + 63);
if (addr == NULL)
tcb = NULL;
else {
tcb = (struct tcb *)(((uintptr_t)(addr) + 63) & ~63);
bzero(tcb, sizeof(struct tcb));
tcb->tcb_addr = addr;
tcb->tcb_thread = thread;
/* XXX - Allocate tdv/tls */
}
return (tcb);
}
void
_tcb_dtor(struct tcb *tcb)
{
void *addr;
addr = tcb->tcb_addr;
tcb->tcb_addr = NULL;
free(addr);
}
struct kcb *
_kcb_ctor(struct kse *kse)
{
struct kcb *kcb;
kcb = malloc(sizeof(struct kcb));
if (kcb != NULL) {
bzero(kcb, sizeof(struct kcb));
kcb->kcb_kse = kse;
}
return (kcb);
}
void
_kcb_dtor(struct kcb *kcb)
{
free(kcb);
}

View File

@ -0,0 +1,85 @@
/*-
* Copyright (C) 2003 Jake Burkholder <jake@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.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include "assym.s"
.weak CNAME(_thr_getcontext)
.set CNAME(_thr_getcontext),CNAME(__thr_getcontext)
ENTRY(__thr_getcontext)
add %o7, 8, %o1
add %o1, 4, %o2
stx %sp, [%o0 + MC_OUT + (6 * 8)]
stx %o1, [%o0 + MC_TPC]
stx %o2, [%o0 + MC_TNPC]
mov 1, %l0 # Validate the context.
stx %l0, [%o0 + MC_GLOBAL]
retl
nop
END(__thr_getcontext)
.weak CNAME(_thr_setcontext)
.set CNAME(_thr_setcontext),CNAME(__thr_setcontext)
ENTRY(__thr_setcontext)
save %sp, -CCFSZ, %sp
flushw
mov %i0, %l0
mov %i1, %l1
mov %i2, %l2
ldx [%l0 + MC_GLOBAL + (1 * 8)], %g1
ldx [%l0 + MC_GLOBAL + (2 * 8)], %g2
ldx [%l0 + MC_GLOBAL + (3 * 8)], %g3
ldx [%l0 + MC_GLOBAL + (4 * 8)], %g4
ldx [%l0 + MC_GLOBAL + (5 * 8)], %g5
ldx [%l0 + MC_GLOBAL + (6 * 8)], %g6
ldx [%l0 + MC_GLOBAL + (7 * 8)], %g7
ldx [%l0 + MC_OUT + (0 * 8)], %i0
ldx [%l0 + MC_OUT + (1 * 8)], %i1
ldx [%l0 + MC_OUT + (2 * 8)], %i2
ldx [%l0 + MC_OUT + (3 * 8)], %i3
ldx [%l0 + MC_OUT + (4 * 8)], %i4
ldx [%l0 + MC_OUT + (5 * 8)], %i5
ldx [%l0 + MC_OUT + (6 * 8)], %i6
ldx [%l0 + MC_OUT + (7 * 8)], %i7
ldx [%l0 + MC_TPC], %l4
ldx [%l0 + MC_TNPC], %l3
brz %l2, 1f
nop
stx %l1, [%l2]
1: jmpl %l3, %g0
return %l4
END(__thr_setcontext)
ENTRY(_sparc64_enter_uts)
save %sp, -CCFSZ, %sp
flushw
add %i2, %i3, %i2
sub %i2, SPOFF + CCFSZ, %sp
jmpl %i1, %g0
mov %i0, %o0
END(_sparc64_enter_uts)