Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/usermode/dev Create an atomic switchto() that has S...



details:   https://anonhg.NetBSD.org/src/rev/aaf65c7ec3cd
branches:  trunk
changeset: 772855:aaf65c7ec3cd
user:      reinoud <reinoud%NetBSD.org@localhost>
date:      Wed Jan 18 19:17:02 2012 +0000

description:
Create an atomic switchto() that has SIGALRM and SIGIO signals blocked that
might otherwise disrupt the setting of curlwp to match the lwp context.

diffstat:

 sys/arch/usermode/dev/cpu.c |  59 ++++++++++++++++++++++++++++++++++----------
 1 files changed, 45 insertions(+), 14 deletions(-)

diffs (125 lines):

diff -r 8e219a730c40 -r aaf65c7ec3cd sys/arch/usermode/dev/cpu.c
--- a/sys/arch/usermode/dev/cpu.c       Wed Jan 18 17:32:41 2012 +0000
+++ b/sys/arch/usermode/dev/cpu.c       Wed Jan 18 19:17:02 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.67 2012/01/15 10:45:03 jmcneill Exp $ */
+/* $NetBSD: cpu.c,v 1.68 2012/01/18 19:17:02 reinoud Exp $ */
 
 /*-
  * Copyright (c) 2007 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -30,7 +30,7 @@
 #include "opt_hz.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.67 2012/01/15 10:45:03 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.68 2012/01/18 19:17:02 reinoud Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -78,6 +78,9 @@
 typedef struct cpu_softc {
        device_t        sc_dev;
        struct cpu_info *sc_ci;
+
+       ucontext_t      sc_ucp;
+       uint8_t         sc_ucp_stack[PAGE_SIZE];
 } cpu_softc_t;
 
 
@@ -108,8 +111,16 @@
        aprint_naive("\n");
        aprint_normal("\n");
 
+       cpu_info_primary.ci_dev = self;
        sc->sc_dev = self;
        sc->sc_ci = &cpu_info_primary;
+
+       thunk_getcontext(&sc->sc_ucp);
+       sc->sc_ucp.uc_stack.ss_sp = sc->sc_ucp_stack;
+       sc->sc_ucp.uc_stack.ss_size = PAGE_SIZE - sizeof(register_t);
+       sc->sc_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
+       thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGALRM);
+       thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGIO);
 }
 
 void
@@ -176,12 +187,34 @@
 {
 }
 
+static
+void
+cpu_switchto_atomic(lwp_t *oldlwp, lwp_t *newlwp)
+{
+       struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL;
+       struct pcb *newpcb = lwp_getpcb(newlwp);
+       struct cpu_info *ci = curcpu();
+
+       ci->ci_stash = oldlwp;
+
+       if (oldpcb)
+               oldpcb->pcb_errno = thunk_geterrno();
+
+       thunk_seterrno(newpcb->pcb_errno);
+
+       curlwp = newlwp;
+       if (thunk_setcontext(&newpcb->pcb_ucp))
+               panic("setcontext failed");
+       /* not reached */
+}
+
 lwp_t *
 cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning)
 {
        struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL;
        struct pcb *newpcb = lwp_getpcb(newlwp);
        struct cpu_info *ci = curcpu();
+       cpu_softc_t *sc = device_private(ci->ci_dev);
 
 #ifdef CPU_DEBUG
        thunk_printf_debug("cpu_switchto [%s,pid=%d,lid=%d] -> [%s,pid=%d,lid=%d]\n",
@@ -207,19 +240,16 @@
        }
 #endif /* !CPU_DEBUG */
 
-       ci->ci_stash = oldlwp;
+       /* create atomic switcher */
+       thunk_makecontext(&sc->sc_ucp, (void (*)(void)) cpu_switchto_atomic,
+                       2, oldlwp, newlwp, NULL);
 
-       if (oldpcb) {
-               oldpcb->pcb_errno = thunk_geterrno();
-               thunk_seterrno(newpcb->pcb_errno);
-               curlwp = newlwp;
-               if (thunk_swapcontext(&oldpcb->pcb_ucp, &newpcb->pcb_ucp))
-                       panic("swapcontext failed");
+       if (!oldpcb) {
+               thunk_setcontext(&sc->sc_ucp);
+               /* never returns */
        } else {
-               thunk_seterrno(newpcb->pcb_errno);
-               curlwp = newlwp;
-               if (thunk_setcontext(&newpcb->pcb_ucp))
-                       panic("setcontext failed");
+               thunk_swapcontext(&oldpcb->pcb_ucp, &sc->sc_ucp);
+               /* returns here */
        }
 
 #ifdef CPU_DEBUG
@@ -344,7 +374,7 @@
        /* get l2 its own stack */
        pcb2->pcb_ucp.uc_stack.ss_sp = pcb2->sys_stack;
        pcb2->pcb_ucp.uc_stack.ss_size = pcb2->sys_stack_top - pcb2->sys_stack;
-       pcb2->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU;
+       pcb2->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
        pcb2->pcb_ucp.uc_link = &pcb2->pcb_userret_ucp;
        thunk_makecontext(&pcb2->pcb_ucp,
            (void (*)(void)) cpu_lwp_trampoline,
@@ -382,6 +412,7 @@
        /* init lwp0 */
        memset(&lwp0pcb, 0, sizeof(lwp0pcb));
        thunk_getcontext(&lwp0pcb.pcb_ucp);
+       lwp0pcb.pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
        uvm_lwp_setuarea(&lwp0, (vaddr_t) &lwp0pcb);
        memcpy(&lwp0pcb.pcb_userret_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t));
 



Home | Main Index | Thread Index | Old Index