source: anotherchoice/tags/jsp-1.4.4-full-UTF8/config/windows/primary_thread.c@ 26

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

initial

File size: 16.1 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 *
9 * 上記著作権者
10は,以下の (1)〜(4) の条件か,Free Software Foundation
11 * によってå…
12¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
13 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
14 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
15å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
16 * 利用と呼ぶ)することを無償で許諾する.
17 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
18 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
19 * スコード中に含まれていること.
20 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
21 * 用できる形で再é…
22å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
23å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
24 * 者
25マニュアルなど)に,上記の著作権表示,この利用条件および下記
26 * の無保証規定を掲載すること.
27 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
28 * 用できない形で再é…
29å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
30 * と.
31 * (a) 再é…
32å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
33マニュアルなど)に,上記の著
34 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
35 * (b) 再é…
36å¸ƒã®å½¢æ…
37‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
38 * 報告すること.
39 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
40 * 害からも,上記著作権者
41およびTOPPERSプロジェクトをå…
42è²¬ã™ã‚‹ã“と.
43 *
44 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
45お
46 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
47 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
48 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
49 *
50 * @(#) $Id: primary_thread.c,v 1.10 2007/04/19 07:44:46 honda Exp $
51 */
52
53#include <vwindows.h>
54#include <hal_msg.h>
55#include <hw_timer.h>
56
57#include <objbase.h>
58#include <shellapi.h>
59#include <resource.h>
60
61#include "jsp_kernel.h"
62#include "task.h"
63#include <eventlog.h>
64#include <cpu_rename.h>
65
66 /* 終了時に破棄を行う関数のキュー */
67struct tagDestructionProcedureQueue
68{
69 struct tagDestructionProcedureQueue * Next;
70 void (*DestructionProcedure)(void *);
71 void * Parameter;
72};
73
74 /*
75 * プロトタイプ宣言
76 */
77extern void kernel_start();
78extern void kernel_exit();
79
80 /*
81 * 大域変数
82 */
83HINSTANCE ProcessInstance;
84HANDLE PrimaryThreadHandle;
85HWND PrimaryDialogHandle;
86HANDLE CurrentRunningThreadHandle;
87BOOL ShutdownPostponementRequest;
88
89static HANDLE WorkerThreadHandle = NULL;
90static struct tagDestructionProcedureQueue * DestructionProcedureQueue;
91
92
93 /*
94 * 現在実行中のスレッドが指定されたタスクであるかどうかのチェック
95 */
96Inline
97int isTaskThreadRunning(TCB * tcb)
98{ return (tcb != 0) && (tcb->tskctxb.ThreadHandle == CurrentRunningThreadHandle); }
99
100
101 /*
102 * カーネルスタータ
103 * kernel_startは最後にexit_and_dispatchを呼ぶので、コンテキスト破棄に
104 * 備えて新しいスレッドを生成する。
105 */
106
107static DWORD WINAPI
108KernelStarter(LPVOID param)
109{
110 TlsAlloc();
111 TlsSetValue(TLS_LOGMASK, (LPVOID)1);
112 TlsSetValue(TLS_THREADHANDLE, (LPVOID)CurrentRunningThreadHandle);
113
114 kprintf(("KernelStarter begins performing kernel initialization.\n"));
115
116 kernel_start();
117
118 /* プログラムはここには来ない */
119
120 return 0;
121}
122
123 /*
124 * タスク例外起動ルーチン
125 * Visual C++ -> cpu_config.c に移動しました
126 * mingw/cygwin -> cpu_insn.S に移動しました
127 */
128extern void TaskExceptionPerformer(void);
129
130 /*
131 * 強制遮断ルーチン
132 * 応答を返さないオブジェクト破棄プロシジャ対策
133 */
134DWORD WINAPI
135ForceShutdownHandler(LPVOID param)
136{
137 do {
138 ShutdownPostponementRequest = FALSE;
139 Sleep(5000);
140 } while(ShutdownPostponementRequest == TRUE);
141 ExitProcess(0);
142 return 0;
143}
144
145 /*
146 * デバッグ時用ダイアログのメッセージハンドラ
147 */
148Inline LRESULT CALLBACK
149PrimaryDialogCommandHandler(WPARAM wParam, LPARAM lParam)
150{
151 static BOOL lock_flag;
152
153 switch(wParam)
154 {
155 /* 「クロックの供給を停止する」ボタン */
156 case IDC_CLOCKSUPPLY:
157 {
158 int state;
159
160 state = SendDlgItemMessage(PrimaryDialogHandle, IDC_CLOCKSUPPLY,BM_GETCHECK,0,0);
161 switch(state)
162 {
163 /* クロック停止 -> クロックを止める and 今動いているスレッドを強制停止 */
164 case BST_CHECKED:
165 if((lock_flag = sense_lock()) != TRUE)
166 dis_int(0);
167 hw_timer_terminate();
168 if(CurrentRunningThreadHandle != NULL)
169 SuspendThread(CurrentRunningThreadHandle);
170 break;
171
172 /* クロック供給再開 -> 最後に止めたスレッドの再開 and クロック供給再開 */
173 case BST_UNCHECKED:
174 if(CurrentRunningThreadHandle != NULL)
175 ResumeThread(CurrentRunningThreadHandle);
176 hw_timer_initialize();
177 if(lock_flag != TRUE)
178 ena_int(0);
179 break;
180 }
181 break;
182 }
183
184 default:
185 return FALSE;
186 }
187
188 return TRUE;
189}
190
191 /*
192 * TOPPERS/JSP スレッドモデル タスクディスパッチャ
193 */
194static void task_dispatcher(int is_taskschedule_required)
195{
196 /* いま動いているスレッド(=割込み+タスク)があれば、それを止める */
197 if(CurrentRunningThreadHandle != NULL)
198 {
199 wait_for_thread_suspension_completion(CurrentRunningThreadHandle);
200
201 //動いていたのがタスクであれば、割込みマスクレベルを保存する
202 if(isTaskThreadRunning(runtsk))
203 vget_ims(&runtsk->tskctxb.InterruptLevel);
204 }
205
206 /* タスク切替 */
207
208 //ディスパッチする必
209要がある
210 if(is_taskschedule_required != 0 && enadsp && runtsk != schedtsk)
211 runtsk = schedtsk;
212
213 //切換å…
214ˆã‚¿ã‚¹ã‚¯ãŒå­˜åœ¨ã™ã‚‹ãªã‚‰ã€ãã®ã‚¿ã‚¹ã‚¯ã‚’起動する
215 if(runtsk != 0l)
216 {
217 CurrentRunningThreadHandle = runtsk->tskctxb.ThreadHandle;
218
219 /* タスク例外がおこったら */
220 if (runtsk->enatex && runtsk->texptn != 0)
221 {
222 /* タスク例外起動ルーチンへと差し替える */
223 CONTEXT context;
224 context.ContextFlags = CONTEXT_FULL;
225 GetThreadContext(CurrentRunningThreadHandle,&context);
226 *(DWORD *)(context.Esp -= 4) = context.Eip;
227 context.Eip = (DWORD)TaskExceptionPerformer;
228 SetThreadContext(CurrentRunningThreadHandle,&context);
229 }else
230 chg_ims(runtsk->tskctxb.InterruptLevel);
231
232 LOG_DSP_LEAVE(runtsk);
233 ResumeThread(runtsk->tskctxb.ThreadHandle);
234 }else
235 {
236 /* 動かすものがないなら、割り込みをあけて待
237つ */
238 CurrentRunningThreadHandle = NULL;
239 ena_int(0);
240 }
241}
242
243
244
245 /*
246 * TOPPERS/JSP スレッドモデル カーネルメッセージハンドラ
247 */
248Inline LRESULT CALLBACK
249HALMessageHandler(WPARAM wParam,LPARAM lParam)
250{
251 switch(wParam)
252 {
253 /*
254 *「タスクを破棄してください」メッセージ
255 * lParam : 破棄対象タスクのTCBのアドレス
256 */
257 case HALMSG_DESTROY:
258 {
259 TCB * tcb = (TCB *)lParam;
260
261 /* tcb == 0 が成立するのは、KernelStarterがexit_and_dispatchしたときのみ */
262 if(tcb == 0 || isTaskThreadRunning(tcb)){
263 CurrentRunningThreadHandle = NULL;
264
265 /* タスクが次の起動要求を出してext_tskすると、この時点ですでに新しいスレッドのハンドルがå…
266¥ã£ã¦ã„るので消してはいけない */
267
268 if(tcb == runtsk)
269 runtsk = 0;
270 }
271 }
272
273 /*
274 *「タスクを切り替えてください」メッセージ
275 */
276 case HALMSG_DISPATCH:
277 task_dispatcher(1);
278 break;
279
280 /*
281 *「割り込みを発生させてください」メッセージ
282 * lParam : 割込み番号 (>0)
283 */
284 case HALMSG_INTERRUPT:
285 if(lParam == 0 || iniflg == FALSE || ras_int((unsigned int)lParam) == FALSE)
286 break;
287
288 /* 割込み受付処理 : このまま次に */
289
290 /*
291 * 「次に実行すべき割り込みを探して、割込み処理を開始してください」メッセージ
292 */
293 case HALMSG_INTERRUPT_FINISH:
294 {
295 /* 現在実行しているスレッドを停止 */
296 wait_for_thread_suspension_completion(CurrentRunningThreadHandle);
297
298 /* 割込みスレッド生成 and ディスパッチ */
299 if((CurrentRunningThreadHandle = sch_int()) != NULL)
300 {
301 //これまで動かしていたタスクの割込みマスクレベルを退避
302 if(isTaskThreadRunning(runtsk))
303 vget_ims(&runtsk->tskctxb.InterruptLevel);
304
305 ResumeThread(CurrentRunningThreadHandle); //割込みスレッド起動
306 }
307 else {
308 // タスクへと戻る
309 task_dispatcher(reqflg);
310 reqflg = 0;
311 }
312
313 break;
314 }
315
316 /*
317 *「管理スレッドの権限でもって関数を実行してください」メッセージ
318 * lParam : パラメータを格納する構造体へのポインタ
319 * パラメータ構造体内
320訳
321 * func : 実行したい関数
322 * param : パラメータとして渡す何でもアリ("void *")な値
323 *
324 * 注) タスクでウィンドウとかを作ると、タスク破棄でウィンドウが消えてしまうよ
325 */
326 case HALMSG_EXECUTEPROCEDURE:
327 {
328 void ** work = (void **)lParam;
329 ((void (*)(void *))(*work))(*(work+1));
330 break;
331 }
332
333 /*
334 *「最後の最後にこの処理を動かしてください(onExitハンドラ)」メッセージ
335 * lParam : 関数実行メッセージといっしょ ( func,paramへのポインタ )
336 */
337 case HALMSG_ADDDESTRUCTIONPROCEDURE:
338 {
339 struct tagDestructionProcedureQueue * scope;
340 void ** work = (void **)lParam;
341
342 scope = DestructionProcedureQueue;
343
344 if((DestructionProcedureQueue = GlobalAlloc(GMEM_FIXED, sizeof(struct tagDestructionProcedureQueue))) != NULL)
345 {
346 DestructionProcedureQueue->DestructionProcedure = *(work);
347 DestructionProcedureQueue->Parameter = *(work+1);
348 DestructionProcedureQueue->Next = scope;
349 }else
350 FatalAssertion(TRUE, "GlobalAlloc could not acquire a memory block at " __FILE__);
351
352 break;
353 }
354
355 /*
356 *「プログラムを止めてください」メッセージ
357 */
358 case HALMSG_QUITREQUEST:
359 {
360 struct tagDestructionProcedureQueue * destqueue;
361 void * destarea;
362
363 dis_int(0); // 割込み受付もこのスレッドがやるので、別に禁止しなくても大丈夫
364
365// WorkerThreadHandle = CreateThread(NULL, 0, ForceShutdownHandler, 0, NULL, NULL);
366
367 hw_timer_terminate();
368
369 if(CurrentRunningThreadHandle != NULL)
370 wait_for_thread_suspension_completion(CurrentRunningThreadHandle);
371
372 destqueue = DestructionProcedureQueue;
373 while(destqueue != NULL)
374 {
375 (*destqueue->DestructionProcedure)(destqueue->Parameter);
376 destarea = destqueue;
377 destqueue = destqueue->Next;
378 GlobalFree((HGLOBAL)destarea);
379 }
380
381 DestroyWindow(PrimaryDialogHandle);
382 break;
383 }
384
385 default:
386 return FALSE;
387 }
388 return TRUE;
389}
390
391/*
392 * カーネルシミュレータの中核となるスレッドのメッセージハンドラ
393 */
394LRESULT CALLBACK PrimaryDialogProc(HWND hDlg,UINT Msg,WPARAM wParam,LPARAM lParam)
395{
396 switch(Msg)
397 {
398 /* タスクトレイアイコンで右クリック */
399 case HALMSG_MESSAGE+1:
400 if(lParam == WM_RBUTTONUP)
401 kernel_exit();
402
403 break;
404
405 /* カーネルメッセージ */
406 case HALMSG_MESSAGE:
407 return HALMessageHandler(wParam,lParam);
408
409 /* デバッグ用ダイアログ上のアイテムのメッセージ */
410 case WM_COMMAND:
411 return PrimaryDialogCommandHandler(wParam,lParam);
412
413 /* ダイアログ生成(メッセージハンドリング用) */
414 case WM_INITDIALOG:
415 {
416 DWORD ThreadID;
417 NOTIFYICONDATA nid;
418
419 PrimaryDialogHandle = hDlg; //一時的
420
421 /* タスクトレイにアイコンを登録 */
422 nid.cbSize = sizeof(NOTIFYICONDATA);
423 nid.uFlags = NIF_ICON|NIF_TIP|NIF_MESSAGE;
424 nid.uID = ID_NOTIFYICON;
425 lstrcpy(nid.szTip,"TOPPERS/JSP");
426 nid.hWnd = hDlg;
427 nid.uCallbackMessage = HALMSG_MESSAGE+1;
428 nid.hIcon = LoadIcon(ProcessInstance,MAKEINTRESOURCE(IDI_ERTLICON));
429
430 Shell_NotifyIcon(NIM_ADD,&nid);
431
432 /* カーネルを別スレッドで起動する */
433 PrimaryThreadHandle = (HANDLE)hDlg;
434 CurrentRunningThreadHandle = CreateThread(NULL,0,KernelStarter,NULL,CREATE_SUSPENDED,&ThreadID);
435 ResumeThread(CurrentRunningThreadHandle);
436
437 FatalAssertion(CurrentRunningThreadHandle != NULL, "CreateThread at " __FILE__);
438
439 break;
440 }
441
442 /* ダイアログを閉じようとしています */
443 case WM_CLOSE:
444 HALQuitRequest();
445 break;
446
447 /* ダイアログが破棄されました */
448 case WM_DESTROY:
449 {
450 /* タスクトレイ始末 */
451 NOTIFYICONDATA nid;
452
453 nid.cbSize = sizeof(NOTIFYICONDATA);
454 nid.uFlags = 0;
455 nid.hWnd = hDlg;
456 nid.uID = ID_NOTIFYICON;
457 Shell_NotifyIcon(NIM_DELETE,&nid);
458
459 PrimaryThreadHandle = NULL;
460 PostQuitMessage(0);
461 break;
462 }
463
464 /* タイマ処理 */
465 case WM_TIMER:
466 /* 上位16ビットがå…
467¨éƒ¨1 -> カーネルのタイマ */
468 if((wParam & 0xffff0000) == 0xffff0000)
469 {
470 /* 下位16ビットは割込み番号 */
471 return HALMessageHandler(HALMSG_INTERRUPT,(wParam & 0x0000ffff));
472 }
473 default:
474 return FALSE;
475 }
476 return TRUE;
477}
478
479
480 /* マルチプロセッサでも安定するよう、わざと単一のプロセッサのみで処理させるようにする */
481void setAffinityMask(void)
482{
483 DWORD process;
484 DWORD system;
485 DWORD newaffinitymask;
486
487 if(GetProcessAffinityMask(GetCurrentProcess(), &process, &system) != 0) {
488 newaffinitymask = 1;
489 while((process & newaffinitymask) == 0)
490 newaffinitymask <<= 1;
491 SetProcessAffinityMask(GetCurrentProcess(), newaffinitymask);
492 }
493
494 kprintf(("setAffinityMask : 0x%08x\n", newaffinitymask));
495}
496
497static void initialize(HANDLE hInstance)
498{
499 ProcessInstance = hInstance;
500 DestructionProcedureQueue = NULL;
501 PrimaryThreadHandle = NULL;
502 CurrentRunningThreadHandle = NULL;
503
504#ifdef KERNEL_DEBUG_MODE
505 AllocConsole();
506#endif
507 /* プロセッサを割り付ける */
508 setAffinityMask();
509
510}
511
512static void finalRelease(void)
513{
514 int i;
515
516 kprintf(("finalRelease()\n"));
517
518 /* 破棄されてないタスクの後始末 */
519 for(i=0;i<_kernel_tmax_tskid;i++)
520 {
521 if(_kernel_tcb_table[i].tskctxb.ThreadHandle != NULL)
522 {
523 if(TerminateThread(_kernel_tcb_table[i].tskctxb.ThreadHandle,0) != 0)
524 CloseHandle(_kernel_tcb_table[i].tskctxb.ThreadHandle);
525 _kernel_tcb_table[i].tskctxb.ThreadHandle = NULL;
526 }
527 }
528
529 /* COM通信をしているスレッドを強制停止 */
530 if(WorkerThreadHandle != NULL)
531 {
532 TerminateThread(WorkerThreadHandle ,0);
533 CloseHandle(WorkerThreadHandle);
534 WorkerThreadHandle = NULL;
535 }
536
537#ifdef KERNEL_DEBUG_MODE
538 MessageBox(NULL, "The kernel will be shut down.", "TOPPERS/JSP", MB_OK);
539 FreeConsole();
540#endif
541
542}
543
544
545/*
546 * メイン関数
547 */
548int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShow)
549{
550 MSG msg;
551 HANDLE hDlg;
552
553 TlsAlloc();
554
555 initialize(hInstance);
556
557 TlsSetValue(TLS_LOGMASK, 0);
558 hDlg = CreateDialog(hInstance,"PrimaryDialog",NULL,PrimaryDialogProc);
559 if(hDlg != NULL)
560 {
561 ShowWindow(PrimaryDialogHandle,SW_HIDE);
562
563 OnDebug(ShowWindow(PrimaryDialogHandle,SW_SHOW));
564
565 while(GetMessage(&msg,NULL,0,0) != 0)
566 {
567 if(msg.message == WM_QUIT)
568 msg.message = 0;
569 TranslateMessage(&msg);
570 DispatchMessage(&msg);
571 }
572 }
573 else
574 FatalAssertion(hDlg != NULL, "CreateDialog at " __FILE__ "(" ")");
575
576 finalRelease();
577
578 ExitProcess(msg.wParam);
579 return msg.wParam;
580}
581
Note: See TracBrowser for help on using the repository browser.