4 #include "lwp_threads.h"
5 #include "lwp_watchdog.h"
15 u32 _wd_ticks_since_boot
;
17 lwp_queue _wd_ticks_queue
;
19 static void __lwp_wd_settimer(wd_cntrl
*wd
)
29 v
.ull
= diff
= diff_ticks(now
,wd
->fire
);
31 printf("__lwp_wd_settimer(%p,%llu,%lld)\n",wd
,wd
->fire
,diff
);
35 printf(" __lwp_wd_settimer(0): %lld<=0\n",diff
);
39 } else if(diff
<0x0000000080000000LL
) {
41 printf("__lwp_wd_settimer(%d): %lld<0x0000000080000000LL\n",v
.ul
[1],diff
);
46 printf("__lwp_wd_settimer(0x7fffffff)\n");
52 void __lwp_watchdog_init()
56 _wd_ticks_since_boot
= 0;
58 __lwp_queue_init_empty(&_wd_ticks_queue
);
61 void __lwp_wd_insert(lwp_queue
*header
,wd_cntrl
*wd
)
68 printf("__lwp_wd_insert(%p,%llu,%llu)\n",wd
,wd
->start
,wd
->fire
);
70 isr_nest_level
= __lwp_isr_in_progress();
71 wd
->state
= LWP_WD_INSERTED
;
75 _CPU_ISR_Disable(level
);
77 for(after
=__lwp_wd_first(header
);;after
=__lwp_wd_next(after
)) {
78 if(fire
==0 || !__lwp_wd_next(after
)) break;
79 if(fire
<after
->fire
) break;
81 _CPU_ISR_Flash(level
);
82 if(wd
->state
!=LWP_WD_INSERTED
) goto exit_insert
;
83 if(_wd_sync_level
>isr_nest_level
) {
84 _wd_sync_level
= isr_nest_level
;
85 _CPU_ISR_Restore(level
);
89 __lwp_wd_activate(wd
);
91 __lwp_queue_insertI(after
->node
.prev
,&wd
->node
);
92 if(__lwp_wd_first(header
)==wd
) __lwp_wd_settimer(wd
);
95 _wd_sync_level
= isr_nest_level
;
97 _CPU_ISR_Restore(level
);
101 u32
__lwp_wd_remove(lwp_queue
*header
,wd_cntrl
*wd
)
107 printf("__lwp_wd_remove(%p)\n",wd
);
109 _CPU_ISR_Disable(level
);
110 prev_state
= wd
->state
;
112 case LWP_WD_INACTIVE
:
114 case LWP_WD_INSERTED
:
115 wd
->state
= LWP_WD_INACTIVE
;
119 wd
->state
= LWP_WD_INACTIVE
;
120 next
= __lwp_wd_next(wd
);
121 if(_wd_sync_count
) _wd_sync_level
= __lwp_isr_in_progress();
122 __lwp_queue_extractI(&wd
->node
);
123 if(!__lwp_queue_isempty(header
) && __lwp_wd_first(header
)==next
) __lwp_wd_settimer(next
);
126 _CPU_ISR_Restore(level
);
130 void __lwp_wd_tickle(lwp_queue
*queue
)
136 if(__lwp_queue_isempty(queue
)) return;
138 wd
= __lwp_wd_first(queue
);
140 diff
= diff_ticks(now
,wd
->fire
);
142 printf("__lwp_wd_tickle(%p,%08x%08x,%08x%08x,%08x%08x,%08x%08x)\n",wd
,(u32
)(now
>>32),(u32
)now
,(u32
)(wd
->start
>>32),(u32
)wd
->start
,(u32
)(wd
->fire
>>32),(u32
)wd
->fire
,(u32
)(diff
>>32),(u32
)diff
);
146 switch(__lwp_wd_remove(queue
,wd
)) {
148 wd
->routine(wd
->usr_data
);
150 case LWP_WD_INACTIVE
:
152 case LWP_WD_INSERTED
:
157 wd
= __lwp_wd_first(queue
);
158 } while(!__lwp_queue_isempty(queue
) && wd
->fire
==0);
164 void __lwp_wd_adjust(lwp_queue
*queue
,u32 dir
,s64 interval
)
169 _CPU_ISR_Disable(level
);
170 abs_int
= gettime()+LWP_WD_ABS(interval
);
171 if(!__lwp_queue_isempty(queue
)) {
173 case LWP_WD_BACKWARD
:
174 __lwp_wd_first(queue
)->fire
+= LWP_WD_ABS(interval
);
178 if(abs_int
<__lwp_wd_first(queue
)->fire
) {
179 __lwp_wd_first(queue
)->fire
-= LWP_WD_ABS(interval
);
182 abs_int
-= __lwp_wd_first(queue
)->fire
;
183 __lwp_wd_first(queue
)->fire
= gettime();
184 __lwp_wd_tickle(queue
);
185 if(__lwp_queue_isempty(queue
)) break;
191 _CPU_ISR_Restore(level
);