11e59d133SFrançois Tigeot /* 21e59d133SFrançois Tigeot * Copyright (c) 2017 François Tigeot 31e59d133SFrançois Tigeot * All rights reserved. 41e59d133SFrançois Tigeot * 51e59d133SFrançois Tigeot * Redistribution and use in source and binary forms, with or without 61e59d133SFrançois Tigeot * modification, are permitted provided that the following conditions 71e59d133SFrançois Tigeot * are met: 81e59d133SFrançois Tigeot * 1. Redistributions of source code must retain the above copyright 91e59d133SFrançois Tigeot * notice unmodified, this list of conditions, and the following 101e59d133SFrançois Tigeot * disclaimer. 111e59d133SFrançois Tigeot * 2. Redistributions in binary form must reproduce the above copyright 121e59d133SFrançois Tigeot * notice, this list of conditions and the following disclaimer in the 131e59d133SFrançois Tigeot * documentation and/or other materials provided with the distribution. 141e59d133SFrançois Tigeot * 151e59d133SFrançois Tigeot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 161e59d133SFrançois Tigeot * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 171e59d133SFrançois Tigeot * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 181e59d133SFrançois Tigeot * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 191e59d133SFrançois Tigeot * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 201e59d133SFrançois Tigeot * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 211e59d133SFrançois Tigeot * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 221e59d133SFrançois Tigeot * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 231e59d133SFrançois Tigeot * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 241e59d133SFrançois Tigeot * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 251e59d133SFrançois Tigeot */ 261e59d133SFrançois Tigeot 271e59d133SFrançois Tigeot #ifndef _LINUX_INTERRUPT_H_ 281e59d133SFrançois Tigeot #define _LINUX_INTERRUPT_H_ 291e59d133SFrançois Tigeot 301e59d133SFrançois Tigeot #include <linux/kernel.h> 311e59d133SFrançois Tigeot #include <linux/bitops.h> 321e59d133SFrançois Tigeot #include <linux/irqflags.h> 331e59d133SFrançois Tigeot #include <linux/kref.h> 341e59d133SFrançois Tigeot 351e59d133SFrançois Tigeot #include <linux/atomic.h> 361e59d133SFrançois Tigeot 371e59d133SFrançois Tigeot struct tasklet_struct { 381e59d133SFrançois Tigeot unsigned long state; 391e59d133SFrançois Tigeot void (*func)(unsigned long); 401e59d133SFrançois Tigeot unsigned long data; 411e59d133SFrançois Tigeot struct lock lock; 421e59d133SFrançois Tigeot }; 431e59d133SFrançois Tigeot 441e59d133SFrançois Tigeot enum { 451e59d133SFrançois Tigeot TASKLET_STATE_SCHED, 461e59d133SFrançois Tigeot TASKLET_STATE_RUN 471e59d133SFrançois Tigeot }; 481e59d133SFrançois Tigeot 491e59d133SFrançois Tigeot /* 501e59d133SFrançois Tigeot * TODO: verify these points: 511e59d133SFrançois Tigeot * - tasklets that have the same type cannot be run on multiple processors at the same time 521e59d133SFrançois Tigeot * - tasklets always run on the processor from which they were originally 531e59d133SFrançois Tigeot * submitted 541e59d133SFrançois Tigeot * - when a tasklet is scheduled, its state is set to TASKLET_STATE_SCHED, and the tasklet 551e59d133SFrançois Tigeot * added to a queue 561e59d133SFrançois Tigeot * - during the execution of its function, the tasklet state is set to TASKLET_STATE_RUN 571e59d133SFrançois Tigeot * and the TASKLET_STATE_SCHED state is removed 581e59d133SFrançois Tigeot */ 591e59d133SFrançois Tigeot 601e59d133SFrançois Tigeot /* XXX scheduling and execution should be handled separately */ 611e59d133SFrançois Tigeot static inline void 621e59d133SFrançois Tigeot tasklet_schedule(struct tasklet_struct *t) 631e59d133SFrançois Tigeot { 64*f06706ddSFrançois Tigeot set_bit(TASKLET_STATE_SCHED, &t->state); 651e59d133SFrançois Tigeot 661e59d133SFrançois Tigeot lockmgr(&t->lock, LK_EXCLUSIVE); 67*f06706ddSFrançois Tigeot clear_bit(TASKLET_STATE_SCHED, &t->state); 681e59d133SFrançois Tigeot 69*f06706ddSFrançois Tigeot set_bit(TASKLET_STATE_RUN, &t->state); 70*f06706ddSFrançois Tigeot if (t->func) 711e59d133SFrançois Tigeot t->func(t->data); 72*f06706ddSFrançois Tigeot clear_bit(TASKLET_STATE_RUN, &t->state); 731e59d133SFrançois Tigeot 741e59d133SFrançois Tigeot lockmgr(&t->lock, LK_RELEASE); 751e59d133SFrançois Tigeot } 761e59d133SFrançois Tigeot 771e59d133SFrançois Tigeot /* This function ensures that the tasklet is not scheduled to run again */ 781e59d133SFrançois Tigeot /* XXX this doesn't kill anything */ 791e59d133SFrançois Tigeot static inline void 801e59d133SFrançois Tigeot tasklet_kill(struct tasklet_struct *t) 811e59d133SFrançois Tigeot { 821e59d133SFrançois Tigeot lockmgr(&t->lock, LK_EXCLUSIVE); 83*f06706ddSFrançois Tigeot clear_bit(TASKLET_STATE_SCHED, &t->state); 841e59d133SFrançois Tigeot lockmgr(&t->lock, LK_RELEASE); 851e59d133SFrançois Tigeot } 861e59d133SFrançois Tigeot 871e59d133SFrançois Tigeot static inline void 881e59d133SFrançois Tigeot tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data) 891e59d133SFrançois Tigeot { 901e59d133SFrançois Tigeot lockinit(&t->lock, "ltasklet", 0, LK_CANRECURSE); 911e59d133SFrançois Tigeot t->state = 0; 921e59d133SFrançois Tigeot t->func = func; 931e59d133SFrançois Tigeot t->data = data; 941e59d133SFrançois Tigeot } 951e59d133SFrançois Tigeot 961e59d133SFrançois Tigeot #endif /* _LINUX_INTERRUPT_H_ */ 97