0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #define PS_VERSION "1.02"
0034
0035 #include <linux/sched.h>
0036 #include <linux/workqueue.h>
0037
0038 static void ps_tq_int(struct work_struct *work);
0039
0040 static void (* ps_continuation)(void);
0041 static int (* ps_ready)(void);
0042 static unsigned long ps_timeout;
0043 static int ps_tq_active = 0;
0044 static int ps_nice = 0;
0045
0046 static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused)));
0047
0048 static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int);
0049
0050 static void ps_set_intr(void (*continuation)(void),
0051 int (*ready)(void),
0052 int timeout, int nice)
0053 {
0054 unsigned long flags;
0055
0056 spin_lock_irqsave(&ps_spinlock,flags);
0057
0058 ps_continuation = continuation;
0059 ps_ready = ready;
0060 ps_timeout = jiffies + timeout;
0061 ps_nice = nice;
0062
0063 if (!ps_tq_active) {
0064 ps_tq_active = 1;
0065 if (!ps_nice)
0066 schedule_delayed_work(&ps_tq, 0);
0067 else
0068 schedule_delayed_work(&ps_tq, ps_nice-1);
0069 }
0070 spin_unlock_irqrestore(&ps_spinlock,flags);
0071 }
0072
0073 static void ps_tq_int(struct work_struct *work)
0074 {
0075 void (*con)(void);
0076 unsigned long flags;
0077
0078 spin_lock_irqsave(&ps_spinlock,flags);
0079
0080 con = ps_continuation;
0081 ps_tq_active = 0;
0082
0083 if (!con) {
0084 spin_unlock_irqrestore(&ps_spinlock,flags);
0085 return;
0086 }
0087 if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) {
0088 ps_continuation = NULL;
0089 spin_unlock_irqrestore(&ps_spinlock,flags);
0090 con();
0091 return;
0092 }
0093 ps_tq_active = 1;
0094 if (!ps_nice)
0095 schedule_delayed_work(&ps_tq, 0);
0096 else
0097 schedule_delayed_work(&ps_tq, ps_nice-1);
0098 spin_unlock_irqrestore(&ps_spinlock,flags);
0099 }
0100
0101
0102