source: asp_wo_cfg/trunk/target/macosx_gcc/target_config.c@ 50

Last change on this file since 50 was 50, checked in by ertl-hiro, 12 years ago

ターゲット依存のエラーチェックコードを追加。

  • Property svn:keywords set to Id
File size: 14.9 KB
Line 
1/*
2 * TOPPERS/ASP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Advanced Standard Profile Kernel
5 *
6 * Copyright (C) 2006-2012 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
8 *
9 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
10 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14 * スコード中に含まれていること.
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18 * の無保証規定を掲載すること.
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
21 * と.
22 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
23 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
24 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
25 * 報告すること.
26 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
27 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
28 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
29 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
30 * 免責すること.
31 *
32 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
33 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
34 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
35 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
36 * の責任を負わない.
37 *
38 * @(#) $Id: target_config.c 50 2012-09-07 03:47:18Z ertl-hiro $
39 */
40
41/*
42 * ターゲット依存モジュール(Mac OS X用)
43 */
44
45#include "kernel_impl.h"
46#include "task.h"
47#include "interrupt.h"
48#include "exception.h"
49
50/*
51 * トレースログマクロのデフォルト定義
52 */
53#ifndef LOG_DSP_ENTER
54#define LOG_DSP_ENTER(p_tcb)
55#endif /* LOG_DSP_ENTER */
56
57#ifndef LOG_DSP_LEAVE
58#define LOG_DSP_LEAVE(p_tcb)
59#endif /* LOG_DSP_LEAVE */
60
61#ifndef LOG_INH_ENTER
62#define LOG_INH_ENTER(inhno)
63#endif /* LOG_INH_ENTER */
64
65#ifndef LOG_INH_LEAVE
66#define LOG_INH_LEAVE(inhno)
67#endif /* LOG_INH_LEAVE */
68
69#ifndef LOG_EXC_ENTER
70#define LOG_EXC_ENTER(excno)
71#endif /* LOG_EXC_ENTER */
72
73#ifndef LOG_EXC_LEAVE
74#define LOG_EXC_LEAVE(excno)
75#endif /* LOG_EXC_LEAVE */
76
77/*
78 * TMIN_INTPRIの範囲のチェック
79 */
80#if (TMIN_INTPRI > -1) || (-6 > TMIN_INTPRI)
81#error TMIN_INTPRI out of range.
82#endif /* (TMIN_INTPRI > -1) || (-6 > TMIN_INTPRI) */
83
84/*
85 * 割込み優先度マスクによるシグナルマスク
86 */
87sigset_t sigmask_table[8];
88
89/*
90 * 割込みロック/CPUロックへの移行でマスクするシグナルを保持する変数
91 */
92sigset_t sigmask_intlock; /* 割込みロックでマスクするシグナル */
93sigset_t sigmask_cpulock; /* CPUロックでマスクするシグナル */
94
95/*
96 * CPUロックフラグ実現のための変数
97 */
98volatile bool_t lock_flag; /* CPUロックフラグを表す変数 */
99volatile sigset_t saved_sigmask; /* シグナルマスクを保存する変数 */
100
101/*
102 * 割込み優先度マスク実現のための変数
103 */
104volatile PRI ipm_value; /* 割込み優先度マスクを表す変数 */
105
106/*
107 * 割込み要求禁止フラグ実現のための変数
108 */
109volatile sigset_t sigmask_disint; /* 個別にマスクしているシグナル */
110
111/*
112 * ディスパッチャ本体の割込み待ち中であることを示す変数
113 */
114static bool_t dispatcher_idle; /* 割込み待ち中である */
115
116/*
117 * ディスパッチャ本体
118 *
119 * LOG_DSP_ENTERとLOG_DSP_LEAVEを,dispatcherに入れず,これを呼び出す
120 * 関数の側に入れている理由は次の通り.LOG_DSP_ENTERは,ディスパッチの
121 * 動作開始時(mainから呼ばれた時)には,呼び出してはならないため,
122 * dispatcherに入れることができない.LOG_DSP_LEAVEは,切換え後のタスク
123 * のスタックで呼び出さなければならないため,_longjmpを実行した後に呼
124 * び出す必要があり,dispatcherを呼び出す関数の側に入れなければならな
125 * い.
126 */
127static void
128dispatcher(void)
129{
130 sigset_t sigmask;
131
132 while ((p_runtsk = p_schedtsk) == NULL) {
133 /*
134 * CPUロック状態を解除する準備をする.sigmaskには,CPUロック状
135 * 態に移行する前のシグナルマスクを取り出す.
136 */
137 lock_flag = false;
138 sigassignset(&sigmask, &saved_sigmask);
139 do {
140 /*
141 * 割込み待ちの間に発生した割込みハンドラではSIGUSR2を
142 * raiseしないように,dispatcher_idleをtrueにする.
143 */
144 dispatcher_idle = true;
145 sigsuspend(&sigmask); /* 割込み待ち */
146 dispatcher_idle = false;
147 } while (!reqflg);
148 reqflg = false;
149
150 /*
151 * CPUロック状態に戻す.割込み待ちの間に実行した割込みハンドラ
152 * により,saved_sigmaskは書き換わる可能性があるため,元の値に
153 * 戻す必要がある.
154 */
155 sigassignset(&saved_sigmask, &sigmask);
156 lock_flag = true;
157 }
158 _longjmp(p_runtsk->tskctxb.env, 1);
159}
160
161/*
162 * 最高優先順位タスクへのディスパッチ
163 */
164void
165dispatch(void)
166{
167#ifdef TOPPERS_SUPPORT_OVRHDR
168 ovrtimer_stop(); /* オーバランタイマの停止 */
169#endif /* TOPPERS_SUPPORT_OVRHDR */
170 if (_setjmp(p_runtsk->tskctxb.env) == 0) {
171 LOG_DSP_ENTER(p_runtsk);
172 dispatcher();
173 assert(0);
174 }
175 LOG_DSP_LEAVE(p_runtsk);
176#ifdef TOPPERS_SUPPORT_OVRHDR
177 ovrtimer_start(); /* オーバランタイマの動作開始 */
178#endif /* TOPPERS_SUPPORT_OVRHDR */
179 calltex();
180}
181
182/*
183 * 最高優先順位タスクへのディスパッチ(シグナルハンドラ用)
184 */
185static void
186dispatch_handler(int sig, struct __siginfo *p_info, void *p_ctx)
187{
188#ifdef TOPPERS_SUPPORT_OVRHDR
189 /*
190 * オーバランハンドラ機能をサポートする場合には,dispatch_handler
191 * は必ず起動される.ディスパッチが必要ない場合には,オーバランハ
192 * ンドラの動作開始のみを行う.
193 */
194 if (!(!dispatcher_idle && reqflg)) {
195 ovrtimer_start(); /* オーバランタイマの動作開始 */
196 return;
197 }
198 reqflg = false;
199#endif /* TOPPERS_SUPPORT_OVRHDR */
200
201 /*
202 * シグナルハンドラの実行開始前のシグナルマスクをsaved_sigmaskに代
203 * 入し,CPUロック状態に移行する.
204 */
205 sigassignset(&saved_sigmask, &(((ucontext_t *) p_ctx)->uc_sigmask));
206 lock_flag = true;
207
208 if (dspflg && p_runtsk != p_schedtsk) {
209 if (_setjmp(p_runtsk->tskctxb.env) == 0) {
210 LOG_DSP_ENTER(p_runtsk);
211 dispatcher();
212 assert(0);
213 }
214 LOG_DSP_LEAVE(p_runtsk);
215 }
216#ifdef TOPPERS_SUPPORT_OVRHDR
217 ovrtimer_start(); /* オーバランタイマの動作開始 */
218#endif /* TOPPERS_SUPPORT_OVRHDR */
219 calltex();
220
221 /*
222 * シグナルハンドラからのリターン後のシグナルマスクがsaved_sigmask
223 * になるように設定し,CPUロック状態を解除する.
224 */
225 lock_flag = false;
226 sigassignset(&(((ucontext_t *) p_ctx)->uc_sigmask), &saved_sigmask);
227}
228
229/*
230 * 現在のコンテキストを捨ててディスパッチ
231 */
232void
233exit_and_dispatch(void)
234{
235 LOG_DSP_ENTER(p_runtsk);
236 dispatcher();
237 assert(0);
238}
239
240/*
241 * 割込みハンドラ出口処理
242 *
243 * 割込みハンドラ中では,カーネル管理の割込みを禁止しているため,出口
244 * 処理で割込みを禁止する必要はない.
245 */
246void
247ret_int(void)
248{
249#ifndef TOPPERS_SUPPORT_OVRHDR
250 /*
251 * ディスパッチャの起動を要求する.
252 *
253 * reqflgをチェックした直後に割込みが入っても,入った側の割込みで
254 * タスクディスパッチャの起動を要求するため,reqflgをチェックする
255 * 前に割込みを禁止する必要がない.
256 */
257 if (!dispatcher_idle && reqflg) {
258 reqflg = false;
259 raise(SIGUSR2);
260 }
261#else /* TOPPERS_SUPPORT_OVRHDR */
262 /*
263 * オーバランハンドラ機能をサポートする場合には,オーバランタイマ
264 * を動作開始するために,dispatch_handlerを必ず起動する.
265 */
266 raise(SIGUSR2);
267#endif /* TOPPERS_SUPPORT_OVRHDR */
268}
269
270/*
271 * CPU例外ハンドラ出口処理
272 */
273void
274ret_exc(void)
275{
276#ifndef TOPPERS_SUPPORT_OVRHDR
277 /*
278 * ディスパッチャの起動を要求する.
279 *
280 * reqflgをチェックした直後に割込みが入っても,入った側の割込みで
281 * タスクディスパッチャの起動を要求するため,reqflgをチェックする
282 * 前に割込みを禁止する必要がない.
283 */
284 if (!dispatcher_idle && reqflg) {
285 reqflg = false;
286 raise(SIGUSR2);
287 }
288#else /* TOPPERS_SUPPORT_OVRHDR */
289 /*
290 * オーバランハンドラ機能をサポートする場合には,オーバランタイマ
291 * を動作開始するために,dispatch_handlerを必ず起動する.
292 */
293 raise(SIGUSR2);
294#endif /* TOPPERS_SUPPORT_OVRHDR */
295}
296
297/*
298 * カーネルの終了処理の呼出し
299 */
300void
301call_exit_kernel(void)
302{
303 sigset_t sigmask;
304 struct sigaction sigact;
305
306 /*
307 * SIGUSR2のシグナルハンドラにexit_kernelを登録
308 */
309 sigact.sa_handler = (void (*)(int)) exit_kernel;
310 sigact.sa_flags = SA_ONSTACK;
311 sigemptyset(&(sigact.sa_mask));
312 sigaction(SIGUSR2, &sigact, NULL);
313
314 /*
315 * SIGUSR2のマスクを解除
316 */
317 sigemptyset(&sigmask);
318 sigaddset(&sigmask, SIGUSR2);
319 sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
320
321 /*
322 * exit_kernelの呼出し
323 */
324 raise(SIGUSR2);
325 assert(0);
326 while (true);
327}
328
329/*
330 * タスク開始時処理
331 */
332void
333start_r(void)
334{
335#ifdef TOPPERS_SUPPORT_OVRHDR
336 ovrtimer_start(); /* オーバランタイマの動作開始 */
337#endif /* TOPPERS_SUPPORT_OVRHDR */
338 t_unlock_cpu();
339 (*(p_runtsk->p_tinib->task))(p_runtsk->p_tinib->exinf);
340 (void) ext_tsk();
341 assert(0);
342}
343
344/*
345 * 割込みハンドラの出入口処理
346 */
347static void
348generic_inthdr(int sig, struct __siginfo *p_info, void *p_ctx)
349{
350 PRI saved_ipm;
351 INHNO inhno;
352 INTNO intno;
353 IINTHDR inthdr;
354
355 saved_ipm = ipm_value;
356 inhno = (INHNO)(sig);
357 intno = INTNO_INHNO(inhno);
358 inthdr = get_inhinib(inhno)->inthdr;
359 ipm_value = get_intinib(intno)->intpri;
360 OVRTIMER_STOP();
361 LOG_INH_ENTER(intno);
362 inthdr(intno); /* 割込みハンドラを呼び出す */
363 LOG_INH_LEAVE(intno);
364 ret_int(); /* 割込みハンドラ出口処理を呼び出す */
365 ipm_value = saved_ipm;
366 lock_flag = false;
367}
368
369/*
370 * CPU例外ハンドラの出入口処理
371 */
372static void
373generic_exchdr(int sig, struct __siginfo *p_info, void *p_ctx)
374{
375 bool_t saved_lock_flag;
376 EXCNO excno;
377 EXCHDR exchdr;
378
379 saved_lock_flag = lock_flag;
380 excno = (EXCNO)(sig);
381 exchdr = get_excinib(excno)->exchdr;
382 if (exc_sense_nonkernel(p_ctx)) {
383 /* カーネル管理外のCPU例外ハンドラの場合 */
384 exchdr(p_ctx); /* CPU例外ハンドラを呼び出す */
385 }
386 else {
387 /* カーネル管理のCPU例外ハンドラの場合 */
388 OVRTIMER_STOP();
389 LOG_EXC_ENTER(excno);
390 exchdr(p_ctx); /* CPU例外ハンドラを呼び出す */
391 LOG_EXC_LEAVE(excno);
392 ret_exc(); /* CPU例外ハンドラ出口処理を呼び出す */
393 }
394 lock_flag = saved_lock_flag;
395}
396
397/*
398 * サービスコールのターゲット依存エラーチェックコード
399 */
400ER
401target_check_cint(INTNO intno, const T_CINT *pk_cint)
402{
403 if ((pk_cint->intatr & TA_EDGE) == 0U) {
404 /*
405 * レベルトリガはサポートしていない.
406 */
407 return(E_RSATR);
408 }
409 else if (excinib_table[INDEX_INTNO(intno)].excatr != TA_NOEXS) {
410 /*
411 * CPU例外ハンドラが定義されたシグナルに対して,割込み要求ライ
412 * ンの属性を設定しようとした場合は,E_OBJエラーとする.
413 */
414 return(E_OBJ);
415 }
416 return(E_OK);
417}
418
419ER
420target_check_dexc(EXCNO excno, const T_DEXC *pk_dexc)
421{
422 if (intinib_table[INDEX_EXCNO(excno)].intatr != TA_NOEXS) {
423 /*
424 * 割込み要求ラインの属性が設定されたシグナルに対して,CPU例外
425 * ハンドラを定義しようとした場合は,E_OBJエラーとする.
426 */
427 return(E_OBJ);
428 }
429 return(E_OK);
430}
431
432/*
433 * ターゲット依存の初期化
434 */
435void
436target_initialize(void)
437{
438 struct sigaction sigact;
439 uint_t i;
440
441 for (i = 0; i < TNUM_INTNO; i++) {
442 intinib_table[i].intpri = 0;
443 }
444
445 /*
446 * マスクできないシグナル
447 */
448 intinib_table[INDEX_INTNO(SIGKILL)].intpri = -7;
449 intinib_table[INDEX_INTNO(SIGSTOP)].intpri = -7;
450
451 /*
452 * デバッグ用にマスクしないシグナル
453 */
454 intinib_table[INDEX_INTNO(SIGINT)].intpri = -7;
455 intinib_table[INDEX_INTNO(SIGBUS)].intpri = -7;
456 intinib_table[INDEX_INTNO(SIGSEGV)].intpri = -7;
457
458 /*
459 * CPUロックフラグ実現のための変数の初期化
460 *
461 * saved_sigmaskは,カーネル起動時に呼び出すset_sigmaskで初期化さ
462 * れる.
463 */
464 lock_flag = true;
465
466 /*
467 * 割込み優先度マスク実現のための変数の初期化
468 */
469 ipm_value = TIPM_ENAALL;
470
471 /*
472 * ディスパッチャ本体のアイドルループ中であることを示す変数の初期化
473 */
474 dispatcher_idle = false;
475
476 /*
477 * SIGUSR2のシグナルハンドラにディスパッチャを登録
478 */
479 sigact.sa_sigaction = dispatch_handler;
480 sigact.sa_flags = SA_SIGINFO;
481 sigassignset(&(sigact.sa_mask), &sigmask_cpulock);
482 sigaction(SIGUSR2, &sigact, NULL);
483}
484
485/*
486 * 割込み/CPU例外の初期化処理(ターゲット依存)
487 */
488void
489target_prepare(void)
490{
491 uint_t i;
492 PRI intpri;
493 sigset_t sigmask;
494 struct sigaction sigact;
495
496 /*
497 * 割込み優先度マスクによるシグナルマスクの設定
498 */
499 for (intpri = 0; intpri >= -6; intpri--) {
500 sigemptyset(&sigmask);
501 for (i = 0; i < TNUM_INTNO; i++) {
502 if (excinib_table[i].excatr == TA_NOEXS
503 && intinib_table[i].intpri >= intpri) {
504 sigaddset(&sigmask, i + 1);
505 }
506 }
507 sigmask_table[-intpri] = sigmask;
508 }
509 sigmask_table[7] = sigmask;
510
511 /*
512 * 割込みロックへの移行でマスクするシグナルを保持する変数の初期化
513 */
514 sigassignset(&sigmask_intlock, &(sigmask_table[6]));
515 sigaddset(&sigmask_intlock, SIGUSR2);
516
517 /*
518 * CPUロックへの移行でマスクするシグナルを保持する変数の初期化
519 */
520 sigassignset(&sigmask_cpulock, &(sigmask_table[-TMIN_INTPRI]));
521 sigaddset(&sigmask_cpulock, SIGUSR2);
522
523 /*
524 * 割込み要求禁止フラグ実現のための変数の初期化
525 */
526 sigemptyset(&sigmask_disint);
527 for (i = 0; i < TNUM_INTNO; i++) {
528 if (intinib_table[i].intatr != TA_NOEXS
529 && (intinib_table[i].intatr & TA_ENAINT) == 0) {
530 sigaddset(&sigmask_disint, i + 1);
531 }
532 }
533
534 for (i = 0; i < TNUM_INHNO; i++) {
535 if (inhinib_table[i].inhatr != TA_NOEXS) {
536 sigact.sa_sigaction = generic_inthdr;
537 sigact.sa_flags = SA_ONSTACK;
538 sigassignset(&(sigact.sa_mask),
539 &sigmask_table[-intinib_table[i].intpri]);
540 sigaddset(&(sigact.sa_mask), SIGUSR2);
541 sigaction(i + 1, &sigact, NULL);
542 }
543 }
544
545 for (i = 0; i < TNUM_EXCNO; i++) {
546 if (excinib_table[i].excatr != TA_NOEXS) {
547 /*
548 * SA_NODEFERにより,シグナルハンドラの起動時に,そのシグ
549 * ナルをマスクするのを抑止している.
550 */
551 sigact.sa_sigaction = generic_exchdr;
552 sigact.sa_flags = (SA_ONSTACK | SA_SIGINFO | SA_NODEFER);
553 sigemptyset(&(sigact.sa_mask));
554 sigaddset(&(sigact.sa_mask), SIGUSR2);
555 sigaction(i + 1, &sigact, NULL);
556 }
557 }
558}
559
560/*
561 * ターゲット依存の終了処理
562 */
563void
564target_exit(void)
565{
566 /*
567 * プロセスの終了処理
568 */
569 exit(0);
570}
571
572/*
573 * システムログの低レベル出力のための文字出力
574 */
575void
576target_fput_log(char c)
577{
578 write(STDERR_FILENO, &c, 1);
579}
580
581/*
582 * メイン関数
583 */
584int
585main()
586{
587 sigset_t sigmask;
588 stack_t ss;
589 struct sigaction sigact;
590
591 /*
592 * SIGUSR2以外のすべてのシグナルをマスク
593 */
594 sigfillset(&sigmask);
595 sigdelset(&sigmask, SIGUSR2);
596 sigprocmask(SIG_BLOCK, &sigmask, NULL);
597
598 /*
599 * シグナルスタック(非タスクコンテキスト用のスタック)の設定
600 */
601 ss.ss_sp = (char *)(istk);
602 ss.ss_size = (int)(istksz);
603 ss.ss_flags = 0;
604 sigaltstack(&ss, NULL);
605
606 /*
607 * SIGUSR2のシグナルハンドラにsta_kerを登録
608 */
609 sigact.sa_handler = (void (*)(int)) sta_ker;
610 sigact.sa_flags = SA_ONSTACK;
611 sigemptyset(&(sigact.sa_mask));
612 sigaction(SIGUSR2, &sigact, NULL);
613
614 /*
615 * sta_kerの呼出し
616 */
617 raise(SIGUSR2);
618
619 /*
620 * ディスパッチャの動作開始
621 *
622 * target_initializeで,lock_flagをtrueに,ipm_valueをTIPM_ENAALL
623 * に初期化しているため,set_sigmaskを呼び出してシグナルマスクと
624 * saved_sigmaskを設定することで,CPUロック状態・(モデル上の)割
625 * 込み優先度マスクがTIPM_ENAALLの状態になる.
626 *
627 * また,initialize_taskでdisdspをfalseに初期化しているため,ディ
628 * スパッチ許可状態になっている.
629 */
630 set_sigmask();
631 dispatcher();
632 assert(0);
633 return(0);
634}
Note: See TracBrowser for help on using the repository browser.