>  some software needs fully functional per-thread %gs base address,
>  hence the diff.  limited testing shows no regressions.
>  INTR_RESTORE_SELECTORS changes include:
>   - %r11 is used to store curpcb instead of rdx that is used for
>     wrmsr and gets trashed (it's safe to use %r11 because it's
>     restored after INTR_RESTORE_SELECTORS gets called);
>
>   - MSR_KERNELGSBASE needs to be updated instead of MSR_GSBASE
>     so that we don't lose kernel gs.base stored in MSR_GSBASE
>     and swapped by the swapgs.
>
>  any objections? corrections?

>
>  Index: sys/arch/amd64/amd64/cpu.c
>  ===================================================================
>  RCS file: /home/cvs/src/sys/arch/amd64/amd64/cpu.c,v
>  retrieving revision 1.47
>  diff -u -p -r1.47 cpu.c
>  --- sys/arch/amd64/amd64/cpu.c       4 Apr 2012 18:44:22 -0000       1.47
>  +++ sys/arch/amd64/amd64/cpu.c       13 Apr 2012 15:26:51 -0000
>  @@ -682,6 +684,7 @@ cpu_init_msrs(struct cpu_info *ci)
>       wrmsr(MSR_SFMASK, PSL_NT|PSL_T|PSL_I|PSL_C);
>
>       ci->ci_cur_fsbase = 0;
>  +    ci->ci_cur_gsbase = (u_int64_t)ci;
>       wrmsr(MSR_FSBASE, 0);
>       wrmsr(MSR_GSBASE, (u_int64_t)ci);
>       wrmsr(MSR_KERNELGSBASE, 0);
>  Index: sys/arch/amd64/amd64/genassym.cf
>  ===================================================================
>  RCS file: /home/cvs/src/sys/arch/amd64/amd64/genassym.cf,v
>  retrieving revision 1.28
>  diff -u -p -r1.28 genassym.cf
>  --- sys/arch/amd64/amd64/genassym.cf 13 Apr 2011 02:49:12 -0000      1.28
>  +++ sys/arch/amd64/amd64/genassym.cf 13 Apr 2012 15:25:26 -0000
>  @@ -86,6 +86,7 @@ member     pcb_rsp
>   member      pcb_rbp
>   member      pcb_kstack
>   member      pcb_fsbase
>  +member      pcb_gsbase
>   member      pcb_onfault
>   member      pcb_fpcpu
>   member      pcb_pmap
>  @@ -100,6 +101,7 @@ member   tss_rsp0
>   struct      cpu_info
>   member      CPU_INFO_SCRATCH        ci_scratch
>   member      CPU_INFO_CUR_FSBASE     ci_cur_fsbase
>  +member      CPU_INFO_CUR_GSBASE     ci_cur_gsbase
>   member  CPU_INFO_SELF               ci_self
>   member  CPU_INFO_CPUID              ci_cpuid
>   member  CPU_INFO_APICID             ci_apicid
>  Index: sys/arch/amd64/amd64/machdep.c
>  ===================================================================
>  RCS file: /home/cvs/src/sys/arch/amd64/amd64/machdep.c,v
>  retrieving revision 1.152
>  diff -u -p -r1.152 machdep.c
>  --- sys/arch/amd64/amd64/machdep.c   13 Jan 2012 12:55:52 -0000      1.152
>  +++ sys/arch/amd64/amd64/machdep.c   12 Apr 2012 16:41:18 -0000
>  @@ -363,7 +363,7 @@ x86_64_proc0_tss_ldt_init(void)
>
>       cpu_info_primary.ci_curpcb = pcb = &proc0.p_addr->u_pcb;
>       pcb->pcb_cr0 = rcr0();
>  -    pcb->pcb_fsbase = 0;
>  +    pcb->pcb_fsbase = pcb->pcb_gsbase = 0;
>       pcb->pcb_kstack = (u_int64_t)proc0.p_addr + USPACE - 16;
>       proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_kstack - 1;
>
>  @@ -1022,6 +1022,7 @@ setregs(struct proc *p, struct exec_pack
>               fpusave_proc(p, 0);
>       p->p_md.md_flags &= ~MDP_USEDFPU;
>       p->p_addr->u_pcb.pcb_fsbase = 0;
>  +    p->p_addr->u_pcb.pcb_gsbase = 0;
>
>       tf = p->p_md.md_regs;
>       tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
>  Index: sys/arch/amd64/amd64/sys_machdep.c
>  ===================================================================
>  RCS file: /home/cvs/src/sys/arch/amd64/amd64/sys_machdep.c,v
>  retrieving revision 1.12
>  diff -u -p -r1.12 sys_machdep.c
>  --- sys/arch/amd64/amd64/sys_machdep.c       13 Apr 2011 02:49:12 -0000      
> 1.12
>  +++ sys/arch/amd64/amd64/sys_machdep.c       12 Apr 2012 16:37:30 -0000
>  @@ -159,6 +159,29 @@ amd64_set_fsbase(struct proc *p, void *a
>   }
>
>   int
>  +amd64_get_gsbase(struct proc *p, void *args)
>  +{
>  +    return copyout(&p->p_addr->u_pcb.pcb_gsbase, args,
>  +        sizeof(p->p_addr->u_pcb.pcb_gsbase));
>  +}
>  +
>  +int
>  +amd64_set_gsbase(struct proc *p, void *args)
>  +{
>  +    int error;
>  +    uint64_t base;
>  +
>  +    if ((error = copyin(args, &base, sizeof(base))) != 0)
>  +            return (error);
>  +
>  +    if (base >= VM_MAXUSER_ADDRESS)
>  +            return (EINVAL);
>  +
>  +    p->p_addr->u_pcb.pcb_gsbase = base;
>  +    return 0;
>  +}
>  +
>  +int
>   sys_sysarch(struct proc *p, void *v, register_t *retval)
>   {
>       struct sys_sysarch_args /* {
>  @@ -196,12 +219,20 @@ sys_sysarch(struct proc *p, void *v, reg
>               break;
>   #endif
>
>  -    case AMD64_GET_FSBASE:
>  +    case AMD64_GET_FSBASE:
>               error = amd64_get_fsbase(p, SCARG(uap, parms));
>               break;
>
>  -    case AMD64_SET_FSBASE:
>  +    case AMD64_SET_FSBASE:
>               error = amd64_set_fsbase(p, SCARG(uap, parms));
>  +            break;
>  +
>  +    case AMD64_GET_GSBASE:
>  +            error = amd64_get_gsbase(p, SCARG(uap, parms));
>  +            break;
>  +
>  +    case AMD64_SET_GSBASE:
>  +            error = amd64_set_gsbase(p, SCARG(uap, parms));
>               break;
>
>       default:
>  Index: sys/arch/amd64/include/cpu.h
>  ===================================================================
>  RCS file: /home/cvs/src/sys/arch/amd64/include/cpu.h,v
>  retrieving revision 1.72
>  diff -u -p -r1.72 cpu.h
>  --- sys/arch/amd64/include/cpu.h     4 Apr 2012 18:44:22 -0000       1.72
>  +++ sys/arch/amd64/include/cpu.h     13 Apr 2012 15:25:13 -0000
>  @@ -73,6 +73,7 @@ struct cpu_info {
>
>       u_int64_t ci_scratch;
>       u_int64_t ci_cur_fsbase;
>  +    u_int64_t ci_cur_gsbase;
>
>       struct proc *ci_fpcurproc;
>       struct proc *ci_fpsaveproc;
>  Index: sys/arch/amd64/include/frameasm.h
>  ===================================================================
>  RCS file: /home/cvs/src/sys/arch/amd64/include/frameasm.h,v
>  retrieving revision 1.6
>  diff -u -p -r1.6 frameasm.h
>  --- sys/arch/amd64/include/frameasm.h        4 Jul 2011 15:54:24 -0000       
> 1.6
>  +++ sys/arch/amd64/include/frameasm.h        13 Apr 2012 19:15:51 -0000
>  @@ -56,16 +56,16 @@
>
>   /*
>    * Restore %ds, %es, %fs, and %gs, dealing with the FS.base MSR for
>  - * %fs and doing the cli/swapgs for %gs.  Uses %rax, %rcx, and %rdx
>  + * %fs and doing the cli/swapgs for %gs.  Uses %rax, %rcx, %rdx and %r11
>    */
>   #define INTR_RESTORE_SELECTORS                                              
> \
>  -    movq    CPUVAR(CURPCB),%rdx     /* for below */                 ; \
>  +    movq    CPUVAR(CURPCB),%r11     /* for below */                 ; \
>       /* %es and %ds */                                                 \
>       movw    TF_ES(%rsp),%es                                         ; \
>       movw    $(GSEL(GUDATA_SEL, SEL_UPL)),%ax                        ; \
>       movw    %ax,%ds                                                 ; \
>       /* Make sure both %fs and FS.base are the desired values */       \
>  -    movq    PCB_FSBASE(%rdx),%rax                                   ; \
>  +    movq    PCB_FSBASE(%r11),%rax                                   ; \
>       cmpq    $0,%rax                                                 ; \
>       jne     96f                                                     ; \
>       movw    TF_FS(%rsp),%fs /* zero FS.base by setting %fs */       ; \
>  @@ -81,7 +81,20 @@
>       movl    $MSR_FSBASE,%ecx                                        ; \
>       wrmsr                                                           ; \
>   98: movq    %rax,CPUVAR(CUR_FSBASE)                                 ; \
>  -99: cli             /* %fs done, so swapgs and do %gs */            ; \
>  +99: /* Make sure GS.base is reset */                                ; \
>  +    movq    PCB_GSBASE(%r11),%rax                                   ; \
>  +    cmpq    $0,%rax                                                 ; \
>  +    jne     100f                                                    ; \
>  +    movq    %rax,CPUVAR(CUR_GSBASE)                                 ; \
>  +    jmp     101f                                                    ; \
>  +100:        cmpq    CPUVAR(CUR_GSBASE),%rax                                 
> ; \
>  +    je      101f                                                    ; \
>  +    movq    %rax,CPUVAR(CUR_GSBASE)                                 ; \
>  +    movq    %rax,%rdx                                               ; \
>  +    shrq    $32,%rdx                                                ; \
>  +    movl    $MSR_KERNELGSBASE,%ecx                                  ; \
>  +    wrmsr                                                           ; \
>  +101:        cli                     /* %gs done, do swapgs */               
> ; \
>       swapgs                                                          ; \
>       movw    TF_GS(%rsp),%gs
>
>  Index: sys/arch/amd64/include/pcb.h
>  ===================================================================
>  RCS file: /home/cvs/src/sys/arch/amd64/include/pcb.h,v
>  retrieving revision 1.12
>  diff -u -p -r1.12 pcb.h
>  --- sys/arch/amd64/include/pcb.h     10 Jul 2011 18:12:03 -0000      1.12
>  +++ sys/arch/amd64/include/pcb.h     12 Apr 2012 17:28:16 -0000
>  @@ -83,18 +83,19 @@ struct pcb {
>       u_int64_t       pcb_rbp;
>       u_int64_t       pcb_kstack;     /* kernel stack address */
>       u_int64_t       pcb_fsbase;     /* per-thread offset: %fs */
>  +    u_int64_t       pcb_gsbase;     /* per-thread offset: %gs */
>       caddr_t pcb_onfault;            /* copyin/out fault recovery */
>       struct  cpu_info *pcb_fpcpu;    /* cpu holding our fp state. */
>       struct  pmap *pcb_pmap;         /* back pointer to our pmap */
>       int     pcb_cr0;                /* saved image of CR0 */
>   };
>
>  -/*
>  - * The pcb is augmented with machine-dependent additional data for
>  +/*
>  + * The pcb is augmented with machine-dependent additional data for
>    * core dumps. For the i386, there is nothing to add.
>  - */
>  + */
>   struct md_coredump {
>       long    md_pad[8];
>  -};
>  +};
>
>   #endif /* _MACHINE_PCB_H_ */
>  Index: sys/arch/amd64/include/sysarch.h
>  ===================================================================
>  RCS file: /home/cvs/src/sys/arch/amd64/include/sysarch.h,v
>  retrieving revision 1.10
>  diff -u -p -r1.10 sysarch.h
>  --- sys/arch/amd64/include/sysarch.h 13 Apr 2011 02:49:12 -0000      1.10
>  +++ sys/arch/amd64/include/sysarch.h 12 Apr 2012 20:57:34 -0000
>  @@ -16,6 +16,8 @@
>   #define     AMD64_PMC_READ          10
>   #define     AMD64_GET_FSBASE        11
>   #define     AMD64_SET_FSBASE        12
>  +#define     AMD64_GET_GSBASE        13
>  +#define     AMD64_SET_GSBASE        14
>
>   struct amd64_iopl_args {
>       int iopl;
>  @@ -67,6 +69,8 @@ struct amd64_pmc_read_args {
>   int amd64_iopl(struct proc *, void *, register_t *);
>   int amd64_set_fsbase(struct proc *, void *);
>   int amd64_get_fsbase(struct proc *, void *);
>  +int amd64_set_gsbase(struct proc *, void *);
>  +int amd64_get_gsbase(struct proc *, void *);
>   #else
>   int amd64_iopl(int);
>   int amd64_get_ioperm(u_long *);
>  @@ -76,6 +80,8 @@ int amd64_pmc_startstop(struct amd64_pmc
>   int amd64_pmc_read(struct amd64_pmc_read_args *);
>   int amd64_set_fsbase(void *);
>   int amd64_get_fsbase(void **);
>  +int amd64_set_gsbase(void *);
>  +int amd64_get_gsbase(void **);
>   int sysarch(int, void *);
>   #endif
>
>  Index: lib/libarch/amd64/Makefile
>  ===================================================================
>  RCS file: /home/cvs/src/lib/libarch/amd64/Makefile,v
>  retrieving revision 1.10
>  diff -u -p -r1.10 Makefile
>  --- lib/libarch/amd64/Makefile       13 Apr 2011 02:49:12 -0000      1.10
>  +++ lib/libarch/amd64/Makefile       13 Apr 2012 19:20:17 -0000
>  @@ -3,15 +3,17 @@
>
>   MANSUBDIR=amd64
>   MAN+=       amd64_iopl.2 amd64_get_ioperm.2 \
>  -    amd64_get_fsbase.2
>  +    amd64_get_fsbase.2 amd64_get_gsbase.2
>   MLINKS+=amd64_get_ioperm.2 amd64_set_ioperm.2 \
>  -    amd64_get_fsbase.2 amd64_set_fsbase.2
>  +    amd64_get_fsbase.2 amd64_set_fsbase.2 \
>  +    amd64_get_gsbase.2 amd64_set_gsbase.2
>
>   .if ${MACHINE_ARCH} == "amd64"
>   .PATH: ${LIBC}/amd64
>   NOPIC=
>   SRCS+=      amd64_iopl.c amd64_get_ioperm.c amd64_set_ioperm.c \
>  -    amd64_get_fsbase.c amd64_set_fsbase.c
>  +    amd64_get_fsbase.c amd64_set_fsbase.c \
>  +    amd64_get_gsbase.c amd64_set_gsbase.c
>   .include <bsd.lib.mk>
>   .else
>   NOPROG=
>  Index: lib/libarch/amd64/amd64_get_gsbase.2
>  ===================================================================
>  RCS file: lib/libarch/amd64/amd64_get_gsbase.2
>  diff -N lib/libarch/amd64/amd64_get_gsbase.2
>  --- /dev/null        1 Jan 1970 00:00:00 -0000
>  +++ lib/libarch/amd64/amd64_get_gsbase.2     13 Apr 2012 19:24:18 -0000
>  @@ -0,0 +1,87 @@
>  +.\" $OpenBSD$
>  +.\" $NetBSD: i386_get_ioperm.2,v 1.3 1996/02/27 22:57:17 jtc Exp $
>  +.\"
>  +.\" Copyright (c) 1996 The NetBSD Foundation, Inc.
>  +.\" All rights reserved.
>  +.\"
>  +.\" This code is derived from software contributed to The NetBSD
>  Foundation
>  +.\" by John T. Kohl and Charles M. Hannum.
>  +.\"
>  +.\" 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 NETBSD FOUNDATION, INC. 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 REGENTS 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.
>  +.\"
>  +.Dd $Mdocdate$
>  +.Dt AMD64_GET_GSBASE 2 amd64
>  +.Os
>  +.Sh NAME
>  +.Nm amd64_get_gsbase ,
>  +.Nm amd64_set_gsbase
>  +.Nd manage amd64 per-thread %gs base address
>  +.Sh SYNOPSIS
>  +.Fd #include <sys/types.h>
>  +.Fd #include <machine/sysarch.h>
>  +.Ft int
>  +.Fn amd64_get_gsbase "void **base"
>  +.Ft int
>  +.Fn amd64_set_gsbase "void *base"
>  +.Sh DESCRIPTION
>  +.Fn amd64_get_gsbase
>  +copies the current base address of the %gs segment into the memory
>  +referenced by
>  +.Fa base .
>  +.Pp
>  +.Fn amd64_set_gsbase
>  +sets the base address of the %gs segment to the address
>  +.Fa base .
>  +.Pp
>  +The segment base address is local to each thread.
>  +The initial thread of a new process inherits its segment base address
>  +from the parent thread.
>  +.Xr __tfork 2
>  +sets the initial segment base address for threads that it creates.
>  +.Pp
>  +.Sy Note:
>  +Code using the
>  +.Fn amd64_get_gsbase
>  +and
>  +.Fn amd64_set_gsbase
>  +functions must be compiled using
>  +.Cm -lamd64 .
>  +.Sh RETURN VALUES
>  +Upon successful completion,
>  +.Fn amd64_get_gsbase
>  +and
>  +.Fn amd64_set_gsbase
>  +return 0.
>  +Otherwise, a value of \-1 is returned and the global variable
>  +.Va errno
>  +is set to indicate the error.
>  +.Sh ERRORS
>  +.Fn amd64_get_gsbase
>  +will fail if:
>  +.Bl -tag -width [EINVAL]
>  +.It Bq Er EFAULT
>  +.Fa base
>  +points outside the process's allocated address space.
>  +.El
>  +.Sh SEE ALSO
>  +.Xr __tfork 2 ,
>  +.Xr fork 2
>  Index: lib/libarch/amd64/amd64_get_gsbase.c
>  ===================================================================
>  RCS file: lib/libarch/amd64/amd64_get_gsbase.c
>  diff -N lib/libarch/amd64/amd64_get_gsbase.c
>  --- /dev/null        1 Jan 1970 00:00:00 -0000
>  +++ lib/libarch/amd64/amd64_get_gsbase.c     13 Apr 2012 19:28:32 -0000
>  @@ -0,0 +1,15 @@
>  +/*  $OpenBSD$       */
>  +
>  +/* Public domain. Written by Mike Belopuhov <mi...@openbsd.org> */
>  +
>  +#include <sys/cdefs.h>
>  +#include <sys/types.h>
>  +
>  +#include <machine/segments.h>
>  +#include <machine/sysarch.h>
>  +
>  +int
>  +amd64_get_gsbase(void **base)
>  +{
>  +    return sysarch(AMD64_GET_GSBASE, base);
>  +}
>  Index: lib/libarch/amd64/amd64_set_gsbase.c
>  ===================================================================
>  RCS file: lib/libarch/amd64/amd64_set_gsbase.c
>  diff -N lib/libarch/amd64/amd64_set_gsbase.c
>  --- /dev/null        1 Jan 1970 00:00:00 -0000
>  +++ lib/libarch/amd64/amd64_set_gsbase.c     13 Apr 2012 19:28:19 -0000
>  @@ -0,0 +1,15 @@
>  +/*  $OpenBSD$       */
>  +
>  +/* Public domain. Written by Mike Belopuhov <mi...@openbsd.org> */
>  +
>  +#include <sys/cdefs.h>
>  +#include <sys/types.h>
>  +
>  +#include <machine/segments.h>
>  +#include <machine/sysarch.h>
>  +
>  +int
>  +amd64_set_gsbase(void *base)
>  +{
>  +    return sysarch(AMD64_SET_GSBASE, &base);
>  +}
>  Index: lib/libpthread/Makefile
>  ===================================================================
>  RCS file: /home/cvs/src/regress/lib/libpthread/Makefile,v
>  retrieving revision 1.38
>  diff -u -p -r1.38 Makefile
>  --- lib/libpthread/Makefile  13 Apr 2012 19:04:09 -0000      1.38
>  +++ lib/libpthread/Makefile  14 Apr 2012 10:27:30 -0000
>  @@ -12,6 +12,9 @@ SUBDIR= barrier blocked_close blocked_du
>       readdir restart select semaphore setjmp setsockopt sigdeliver siginfo \
>       siginterrupt signal signals signodefer sigsuspend sigwait sleep \
>       socket stack stdarg stdio switch system
>  +.if ${MACHINE_ARCH} == "amd64"
>  +SUBDIR+=amd64_set_gsbase
>  +.endif
>
>   # Not available or disabled: fcntl, getaddrinfo, pause, pw, sigmask,
>  stdfiles
>
>  Index: lib/libpthread/amd64_set_gsbase/Makefile
>  ===================================================================
>  RCS file: lib/libpthread/amd64_set_gsbase/Makefile
>  diff -N lib/libpthread/amd64_set_gsbase/Makefile
>  --- /dev/null        1 Jan 1970 00:00:00 -0000
>  +++ lib/libpthread/amd64_set_gsbase/Makefile 14 Apr 2012 10:54:33 -0000
>  @@ -0,0 +1,10 @@
>  +# $OpenBSD$
>  +
>  +PROG=       amd64_set_gsbase
>  +
>  +LIBARCH=    /usr/lib/libamd64.a
>  +
>  +LDADD+=             ${LIBARCH}
>  +DPADD+=             ${LIBARCH}
>  +
>  +.include <bsd.regress.mk>
>  Index: lib/libpthread/amd64_set_gsbase/amd64_set_gsbase.c
>  ===================================================================
>  RCS file: lib/libpthread/amd64_set_gsbase/amd64_set_gsbase.c
>  diff -N lib/libpthread/amd64_set_gsbase/amd64_set_gsbase.c
>  --- /dev/null        1 Jan 1970 00:00:00 -0000
>  +++ lib/libpthread/amd64_set_gsbase/amd64_set_gsbase.c       14 Apr 2012
>  11:25:53 -0000
>  @@ -0,0 +1,52 @@
>  +/*  $OpenBSD$       */
>  +
>  +/*
>  + * Public domain.  Written by Mike Belopuhov.
>  + *
>  + * Test amd64_set_gsbase and amd64_get_gsbase
>  + */
>  +
>  +#include <sys/types.h>
>  +#include <machine/sysarch.h>
>  +#include <pthread.h>
>  +#include <stdio.h>
>  +#include <stdlib.h>
>  +#include <unistd.h>
>  +#include "test.h"
>  +
>  +#define NTHREADS 128
>  +
>  +void *
>  +new_thread(void *arg)
>  +{
>  +    int *val = NULL;
>  +
>  +    amd64_set_gsbase(arg);
>  +
>  +    pthread_yield();
>  +    sleep(arc4random_uniform(10));
>  +    pthread_yield();
>  +
>  +    amd64_get_gsbase((void **)&val);
>  +
>  +    ASSERT(val == arg);
>  +
>  +    return (NULL);
>  +}
>  +
>  +int
>  +main(int argc, char *argv[])
>  +{
>  +    pthread_t threads[NTHREADS];
>  +    int vals[NTHREADS];
>  +    int i;
>  +
>  +    for (i = 0; i < NTHREADS; i++) {
>  +            CHECKr(pthread_create(&threads[i], NULL, new_thread,
>  +                (void *)&vals[i]));
>  +    }
>  +    for (i = 0; i < NTHREADS; i++) {
>  +            CHECKr(pthread_join(threads[i], NULL));
>  +    }
>  +    SUCCEED;
>  +}

Reply via email to