Subject: Re: cpufunc.h
To: John Fremlin <vii@users.sourceforge.net>
From: Richard Earnshaw <rearnsha@buzzard.freeserve.co.uk>
List: port-arm
Date: 05/31/2001 22:59:58
> set_current_stackptr is a low level primitive. Its semantics mean that
> it does lowlevel stuff. If you use it wrong, you get screwed. So
> what. Caveat emptor. 

No; caveat the poor guy who's trying to work out why the kernel no-longer 
runs correctly if built with gcc-8.7!

> (Ben Harris suggested that the compiler might
> mess with the stack with inline functions so I've turned it into a
> macro.)

Inline functions are probably no worse than macros in this context.  
Except that there is no absoulte guarantee that a function will be 
inlined; and that if it isn't and it tries to save a return value on the 
stack before executing your asm, the return sequence will jump to 
never-never land -- beware trying to build such a kernel with the 
optimizer off, since all these will happen.

> 
> Please explain in more detail the reason for which it is impossible to
> use. 

Try the following:

extern void *newstack;

my_func()
{
  printf("Running from old stack pointer\n");
  set_current_stackptr(newstack);
  printf("Running from new stack pointer: %d %d %d %d\n", 1, 2, 3, 4);
  ...
}

Nothing obviously wrong with this code, but you will almost certainly find 
one of the following three things happens (and it may change depending on 
the optimization options used when compiling):
1) the 5th argument to printf clobbers something important on your new 
stack
2) The stack underflows if it was empty (which might fault)
3) an incorrect value is printed out.

However, my objection is as much conceptual as it is based on any known 
problems that make it impossible right now.

My feeling is that you shouldn't be trying to encode something in the 
middle of a C function that fundamentally breaks the model the compiler is 
using.  A function that switches to another stack (in a non-temporary 
manner, as a subroutine might do) very definitely breaks this model.

Developing a compiler is as much about agreeing a contract between the 
compiler developer and the programmer as it is about getting good 
optimizations.  I don't think this sort of asm is something that a 
compiler developer can accept in such a contract so I (with my gcc 
developer hat on) will make no guarantees that, even if it works now, it 
will continue to work in the future with another release of the compiler.

I strongly believe that routines that want to mess with the stack in this 
way (or, for that matter, want to switch processor mode), should kept 
short and written entirely in assembler.  The only time I'll change this 
opinion is when C grows propper semantics for describing these operations 
(since I think this is unlikely to happen, I guess that means I'm unlikely 
to change my mind on this :-)

Note that this doesn't mean that I think all use of "asm" is bad.  
Disabling (temporarily of course!) interrupts is perfectly OK; as is using 
the swp instruction for semaphone type operations.  But that doesn't mean 
the feature should be abused by using it for things that just aren't 
likely to be safe -- that way lies all the problems that Linux kernel 
builds seem to have.

R.