OSDN Git Service

Initial Commit. Toppers/JSP for Blackfin 3.3.1
[trx-305dsp/dsp.git] / trx305 / kernel / sample / cxx_sample2.cpp
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) 2003-2004 Takagi Nobuhisa
9  * 
10  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
11  *  によって公表されている GNU General Public License の Version 2 に記
12  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
13  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
14  *  利用と呼ぶ)することを無償で許諾する.
15  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17  *      スコード中に含まれていること.
18  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
20  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
21  *      の無保証規定を掲載すること.
22  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
23  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
24  *      と.
25  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
26  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
27  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
28  *        報告すること.
29  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
30  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
31  * 
32  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
33  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
34  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
35  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
36  * 
37  *  @(#) $Id: cxx_sample2.cpp,v 1.1 2009/01/31 05:27:37 suikan Exp $
38  */
39
40 /*
41  *  C++サンプルプログラム(2)の本体
42  *
43  *  このサンプルプログラムは「哲学者の食事」をベースとして、C++の各機能
44  *  のデモを行っている。
45  *  5人の哲学者が左右のフォークを取る際、故意にデッドロックを発生させ、
46  *  タイムアウトを検出した時点でC++の例外を送出している。
47  *
48  *  動作中に'q'を入力すると動作を停止することができ、restart? [y|n]に対
49  *  して'y'を入力すれば再起動、'n'を入力すれば終了する。
50  *  また、動作中に'a'を入力すればアボートする。
51  */
52
53 #include <t_services.h>
54 #include <cstdlib>
55 #include <new>
56 #include "kernel_id.h"
57 #include "cxx_sample2.h"
58
59 //  非マルチタスクテストクラス
60 //  静的オブジェクトのコンストラクタとデストラクタの動作サンプル
61 class non_multitask_test
62 {
63     int* x_;
64 public:
65     non_multitask_test()
66         : x_(new int(12345))    // カーネル非動作状態でのnew演算子
67     {
68     }
69     ~non_multitask_test()
70     {
71         if (*x_== 12345)
72             syslog(LOG_NOTICE,"non-multitask test succeeded");
73         else
74             syslog(LOG_NOTICE,"non-multitask test failed");
75         delete x_;              // カーネル非動作状態でのdelete演算子
76         x_ = 0;
77     }
78 } test;
79
80 class timeout_error
81 {
82 };
83
84 // 擬似乱数
85 int rnd()
86 {
87     static unsigned int seed = 1;
88     loc_cpu();
89     seed = seed * 1566083941UL + 1;
90     unl_cpu();
91     return (seed >> 16) % 0x7fff;
92 }
93
94 //  フォーククラス
95 class fork
96 {
97     ID semid_;
98     bool used_;
99 public:
100     explicit fork(int semid)
101         : semid_(semid), used_(false)
102     {
103     }
104     ~fork()
105     {
106         if (used_)
107             give();
108     }
109     ID id() const { return semid_; }
110     bool is_used() const { return used_; }
111     void take()
112     {
113         if (twai_sem(semid_, 500*5) == E_TMOUT)
114             throw timeout_error();
115         used_ = true;
116     }
117     void give()
118     {
119         used_ = false;
120         sig_sem(semid_);
121     }
122 };
123
124 fork* p_fork[5];
125
126 //  哲学者クラス
127 class philosopher
128 {
129     ID      tskid_;
130     fork* left_;
131     fork* right_;
132 public:
133     explicit philosopher(int tskid, fork* left, fork* right)
134         : tskid_(tskid),
135             left_(left), right_(right)
136     {
137         syslog(LOG_NOTICE,"philosofer #%d", tskid);
138     }
139     void think()
140     {
141         syslog(LOG_NOTICE, "#%d thinking...", tskid_);
142         dly_tsk(100 * (rnd() % 5 + 1));
143     }
144     void eat()
145     {
146         syslog(LOG_NOTICE, "#%d eat up", tskid_);
147         dly_tsk(100 * (rnd() % 5 + 1));
148     }
149     void run()
150     {
151         for (;;)
152         {
153             try
154             {
155                 //  意図的にデッドロックを発生させる。
156                 left_->take();
157                 syslog(LOG_NOTICE, "#%d take left fork(%d)", tskid_, left_->id());
158
159                 dly_tsk(100 * (rnd() % 5 + 1));
160
161                 right_->take();
162                 syslog(LOG_NOTICE, "#%d take right fork(%d)", tskid_, right_->id());
163
164                 eat();
165
166                 left_->give();
167                 syslog(LOG_NOTICE, "#%d give left fork(%d)", tskid_, left_->id());
168                 right_->give();
169                 syslog(LOG_NOTICE, "#%d give right fork(%d)", tskid_, right_->id());
170                 think();
171             }
172             catch (timeout_error&)
173             {
174                 //  タイムアウトによりデッドロックを検出すると、フォークを放す。
175                 syslog(LOG_NOTICE, "#%d !!!! timeout error !!!!", tskid_);
176                 if (left_->is_used())
177                 {
178                     left_->give();
179                     syslog(LOG_NOTICE, "#%d give left fork(%d)", tskid_, left_->id());
180                 }
181                 if (right_->is_used())
182                 {
183                     right_->give();
184                     syslog(LOG_NOTICE, "#%d give right fork(%d)", tskid_, right_->id());
185                 }
186                 rot_rdq(TPRI_SELF);
187             }
188         }
189     }
190 };
191
192 void task(VP_INT exinf)
193 {
194     _toppers_cxxrt_reset_specific();    // タスクの再起動を可能にするための初期化処理
195     ID      tskid = ID(exinf);
196     fork* left  = p_fork[(tskid - 1) % 5];
197     fork* right = p_fork[(tskid - 1 + 4) % 5];
198     philosopher phil(tskid, left, right);
199     phil.run();
200 }
201
202 //  std::atexitで登録する終了時関数
203 void finish()
204 {
205     syslog(LOG_NOTICE, "finish");
206 }
207
208
209 //  メインタスク
210 void main_task(VP_INT exinf)
211 {
212     serial_ctl_por(TASK_PORTID, (IOCTL_CRLF | IOCTL_FCSND | IOCTL_FCRCV));
213     syslog(LOG_NOTICE,"Sample program starts (exinf = %d)", exinf);
214
215     std::atexit(finish);
216
217     try
218     {
219         for (;;)
220         {
221             for (ID semid = 1; semid <= 5; semid++)
222                 p_fork[semid - 1] = new fork(semid);
223
224             for (ID tskid = 1; tskid <= 5; tskid++)
225                 act_tsk(tskid);
226
227             char c;
228             do
229             {
230                 serial_rea_dat(TASK_PORTID, &c, 1);
231                 if (c == 'a')
232                     std::abort();
233             } while (c != 'q' && c != 'Q');
234
235             for (ID tskid = 1; tskid <= 5; tskid++)
236             {
237                 ter_tsk(tskid);
238             }
239
240             for (ID semid = 1; semid <= 5; semid++)
241             {
242                 delete p_fork[semid - 1];
243                 p_fork[semid - 1] = 0;
244             }
245
246             do
247             {
248                 syslog(LOG_NOTICE, "restart? [y|n] ");
249                 serial_rea_dat(TASK_PORTID, &c, 1);
250             } while (c != 'y' && c != 'n');
251
252             if (c == 'n')
253                 break;
254         }
255
256         syslog(LOG_NOTICE, "multitask test succeeded");
257     }
258     catch (std::bad_alloc&)
259     {
260         syslog(LOG_NOTICE, "multitask test failed");
261     }
262
263     std::exit(0);
264 }
265