X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=dummynet2%2Finclude%2Fsys%2Fsystm.h;fp=dummynet2%2Finclude%2Fsys%2Fsystm.h;h=db8ef7a429263588b2d1dd5e437b8422bef1837d;hb=40445faa1db58b90083115bc315d095e7eb2fe51;hp=238a7d3727671b8a3dd9fe9b5eca430da1074f7d;hpb=fccf30d4bf6b00b317756a9ff9d2135b361d2599;p=ipfw.git diff --git a/dummynet2/include/sys/systm.h b/dummynet2/include/sys/systm.h index 238a7d3..db8ef7a 100644 --- a/dummynet2/include/sys/systm.h +++ b/dummynet2/include/sys/systm.h @@ -1,6 +1,9 @@ #ifndef _SYS_SYSTM_H_ #define _SYS_SYSTM_H_ +#define CALLOUT_ACTIVE 0x0002 /* callout is currently active */ +#define CALLOUT_MPSAFE 0x0008 /* callout handler is mp safe */ + #ifndef _WIN32 /* this is the linux version */ /* callout support, in on FreeBSD */ /* @@ -25,49 +28,94 @@ callout_reset(struct callout *co, int ticks, void (*fn)(void *), void *arg) #define callout_drain(co) del_timer(co) #define callout_stop(co) del_timer(co) -#define CALLOUT_ACTIVE 0x0002 /* callout is currently active */ -#define CALLOUT_MPSAFE 0x0008 /* callout handler is mp safe */ - #else /* _WIN32 */ +#include /* This is the windows part for callout support */ struct callout { - int dummy; + KTIMER thetimer; + KDPC timerdpc; + int dpcinitialized; + LARGE_INTEGER duetime; }; + +void dummynet (void*); +VOID dummynet_dpc( + __in struct _KDPC *Dpc, + __in_opt PVOID DeferredContext, + __in_opt PVOID SystemArgument1, + __in_opt PVOID SystemArgument2 + ); + +VOID ipfw_dpc( + __in struct _KDPC *Dpc, + __in_opt PVOID DeferredContext, + __in_opt PVOID SystemArgument1, + __in_opt PVOID SystemArgument2 + ); + +/* callout_reset must handle two problems: + * - dummynet() scheduler must be run always on the same processor + * because do_gettimeofday() is based on cpu performance counter, and + * _occasionally_ can leap backward in time if we query another cpu. + * typically this won't happen that much, and the cpu will almost always + * be the same even without the affinity restriction, but better to be sure. + * - ipfw_tick() does not have the granularity requirements of dummynet() + * but we need to pass a pointer as argument. + * + * for these reasons, if we are called for dummynet() timer, + * KeInitializeDpc is called only once as it should be, and the thread + * is forced on cpu0 (which is always present), while if we're called + * for ipfw_tick(), we re-initialize the DPC each time, using + * parameter DeferredContext to pass the needed pointer. since this + * timer is called only once a sec, this won't hurt that much. + */ static __inline int -callout_reset(struct callout *co, int ticks, void (*fn)(void *), void *arg) +callout_reset(struct callout *co, int ticks, void (*fn)(void *), void *arg) { + if(fn == &dummynet) + { + if(co->dpcinitialized == 0) + { + KeInitializeDpc(&co->timerdpc, dummynet_dpc, NULL); + KeSetTargetProcessorDpc(&co->timerdpc, 0); + co->dpcinitialized = 1; + } + } + else + { + KeInitializeDpc(&co->timerdpc, ipfw_dpc, arg); + } + co->duetime.QuadPart = (-ticks)*10000; + KeSetTimer(&co->thetimer, co->duetime, &co->timerdpc); return 0; } -#define callout_init(co, safe) -#define callout_drain(co) -#define callout_stop(co) -#endif /* !_WIN32 */ +static __inline void +callout_init(struct callout* co, int safe) +{ + printf("%s: initializing timer at %p\n",__FUNCTION__,co); + KeInitializeTimer(&co->thetimer); +} +static __inline int +callout_drain(struct callout* co) +{ + BOOLEAN canceled = KeCancelTimer(&co->thetimer); + while (canceled != TRUE) + { + canceled = KeCancelTimer(&co->thetimer); + } + printf("%s: stopping timer at %p\n",__FUNCTION__,co); + return 0; +} -#if 0 -/* add out timer to the kernel global timer list */ -NTSTATUS - IoInitializeTimer( - IN PDEVICE_OBJECT DeviceObject, - IN PIO_TIMER_ROUTINE TimerRoutine, - IN PVOID Context - ); +static __inline int +callout_stop(struct callout* co) +{ + return callout_drain(co); +} -/* see differences : -IoInitializeDpcRequest - http://dsrg.mff.cuni.cz/~ceres/sch/osy/text/ch04s01s01.php - example http://www.beyondlogic.org/interrupts/winnt_isr_dpc.htm -KeInitializeDpc IRQL: Any level -IoInitializeTimer IRQL: Passive level -KeInitializeTimer */ -VOID - KeInitializeDpc( - IN PRKDPC Dpc, - IN PKDEFERRED_ROUTINE DeferredRoutine, - IN PVOID DeferredContext - ); -#endif /* commented out */ +#endif /* _WIN32 */ #endif /* _SYS_SYSTM_H_ */