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