Home | History | Annotate | Line # | Download | only in rumpkern
intr.c revision 1.2.14.3
      1       1.2   ad /*	$NetBSD: intr.c,v 1.2.14.3 2009/01/17 13:29:36 mjf Exp $	*/
      2       1.2   ad 
      3  1.2.14.3  mjf /*
      4  1.2.14.3  mjf  * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
      5       1.2   ad  *
      6       1.2   ad  * Redistribution and use in source and binary forms, with or without
      7       1.2   ad  * modification, are permitted provided that the following conditions
      8       1.2   ad  * are met:
      9       1.2   ad  * 1. Redistributions of source code must retain the above copyright
     10       1.2   ad  *    notice, this list of conditions and the following disclaimer.
     11       1.2   ad  * 2. Redistributions in binary form must reproduce the above copyright
     12       1.2   ad  *    notice, this list of conditions and the following disclaimer in the
     13       1.2   ad  *    documentation and/or other materials provided with the distribution.
     14       1.2   ad  *
     15  1.2.14.3  mjf  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16  1.2.14.3  mjf  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  1.2.14.3  mjf  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  1.2.14.3  mjf  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  1.2.14.3  mjf  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  1.2.14.3  mjf  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  1.2.14.3  mjf  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  1.2.14.3  mjf  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  1.2.14.3  mjf  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  1.2.14.3  mjf  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  1.2.14.3  mjf  * SUCH DAMAGE.
     26       1.2   ad  */
     27       1.2   ad 
     28  1.2.14.3  mjf #include <sys/cdefs.h>
     29  1.2.14.3  mjf __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.2.14.3 2009/01/17 13:29:36 mjf Exp $");
     30  1.2.14.3  mjf 
     31       1.2   ad #include <sys/param.h>
     32       1.2   ad #include <sys/cpu.h>
     33  1.2.14.3  mjf #include <sys/kmem.h>
     34  1.2.14.3  mjf #include <sys/kthread.h>
     35  1.2.14.3  mjf #include <sys/intr.h>
     36  1.2.14.3  mjf 
     37  1.2.14.3  mjf #include <rump/rumpuser.h>
     38  1.2.14.3  mjf 
     39  1.2.14.3  mjf #include "rump_private.h"
     40  1.2.14.3  mjf 
     41  1.2.14.3  mjf /*
     42  1.2.14.3  mjf  * Interrupt simulator.  It executes hardclock() and softintrs.
     43  1.2.14.3  mjf  */
     44       1.2   ad 
     45  1.2.14.3  mjf time_t time_uptime = 1;
     46  1.2.14.3  mjf 
     47  1.2.14.3  mjf struct softint {
     48  1.2.14.3  mjf 	void (*si_func)(void *);
     49  1.2.14.3  mjf 	void *si_arg;
     50  1.2.14.3  mjf 	bool si_onlist;
     51  1.2.14.3  mjf 	bool si_mpsafe;
     52  1.2.14.3  mjf 
     53  1.2.14.3  mjf 	LIST_ENTRY(softint) si_entries;
     54       1.2   ad };
     55  1.2.14.3  mjf static LIST_HEAD(, softint) si_pending = LIST_HEAD_INITIALIZER(si_pending);
     56  1.2.14.3  mjf static kmutex_t si_mtx;
     57  1.2.14.3  mjf static kcondvar_t si_cv;
     58  1.2.14.3  mjf 
     59  1.2.14.3  mjf #define INTRTHREAD_DEFAULT	2
     60  1.2.14.3  mjf #define INTRTHREAD_MAX		20
     61  1.2.14.3  mjf static int wrkidle, wrktotal;
     62       1.2   ad 
     63  1.2.14.3  mjf static void sithread(void *);
     64  1.2.14.3  mjf 
     65  1.2.14.3  mjf static void
     66  1.2.14.3  mjf makeworker(bool bootstrap)
     67  1.2.14.3  mjf {
     68  1.2.14.3  mjf 	int rv;
     69  1.2.14.3  mjf 
     70  1.2.14.3  mjf 	if (wrktotal > INTRTHREAD_MAX) {
     71  1.2.14.3  mjf 		/* XXX: ratecheck */
     72  1.2.14.3  mjf 		printf("maximum interrupt threads (%d) reached\n",
     73  1.2.14.3  mjf 		    INTRTHREAD_MAX);
     74  1.2.14.3  mjf 		return;
     75  1.2.14.3  mjf 	}
     76  1.2.14.3  mjf 	rv = kthread_create(PRI_NONE, 0, NULL, sithread,
     77  1.2.14.3  mjf 	    NULL, NULL, "rumpsi");
     78  1.2.14.3  mjf 	if (rv) {
     79  1.2.14.3  mjf 		if (bootstrap)
     80  1.2.14.3  mjf 			panic("intr thread creation failed %d", rv);
     81  1.2.14.3  mjf 		else
     82  1.2.14.3  mjf 			printf("intr thread creation failed %d\n", rv);
     83  1.2.14.3  mjf 	} else {
     84  1.2.14.3  mjf 		wrkidle++;
     85  1.2.14.3  mjf 		wrktotal++;
     86  1.2.14.3  mjf 	}
     87  1.2.14.3  mjf }
     88  1.2.14.3  mjf 
     89  1.2.14.3  mjf /*
     90  1.2.14.3  mjf  * clock "interrupt"
     91  1.2.14.3  mjf  */
     92  1.2.14.3  mjf static void
     93  1.2.14.3  mjf doclock(void *noarg)
     94  1.2.14.3  mjf {
     95  1.2.14.3  mjf 	static int ticks = 0;
     96  1.2.14.3  mjf 	extern int hz;
     97  1.2.14.3  mjf 
     98  1.2.14.3  mjf 	for (;;) {
     99  1.2.14.3  mjf 		callout_hardclock();
    100  1.2.14.3  mjf 
    101  1.2.14.3  mjf 		/* XXX: will drift */
    102  1.2.14.3  mjf 		if (++ticks == hz) {
    103  1.2.14.3  mjf 			time_uptime++;
    104  1.2.14.3  mjf 			ticks = 0;
    105  1.2.14.3  mjf 		}
    106  1.2.14.3  mjf 		kpause("tickw8", false, 1, NULL);
    107  1.2.14.3  mjf 	}
    108  1.2.14.3  mjf }
    109  1.2.14.3  mjf 
    110  1.2.14.3  mjf /*
    111  1.2.14.3  mjf  * run a scheduled soft interrupt
    112  1.2.14.3  mjf  */
    113  1.2.14.3  mjf static void
    114  1.2.14.3  mjf sithread(void *arg)
    115       1.2   ad {
    116  1.2.14.3  mjf 	struct softint *si;
    117  1.2.14.3  mjf 	void (*func)(void *) = NULL;
    118  1.2.14.3  mjf 	void *funarg;
    119  1.2.14.3  mjf 	bool mpsafe;
    120  1.2.14.3  mjf 
    121  1.2.14.3  mjf 	mutex_enter(&si_mtx);
    122  1.2.14.3  mjf 	for (;;) {
    123  1.2.14.3  mjf 		if (!LIST_EMPTY(&si_pending)) {
    124  1.2.14.3  mjf 			si = LIST_FIRST(&si_pending);
    125  1.2.14.3  mjf 			func = si->si_func;
    126  1.2.14.3  mjf 			funarg = si->si_arg;
    127  1.2.14.3  mjf 			mpsafe = si->si_mpsafe;
    128  1.2.14.3  mjf 
    129  1.2.14.3  mjf 			si->si_onlist = false;
    130  1.2.14.3  mjf 			LIST_REMOVE(si, si_entries);
    131  1.2.14.3  mjf 		} else {
    132  1.2.14.3  mjf 			cv_wait(&si_cv, &si_mtx);
    133  1.2.14.3  mjf 			continue;
    134  1.2.14.3  mjf 		}
    135  1.2.14.3  mjf 		wrkidle--;
    136  1.2.14.3  mjf 		if (__predict_false(wrkidle == 0))
    137  1.2.14.3  mjf 			makeworker(false);
    138  1.2.14.3  mjf 		mutex_exit(&si_mtx);
    139  1.2.14.3  mjf 
    140  1.2.14.3  mjf 		if (!mpsafe)
    141  1.2.14.3  mjf 			KERNEL_LOCK(1, curlwp);
    142  1.2.14.3  mjf 		func(funarg);
    143  1.2.14.3  mjf 		if (!mpsafe)
    144  1.2.14.3  mjf 			KERNEL_UNLOCK_ONE(curlwp);
    145       1.2   ad 
    146  1.2.14.3  mjf 		mutex_enter(&si_mtx);
    147  1.2.14.3  mjf 		wrkidle++;
    148       1.2   ad 	}
    149       1.2   ad }
    150       1.2   ad 
    151       1.2   ad void
    152  1.2.14.3  mjf softint_init(struct cpu_info *ci)
    153  1.2.14.3  mjf {
    154  1.2.14.3  mjf 	int rv;
    155  1.2.14.3  mjf 
    156  1.2.14.3  mjf 	mutex_init(&si_mtx, MUTEX_DEFAULT, IPL_NONE);
    157  1.2.14.3  mjf 	cv_init(&si_cv, "intrw8"); /* cv of temporary w8ness */
    158  1.2.14.3  mjf 
    159  1.2.14.3  mjf 	/* XXX: should have separate "wanttimer" control */
    160  1.2.14.3  mjf 	if (rump_threads) {
    161  1.2.14.3  mjf 		rv = kthread_create(PRI_NONE, 0, NULL, doclock,
    162  1.2.14.3  mjf 		    NULL, NULL, "rumpclk");
    163  1.2.14.3  mjf 		if (rv)
    164  1.2.14.3  mjf 			panic("clock thread creation failed: %d", rv);
    165  1.2.14.3  mjf 		mutex_enter(&si_mtx);
    166  1.2.14.3  mjf 		while (wrktotal < INTRTHREAD_DEFAULT) {
    167  1.2.14.3  mjf 			makeworker(true);
    168  1.2.14.3  mjf 		}
    169  1.2.14.3  mjf 		mutex_exit(&si_mtx);
    170  1.2.14.3  mjf 	}
    171  1.2.14.3  mjf }
    172  1.2.14.3  mjf 
    173  1.2.14.3  mjf /*
    174  1.2.14.3  mjf  * Soft interrupts bring two choices.  If we are running with thread
    175  1.2.14.3  mjf  * support enabled, defer execution, otherwise execute in place.
    176  1.2.14.3  mjf  * See softint_schedule().
    177  1.2.14.3  mjf  *
    178  1.2.14.3  mjf  * As there is currently no clear concept of when a thread finishes
    179  1.2.14.3  mjf  * work (although rump_clear_curlwp() is close), simply execute all
    180  1.2.14.3  mjf  * softints in the timer thread.  This is probably not the most
    181  1.2.14.3  mjf  * efficient method, but good enough for now.
    182  1.2.14.3  mjf  */
    183  1.2.14.3  mjf void *
    184  1.2.14.3  mjf softint_establish(u_int flags, void (*func)(void *), void *arg)
    185       1.2   ad {
    186  1.2.14.3  mjf 	struct softint *si;
    187       1.2   ad 
    188  1.2.14.3  mjf 	si = kmem_alloc(sizeof(*si), KM_SLEEP);
    189  1.2.14.3  mjf 	si->si_func = func;
    190  1.2.14.3  mjf 	si->si_arg = arg;
    191  1.2.14.3  mjf 	si->si_onlist = false;
    192  1.2.14.3  mjf 	si->si_mpsafe = flags & SOFTINT_MPSAFE;
    193  1.2.14.3  mjf 
    194  1.2.14.3  mjf 	return si;
    195       1.2   ad }
    196       1.2   ad 
    197       1.2   ad void
    198       1.2   ad softint_schedule(void *arg)
    199       1.2   ad {
    200  1.2.14.3  mjf 	struct softint *si = arg;
    201       1.2   ad 
    202  1.2.14.3  mjf 	if (!rump_threads) {
    203  1.2.14.3  mjf 		si->si_func(si->si_arg);
    204  1.2.14.3  mjf 	} else {
    205  1.2.14.3  mjf 		mutex_enter(&si_mtx);
    206  1.2.14.3  mjf 		if (!si->si_onlist) {
    207  1.2.14.3  mjf 			LIST_INSERT_HEAD(&si_pending, si, si_entries);
    208  1.2.14.3  mjf 			si->si_onlist = true;
    209  1.2.14.3  mjf 		}
    210  1.2.14.3  mjf 		cv_signal(&si_cv);
    211  1.2.14.3  mjf 		mutex_exit(&si_mtx);
    212  1.2.14.3  mjf 	}
    213       1.2   ad }
    214       1.2   ad 
    215       1.2   ad bool
    216       1.2   ad cpu_intr_p(void)
    217       1.2   ad {
    218       1.2   ad 
    219       1.2   ad 	return false;
    220       1.2   ad }
    221