1*1e59d133SFrançois Tigeot /* 2*1e59d133SFrançois Tigeot * Copyright (c) 2017 François Tigeot 3*1e59d133SFrançois Tigeot * All rights reserved. 4*1e59d133SFrançois Tigeot * 5*1e59d133SFrançois Tigeot * Redistribution and use in source and binary forms, with or without 6*1e59d133SFrançois Tigeot * modification, are permitted provided that the following conditions 7*1e59d133SFrançois Tigeot * are met: 8*1e59d133SFrançois Tigeot * 1. Redistributions of source code must retain the above copyright 9*1e59d133SFrançois Tigeot * notice unmodified, this list of conditions, and the following 10*1e59d133SFrançois Tigeot * disclaimer. 11*1e59d133SFrançois Tigeot * 2. Redistributions in binary form must reproduce the above copyright 12*1e59d133SFrançois Tigeot * notice, this list of conditions and the following disclaimer in the 13*1e59d133SFrançois Tigeot * documentation and/or other materials provided with the distribution. 14*1e59d133SFrançois Tigeot * 15*1e59d133SFrançois Tigeot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*1e59d133SFrançois Tigeot * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*1e59d133SFrançois Tigeot * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*1e59d133SFrançois Tigeot * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*1e59d133SFrançois Tigeot * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*1e59d133SFrançois Tigeot * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*1e59d133SFrançois Tigeot * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*1e59d133SFrançois Tigeot * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*1e59d133SFrançois Tigeot * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*1e59d133SFrançois Tigeot * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*1e59d133SFrançois Tigeot */ 26*1e59d133SFrançois Tigeot 27*1e59d133SFrançois Tigeot #ifndef _LINUX_INTERRUPT_H_ 28*1e59d133SFrançois Tigeot #define _LINUX_INTERRUPT_H_ 29*1e59d133SFrançois Tigeot 30*1e59d133SFrançois Tigeot #include <linux/kernel.h> 31*1e59d133SFrançois Tigeot #include <linux/bitops.h> 32*1e59d133SFrançois Tigeot #include <linux/irqflags.h> 33*1e59d133SFrançois Tigeot #include <linux/kref.h> 34*1e59d133SFrançois Tigeot 35*1e59d133SFrançois Tigeot #include <linux/atomic.h> 36*1e59d133SFrançois Tigeot 37*1e59d133SFrançois Tigeot struct tasklet_struct { 38*1e59d133SFrançois Tigeot unsigned long state; 39*1e59d133SFrançois Tigeot void (*func)(unsigned long); 40*1e59d133SFrançois Tigeot unsigned long data; 41*1e59d133SFrançois Tigeot struct lock lock; 42*1e59d133SFrançois Tigeot }; 43*1e59d133SFrançois Tigeot 44*1e59d133SFrançois Tigeot enum { 45*1e59d133SFrançois Tigeot TASKLET_STATE_SCHED, 46*1e59d133SFrançois Tigeot TASKLET_STATE_RUN 47*1e59d133SFrançois Tigeot }; 48*1e59d133SFrançois Tigeot 49*1e59d133SFrançois Tigeot /* 50*1e59d133SFrançois Tigeot * TODO: verify these points: 51*1e59d133SFrançois Tigeot * - tasklets that have the same type cannot be run on multiple processors at the same time 52*1e59d133SFrançois Tigeot * - tasklets always run on the processor from which they were originally 53*1e59d133SFrançois Tigeot * submitted 54*1e59d133SFrançois Tigeot * - when a tasklet is scheduled, its state is set to TASKLET_STATE_SCHED, and the tasklet 55*1e59d133SFrançois Tigeot * added to a queue 56*1e59d133SFrançois Tigeot * - during the execution of its function, the tasklet state is set to TASKLET_STATE_RUN 57*1e59d133SFrançois Tigeot * and the TASKLET_STATE_SCHED state is removed 58*1e59d133SFrançois Tigeot */ 59*1e59d133SFrançois Tigeot 60*1e59d133SFrançois Tigeot /* XXX scheduling and execution should be handled separately */ 61*1e59d133SFrançois Tigeot static inline void 62*1e59d133SFrançois Tigeot tasklet_schedule(struct tasklet_struct *t) 63*1e59d133SFrançois Tigeot { 64*1e59d133SFrançois Tigeot set_bit(TASKLET_STATE_SCHED, t->state); 65*1e59d133SFrançois Tigeot 66*1e59d133SFrançois Tigeot lockmgr(&t->lock, LK_EXCLUSIVE); 67*1e59d133SFrançois Tigeot clear_bit(TASKLET_STATE_SCHED, t->state); 68*1e59d133SFrançois Tigeot 69*1e59d133SFrançois Tigeot set_bit(TASKLET_STATE_RUN, t->state); 70*1e59d133SFrançois Tigeot t->func(t->data); 71*1e59d133SFrançois Tigeot clear_bit(TASKLET_STATE_RUN, t->state); 72*1e59d133SFrançois Tigeot 73*1e59d133SFrançois Tigeot lockmgr(&t->lock, LK_RELEASE); 74*1e59d133SFrançois Tigeot } 75*1e59d133SFrançois Tigeot 76*1e59d133SFrançois Tigeot /* This function ensures that the tasklet is not scheduled to run again */ 77*1e59d133SFrançois Tigeot /* XXX this doesn't kill anything */ 78*1e59d133SFrançois Tigeot static inline void 79*1e59d133SFrançois Tigeot tasklet_kill(struct tasklet_struct *t) 80*1e59d133SFrançois Tigeot { 81*1e59d133SFrançois Tigeot lockmgr(&t->lock, LK_EXCLUSIVE); 82*1e59d133SFrançois Tigeot clear_bit(TASKLET_STATE_SCHED, t->state); 83*1e59d133SFrançois Tigeot lockmgr(&t->lock, LK_RELEASE); 84*1e59d133SFrançois Tigeot } 85*1e59d133SFrançois Tigeot 86*1e59d133SFrançois Tigeot static inline void 87*1e59d133SFrançois Tigeot tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data) 88*1e59d133SFrançois Tigeot { 89*1e59d133SFrançois Tigeot lockinit(&t->lock, "ltasklet", 0, LK_CANRECURSE); 90*1e59d133SFrançois Tigeot t->state = 0; 91*1e59d133SFrançois Tigeot t->func = func; 92*1e59d133SFrançois Tigeot t->data = data; 93*1e59d133SFrançois Tigeot } 94*1e59d133SFrançois Tigeot 95*1e59d133SFrançois Tigeot #endif /* _LINUX_INTERRUPT_H_ */ 96