Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 May 1995 23:06:22 -0700
From:      William Maddox <maddox@CS.Berkeley.EDU>
To:        Tatu Ylonen <ylo@fx7.cs.hut.fi>
Cc:        freebsd-bugs@freefall.cdrom.com, maddox@redwood.CS.Berkeley.EDU
Subject:   Re: i386/395: CRITICAL PROBLEM: spl functions implemented incorrectly 
Message-ID:  <199505120606.XAA13119@redwood.CS.Berkeley.EDU>
In-Reply-To: Your message of "Thu, 11 May 1995 16:40:02 PDT." <199505112340.QAA19464@freefall.cdrom.com> 

next in thread | previous in thread | raw e-mail | index | archive | help

You recently reported a bug in "spl.h" :

>	Spl functions (splbio, splclock, splhigh, splimp, splnet,
>	splsoftclock, splsofttty, splstatclock, spltty, spl0, splx)
>	are defined in /usr/src/sys/i386/include/spl.h as inline
>	functions that modify the ordinary variable cpl (extern
>	unsigned cpl in the same header).
>
>	This means that the compiler has full knowledge about the
>	semantics, side-effects, and dependencies of these functions.
>	The compiler inlines these functions, and can mix (reorder) the
>	resulting code with other code in the function that calls the
>	spl function.

	...
>Fix:
	...

>	i386/include/spl.h:
>	  - Move the GENSPL macro and its uses, and spl0 and splx to
>	    i386/386/sys_machdep.c.  Edit the macro and functions to
>	    make them normal non-static, non-inline functions.
       ....



I think there is another potential problem lurking in spl.h, in the following:

	/*
	 * ipending has to be volatile so that it is read every time it is accessed
	 * in splx() and spl0(), but we don't want it to be read nonatomically when
	 * it is changed.  Pretending that ipending is a plain int happens to give
	 * suitable atomic code for "ipending |= constant;".
	*/
	#define	setdelayed()	(*(unsigned *)&ipending |= loadandclear(&idelayed))
	#define	setsoftast()	(*(unsigned *)&ipending |= SWI_AST_PENDING)
	#define	setsoftclock()	(*(unsigned *)&ipending |= SWI_CLOCK_PENDING)
	#define	setsoftnet()	(*(unsigned *)&ipending |= SWI_NET_PENDING)
	#define	setsofttty()	(*(unsigned *)&ipending |= SWI_TTY_PENDING)

I assume that the remark above regarding "suitable atomic code" means
that the bits are set in place in memory, using a single instruction.
Just because GCC happens to do this today doesn't mean it will tomorrow.
As the internal execution mechanisms of new-generation x86 processors become 
more heavily parallel and RISC-like, instruction sequences involving 
architecturally
unnecessary register temporaries may turn out to be faster.  I wouldn't bet on 
the stability
of a compiler's choice of instructions in future releases, and I doubt that 
anyone is
going to check this each time a new version of GCC is integrated into FreeBSD.

I would suggest defining these functions as in-line assembly-language 
functions.
In any case, this is the sort of thing that should be done in assembler, not C.

--Bill




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199505120606.XAA13119>