From owner-cvs-sys Fri Oct 27 15:00:32 1995 Return-Path: owner-cvs-sys Received: (from root@localhost) by freefall.freebsd.org (8.6.12/8.6.6) id PAA24570 for cvs-sys-outgoing; Fri, 27 Oct 1995 15:00:32 -0700 Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.19]) by freefall.freebsd.org (8.6.12/8.6.6) with ESMTP id PAA24532 ; Fri, 27 Oct 1995 15:00:04 -0700 Received: (from bde@localhost) by godzilla.zeta.org.au (8.6.9/8.6.9) id HAA29637; Sat, 28 Oct 1995 07:57:34 +1000 Date: Sat, 28 Oct 1995 07:57:34 +1000 From: Bruce Evans Message-Id: <199510272157.HAA29637@godzilla.zeta.org.au> To: bde@zeta.org.au, terry@lambert.org Subject: Re: SYSCALL IDEAS [Was: cvs commit: src/sys/kern sysv_msg.c sysv_sem.c sysv_shm.c] Cc: CVS-commiters@freefall.freebsd.org, bde@freefall.freebsd.org, cvs-sys@freefall.freebsd.org, hackers@freebsd.org, swallace@ece.uci.edu Sender: owner-cvs-sys@freebsd.org Precedence: bulk >> All #pragmas are unportable. >All packing assumptions are unportable. I argue that a #pragma beats >the __attrib crap because a compiler may ignore it. A compiler may exec /usr/games/hack to handle every pragma. gcc used to do this. >> 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-(. It's machine generated. It looks better than va_arg(). Don't look at it. >BTW: the 'path' line is broken... "*(const char **)", maybe? Oops. >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)); Assignment at declaration time is consider bad style by the 4.4lite2 style guide and by me. The offsets would actually be literal numbers. They are too hard to create using macros. >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); >> } The last ARG() might cause a fatal trap if the arg doesn't exist. It might be worth guaranteeing that argp points to a safe place to ARG() can't trap here. But then the caller might have to do more work to provide a safe place or recover from the trap. This is currently handled very efficiently by copyin() recovering from traps if the user doesn't supply enough args. >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); >> } This would require large table of #defines of OFFSETs. I prefer to use literal offsets. >I know the XDR aspects re structure packing are an issue, though since >you seem to be assuming the same compiler source everywhere (GCC), No, the OFFSETs depend on the compiler. I assumed the same endianness in my example, but endianness changes can be handled by more complicated ARG() code. Pointer alignment for *(foo_t *) is unlikely to be a problem because the args are usually laid out so that they can be accessed. >I don't see where a packing paragma would be more of an issue than >any other approach requiring compiler modifications. It would take about the same work to machine-generate all the pragmas and padding as to machine-generate all the offsets, e.g., #pragma pack(0) /* or whatever stops all packing */ struct read_args { char const *path; int flags; char pad1[4]; /* little endian, 4 byte ints, 8 byte regs */ mode_t mode; char pad2[6]; }; vs. #define read_path_OFFSET 0 #define read_path_type char const * #define read_flags_OFFSET 8 #define read_flags_type int #define read_mode_OFFSET 16 #define read_mode_type mode_t >> 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. `lcall' allow users to trace into syscalls. This can be recovered from but is ugly. Trap gates don't have this problem. NetBSD and Linux already use trap gates for their native system calls and we don't want to be uglier or slower than NetBSD or Linux :-). We need to support trap gates for emulation anyway. If we change to trap gates then we should consider changing other parts of the syscall interface. We don't need to copy NetBSD's or Linux's interface except for emulation. >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). if (lseek(fd, (off_t)foo, SEEK_SET) == (off_t)-1) perror("lseek"); works without a prototype in scope even if off_t is quad or double. >> 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)? i386's are enough like vaxes and gcc uses stupid enough function call conventions for there to be no problems. Just put the first arg in the first register, etc. >> 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-(. But not stupid :-). >> 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. I thought it doesn't use them for llseek. I guess it doesn't matter. Two longs together look like a quad. Bruce