Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Oct 1995 13:09:46 -0700 (MST)
From:      Terry Lambert <terry@lambert.org>
To:        bde@zeta.org.au (Bruce Evans)
Cc:        bde@zeta.org.au, terry@lambert.org, CVS-commiters@freefall.freebsd.org, bde@freefall.freebsd.org, cvs-sys@freefall.freebsd.org, hackers@freebsd.org, swallace@ece.uci.edu
Subject:   Re: SYSCALL IDEAS [Was: cvs commit: src/sys/kern sysv_msg.c sysv_sem.c sysv_shm.c]
Message-ID:  <199510272009.NAA23809@phaeton.artisoft.com>
In-Reply-To: <199510271903.FAA24658@godzilla.zeta.org.au> from "Bruce Evans" at Oct 28, 95 05:03:48 am

next in thread | previous in thread | raw e-mail | index | archive | help
> >What wall time differentials do you expect from the conversion, and
> >why?
> 
> Small.  The current unportable code is close to optimal.  I wouldn't
> make it slower.  The machine generated code for the current FreeBSD
> i386 ABI might even be exactly the same as now because all conversions
> can be reduced to no-ops (this must be possible because the unportable
> code actually works).

The reason for my asking was to determine if you believed this to be
a speed optimization (which I might be able to get behind) or if it's
simply an interface change (which I suspected it was, and so it's
now an issue of whether it's gratuitious or if ti really buys something).

[ ... reordered for coherency ... ]

> >#pragma.  If we are talking about compiler modifications, packing #pragma's
> >are much more generally useful than register call wrappings and the
> >internal code you have suggested for varargs.
> 
> All #pragmas are unportable.

All packing assumptions are unportable.  I argue that a #pragma beats
the __attrib crap because a compiler may ignore it.


> Conceptually it's a different layer but it shouldn't be implemented as
> a separate layer.  My idea is to introduce such a conceptual layer
> somewhere between the syscall entry point (Xsyscall()) and the syscall
> implementing functions (e.g., read()) and then merge the layers as
> much as possible using machine-generated code.

[ ...]

> >What is your wrapper for open( const char *, int, ...)?
> 
> On the user side (so that the open syscall doesn't have a variable number
> of args:
> 
> int open(char const *path, int flags, ...)

Whoah.  Right there we have a problem.  I'll be happy to give you my
varrarg macros to make them ANSI-C and K&R C independent.  Usign varrargs
in an ANSI dependent fashion reduces portability to non-ANIC-C envirnments.

The things belong in ctypes.h anyway.

[ ... ]

> int open(char const *path, int flags, ...)
> {
>     va_list argp;
>     int retval;
> 
>     va_start(argp, flags);
>     if (flags & O_CREAT) {
> 	promoted_mode_t mode;
> 	registered_mode_t rmode;
> 
> 	mode = va_arg(argp, int);
> 	rmode = = (registered_mode_t)mode;
> 	retval = three_arg_open_syscall(path, flags, rmode);
>     } else
> 	retval = two_arg_open_syscall(path, flags);
>     va_end(argp);
>     return retval;
> }

I think that the system call itself could make the decision based on the
O_CREAT itself.  I'd suggest changing:

> 	retval = three_arg_open_syscall(path, flags, rmode);
>     } else
> 	retval = two_arg_open_syscall(path, flags);

to:

> 	retval = three_arg_open_syscall(path, flags, rmode);
>     } else
> 	retval = three_arg_open_syscall(path, flags, 0);


[ ... ]

> On the kernel side: I can't write it without knowing the target machine.
> Assuming a simple case where the user side stored the args in a uniform
> way on the stack or in registers and the lower level kernel code has
> copied the args from to memory:

[ ... ]

>     path = *(char const *)((char *)argp + PATH_OFFSET);
>     flags = *(int *)((char *)argp + FLAGS_OFFSET);
> 	mode = *(promoted_mode_t *)((char *)argp + MODE_OFFSET);

Forgive me... but this is butt-ugly.  I mean really, *really* butt-ugly.

