Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/powerpc/powerpc create a syscall_plain() like on ot...



details:   https://anonhg.NetBSD.org/src/rev/7898931c66ca
branches:  trunk
changeset: 534491:7898931c66ca
user:      chs <chs%NetBSD.org@localhost>
date:      Sun Jul 28 07:05:53 2002 +0000

description:
create a syscall_plain() like on other platforms
and avoid getting the kernel lock for MPSAFE syscalls.

diffstat:

 sys/arch/powerpc/powerpc/syscall.c |  111 ++++++++++++++++++++++++++++++++++++-
 1 files changed, 108 insertions(+), 3 deletions(-)

diffs (132 lines):

diff -r 1d7c6c92e622 -r 7898931c66ca sys/arch/powerpc/powerpc/syscall.c
--- a/sys/arch/powerpc/powerpc/syscall.c        Sun Jul 28 07:05:19 2002 +0000
+++ b/sys/arch/powerpc/powerpc/syscall.c        Sun Jul 28 07:05:53 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: syscall.c,v 1.2 2002/07/11 19:32:43 matt Exp $ */
+/*     $NetBSD: syscall.c,v 1.3 2002/07/28 07:05:53 chs Exp $  */
 
 /*
  * Copyright (C) 2002 Matt Thomas
@@ -70,7 +70,100 @@
 #define        NARGREG         8               /* 8 args are in registers */
 #define        MOREARGS(sp)    ((caddr_t)((uintptr_t)(sp) + 8)) /* more args go here */
 
-static void syscall_fancy(struct trapframe *frame);
+void syscall_plain(struct trapframe *frame);
+void syscall_fancy(struct trapframe *frame);
+
+void
+syscall_plain(struct trapframe *frame)
+{
+       struct proc *p = curproc;
+       const struct sysent *callp;
+       size_t argsize;
+       register_t code;
+       register_t *params, rval[2];
+       register_t args[10];
+       int error;
+       int n;
+
+       curcpu()->ci_ev_scalls.ev_count++;
+       uvmexp.syscalls++;
+
+       code = frame->fixreg[0];
+       callp = p->p_emul->e_sysent;
+       params = frame->fixreg + FIRSTARG;
+       n = NARGREG;
+
+       switch (code) {
+       case SYS_syscall:
+               /*
+                * code is first argument,
+                * followed by actual args.
+                */
+               code = *params++;
+               n -= 1;
+               break;
+       case SYS___syscall:
+               params++;
+               code = *params++;
+               n -= 2;
+               break;
+       default:
+               break;
+       }
+
+       code &= (SYS_NSYSENT - 1);
+       callp += code;
+       argsize = callp->sy_argsize;
+
+       if (argsize > n * sizeof(register_t)) {
+               memcpy(args, params, n * sizeof(register_t));
+               KERNEL_PROC_LOCK(p);
+               error = copyin(MOREARGS(frame->fixreg[1]),
+                      args + n,
+                      argsize - n * sizeof(register_t));
+               KERNEL_PROC_UNLOCK(p);
+               if (error)
+                       goto syscall_bad;
+               params = args;
+       }
+
+       rval[0] = 0;
+       rval[1] = 0;
+
+       if ((callp->sy_flags & SYCALL_MPSAFE) == 0) {
+               KERNEL_PROC_LOCK(p);
+       }
+
+       error = (*callp->sy_call)(p, params, rval);
+
+       if ((callp->sy_flags & SYCALL_MPSAFE) == 0) {
+               KERNEL_PROC_UNLOCK(p);
+       }
+
+       switch (error) {
+       case 0:
+               frame->fixreg[FIRSTARG] = rval[0];
+               frame->fixreg[FIRSTARG + 1] = rval[1];
+               frame->cr &= ~0x10000000;
+               break;
+       case ERESTART:
+               /*
+                * Set user's pc back to redo the system call.
+                */
+               frame->srr0 -= 4;
+               break;
+       case EJUSTRETURN:
+               /* nothing to do */
+               break;
+       default:
+syscall_bad:
+               if (p->p_emul->e_errno)
+                       error = p->p_emul->e_errno[error];
+               frame->fixreg[FIRSTARG] = error;
+               frame->cr |= 0x10000000;
+               break;
+       }
+}
 
 void
 syscall_fancy(struct trapframe *frame)
@@ -163,7 +256,19 @@
 void
 syscall_intern(struct proc *p)
 {
-       p->p_md.md_syscall = syscall_fancy;
+#ifdef KTRACE
+       if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) {
+               p->p_md.md_syscall = syscall_fancy;
+               return;
+       }
+#endif
+#ifdef SYSTRACE
+       if (ISSET(p->p_flag, P_SYSTRACE)) {
+               p->p_md.md_syscall = syscall_fancy;
+               return;
+       } 
+#endif
+       p->p_md.md_syscall = syscall_plain;
 }
 
 #ifdef COMPAT_LINUX



Home | Main Index | Thread Index | Old Index