|
Smart Timing Mechanism
8 _+ R; U0 `# h% Z' r& Z+ P/ B
: m0 Z# b: p6 B+ {" ^8 l1 Q: n1. Why need this mechanism?6 `% z* `( C. K- ~
) }) I s' L9 q- A
最近在跑一个超薄NB专案,这个专案的power sequence比较奇怪,很多地方需要很多的定时一段时间然后再去调整某一部分的时序。我真是受够了code base中的定时方式。每次定时都要定义一个变量,需要使用时给它赋值,然后再8051的定时器中断到来时,再计数累加。一个函数非常的长,而且充斥着乱七八糟的变量。经过这么多年的发展,代码里到处都是坏味道,看的我非常不爽,于是就产生了改造这个机制的想法。6 \8 I4 p1 e) @5 k" r' h( L; K
$ M* Q! }. Q/ b D
2. How to improve it?! N4 g/ l2 Y. [0 b6 D
$ }. r9 _+ i$ p/ U
既然决定了那么就行动吧! 打开google 大神进入code search,看看有没有什么好东西(J我不想重新造轮子,如果有好的代码那么就拿来参考)。搜来搜去,发现linux 2.6内核中的定时机制很酷,可是不适合我的环境,它太大了,光这个机制就能把我的EC搞爆了L。然后再狂搜!果然不负我一番苦心,我发现linux 0.95内核中的定时机制挺适合。可是仔细阅读之后发现这个机制有些缺陷,它只处理了插入结点时间比头结点时间长的情况,而没有处理插入结点时间比链表头结点短的状况。下面就是我修改后的source code:
9 S( w/ I9 \ k- a7 s; p% i
- D; P/ m$ r2 ~! ^5 |) C* Q+ Z//header file
1 ?( P2 W& Z) \& Y/////////////////////////////////////////////////7 j! j! \7 u8 L. c. Y1 Z7 i% h
#ifndef3 D, e0 q: G2 j$ ^
OEM_TIMER_SERVICE__H' K) r8 B" v: b2 F8 _. J, T& O* M2 }
#define( x3 `7 G" T( R8 }7 X6 H9 ]/ n
OEM_TIMER_SERVIEC__H2 V e( M/ ]* e9 S
2 n7 j7 `7 N( h! [1 v/ n" `( r' _) {3 ~. c+ E1 P
void add_timer(unsigned short# m+ r) P d9 Q' e* L# |& V
jiffies,void (*callback)());8 H9 m$ D2 c7 i- [2 @' J; w/ w. H6 B
8 L( A- U: y3 z+ M) ?8 B. p% z: @
void do_timer(void);& y0 ^0 l2 m% B* }) L
+ W7 G% j, C& z. v N" @& }
#endif; B" p. w, `4 @7 _
/////////////////////////////////////////////////
. x- I( a4 c- n/ V( {1 D0 y- O/////////////////////////////////////////////////; g$ }( l! v9 t+ N
//impl file+ G8 u' p, O2 z& S
#include <stdio.h>6 d0 `4 ?4 K/ H" S% \$ F8 d z
#include "OEMTimerService.H"2 G6 a6 P! u0 D+ w- g2 Y- f
& }+ P3 Q6 B1 b
$ b, e- ] x: r9 e& H, q$ I#define
. T8 x4 y) f- q& GTIMER_REQUESTS
0 L2 B0 L E, t7 O, S& W6 W* i0x30
; |6 E7 z& v5 a1 N; D1 t, f6 q, t0 N p) ^+ ] X
struct timer_list * A/ f. P/ q' `
{
5 X3 s$ m1 i* F* f2 H( B
$ i, a4 a5 i" [+ qstruct timer_list *next;
) }0 h6 Z) T G/ p9 C u4 ]$ O9 N2 l1 l2 K( P1 ~ {( Z. B7 m
unsigned short jiffies;( g+ r5 ]( T( i. x0 H; v
7 E$ C0 G. }4 B, \! a) F$ ~* Y; fvoid (*callback)(void);+ @5 q9 |. T# a) }( I g" u+ q, G
};* z, H* K0 N0 y3 [1 \
7 Z' t! `" W( u6 M+ R' G& ~
9 O4 @' s. T/ K$ k9 k- v
struct timer_list timer_list[TIMER_REQUESTS] = {NULL};
# P) r" h, d( @* T; J% n; ?$ w* S. ~, d0 F# K$ ~3 ~0 R
struct timer_list *timer_header = NULL;& V1 Y) l, k: J) U* `1 I o
! Q, R3 E% V+ C
4 k- ~: I; J1 A& Gvoid add_timer(unsigned short
0 {( Z" S; ^4 U/ K: Y$ Njiffies,void (*callback)())+ F& E5 G& s1 p. z
{! U! m; _ o; O8 ?/ _
! s ?- H! b) d+ ^struct timer_list *ptmp;. H `6 h( r3 @$ }9 k& r$ r U+ @
1 P5 O4 ~9 ~ j9 h; o9 L, r2 e
; V0 {6 V& }$ R' S. Wif(!callback)' X0 {8 _- W {7 s
) j+ | h" T+ Ureturn ;5 |5 g* u6 ^4 I8 a7 }* ~
1 w, W4 K V) u- C2 Y6 R9 f, N+ Z) H% [
0 X, ?" O7 F9 ]& [0 K) ]- X& Q: T2 _& q: q5 G! w
EA = 0;
, y. k7 @5 f; k* H& e
4 y5 K% q5 D/ { @7 {/ z+ u6 D6 D: ~/ q4 a1 Z
if(jiffies <= 0)
8 ]: Q+ l) y& v; j3 m) l
' N! S. H) A. h0 x. C(*callback)();
4 ], D, d; L7 E& V$ ~% J; D2 D; N9 s" l# v# _7 v" R
* u2 b" v) i* c2 G$ ?6 U$ ?: J
$ m( b+ _5 N+ @2 ^; hfor(ptmp = timer_list; ptmp < timer_list + TIMER_REQUESTS; ptmp++)
, |3 T* {' k0 t0 S+ O* r7 p4 a' ` x
if(ptmp->callback == NULL)5 e" P9 g5 E d) i! Z9 T
; R$ I6 E/ k. J5 Ebreak;
3 {! f# Z/ |+ f6 g1 ^. G$ E& L5 k
) x( o$ P. Y/ h4 ~9 ?
. v, z( n' G7 Z6 u5 i0 h
- V& G8 T' Z6 k! G, hif(ptmp >= timer_list + TIMER_REQUESTS) w* w+ q% w7 J) r h4 Z( v8 j
, k. X& J1 E* M, e9 s; H{( Q% ]7 _" a" u2 a# Q& I2 Y8 M4 V2 k
O/ z1 @1 r1 F! }2 O! i+ ~4 O
goto EXIT;% [# Q5 I1 x* S2 q1 |
1 v$ v/ s5 B+ \; `
} - [; u* `8 @' H/ e y x
$ w( i9 z& \: g
, p" T# b1 F, S; O9 t* n# L! e: ?# }0 T4 Eptmp->jiffies = jiffies;: s: m& x& @/ E; ?
) s8 M" L+ N0 D* H4 Optmp->callback = callback;
% X, ] z" ?- q( @0 h: C- R" h- N3 E
8 J2 f0 r @2 G3 ^
6 Z& A% R4 s, x5 s4 {2 N
ptmp->next = timer_header;
; K8 a8 A b5 a# r& B( ]0 w0 r! F# W
timer_header = ptmp;
- O4 }- y9 n6 x+ Z5 Y. C& f" E8 }
5 E! O1 s3 f: C9 F, U$ ]/ ~% V//add bellow code to fix linux on timer’s bugs ++
; ]" I3 K- ~! \9 U4 m6 D" |
. c4 Z, @& j$ T3 ]3 Z& l5 xif(ptmp->next && ptmp->next->jiffies > ptmp->jiffies)
9 u8 E2 S5 k. T, h ^% f( X; R6 b+ d5 Q" h) u: h
{3 F3 W( S; M4 K9 T2 g& ?; O% P
' ?' l* y1 B9 ]6 @ptmp->next->jiffies -= ptmp->jiffies;
( w) S( r" H) B3 }8 n1 C# T
) a6 I) A0 v9 v# O/ N% G}//end ++
: w# g& |7 B0 E! u/ g! ]
; \2 V1 L- B- k, _7 `) f7 k' u( {else0 [1 d) r+ ?' _1 J% }
2 _7 A. o) ~: K' u9 n3 F
{6 \1 ]8 _7 y8 V; t, F
; E2 A' j5 D3 ]: H3 L" X2 G; L; }
while(ptmp->next && (ptmp->next->jiffies < ptmp->jiffies))" G6 e" {/ E7 m# i# c5 h- N
, X) c* m; n9 C' Q8 G* P5 X2 l% V. B7 h# j. D I( L
{) M1 v1 d7 N. `4 e- N7 n
5 n& \1 j! x5 a: T) eptmp->jiffies -= ptmp->next->jiffies;& x* g s6 y5 a2 |$ D
! d) Z9 N2 N8 R2 Ucallback = ptmp->callback; U3 ]8 y% x2 k( L
7 [5 U1 Z% g4 z
ptmp->callback = ptmp->next->callback;
; A ^) u; ?6 A9 x+ ?2 h1 P
. H! c. R9 F# f2 U; W- U5 Gptmp->next->callback = callback;
) J! l1 p: u. O6 _, m7 m9 D) z9 {" q
@1 n5 {# K5 C$ d4 _jiffies = ptmp->jiffies;
, A) N4 {4 ~8 [. F( W
+ C* K* W q1 o. p; Iptmp->jiffies = ptmp->next->jiffies;# E$ q* ]3 G# r+ l
+ T4 ]! x( ^* ^8 q6 O1 W/ g) E
ptmp->next->jiffies = jiffies;8 g A3 E5 e2 C
7 t% p+ Z& F4 J# j8 B% ~; D3 R
ptmp = ptmp->next;
9 p! x+ @6 y9 k4 M
0 T/ u2 p* Q, G8 d: H}; A) O4 M0 x* O5 B5 Y+ \: |% H
5 M: J7 \+ \( |2 E$ g: B
}* z$ j9 |# q! a% C! D, f0 y
# z7 V$ T1 s. o( ^& o3 W
EXIT:
/ T' ]2 R) g! T7 t8 b" U
# `8 S' {( B, |8 c4 eEA = 1;% A! ]) \# m, }, ?7 T
3 X0 d) X% ~" }! | d) Preturn;! r* @6 l+ J* }+ r$ T
}) T1 a7 w5 a+ v7 C8 {4 Q" y$ X
7 ^& ^) @9 I+ s) | ^4 I
void do_timer(void)
( t T) Q* ~9 r" R6 c" a5 E- m{1 W+ V' o% m3 ~3 \) T( k( I5 i) o
' P3 N7 T, e; J8 v
9 a2 }, ?$ g/ N- Y* A& X+ Dwhile((timer_header != NULL)
! o3 B4 `* r: ^8 u5 d4 c; s
4 w1 a* L) F% R( P1 t; b6 u/ O) D1 H7 W) u% b9 A& S
&&(timer_header->callback != NULL)! ?, \- J: W) t& Z7 W
+ L: f( E9 \& v: m1 J. y% X5 i) w- i. w1 ^
&&(--timer_header->jiffies <= 0))2 G/ T: h d9 c- y- x
1 {1 B6 L V) \ l/ }" I{
& G& [0 X3 C% P) c0 {; Q% P0 y; K+ y7 w4 e' k
void (*callback_fptr)(void);
# ~5 v$ q0 `" S, j/ R+ g+ ?6 N3 k& Q/ v( q, D; S4 Y
+ n z) l7 A' R. N- Xcallback_fptr = timer_header->callback;
. A/ v* t" k$ X* P- @
4 g, s7 A) L; {6 N4 x$ wtimer_header->callback = NULL;
) E0 z' A* y) |' U
) T. U8 S$ d, f: r+ g$ {2 X- ytimer_header = timer_header->next;
# z- k2 o: o& L x" f% R% M6 t
: g- B' F. ~. f( Q K0 r- s5 h(*callback_fptr)();
: d8 X( \+ J3 C2 {! {& t5 L2 W
7 j$ E0 z) p# W4 ]}, Y" i' N* M O6 T" S, A- T
4 q5 k! h1 j! L) w5 v1 C
/ l, x- w2 s; c# P4 U
}
5 U( g) V f8 V4 g///////////////////////////////////////////////////" I4 u( |4 i$ }4 R" L/ n, T
$ {. h) g; _7 f5 i0 |8 r6 X. V; x3 I8 P4 J5 V2 g! E
上述code,我已经导入并开始测试了,短短几十行代码大大改善了我的code base的感官,降低了代码的耦合度,现在看上去清爽多了J!
" i9 @9 D, `3 u, w* d: R, r+ t/ t6 R
野人献曝,博君一笑. D. O* J+ N- \, c: x4 b3 Q
: K1 F4 e2 m% f8 Q8 |
Peter
& ]3 w0 @. {3 j% c# w
1 c) \% F7 T: w: p' U9 N, w3 V( \) K, z; Y# h
[ 本帖最后由 peterhu 于 2009-4-20 09:51 编辑 ] |
|