I find this horribly obfucated.  This is exactly what I feared when I
objected.  8-(.

BTW: the 'path' line is broken... "*(const char **)", maybe?

Since the stack variable assigns are based on an entry argument, then
the assignments can be done at declaration time.  Therefore something
like:

#define	ARG(argtype,arg)						\
	argtype arg = *(__CONCAT(argtype,*))((char *)argp +		\
		      __CONCAT(arg,_OFFSET));

	

Then:

> int syscall_entry_open(struct proc *p, void *argp, int *retval)
> {
>     ARG( char const *,	PATH);
>     ARG( int,			FLAGS);
>     ARG( promoted_mode_t,	MODE);
>
>     if (flags & O_CREAT) {
>       return open(p, retval, PATH, FLAGS, MODE);
>     }
>     return open(p, retval, PATH, FLAGS);
> }

Would be more readable.

I don't understand why passing a bogus mode to open when O_CREAT wasn't
present would be a problem???

That is, why not:

> int syscall_entry_open(struct proc *p, void *argp, int *retval)
> {
>     ARG( char const *,	PATH);
>     ARG( int,			FLAGS);
>     ARG( promoted_mode_t,	MODE);
>
>     return open(p, retval, PATH, FLAGS, MODE);
> }

???

Hell:

#define	SYSCALL_ENTRY(function)						\
	int __CONCAT(syscall_entry_,function)				\
			(struct proc *p, void *argp, int *retval)

> SYSCALL_ENTRY(open)
> {
>     ARG( char const *,	PATH);
>     ARG( int,			FLAGS);
>     ARG( promoted_mode_t,	MODE);
>
>     return open(p, retval, PATH, FLAGS, MODE);
> }


> >What about non-native architecture ABI support?
> 
> It requires more code to generate the conversion code.  In particular,
> sizeof() and `struct' can't be used, because the non-native compiler
> may have completely different behaviour (of course, it's not practical
> to emulate a machine with a larger address space or ints larger than
> your quads).

I agree with the practicality argument: after all, that's exactly what
we are doing already with lseek, et al.  8-).

I know the XDR aspects re structure packing are an issue, though since
you seem to be assuming the same compiler source everywhere (GCC),
I don't see where a packing paragma would be more of an issue than
any other approach requiring compiler modifications.


> >By going to a register passing mechanism, you destroy this, and complicate
> >the non-native ABI's at the same time... don't you see this as well?
> 
> The register passing mechanism for syscalls is a side issue.  I only
> mentioned it as an example of an ABI that we have to emulate (for Linux)
> and which is better so we should use it.  There would be no new
> complications (except for improvements) because we already support the
> Linux ABI.

I'm glad to see this.  I think, though, the rationale for the changes
still hasn't been clarified.


> >??? If it's not required, then either you *aren't* talking about passing
> >arguments to system calls in registers *or* you expect the compiler to
> >"do the right thing" magically.
> 
> I'm talking about the requirement in C to pass parameters of the correct
> type (if a prototype is in scope, then there are more correct types).

OK.  I buy this too.

But this implies that if there is not a prototype in scope, a function
that uses a type that is not correct without a prototype in scope should
not generate a bogus call reference.

This was my point on the quad crap and reverting the default interfaces
to POSIX compliance (and double doesn't count unless you can use it
without a prototype in scope).


> >Right now I can write code that makes system calls in assembly.  With
> >register passing conventions, I will need to either use library or
> >machine generated external routine calls (unacceptable), or I will have
> >to have documentation of what the compiler has done so that I can do
> >the same thing (non-portable as hell -- ever use M4 to write machine
> >independent assembly code?).
> 
> It's always been necessary to know what what the compiler does if you
> write glue functions in assembler.  (gcc) inline assembler has many
> advantages here.  You don't need to know what the compiler does (you
> just tell it how to load syscall args), and one layer of glue can be
> avoided.

But *lord*!  Having to happen to know what register the argument goes
into before the call!

> >> >Note that prototypes of system calls screw up your ability to properly
> >> >utilize the syscall(2) call gate mechanism the way it was intended.  A
> >> 
> >> The use of syscall() in general requires handling all the messy conversion
> >> issues that we have been discussing in your own code.
> 
> >Why is that?  A push is a push.  A trap is a trap.
> 
> >The only "messy conversion" is in pushing the arguments on the stack,
> >and I still fail to see the benefit of playing "keep up with Linux"
> >in this regard.
> 
> syscall() is written in C, so the compiler can pass args to it anywhere it
> wants.  syscall() then has the task of putting the args where the kernel
> expects them.  In general, it would have to know about all syscalls and
> do the inverse of the conversions that I'm talking about doing in the
> kernel.

Bletch.  How does Linux deal with it (my linux box is running Win95
right now)?


> Consider a 68K compiler that passes the first 2 pointer args (if any)
> in a0-a1 and the first 2 integer args (if any) in d0-d1 and the other
> args on the stack.  How are you going to push the args in syscall()?
> Hint: you'll need to know the arg types of all syscalls.

That's an evil way to pass arguments, then.  8-(.

> >> (2) choose a different violation of the ANSI C
> >> >and POSIX standards -- interface extension -- instead of passing quad's
> >> 
> >> POSIX allows most reasonable extensions.
> 
> >Yeah, well using quad for off_t isn't one of them.
> 
> Would you prefer double?  Allowing it seems to be a bug in POSIX.1-1990.
> More things would break.

No.  I'd prefer int/long.

> It's worse than that.  Linux doesn't have quads.  Applications have to use
> pairs of longs and do their own (equivalent to quad) arithmetic on them.
> So ifdefs like the above all through the code might be necessary.

Linux has GCC.  Linux has quads.

> We're in violent agreement :-).  I'd like to hide the current
> unportabilities and scattered casts in a conceptually simple layer.

I agree.

> This requires a complicated and unportable implementation for the 
> layer.

I don't agree.  8-).


					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.



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