OSDN Git Service

Merge branch 'experimental-1843-clean'
[toppersasp4lpc/asp.git] / asp / kernel / alarm.c
1 /*
2  *  TOPPERS/ASP Kernel
3  *      Toyohashi Open Platform for Embedded Real-Time Systems/
4  *      Advanced 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) 2005-2007 by Embedded and Real-Time Systems Laboratory
9  *              Graduate School of Information Science, Nagoya Univ., JAPAN
10  * 
11  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
12  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
13  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
14  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
15  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
16  *      スコード中に含まれていること.
17  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
18  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
19  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
20  *      の無保証規定を掲載すること.
21  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
22  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
23  *      と.
24  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
25  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
26  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
27  *        報告すること.
28  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
29  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
30  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
31  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
32  *      免責すること.
33  * 
34  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
35  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
36  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
37  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
38  *  の責任を負わない.
39  * 
40  *  @(#) $Id: alarm.c 748 2008-03-07 17:18:06Z hiro $
41  */
42
43 /*
44  *              アラームハンドラ機能
45  */
46
47 #include "kernel_impl.h"
48 #include "check.h"
49 #include "alarm.h"
50
51 /*
52  *  トレースログマクロのデフォルト定義
53  */
54 #ifndef LOG_ALM_ENTER
55 #define LOG_ALM_ENTER(p_almcb)
56 #endif /* LOG_ALM_ENTER */
57
58 #ifndef LOG_ALM_LEAVE
59 #define LOG_ALM_LEAVE(p_almcb)
60 #endif /* LOG_ALM_LEAVE */
61
62 #ifndef LOG_STA_ALM_ENTER
63 #define LOG_STA_ALM_ENTER(almid, almtim)
64 #endif /* LOG_STA_ALM_ENTER */
65
66 #ifndef LOG_STA_ALM_LEAVE
67 #define LOG_STA_ALM_LEAVE(ercd)
68 #endif /* LOG_STA_ALM_LEAVE */
69
70 #ifndef LOG_ISTA_ALM_ENTER
71 #define LOG_ISTA_ALM_ENTER(almid, almtim)
72 #endif /* LOG_ISTA_ALM_ENTER */
73
74 #ifndef LOG_ISTA_ALM_LEAVE
75 #define LOG_ISTA_ALM_LEAVE(ercd)
76 #endif /* LOG_ISTA_ALM_LEAVE */
77
78 #ifndef LOG_STP_ALM_ENTER
79 #define LOG_STP_ALM_ENTER(almid)
80 #endif /* LOG_STP_ALM_ENTER */
81
82 #ifndef LOG_STP_ALM_LEAVE
83 #define LOG_STP_ALM_LEAVE(ercd)
84 #endif /* LOG_STP_ALM_LEAVE */
85
86 #ifndef LOG_ISTP_ALM_ENTER
87 #define LOG_ISTP_ALM_ENTER(almid)
88 #endif /* LOG_ISTP_ALM_ENTER */
89
90 #ifndef LOG_ISTP_ALM_LEAVE
91 #define LOG_ISTP_ALM_LEAVE(ercd)
92 #endif /* LOG_ISTP_ALM_LEAVE */
93
94 #ifndef LOG_REF_ALM_ENTER
95 #define LOG_REF_ALM_ENTER(almid, pk_ralm)
96 #endif /* LOG_REF_ALM_ENTER */
97
98 #ifndef LOG_REF_ALM_LEAVE
99 #define LOG_REF_ALM_LEAVE(ercd, pk_ralm)
100 #endif /* LOG_REF_ALM_LEAVE */
101
102 /*
103  *  アラームハンドラの数
104  */
105 #define tnum_alm        ((uint_t)(tmax_almid - TMIN_ALMID + 1))
106
107 /*
108  *  アラームハンドラIDからアラームハンドラ管理ブロックを取り出すためのマクロ
109  */
110 #define INDEX_ALM(almid)        ((uint_t)((almid) - TMIN_ALMID))
111 #define get_almcb(almid)        (&(almcb_table[INDEX_ALM(almid)]))
112
113 /*
114  *  アラームハンドラ機能の初期化
115  */
116 #ifdef TOPPERS_almini
117
118 void
119 initialize_alarm(void)
120 {
121         uint_t  i;
122         ALMCB   *p_almcb;
123
124         for (p_almcb = almcb_table, i = 0; i < tnum_alm; p_almcb++, i++) {
125                 p_almcb->p_alminib = &(alminib_table[i]);
126                 p_almcb->almsta = false;
127         }
128 }
129
130 #endif /* TOPPERS_almini */
131
132 /*
133  *  アラームハンドラの動作開始
134  */
135 #ifdef TOPPERS_sta_alm
136
137 ER
138 sta_alm(ID almid, RELTIM almtim)
139 {
140         ALMCB   *p_almcb;
141         ER              ercd;
142
143         LOG_STA_ALM_ENTER(almid, almtim);
144         CHECK_TSKCTX_UNL();
145         CHECK_ALMID(almid);
146         CHECK_PAR(almtim <= TMAX_RELTIM);
147         p_almcb = get_almcb(almid);
148
149         t_lock_cpu();
150         if (p_almcb->almsta) {
151                 tmevtb_dequeue(&(p_almcb->tmevtb));
152         }
153         else {
154                 p_almcb->almsta = true;
155         }
156         tmevtb_enqueue(&(p_almcb->tmevtb), almtim,
157                                                                 (CBACK) call_almhdr, (void *) p_almcb);
158         ercd = E_OK;
159         t_unlock_cpu();
160
161   error_exit:
162         LOG_STA_ALM_LEAVE(ercd);
163         return(ercd);
164 }
165
166 #endif /* TOPPERS_sta_alm */
167
168 /*
169  *  アラームハンドラの動作開始(非タスクコンテキスト用)
170  */
171 #ifdef TOPPERS_ista_alm
172
173 ER
174 ista_alm(ID almid, RELTIM almtim)
175 {
176         ALMCB   *p_almcb;
177         ER              ercd;
178
179         LOG_ISTA_ALM_ENTER(almid, almtim);
180         CHECK_INTCTX_UNL();
181         CHECK_ALMID(almid);
182         CHECK_PAR(almtim <= TMAX_RELTIM);
183         p_almcb = get_almcb(almid);
184
185         i_lock_cpu();
186         if (p_almcb->almsta) {
187                 tmevtb_dequeue(&(p_almcb->tmevtb));
188         }
189         else {
190                 p_almcb->almsta = true;
191         }
192         tmevtb_enqueue(&(p_almcb->tmevtb), almtim,
193                                                                 (CBACK) call_almhdr, (void *) p_almcb);
194         ercd = E_OK;
195         i_unlock_cpu();
196
197   error_exit:
198         LOG_ISTA_ALM_LEAVE(ercd);
199         return(ercd);
200 }
201
202 #endif /* TOPPERS_ista_alm */
203
204 /*
205  *  アラームハンドラの動作停止
206  */
207 #ifdef TOPPERS_stp_alm
208
209 ER
210 stp_alm(ID almid)
211 {
212         ALMCB   *p_almcb;
213         ER              ercd;
214
215         LOG_STP_ALM_ENTER(almid);
216         CHECK_TSKCTX_UNL();
217         CHECK_ALMID(almid);
218         p_almcb = get_almcb(almid);
219
220         t_lock_cpu();
221         if (p_almcb->almsta) {
222                 p_almcb->almsta = false;
223                 tmevtb_dequeue(&(p_almcb->tmevtb));
224         }
225         ercd = E_OK;
226         t_unlock_cpu();
227
228   error_exit:
229         LOG_STP_ALM_LEAVE(ercd);
230         return(ercd);
231 }
232
233 #endif /* TOPPERS_stp_alm */
234
235 /*
236  *  アラームハンドラの動作停止(非タスクコンテキスト用)
237  */
238 #ifdef TOPPERS_istp_alm
239
240 ER
241 istp_alm(ID almid)
242 {
243         ALMCB   *p_almcb;
244         ER              ercd;
245
246         LOG_ISTP_ALM_ENTER(almid);
247         CHECK_INTCTX_UNL();
248         CHECK_ALMID(almid);
249         p_almcb = get_almcb(almid);
250
251         i_lock_cpu();
252         if (p_almcb->almsta) {
253                 p_almcb->almsta = false;
254                 tmevtb_dequeue(&(p_almcb->tmevtb));
255         }
256         ercd = E_OK;
257         i_unlock_cpu();
258
259   error_exit:
260         LOG_ISTP_ALM_LEAVE(ercd);
261         return(ercd);
262 }
263
264 #endif /* TOPPERS_istp_alm */
265
266 /*
267  *  アラームハンドラの状態参照
268  */
269 #ifdef TOPPERS_ref_alm
270
271 ER
272 ref_alm(ID almid, T_RALM *pk_ralm)
273 {
274         ALMCB   *p_almcb;
275         ER              ercd;
276     
277         LOG_REF_ALM_ENTER(almid, pk_ralm);
278         CHECK_TSKCTX_UNL();
279         CHECK_ALMID(almid);
280         p_almcb = get_almcb(almid);
281
282         t_lock_cpu();
283         if (p_almcb->almsta) {
284                 pk_ralm->almstat = TALM_STA;
285                 pk_ralm->lefttim = tmevt_lefttim(&(p_almcb->tmevtb));
286         }
287         else {
288                 pk_ralm->almstat = TALM_STP;
289         }
290         ercd = E_OK;
291         t_unlock_cpu();
292
293   error_exit:
294         LOG_REF_ALM_LEAVE(ercd, pk_ralm);
295         return(ercd);
296 }
297
298 #endif /* TOPPERS_ref_alm */
299
300 /*
301  *  アラームハンドラ起動ルーチン
302  */
303 #ifdef TOPPERS_almcal
304
305 void
306 call_almhdr(ALMCB *p_almcb)
307 {
308         PRI             saved_ipm;
309
310         /*
311          *  アラームハンドラを停止状態にする.
312          */
313         p_almcb->almsta = false;
314
315         /*
316          *  アラームハンドラを,CPUロック解除状態で呼び出す.
317          */
318         saved_ipm = i_get_ipm();
319         i_unlock_cpu();
320
321         LOG_ALM_ENTER(p_almcb);
322         (*((ALMHDR)(p_almcb->p_alminib->almhdr)))(p_almcb->p_alminib->exinf);
323         LOG_ALM_LEAVE(p_almcb);
324
325         if (!i_sense_lock()) {
326                 i_lock_cpu();
327         }
328         i_set_ipm(saved_ipm);
329 }
330
331 #endif /* TOPPERS_almcal */