e98335e7908a4b5ebab3d5e982481f86502826c7
[ipfw.git] / dummynet2 / include / sys / systm.h
1 #ifndef _SYS_SYSTM_H_
2 #define _SYS_SYSTM_H_
3
4 #define CALLOUT_ACTIVE          0x0002 /* callout is currently active */
5 #define CALLOUT_MPSAFE          0x0008 /* callout handler is mp safe */
6
7 #ifndef _WIN32  /* this is the linux version */
8 /* callout support, in <sys/callout.h> on FreeBSD */
9 /*
10  * callout support on linux module is done using timers
11  */
12 #include <linux/timer.h>
13 #ifdef LINUX_24
14 #include <linux/sched.h>        /* jiffies definition is here in 2.4 */
15 #endif
16 #define callout timer_list
17 static __inline int
18 callout_reset_on(struct callout *co, int ticks, void (*fn)(void *), void *arg, int cpu)
19 {
20         co->expires = jiffies + ticks;
21         co->function = (void (*)(unsigned long))fn;
22         co->data = (unsigned long)arg;
23         /*
24          * Linux 2.6.31 and above has add_timer_on(co, cpu),
25          * otherwise add_timer() always schedules a callout on the same
26          * CPU used the first time, so we don't need more.
27          */
28         add_timer(co);
29         return 0;
30 }
31
32 #define callout_init(co, safe)  init_timer(co)
33 #define callout_drain(co)       del_timer(co)
34 #define callout_stop(co)        del_timer(co)
35
36 #else /* _WIN32 */
37 #include <ndis.h>
38
39 /* This is the windows part for callout support */
40 struct callout {
41         KTIMER thetimer;
42         KDPC timerdpc;
43         int dpcinitialized;
44         LARGE_INTEGER duetime;
45 };
46
47 void dummynet (void*);
48 VOID dummynet_dpc(
49     __in struct _KDPC  *Dpc,
50     __in_opt PVOID  DeferredContext,
51     __in_opt PVOID  SystemArgument1,
52     __in_opt PVOID  SystemArgument2
53     );
54
55 VOID ipfw_dpc(
56     __in struct _KDPC  *Dpc,
57     __in_opt PVOID  DeferredContext,
58     __in_opt PVOID  SystemArgument1,
59     __in_opt PVOID  SystemArgument2
60     );
61
62 /* callout_reset must handle two problems:
63  * - dummynet() scheduler must be run always on the same processor
64  * because do_gettimeofday() is based on cpu performance counter, and
65  * _occasionally_ can leap backward in time if we query another cpu.
66  * typically this won't happen that much, and the cpu will almost always
67  * be the same even without the affinity restriction, but better to be sure.
68  * - ipfw_tick() does not have the granularity requirements of dummynet()
69  * but we need to pass a pointer as argument.
70  *
71  * for these reasons, if we are called for dummynet() timer,
72  * KeInitializeDpc is called only once as it should be, and the thread
73  * is forced on cpu0 (which is always present), while if we're called
74  * for ipfw_tick(), we re-initialize the DPC each time, using
75  * parameter DeferredContext to pass the needed pointer. since this
76  * timer is called only once a sec, this won't hurt that much.
77  */
78 static __inline int
79 callout_reset_on(struct callout *co, int ticks, void (*fn)(void *), void *arg, int cpu) 
80 {
81         if(fn == &dummynet)
82         {
83                 if(co->dpcinitialized == 0)
84                 {
85                         KeInitializeDpc(&co->timerdpc, dummynet_dpc, NULL);
86                         KeSetTargetProcessorDpc(&co->timerdpc, cpu);
87                         co->dpcinitialized = 1;
88                 }
89         }
90         else
91         {
92                 KeInitializeDpc(&co->timerdpc, ipfw_dpc, arg);
93         }
94         co->duetime.QuadPart = (-ticks)*10000;
95         KeSetTimer(&co->thetimer, co->duetime, &co->timerdpc);
96         return 0;
97 }
98
99 static __inline void
100 callout_init(struct callout* co, int safe)
101 {
102         printf("%s: initializing timer at %p\n",__FUNCTION__,co);
103         KeInitializeTimer(&co->thetimer);
104 }
105
106 static __inline int
107 callout_drain(struct callout* co)
108 {
109         BOOLEAN canceled = KeCancelTimer(&co->thetimer);
110         while (canceled != TRUE)
111         {
112                 canceled = KeCancelTimer(&co->thetimer);
113         }
114         printf("%s: stopping timer at %p\n",__FUNCTION__,co);
115         return 0;
116 }
117
118 static __inline int
119 callout_stop(struct callout* co)
120 {
121         return callout_drain(co);
122 }
123
124 #endif /* _WIN32 */
125
126 #endif /* _SYS_SYSTM_H_ */