Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Oct 1995 07:57:12 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        bde@zeta.org.au, terry@lambert.org
Cc:        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:  <199510242157.HAA01465@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>OK.  I hate leaving all of the above in for context, but I have to.

I left it out to stop the context expanding forever :-).

>The disadvantage you cite is false.  Internal kernel calls to read
>do not follow the same rules on inlining.  The inlining is to

They can do whatever is convenient.

>The problem seems to be one of understanding trap vector argument
>decodes.

>When a system call is made, arguments are pushed on the user stack
>and then the trap vector is called.  There is a necessity to copy
>the arguments as if they were on the stack down to a kernel space
>buffer area because of the address space differences.  The amount
>that is copied is determined by an integer count of integers: that
>is, it is some number 'n' * sizeof(int) bytes that get copied.

Only in some ABI's.  This is probably the best way, but it may
requires messy conversions in the library to put the args on the
stack with consistent padding.

Since we don't control foreign ABI's we shouldn't assume this.  For
example, in Linux all the args are passed in registers.  In Minix,
the args are stored in a syscall-dependent struct and a pointer
to the struct is passed in %ebx.  The struct is not always nicely
padded (it can have packed char and short fields).

>This is dependent on the arguments pushed on the stack being
>representable as integer values (we are guaranteed this by the
>fact that we are calling a non-local function that is not inlined).

There is no such guarantee.  gcc for the i386 happens to use this
slow parameter passing convention for portability.  (Unless you
compile with -mregparm.  -mregparm is officially supported in gcc-2.7.0.
It is apparently necessary for OS/2 or Windows-NT.)

>[copyin() of the args]
>Now each of the arguments are themselves, potentially, pointers to
>additional information in call/subcode specific user space structures
>that must, additionally be copied in (or out to).

Not quite.  The args may be padded.  In NetBSD for the alpha, the args
are apparently padded to 8 bytes and the SCARG macro is mainly to
extract the relevant subfield which is usually 4 bytes.  There may be
complications for endianness.

>While BSD could very well benefit from a single verification, avoiding
>the mapping issues in copyin/copyout, giving one check instead of two

It could benefit most from passing args in registers, as in Linux, so
that no copyin() is required.

>What does it do?  What use is the change?

It avoids scattering unportable casts and ugly macros to perform them
throughout the "machine-independent" code.  Now we have only unportable
casts.  4.4lite2 has slightly less unportable casts and ugly macros.
NetBSD has much less unportable casts and ugly macros.

>If we are trying for this small an incremental improvement, I suggest
>spending coding time on getting callee pop working within the kernel
>code.  It would be a much higher gain for less effort.

That will work when I get everything prototyped properly.  Prototyping
syscalls is one of the easiest parts.

>It's very arguable that the compiler would generate incorrectly window
>optimized code for inlined system calls at present.  Specifically,
>it would fail to see the need to push the arguments.

Earth to Terry :-).  We're talking about inlining syscall handlers, not
syscalls.

>> No.  Varargs syscalls such as open(), fcntl() and shmsys() mess up the
>> ABI.  The args for them have to be copied from different places depending
>> on codes in the early args.  syscall() currently assumes that the args
>> are on the stack in user space and copies more args than are necessary
>> and sometimes more than are officially supplied.  Varargs for syscall
>> xxx should handled by fetching them from the appropriate place in
>> foo_os_syscall_entry_xxx() and passing them in the normal varargs way
>> to xxx().

>This is incorrect.  The argument count specified in the systent[] table
>should result in the correct copyin size.

There may be no correct size.  A size of 3 ints wouldn't work for
open("foo", 0) if the caller has perversely passed 2 args on the stack
at the top of the address space.  Where are the ABI specs that disallow
this?

Also, a single number doesn't tell you where the args are.  In general
you need an offset and a size for each arg on the user stack (let's not
worry about endianness conversions :-) and a mapping of user registers
to args.

>> No, this (not syscalls #220-231) is yucky.  Multiplexing syscalls
>> takes more code to handle even incorrectly like it does now.

>The amount of code is a single computed goto.  One might as well

Not if there are nontrivial conversions.

>What portability problems do you see in the system call multiplex
>interfaces, and under what circumstances can you cause incorrect code
>to be generated?

A reasonable parameter passing convention should put the first few
args (a fixed number) in registers but stop at the first `...' arg or
the one before (so a variable number of args may be in registers.
Where are you going to translate this?  Portability problems would
result from delaying the translation.  Incorrect code would be generated,
as usual, due to bugs.

>> They are a problem because they give more special cases to write code for.

>As opposed to generating code?  I don't see less total code in the long
>run, and applying a cookie cutter and forcing all the calls to fit the
>mold is not an optimal approach to solving the problem.

Er, isn't the array of args a mold?  I want to make args in the kernel
fit the same molds as args in user space:

	int open(path, flags, ...)

is a completely different mold from

	int open(path, flags, mode) 

For the former, the compiler should use a special, slow parameter passing
convention and pop the args in the caller.  For the latter, the compiler
should pass at least the first one or two args in registers and pop the
args in the callee.

Bruce



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