Skip site navigation (1)Skip section navigation (2)
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>