Date: Wed, 13 May 2009 10:16:31 +0000 (UTC) From: Robert Watson <rwatson@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r192038 - in projects/pnet/sys: net sys Message-ID: <200905131016.n4DAGVLR048770@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rwatson Date: Wed May 13 10:16:31 2009 New Revision: 192038 URL: http://svn.freebsd.org/changeset/base/192038 Log: Use SWIs for netisr2 rather than kthreads -- SWIs have a slightly more efficient wakeup routine (since they don't need to look up sleep queues). Suggested by: jhb Modified: projects/pnet/sys/net/netisr2.c projects/pnet/sys/sys/pcpu.h Modified: projects/pnet/sys/net/netisr2.c ============================================================================== --- projects/pnet/sys/net/netisr2.c Wed May 13 09:03:54 2009 (r192037) +++ projects/pnet/sys/net/netisr2.c Wed May 13 10:16:31 2009 (r192038) @@ -69,7 +69,6 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/bus.h> -#include <sys/condvar.h> #include <sys/kernel.h> #include <sys/kthread.h> #include <sys/interrupt.h> @@ -196,11 +195,12 @@ struct netisr_work { * Currently, #workstreams must equal #CPUs. */ struct netisr_workstream { - struct thread *nws_thread; /* Thread serving stream. */ + struct intr_event *nws_intr_event; /* Handler for stream. */ + void *nws_swi_cookie; /* swi(9) cookie for stream. */ struct mtx nws_mtx; /* Synchronize work. */ - struct cv nws_cv; /* Wake up worker. */ u_int nws_cpu; /* CPU pinning. */ u_int nws_flags; /* Wakeup flags. */ + u_int nws_swi_flags; /* Flags used in swi. */ u_int nws_pendingwork; /* Across all protos. */ /* @@ -210,11 +210,6 @@ struct netisr_workstream { } __aligned(CACHE_LINE_SIZE); /* - * Kernel process associated with worker threads. - */ -static struct proc *netisr2_proc; - -/* * Per-CPU workstream data, indexed by CPU ID. */ static struct netisr_workstream nws[MAXCPU]; @@ -239,15 +234,19 @@ static u_int nws_count; #define NWS_SIGNALED 0x00000002 /* Signal issued. */ /* + * Flags used internally to the SWI handler -- no locking required. + */ +#define NWS_SWI_BOUND 0x00000001 /* SWI bound to CPU. */ + +/* * Synchronization for each workstream: a mutex protects all mutable fields - * in each stream, including per-protocol state (mbuf queues). The CV will - * be used to wake up the worker if asynchronous dispatch is required. + * in each stream, including per-protocol state (mbuf queues). The SWI is + * woken up if asynchronous dispatch is required. */ #define NWS_LOCK(s) mtx_lock(&(s)->nws_mtx) #define NWS_LOCK_ASSERT(s) mtx_assert(&(s)->nws_mtx, MA_OWNED) #define NWS_UNLOCK(s) mtx_unlock(&(s)->nws_mtx) -#define NWS_SIGNAL(s) cv_signal(&(s)->nws_cv) -#define NWS_WAIT(s) cv_wait(&(s)->nws_cv, &(s)->nws_mtx) +#define NWS_SIGNAL(s) swi_sched((s)->nws_swi_cookie, 0) /* * Utility routines for protocols that implement their own mapping of flows @@ -498,38 +497,33 @@ netisr2_process_workstream(struct netisr } /* - * Worker thread that waits for and processes packets in a set of workstreams - * that it owns. Each thread has one cv, which is uses for all workstreams - * it handles. + * SWI handler for netisr2 -- processes prackets in a set of workstreams that + * it owns. */ static void -netisr2_worker(void *arg) +swi_net(void *arg) { struct netisr_workstream *nwsp; nwsp = arg; - thread_lock(curthread); - sched_prio(curthread, SWI_NET * RQ_PPQ + PI_SOFT); - sched_bind(curthread, nwsp->nws_cpu); - thread_unlock(curthread); - /* - * Main work loop. In the future we will want to support stopping - * workers, as well as re-balancing work, in which case we'll need to - * also handle state transitions. - * - * XXXRW: netisr_rwlock. + * On first execution, force the ithread to the desired CPU. There + * should be a better way to do this. */ + if (!(nwsp->nws_swi_flags & NWS_SWI_BOUND)) { + thread_lock(curthread); + sched_bind(curthread, nwsp->nws_cpu); + thread_unlock(curthread); + nwsp->nws_swi_flags |= NWS_SWI_BOUND; + } + NWS_LOCK(nwsp); - while (1) { - while (nwsp->nws_pendingwork == 0) { - nwsp->nws_flags &= ~(NWS_SIGNALED | NWS_RUNNING); - NWS_WAIT(nwsp); - nwsp->nws_flags |= NWS_RUNNING; - } + nwsp->nws_flags |= NWS_RUNNING; + while (nwsp->nws_pendingwork != 0) netisr2_process_workstream(nwsp, NETISR_ALLPROT); - } + nwsp->nws_flags &= ~(NWS_SIGNALED | NWS_RUNNING); + NWS_UNLOCK(nwsp); } static int @@ -624,6 +618,26 @@ netisr2_dispatch(u_int proto, uintptr_t return (0); } +static void +netisr2_start_swi(u_int cpuid, struct pcpu *pc) +{ + char swiname[12]; + struct netisr_workstream *nwsp; + int error; + + nwsp = &nws[cpuid]; + mtx_init(&nwsp->nws_mtx, "netisr2_mtx", NULL, MTX_DEF); + nwsp->nws_cpu = cpuid; + snprintf(swiname, sizeof(swiname), "netisr2: %d", cpuid); + error = swi_add(&nwsp->nws_intr_event, swiname, swi_net, nwsp, + SWI_NET, INTR_MPSAFE, &nwsp->nws_swi_cookie); + if (error) + panic("netisr2_init: swi_add %d", error); + pc->pc_netisr2 = nwsp->nws_intr_event; + nws_array[nws_count] = nwsp->nws_cpu; + nws_count++; +} + /* * Initialize the netisr subsystem. We rely on BSS and static initialization * of most fields in global data structures. @@ -635,30 +649,16 @@ netisr2_dispatch(u_int proto, uintptr_t static void netisr2_init(void *arg) { - struct netisr_workstream *nwsp; - u_int cpuid; - int error; KASSERT(curcpu == 0, ("netisr2_init: not on CPU 0")); NETISR_LOCK_INIT(); - - KASSERT(PCPU_GET(netisr2) == NULL, ("netisr2_init: pc_netisr2")); - - cpuid = curcpu; - nwsp = &nws[cpuid]; - mtx_init(&nwsp->nws_mtx, "netisr2_mtx", NULL, MTX_DEF); - cv_init(&nwsp->nws_cv, "netisr2_cv"); - nwsp->nws_cpu = cpuid; - error = kproc_kthread_add(netisr2_worker, nwsp, &netisr2_proc, - &nwsp->nws_thread, 0, 0, "netisr2", "netisr2: cpu%d", cpuid); - PCPU_SET(netisr2, nwsp->nws_thread); - if (error) - panic("netisr2_init: kproc_kthread_add %d", error); - nws_array[nws_count] = nwsp->nws_cpu; - nws_count++; if (netisr_maxthreads < 1) netisr_maxthreads = 1; + if (netisr_maxthreads > MAXCPU) + netisr_maxthreads = MAXCPU; + + netisr2_start_swi(curcpu, pcpu_find(curcpu)); } SYSINIT(netisr2_init, SI_SUB_SOFTINTR, SI_ORDER_FIRST, netisr2_init, NULL); @@ -669,9 +669,7 @@ SYSINIT(netisr2_init, SI_SUB_SOFTINTR, S static void netisr2_start(void *arg) { - struct netisr_workstream *nwsp; struct pcpu *pc; - int error; SLIST_FOREACH(pc, &cpuhead, pc_allcpu) { if (nws_count >= netisr_maxthreads) @@ -682,18 +680,7 @@ netisr2_start(void *arg) /* Worker will already be present for boot CPU. */ if (pc->pc_netisr2 != NULL) continue; - nwsp = &nws[pc->pc_cpuid]; - mtx_init(&nwsp->nws_mtx, "netisr2_mtx", NULL, MTX_DEF); - cv_init(&nwsp->nws_cv, "netisr2_cv"); - nwsp->nws_cpu = pc->pc_cpuid; - error = kproc_kthread_add(netisr2_worker, nwsp, - &netisr2_proc, &nwsp->nws_thread, 0, 0, "netisr2", - "netisr2: cpu%d", pc->pc_cpuid); - pc->pc_netisr2 = nwsp->nws_thread; - if (error) - panic("netisr2_start: kproc_kthread_add %d", error); - nws_array[nws_count] = pc->pc_cpuid; - nws_count++; + netisr2_start_swi(pc->pc_cpuid, pc); } } SYSINIT(netisr2_start, SI_SUB_SMP, SI_ORDER_MIDDLE, netisr2_start, NULL); @@ -709,7 +696,7 @@ DB_SHOW_COMMAND(netisr2, db_show_netisr2 "Proto", "Len", "WMark", "Max", "Disp", "Drop", "Queue", "Handle"); for (cpu = 0; cpu < MAXCPU; cpu++) { nwsp = &nws[cpu]; - if (nwsp->nws_thread == NULL) + if (nwsp->nws_intr_event == NULL) continue; first = 1; for (proto = 0; proto < NETISR_MAXPROT; proto++) { Modified: projects/pnet/sys/sys/pcpu.h ============================================================================== --- projects/pnet/sys/sys/pcpu.h Wed May 13 09:03:54 2009 (r192037) +++ projects/pnet/sys/sys/pcpu.h Wed May 13 10:16:31 2009 (r192038) @@ -86,6 +86,7 @@ struct pcpu { struct vmmeter pc_cnt; /* VM stats counters */ long pc_cp_time[CPUSTATES]; /* statclock ticks */ struct device *pc_device; + void *pc_netisr2; /* netisr2 SWI cookie. */ /* * Stuff for read mostly lock
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905131016.n4DAGVLR048770>