Date: Wed, 10 Jan 2001 00:54:48 -0500 From: Jake Burkholder <jake@freebsd.org> To: Bruce Evans <bde@zeta.org.au> Cc: cvs-committers@FreeBSD.org, cvs-all@FreeBSD.org Subject: Re: cvs commit: src/sys/alpha/alpha interrupt.c machdep.c mp_machdep.c prom.c trap.c src/sys/dev/usb ohci.c uhci.c usbdi.c src/sys/dev/vinum vinumhdr.h vinummemory.c src/sys/i386/i386 bios.c db_interface.c machdep.c mp_machdep.c mpapic.c pmap.c ... Message-ID: <20010110055449.E3743BA7F@cr66388-a.rchrd1.on.wave.home.com> In-Reply-To: Message from Bruce Evans <bde@zeta.org.au> of "Wed, 10 Jan 2001 16:29:05 %2B1100." <Pine.BSF.4.21.0101101602240.25131-100000@besplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
>
> I wish I had objected earlier to your previous changes to prepare for
> this mistake. Machine-independent code shouldn't know that some
> variables are per-cpu. We had perfectly good access macros named
> curproc, etc. (except they weren't ifdefed right for modules). There
> is no need for function-like macros, since rvalue-like variables can
> always be implemented using macros (or [inline] functions) that return
> the value of the variable, and lvalue-like variables can always be
> implemented as `*(macro_that_returns_address_of_variable)'. This is
> what the old macros did. The `SET' macros can be more efficient in
> some cases, since they may be able to access the variable directly,
> but we currently don't do this. In fact, even the i386 `GET' macros
> have regressed from direct accesses in the %fs segment to indirect
> accesses via a pointer loaded from the %fs segment.
>
This is a matter of opinion. The reason that I like this better
than l-value like macros is that per-cpu variables don't need
the same locking as normal variables. This makes it clear that
they are per-cpu.
The way they were implemented before was difficult to understand
and difficult to maintain. It required modifications to too many
files in order to add a new variable.
I know that they could be more efficient, but these work and we
don't need h0h0 optimizations at this point.
Here is the fast version...
/*-
* Copyright (c) 1999 Luoqi Chen <luoqi@freebsd.org>
* All rights reserved.
* Copyright (c) 2000 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. 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 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: src/sys/i386/include/globals.h,v 1.15 2001/01/06 19:55:42 jake Exp $
*/
#ifndef _MACHINE_GLOBALS_H_
#define _MACHINE_GLOBALS_H_
#ifdef _KERNEL
#include <machine/globaldata.h>
#ifndef __GNUC__
#error gcc is required to use this file
#endif
/*
* Evaluates to the byte offset of the per-cpu variable name.
*/
#define __pcpu_offset(name) \
__offsetof(struct globaldata, name)
/*
* Evaluates to the type of the per-cpu variable name.
*/
#define __pcpu_type(name) \
__typeof(((struct globaldata *)0)->name)
/*
* Evaluates to the address of the per-cpu variable name.
*/
#define __PCPU_ADDR(name) ({ \
__pcpu_type(name) *__p; \
\
__asm __volatile("movl %%fs:%1,%0; addl %2,%0" \
: "=a" (__p) \
: "m" (*(struct globaldata *)(__pcpu_offset(gd_prvspace))), \
"i" (__pcpu_offset(name))); \
\
__p; \
})
/*
* Evaluates to the value of the per-cpu variable name.
*/
#define __PCPU_GET(name) ({ \
__pcpu_type(name) __result; \
\
if (sizeof(__result) == 1) { \
u_char __b; \
__asm __volatile("movb %%fs:%1,%0" \
: "=a" (__b) \
: "m" (*(u_char *)(__pcpu_offset(name)))); \
__result = *(__pcpu_type(name) *)&__b; \
} else if (sizeof(__result) == 4) { \
u_int __i; \
__asm __volatile("movl %%fs:%1,%0" \
: "=a" (__i) \
: "m" (*(u_int *)(__pcpu_offset(name)))); \
__result = *(__pcpu_type(name) *)&__i; \
} else { \
__result = *__PCPU_ADDR(name); \
} \
\
__result; \
})
/*
* Set the value of the per-cpu variable name to value val.
*/
#define __PCPU_SET(name, val) ({ \
__pcpu_type(name) __val = (val); \
\
if (sizeof(__val) == 1) { \
u_char __b; \
__b = *(u_char *)&__val; \
__asm __volatile("movb %1,%%fs:%0" \
: "=m" (*(u_char *)(__pcpu_offset(name))) \
: "a" (__b)); \
} else if (sizeof(__val) == 4) { \
u_int __i; \
__i = *(u_int *)&__val; \
__asm __volatile("movl %1,%%fs:%0" \
: "=m" (*(u_int *)(__pcpu_offset(name))) \
: "a" (__i)); \
} else { \
*__PCPU_ADDR(name) = __val; \
} \
})
#define PCPU_ADDR(member) __PCPU_ADDR(gd_ ## member)
#define PCPU_GET(member) __PCPU_GET(gd_ ## member)
#define PCPU_SET(member, val) __PCPU_SET(gd_ ## member, val)
#define CURPROC PCPU_GET(curproc)
#define CURTHD PCPU_GET(curproc)
#define GLOBALDATA PCPU_GET(prvspace)
#define curproc PCPU_GET(curproc)
#endif /* _KERNEL */
#endif /* !_MACHINE_GLOBALS_H_ */
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe cvs-all" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010110055449.E3743BA7F>
