source: anotherchoice/tags/jsp-1.4.4-full-UTF8/kernel/time_event.c@ 26

Last change on this file since 26 was 26, checked in by ykominami, 10 years ago

initial

File size: 11.3 KB
Line 
1/*
2 * TOPPERS/JSP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Just Standard Profile Kernel
5 *
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 * Copyright (C) 2006 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 *
11 * 上記著作権者
12は,以下の (1)〜(4) の条件か,Free Software Foundation
13 * によってå…
14¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
15 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
16 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
17å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
18 * 利用と呼ぶ)することを無償で許諾する.
19 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
20 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
21 * スコード中に含まれていること.
22 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
23 * 用できる形で再é…
24å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
25å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
26 * 者
27マニュアルなど)に,上記の著作権表示,この利用条件および下記
28 * の無保証規定を掲載すること.
29 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
30 * 用できない形で再é…
31å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
32 * と.
33 * (a) 再é…
34å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
35マニュアルなど)に,上記の著
36 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
37 * (b) 再é…
38å¸ƒã®å½¢æ…
39‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
40 * 報告すること.
41 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
42 * 害からも,上記著作権者
43およびTOPPERSプロジェクトをå…
44è²¬ã™ã‚‹ã“と.
45 *
46 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
47お
48 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
49 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
50 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
51 *
52 * @(#) $Id: time_event.c,v 1.9 2006/02/12 05:28:07 hiro Exp $
53 */
54
55/*
56 * タイムイベント管理モジュール
57 */
58
59#include "jsp_kernel.h"
60#include "check.h"
61#include "time_event.h"
62
63/*
64 * タイムイベントヒープ操作マクロ
65 */
66#define PARENT(index) ((index) >> 1) /* 親ノードを求める */
67#define LCHILD(index) ((index) << 1) /* 右の子ノードを求める */
68#define TMEVT_NODE(index) (tmevt_heap[(index) - 1])
69
70/*
71 * イベント発生時刻比較マクロ
72 *
73 * イベント発生時刻は,current_time からの相対値で比較する.すなわち,
74 * current_time を最小値(最も近い時刻),current_time - 1 が最大値
75 * (最も遠い時刻)とみなして比較する.
76 */
77#define EVTTIM_LT(t1, t2) (((t1) - current_time) < ((t2) - current_time))
78#define EVTTIM_LE(t1, t2) (((t1) - current_time) <= ((t2) - current_time))
79
80#ifdef __tmeini
81
82/*
83 * システム時刻のオフセット
84 */
85SYSTIM systim_offset;
86
87/*
88 * 現在のシステム時刻(単位: ミリ秒)
89 *
90 * 厳密には,前のタイムティックのシステム時刻.
91 */
92SYSTIM current_time;
93
94/*
95 * 次のタイムティックのシステム時刻(単位: 1ミリ秒)
96 */
97SYSTIM next_time;
98
99/*
100 * システム時刻積算用変数(単位: 1/TIM_DENOミリ秒)
101 */
102#if TIC_DENO != 1
103UINT next_subtime;
104#endif /* TIC_DENO != 1 */
105
106/*
107 * タイムイベントヒープの最後の使用領域のインデックス
108 */
109UINT last_index;
110
111/*
112 * タイマモジュールの初期化
113 */
114void
115tmevt_initialize(void)
116{
117 systim_offset = 0;
118 current_time = 0;
119#if TIC_DENO == 1
120 next_time = current_time + TIC_NUME;
121#else /* TIC_DENO == 1 */
122 next_subtime += TIC_NUME;
123 next_time = current_time + next_subtime / TIC_DENO;
124 next_subtime %= TIC_DENO;
125#endif /* TIC_DENO == 1 */
126 last_index = 0;
127}
128
129#endif /* __tmeini */
130
131/*
132 * タイムイベントの挿å…
133¥ä½ç½®ã‚’上向きに探索
134 *
135 * 時刻 time に発生するタイムイベントを挿å…
136¥ã™ã‚‹ãƒŽãƒ¼ãƒ‰ã‚’空けるために,
137 * ヒープの上に向かって空ノードを移動させる.移動前の空ノードの位置を
138 * index に渡すと,移動後の空ノードの位置(すなわち挿å…
139¥ä½ç½®ï¼‰ã‚’返す.
140 */
141#ifdef __tmeup
142
143UINT
144tmevt_up(UINT index, EVTTIM time)
145{
146 UINT parent;
147
148 while (index > 1) {
149 /*
150 * 親ノードのイベント発生時刻の方が早い(または同じ)
151 * ならば,index が挿å…
152¥ä½ç½®ãªã®ã§ãƒ«ãƒ¼ãƒ—を抜ける.
153 */
154 parent = PARENT(index);
155 if (EVTTIM_LE(TMEVT_NODE(parent).time, time)) {
156 break;
157 }
158
159 /*
160 * 親ノードを index の位置に移動させる.
161 */
162 TMEVT_NODE(index) = TMEVT_NODE(parent);
163 TMEVT_NODE(index).tmevtb->index = index;
164
165 /*
166 * index を親ノードの位置に更新.
167 */
168 index = parent;
169 }
170 return(index);
171}
172
173#endif /* __tmeup */
174
175/*
176 * タイムイベントの挿å…
177¥ä½ç½®ã‚’下向きに探索
178 *
179 * 時刻 time に発生するタイムイベントを挿å…
180¥ã™ã‚‹ãƒŽãƒ¼ãƒ‰ã‚’空けるために,
181 * ヒープの下に向かって空ノードを移動させる.移動前の空ノードの位置を
182 * index に渡すと,移動後の空ノードの位置(すなわち挿å…
183¥ä½ç½®ï¼‰ã‚’返す.
184 */
185#ifdef __tmedown
186
187UINT
188tmevt_down(UINT index, EVTTIM time)
189{
190 UINT child;
191
192 while ((child = LCHILD(index)) <= last_index) {
193 /*
194 * 左右の子ノードのイベント発生時刻を比較し,早い方の
195 * 子ノードの位置を child に設定する.以下の子ノード
196 * は,ここで選ばれた方の子ノードのこと.
197 */
198 if (child + 1 <= last_index
199 && EVTTIM_LT(TMEVT_NODE(child + 1).time,
200 TMEVT_NODE(child).time)) {
201 child = child + 1;
202 }
203
204 /*
205 * 子ノードのイベント発生時刻の方が遅
206い(または同じ)
207 * ならば,index が挿å…
208¥ä½ç½®ãªã®ã§ãƒ«ãƒ¼ãƒ—を抜ける.
209 */
210 if (EVTTIM_LE(time, TMEVT_NODE(child).time)) {
211 break;
212 }
213
214 /*
215 * 子ノードを index の位置に移動させる.
216 */
217 TMEVT_NODE(index) = TMEVT_NODE(child);
218 TMEVT_NODE(index).tmevtb->index = index;
219
220 /*
221 * index を子ノードの位置に更新.
222 */
223 index = child;
224 }
225 return(index);
226}
227
228#endif /* __tmedown */
229
230/*
231 * タイムイベントヒープへの登録
232 *
233 * タイムイベントブロック tmevtb を,time で指定した時間が経過後にイ
234 * ベントが発生するように,タイムイベントヒープに登録する.
235 */
236#ifdef __tmeins
237
238void
239tmevtb_insert(TMEVTB *tmevtb, EVTTIM time)
240{
241 UINT index;
242
243 /*
244 * last_index をインクリメントし,そこから上に挿å…
245¥ä½ç½®ã‚’探す.
246 */
247 index = tmevt_up(++last_index, time);
248
249 /*
250 * タイムイベントを index の位置に挿å…
251¥ã™ã‚‹ï¼Ž
252 */
253 TMEVT_NODE(index).time = time;
254 TMEVT_NODE(index).tmevtb = tmevtb;
255 tmevtb->index = index;
256}
257
258#endif /* __tmeins */
259
260/*
261 * タイムイベントヒープからの削除
262 */
263#ifdef __tmedel
264
265void
266tmevtb_delete(TMEVTB *tmevtb)
267{
268 UINT index = tmevtb->index;
269 UINT parent;
270 EVTTIM event_time = TMEVT_NODE(last_index).time;
271
272 /*
273 * 削除によりタイムイベントヒープが空になる場合は何もしない.
274 */
275 if (--last_index == 0) {
276 return;
277 }
278
279 /*
280 * 削除したノードの位置に最後のノード(last_index + 1 の位置
281 * のノード)を挿å…
282¥ã—,それを適切な位置へ移動させる.実際には,
283 * 最後のノードを実際に挿å…
284¥ã™ã‚‹ã®ã§ã¯ãªãï¼Œå‰Šé™¤ã—たノードの位
285 * 置が空ノードになるので,最後のノードを挿å…
286¥ã™ã¹ãä½ç½®ã¸å‘け
287 * て空ノードを移動させる.
288 * 最後のノードのイベント発生時刻が,削除したノードの親ノード
289 * のイベント発生時刻より前の場合には,上に向かって挿å…
290¥ä½ç½®ã‚’
291 * 探す.そうでない場合には,下に向かって探す.
292 */
293 if (index > 1 && EVTTIM_LT(event_time,
294 TMEVT_NODE(parent = PARENT(index)).time)) {
295 /*
296 * 親ノードを index の位置に移動させる.
297 */
298 TMEVT_NODE(index) = TMEVT_NODE(parent);
299 TMEVT_NODE(index).tmevtb->index = index;
300
301 /*
302 * 削除したノードの親ノードから上に向かって挿å…
303¥ä½ç½®ã‚’
304 * 探す.
305 */
306 index = tmevt_up(parent, event_time);
307 }
308 else {
309 /*
310 * 削除したノードから下に向かって挿å…
311¥ä½ç½®ã‚’探す.
312 */
313 index = tmevt_down(index, event_time);
314 }
315
316 /*
317 * 最後のノードを index の位置に挿å…
318¥ã™ã‚‹ï¼Ž
319 */
320 TMEVT_NODE(index) = TMEVT_NODE(last_index + 1);
321 TMEVT_NODE(index).tmevtb->index = index;
322}
323
324#endif /* __tmedel */
325
326/*
327 * タイムイベントヒープのå…
328ˆé ­ã®ãƒŽãƒ¼ãƒ‰ã®å‰Šé™¤
329 */
330Inline void
331tmevtb_delete_top(void)
332{
333 UINT index;
334 EVTTIM event_time = TMEVT_NODE(last_index).time;
335
336 /*
337 * 削除によりタイムイベントヒープが空になる場合は何もしない.
338 */
339 if (--last_index == 0) {
340 return;
341 }
342
343 /*
344 * ルートノードに最後のノード(last_index + 1 の位置のノード)
345 * を挿å…
346¥ã—,それを適切な位置へ移動させる.実際には,最後のノー
347 * ドを実際に挿å…
348¥ã™ã‚‹ã®ã§ã¯ãªãï¼Œãƒ«ãƒ¼ãƒˆãƒŽãƒ¼ãƒ‰ãŒç©ºãƒŽãƒ¼ãƒ‰ã«ãªã‚‹
349 * ので,最後のノードを挿å…
350¥ã™ã¹ãä½ç½®ã¸å‘けて空ノードを移動さ
351 * せる.
352 */
353 index = tmevt_down(1, event_time);
354
355 /*
356 * 最後のノードを index の位置に挿å…
357¥ã™ã‚‹ï¼Ž
358 */
359 TMEVT_NODE(index) = TMEVT_NODE(last_index + 1);
360 TMEVT_NODE(index).tmevtb->index = index;
361}
362
363/*
364 * タイムティックの供給
365 *
366 * TIC_NUME < TIC_DENO の時は,除算を使わずに時刻の更新ができるが,ソー
367 * スコードを読みやすくにするために #if の多用を避けている.
368 */
369#ifdef __isig_tim
370
371SYSCALL ER
372isig_tim(void)
373{
374 TMEVTB *tmevtb;
375 ER ercd;
376
377 LOG_ISIG_TIM_ENTER();
378 CHECK_INTCTX_UNL();
379 i_lock_cpu();
380
381 /*
382 * next_time よりイベント発生時刻の早い(または同じ)タイムイ
383 * ベントを,タイムイベントヒープから削除し,コールバック関数
384 * を呼び出す.
385 */
386 while (last_index > 0 && EVTTIM_LE(TMEVT_NODE(1).time, next_time)) {
387 tmevtb = TMEVT_NODE(1).tmevtb;
388 tmevtb_delete_top();
389 (*(tmevtb->callback))(tmevtb->arg);
390
391 /*
392 * ここで優å…
393ˆåº¦ã®é«˜ã„割込みを受け付ける.
394 */
395 i_unlock_cpu();
396 i_lock_cpu();
397 }
398
399 /*
400 * current_time を更新する.
401 */
402 current_time = next_time;
403
404 /*
405 * next_time,next_subtime を更新する.
406 */
407#if TIC_DENO == 1
408 next_time = current_time + TIC_NUME;
409#else /* TIC_DENO == 1 */
410 next_subtime += TIC_NUME % TIC_DENO;
411 next_time = current_time + TIC_NUME / TIC_DENO;
412 if (next_subtime >= TIC_DENO) {
413 next_subtime -= TIC_DENO;
414 next_time += 1u;
415 }
416#endif /* TIC_DENO == 1 */
417
418 ercd = E_OK;
419 i_unlock_cpu();
420
421 exit:
422 LOG_ISIG_TIM_LEAVE(ercd);
423 return(ercd);
424}
425
426#endif /* __isig_tim */
Note: See TracBrowser for help on using the repository browser.