On Tue, 13 Feb 2007, Davide Libenzi wrote:
> > > I can understand that chaining syscalls requires variable sharing, but
> > > the majority of the parameters passed to syscalls are just direct
> > > ones. Maybe a smart method that allows you to know if a parameter is a
> > > direct one or a pointer to one? An "unsigned int pmap" where bit N is
> > > 1 if param N is an indirection? Hmm?
> >
> > adding such things tends to slow down atom parsing.
>
> I really think it simplifies it. You simply *copy* the parameter (I'd say
> that 70+% of cases falls inside here), and if the current "pmap" bit is
> set, then you do all the indirection copy-from-userspace stuff.
> It also simplify userspace a lot, since you can now pass arrays and
> structure pointers directly, w/out saving them in a temporary variable.
Very rough sketch below ...
---
struct syslet_uatom {
unsigned long flags;
unsigned int nr;
unsigned short nparams;
unsigned short pmap;
long __user *ret_ptr;
struct syslet_uatom __user *next;
unsigned long __user args[6];
void __user *private;
};
long copy_uatom(struct syslet_atom *atom, struct syslet_uatom __user *uatom)
{
unsigned short i, pmap;
unsigned long __user *arg_ptr;
long ret = 0;
if (!access_ok(VERIFY_WRITE, uatom, sizeof(*uatom)))
return -EFAULT;
ret = __get_user(atom->nr, &uatom->nr);
ret |= __get_user(atom->nparams, &uatom->nparams);
ret |= __get_user(pmap, &uatom->pmap);
ret |= __get_user(atom->ret_ptr, &uatom->ret_ptr);
ret |= __get_user(atom->flags, &uatom->flags);
ret |= __get_user(atom->next, &uatom->next);
if (unlikely(atom->nparams >= 6))
return -EINVAL;
for (i = 0; i < atom->nparams; i++, pmap >>= 1) {
atom->args[i] = uatom->args[i];
if (unlikely(pmap & 1)) {
arg_ptr = (unsigned long __user *) atom->args[i];
if (!access_ok(VERIFY_WRITE, arg_ptr, sizeof(*arg_ptr)))
return -EFAULT;
ret |= __get_user(atom->args[i], arg_ptr);
}
}
return ret;
}
void init_utaom(struct syslet_uatom *ua, unsigned long flags, unsigned int nr,
long *ret_ptr, struct syslet_uatom *next, void *private,
int nparams, ...)
{
int i, mode;
va_list args;
ua->flags = flags;
ua->nr = nr;
ua->ret_ptr = ret_ptr;
ua->next = next;
ua->private = private;
ua->nparams = nparams;
ua->pmap = 0;
va_start(args, nparams);
for (i = 0; i < nparams; i++) {
mode = va_arg(args, int);
ua->args[i] = va_arg(args, unsigned long);
if (mode == UASYNC_INDIR)
ua->pmap |= 1 << i;
}
va_end(args);
}
#define UASYNC_IMM 0
#define UASYNC_INDIR 1
#define UAPD(a) UASYNC_IMM, (unsigned long) (a)
#define UAPI(a) UASYNC_INDIR, (unsigned long) (a)
void foo(void)
{
int fd;
long res;
struct stat stb;
struct syslet_uatom ua;
init_utaom(&ua, 0, __NR_fstat, &res, NULL, NULL, 2,
UAPI(&fd), UAPD(&stb));
...
}
---
- Davide
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]