source: anotherchoice/tags/jsp-1.4.4-full-UTF8/config/windows/com_support.cpp@ 26

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

initial

File size: 35.5 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: com_support.cpp,v 1.10 2003/12/15 07:19:22 takayuki Exp $
51 */
52
53#include <vitron.h>
54#include <com_support.h>
55#include <eventlog.h>
56#include "syslog.h"
57
58#include <resource.h>
59
60#include <commctrl.h>
61
62/*
63 * 前に聞かれた事の説明
64 * Q: CスタイルコメントとC++スタイルコメントが混ざっていますが?
65 * A: 気楽にコメントアウトされると困る処理がCスタイルコメントで、似たような処理をする場所の説明にC++スタイルコメントを使っています。
66 *
67 * Q: 変数の名づけ規則がめちゃくちゃですが?
68 * A: 基本的にスコープ範囲で使い分けています。
69 * ローカルが小文字+"_", グローバルが大文字小文字, メンバがJavaっぽいスタイル
70 *
71 * Q: INVALID_HANDLE_VALUE と NULL をどう使い分けているのですか?
72 * A: CreateXxxxが失敗時に返却する値であわせました。
73 * å…
74·ä½“的には、ファイルはINVALID_HANDLE_VALUE(CreateFile)で、それ以外がNULLになってます。
75 */
76
77#ifndef __COM_NOT_REQUIRED__
78
79
80//===================================================
81/*
82 * å…
83±é€šéƒ¨
84 */
85extern "C" SYSTIM _kernel_systim_offset;
86extern "C" SYSTIM _kernel_current_time;
87extern "C" HINSTANCE ProcessInstance;
88extern "C" HANDLE PrimaryDialogHandle;
89extern "C" BOOL ShutdownPostponementRequest;
90extern "C" int CPUStatus;
91
92extern "C" void FatalAssertion(int exp, LPCSTR format, ... );
93
94extern "C" void enter_system_critical_section(BOOL * cookie);
95extern "C" void leave_system_critiacl_section(BOOL * cookie);
96
97#ifdef KERNEL_DEBUG_MODE
98 extern "C" _kernel_debugprintf(const char * format, ... );
99# define kprintf(x) _kernel_debugprintf x
100#else
101# define kprintf(x)
102#endif
103
104//===================================================
105
106 /* ユーザ定義のログ */
107#define USERDEFINED 0x60
108#define LOG_MODULENAME (0 | USERDEFINED) /* モジュールの名前 */
109#define LOG_TIMESTAMP (1 | USERDEFINED) /* 記録を開始した時刻 (SYSTEMTIME構造体をそのままダンプ) */
110
111#define __HAL_MSG_MSGONLY
112#include <hal_msg.h>
113
114#include <string>
115
116namespace
117{
118 /*
119 * COMインターフェース関連の定義
120 */
121
122 //諸々
123のIDの宣言
124 const IID IID_IKernelEvents = {0x1353969D,0xE84F,0x463F,{0xB2,0x11,0x33,0x7E,0x9B,0xCF,0xB9,0x9E}};
125 const IID IID_IKernel = {0xD3E42099,0x3FDD,0x4A78,{0xBD,0xBD,0x4E,0x57,0xD3,0x62,0xF5,0xED}};
126 const CLSID CLSID_Kernel = {0x51789667,0x9F20,0x40AF,{0xAF,0x7F,0x98,0x56,0x32,0x5D,0xFB,0x0B}};
127
128 // IKernelインターフェース定義
129 class IKernel : public IUnknown
130 {
131 public:
132 STDMETHOD(Read)(unsigned long address,unsigned long sz,char __RPC_FAR data[]) PURE;
133 STDMETHOD(IsValid)(BOOL __RPC_FAR * valid) PURE;
134 STDMETHOD(Write)(unsigned long address,unsigned long sz,char __RPC_FAR data[]) PURE;
135 STDMETHOD(OnLogEvent)(long sz, unsigned char __RPC_FAR data[]) PURE;
136 };
137
138 // IKernelEventsインタフェース定義
139 class IKernelEvents : public IUnknown
140 {
141 public:
142 STDMETHOD(QueryInterface)(REFIID iid, void ** unk);
143 STDMETHOD_(ULONG,AddRef)();
144 STDMETHOD_(ULONG,Release)();
145 STDMETHOD(OnInterruptRequest)(long inhno);
146
147 IKernelEvents(void);
148
149 long RefCount;
150 };
151
152 /*
153 * IKernelEvents実装
154
155 */
156
157 IKernelEvents::IKernelEvents(void) : RefCount(0)
158 {}
159
160 STDMETHODIMP IKernelEvents::QueryInterface(REFIID iid, void ** unk)
161 {
162 if( iid == IID_IKernelEvents || iid == IID_IUnknown )
163 {
164 *unk = this;
165 ::InterlockedIncrement(&RefCount);
166 return S_OK;
167 }
168
169 return E_NOINTERFACE;
170 }
171
172 STDMETHODIMP_(ULONG) IKernelEvents::AddRef()
173 { return ::InterlockedIncrement(&RefCount); }
174
175 STDMETHODIMP_(ULONG) IKernelEvents::Release()
176 {
177 if( ::InterlockedDecrement(&RefCount) == 0)
178 delete this;
179 return RefCount;
180 }
181
182 STDMETHODIMP IKernelEvents::OnInterruptRequest(long inhno)
183 {
184
185 if(inhno < 0)
186 {
187 /* inhno < 0 は特殊な意味を持つ */
188
189 /* inhno = -1 : keep-alive */
190 }else
191 ::PostMessage((HWND)PrimaryDialogHandle,HALMSG_MESSAGE,HALMSG_INTERRUPT,(LPARAM)inhno);
192 return S_OK;
193 }
194}
195
196namespace {
197 /*
198 * COM通信用作業スレッドに関する定義
199 */
200
201 HANDLE request_semaphore = NULL; //要求待
202ちセマフォ
203 HANDLE worker_thread_handle = NULL; //作業スレッドのハンドル
204
205 //==============================================================================
206
207 //COM作業スレッドが正常に作動しているか否か
208 inline bool IsValid(void)
209 { return (request_semaphore != NULL) && (worker_thread_handle != NULL); }
210
211 //===================================================
212
213 /*
214 * Q: どうしてシステムロックが必
215要なの?
216 * A: ログイベントをキューイングするために各タスク/割込みスレッドがメモリを取る
217 * -> VisualC++のマルチスレッド用メモリ確保ライブラリは内
218部でクリティカルセクションオブジェクトを使って排他制御している
219 * -> TOPPERS/JSP Windowsのディスパッチャ(管理スレッド)は要求が来ると今動いているスレッドを止めにかかる
220 * -> メモリ確保用のクリティカルセクションを持ったままSuspendThreadされてしまい、メモリ確保要求を出した他のスレッドå…
221¨ã¦ãŒãƒ­ãƒƒã‚¯
222 * -> 管理スレッドもログを出すためにメモリをとりに来るので、管理スレッドもロック
223 * -> 管理スレッドがロックされると、最初にSuspendThreadされたヤツを起こすスレッドがいない
224 * -> デッドロック
225 * 補足 : COM通信作業スレッドやコンソール管理スレッドのように管理スレッドのSuspendThreadの対象にならないスレッドはロックしなくてもいい
226 */
227
228 //===================================================
229
230 /* 作業スレッドに与えるデータを保持するクラス */
231 class Request
232 {
233 public:
234 enum tagRequestType
235 {
236 Confirmation = 0x00, /* ワーカスレッドの動作確認 (セマフォをたたくだけ) */
237
238 DeviceRead = 0x01, /* デバイスエミュレーション 読出し操作 */
239 DeviceWrite = 0x02, /* デバイスエミュレーション 書込み操作 */
240
241 EventLog = 0x03, /* イベントログ送出 */
242
243 QuitThread = 0xff /* 作業スレッドの終了 */
244 };
245
246 protected:
247 bool blocking;
248 bool allocated;
249 enum tagRequestType type;
250 unsigned long address; /* デバイス : デバイスのあるアドレス */
251 unsigned long size; /* å…
252±é€š : storageが持つデータのサイズ */
253 HGLOBAL storage; /* å…
254±é€š : データを格納している領域のアドレス(ハンドル) */
255 int result; /* å…
256±é€š : ブロッキング実行時の返却地 */
257 HANDLE signalobject; /* å…
258±é€š : ブロッキング実行時のスレッドハンドル */
259
260 Request * next; /* キューにするためのリンク */
261
262 static LONG RequestCount; //キューにつながっているリクエストの数
263 static Request * top; //リクエストキューのå…
264ˆé ­ (もっとも古いリクエスト)
265 static Request * tail; //リクエストキューの末尾 (もっとも新しいリクエスト)
266 static CRITICAL_SECTION cs; //排他キュー操作用危険領域オブジェクト
267
268 void connect(void)
269 {
270 //要求をキューにつなぐ
271 ::EnterCriticalSection(&cs);
272 next = NULL;
273 if(tail != NULL)
274 tail->next = this;
275 tail = this;
276 if(top == NULL)
277 top = tail;
278 ::LeaveCriticalSection(&cs);
279
280 ::InterlockedIncrement(&RequestCount);
281 }
282
283 protected:
284 //コンストラクタ
285 Request(enum tagRequestType _type, bool _block, unsigned int _size = 0, void * _storage = NULL, unsigned long _address = 0)
286 : blocking(_block), allocated(false), type(_type), address(_address),
287 size(0), storage(NULL), result(-1), signalobject(NULL), next(NULL)
288 {
289 size = _size;
290
291 if(size != 0)
292 {
293 //領域が指定されてない場合、動的に確保する
294 if(_storage != NULL)
295 storage = static_cast<HGLOBAL>(_storage);
296 else
297 allocate(size, false);
298 }
299 }
300
301 public:
302 //デストラクタ
303 virtual ~Request(void)
304 {
305
306 //領域が動的確保されていた場合、破棄を行う
307 if(storage != NULL && allocated)
308 {
309 BOOL lock;
310
311 enter_system_critical_section(&lock);
312 ::GlobalFree(storage);
313 leave_system_critiacl_section(&lock);
314 }
315 }
316
317 static void initialize(void)
318 {
319 kprintf(("Request::initialize()\n"));
320 if(RequestCount == -1)
321 {
322 ::InitializeCriticalSection(&cs);
323 RequestCount = 0;
324 top = NULL;
325 tail = NULL;
326 }
327 }
328
329 static void finalize(void)
330 {
331 kprintf(("Request::finalize()\n"));
332 if(RequestCount != -1)
333 {
334 while(top != NULL)
335 {
336 Request * target = top;
337 top = top->next;
338 delete target;
339 }
340
341 ::DeleteCriticalSection(&cs);
342 RequestCount = -1;
343 }
344 }
345
346 // システムをロックしないでメモリ開放
347 inline void release(void)
348 {
349 if(storage != NULL && allocated)
350 {
351 ::GlobalFree(storage);
352 storage = 0;
353 }
354 }
355
356 inline bool isBlockingRequest(void) const
357 { return blocking; }
358
359 inline enum tagRequestType getType(void) const
360 { return type; }
361
362 inline bool operator == (enum tagRequestType _type) const
363 { return type == _type; }
364
365 inline bool operator != (enum tagRequestType _type) const
366 { return !(operator ==(_type)); }
367
368 inline void * getStorage(void)
369 { return reinterpret_cast<void *>(storage); }
370
371 inline unsigned long getAddress(void) const
372 { return address; }
373
374 inline unsigned long getSize(void) const
375 { return size; }
376
377 inline int getResult(void) const
378 { return result; }
379
380 static inline LONG getRequestCount(void)
381 { return RequestCount; }
382
383 //領域の確保
384 // _size : 必
385要とする領域のサイズ
386 // realloc : 内
387容を保持するか否か
388 bool allocate(unsigned int _size, bool realloc = false)
389 {
390 unsigned long old_size;
391 HGLOBAL old_storage;
392 BOOL lock;
393
394 FatalAssertion(type != Confirmation, "Request::allocate was performed with Confirmation Request Object.");
395
396 old_size = size;
397 old_storage = storage;
398
399 enter_system_critical_section(&lock);
400 storage = ::GlobalAlloc(GMEM_FIXED, _size);
401
402 FatalAssertion(storage != NULL, "Request::allocate failed to allocate a memory block.");
403
404 //前の内
405容の保持 および領域破棄
406 if(old_storage != NULL)
407 {
408 if(realloc)
409 ::CopyMemory(storage, old_storage, old_size);
410
411 if(allocated)
412 ::GlobalFree(old_storage);
413 }
414 leave_system_critiacl_section(&lock);
415
416 allocated = true;
417 size = _size;
418
419 return true;
420 }
421
422 //内
423容を保持したまま再アロケート
424 inline bool reallocate(unsigned int _size)
425 { return allocate(_size, true); }
426
427 //保持領域に対する書込み
428 inline void set(void * data, unsigned int sz, unsigned int offset = 0)
429 {
430 if(size < sz)
431 reallocate(sz + offset);
432
433 ::CopyMemory(reinterpret_cast<char *>(storage) + offset, data, sz);
434 }
435
436 //保持領域に対する読込み
437 inline bool get(void * data, unsigned int sz, unsigned int offset = 0)
438 {
439 if(size < sz + offset)
440 return false;
441
442 ::CopyMemory(data, reinterpret_cast<char *>(storage) + offset, sz);
443 }
444
445 //保持領域の任意の位置に対するポインタ取得
446 // offset : å…
447ˆé ­ã‹ã‚‰ã®ãƒã‚¤ãƒˆã‚ªãƒ•ã‚»ãƒƒãƒˆ
448 void * getptr(unsigned int offset = 0)
449 {
450 if(offset > size || storage == NULL)
451 return NULL;
452
453 return reinterpret_cast<void *>(reinterpret_cast<char *>(storage) + offset);
454 }
455
456 /*
457 * Requestオブジェクトファクトリ
458 * Q: どうしてファクトリが必
459要なのか?
460 * A: メモリ確保よりもå…
461ˆã«CPUをロックする必
462要があるため (詳細は上記CPUロックする理由を参ç…
463§)
464 */
465 static Request * Create(enum tagRequestType _type, bool _block, unsigned int _size = 0, void * _storage = NULL, unsigned long _address = 0)
466 {
467 Request * request;
468 BOOL lock;
469
470 enter_system_critical_section(&lock);
471 request = new Request(_type, _block, _size, _storage, _address);
472 leave_system_critiacl_section(&lock);
473
474 return request;
475 }
476
477 static Request * GetRequest(void)
478 {
479 Request * result;
480
481 ::EnterCriticalSection(&cs);
482 result = top;
483 if(top != NULL)
484 {
485 top = top->next;
486 if(top == NULL)
487 tail = NULL;
488 }
489 ::LeaveCriticalSection(&cs);
490
491 ::InterlockedDecrement(&RequestCount);
492
493 return result;
494 }
495
496 void Finalize(bool succeeded)
497 {
498 if(this != 0) {
499 if(isBlockingRequest())
500 signal(succeeded ? getSize() : -1);
501 else
502 {
503 BOOL lock;
504
505 enter_system_critical_section(&lock);
506 delete this;
507 leave_system_critiacl_section(&lock);
508 }
509 }
510 }
511
512 virtual void signal(int _result = 0)
513 {
514 result = _result;
515 if(signalobject != NULL)
516 ::PostThreadMessage((DWORD)signalobject, WM_QUIT, 0, 0);
517 }
518
519 /*
520 * 新しい要求の発行
521 * (この関数を使うスレッド : 管理スレッド, 割込みスレッド, タスクスレッド)
522 */
523 virtual int invoke(void)
524 {
525 int _result;
526 BOOL lock;
527 MSG msg;
528
529 _result = 0;
530
531 if(!IsValid())
532 return -1;
533
534 enter_system_critical_section(&lock);
535
536 connect();
537
538 //要求の実行待
539ち
540 if(blocking)
541 {
542 signalobject = (HANDLE)::GetCurrentThreadId();
543
544 //新しい要求をだしたことを通知
545 ::ReleaseSemaphore(request_semaphore,1,NULL);
546 leave_system_critiacl_section(&lock);
547
548 //WM_QUITメッセージを使って同期を取る
549 while(::GetMessage(&msg, 0, 0, 0) != 0)
550 ::DispatchMessage(&msg);
551
552 //このオブジェクトを破棄するのでバックアップを取る
553 _result = result;
554
555 //キューからはずす処理は作業スレッドがやる
556 //delete requestは、ノンブロッキングなら作業スレッド責任、ブロッキングならここでやる
557 enter_system_critical_section(&lock);
558 delete this;
559 leave_system_critiacl_section(&lock);
560 }else
561 {
562 //新しい要求をだしたことを通知
563 ::ReleaseSemaphore(request_semaphore,1,NULL);
564 leave_system_critiacl_section(&lock);
565 }
566
567 return _result;
568 }
569 };
570
571 class EventDumpRequest : public Request
572 {
573 protected:
574 static HANDLE FileHandle;
575
576 EventDumpRequest(enum tagRequestType _type, bool _block, unsigned int _size = 0, void * _storage = NULL, unsigned long _address = 0) : Request(_type, _block, _size, _storage, _address)
577 {}
578
579 public:
580 static void initialize(void)
581 {
582 SYSTEMTIME systim;
583 DWORD written;
584 char buffer[1024];
585 char * top;
586 char * work;
587
588 ::GetLocalTime(&systim);
589 ::wsprintf(buffer, "kernel-log-%04d%02d%02d-%02d%02d%02d.log", systim.wYear, systim.wMonth, systim.wDay, systim.wHour, systim.wMinute, systim.wSecond);
590 FileHandle = ::CreateFile(buffer, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
591
592 kprintf(("EventDumpRequest : initialize (filename = '%s')\n", buffer));
593
594 T_RGLOG_HEADER log;
595
596 log.logtype = LOG_TIMESTAMP;
597 log.logtim = 0;
598 log.bufsz = sizeof(SYSTEMTIME);
599 log.valid = 1;
600 ::WriteFile(FileHandle, &log, sizeof(log), &written, NULL);
601 ::WriteFile(FileHandle, &systim, sizeof(SYSTEMTIME), &written, NULL);
602
603 /* モジュール名を取り出す */
604 ::lstrcpyn(buffer, ::GetCommandLine(), 1023);
605 top = buffer;
606 buffer[1023] = '\x0'; //サーチ用番å…
607µ
608
609 if(*top == '"')
610 {
611 ++ top;
612 for(work = top; *work != '\x0' && *work != '"'; ++work);
613 }
614 else
615 for(work = top; *work != '\x0' && *work != ' '; ++work);
616
617 *work = '\x0'; //ターミネート処理
618
619 log.logtype = LOG_MODULENAME;
620 log.logtim = 0;
621 log.bufsz = work - top + 1; //ターミネータの分
622 log.valid = 1;
623 ::WriteFile(FileHandle, &log, sizeof(log), &written, NULL);
624 ::WriteFile(FileHandle, top, log.bufsz, &written, NULL);
625 }
626
627 static void finalize(void)
628 {
629 kprintf(("EventDumpRequest : finalize()\n"));
630
631 if(FileHandle != INVALID_HANDLE_VALUE) //CreateFile returns INVALID_HANDLE_VALUE if it failed
632 ::CloseHandle(FileHandle);
633 }
634
635 static EventDumpRequest * Create(enum tagRequestType _type, bool _block, unsigned int _size = 0, void * _storage = NULL, unsigned long _address = 0)
636 {
637 EventDumpRequest * request;
638 BOOL lock;
639
640 enter_system_critical_section(&lock);
641 request = new EventDumpRequest(_type, _block, _size, _storage, _address);
642 leave_system_critiacl_section(&lock);
643
644 return request;
645 }
646
647 virtual int invoke(void)
648 {
649 DWORD written;
650 BOOL lock;
651
652 enter_system_critical_section(&lock);
653 if(FileHandle != INVALID_HANDLE_VALUE) //CreateFile return INVALID_HANDLE_VALUE, not NULL, if it failed its operatation.
654 ::WriteFile(FileHandle, storage, size, &written, NULL);
655 delete this;
656 leave_system_critiacl_section(&lock);
657
658 return 0;
659 }
660 };
661
662 class ExclusiveDeviceRequest : public Request
663 {
664 protected:
665 static HANDLE blocker;
666 public:
667
668 static void initialize(void) throw()
669 {
670 kprintf(("ExclusiveDeviceRequest::initialize()\n"));
671
672 if(blocker == NULL) {
673 blocker = ::CreateEvent(NULL, FALSE, FALSE, NULL);
674 }
675 }
676
677 static void finalize(void) throw()
678 {
679 kprintf(("ExclusiveDeviceRequest::finalize()\n"));
680
681 if(blocker != NULL) {
682 ::CloseHandle(blocker);
683 }
684 }
685
686 virtual void signal(int _result = 0)
687 {
688 result = _result;
689 ::SetEvent(blocker);
690 }
691
692 virtual int invoke(void)
693 {
694 int _result = 0;
695 BOOL lock;
696 BOOL cpustate;
697
698 //割り込みを禁止する
699 if((cpustate = CPUStatus) == 0)
700 dis_int(0);
701
702 enter_system_critical_section(&lock);
703
704 //要求をキューのå…
705ˆé ­ã«ã¤ãªã
706 ::EnterCriticalSection(&cs);
707 next = top;
708 top = this;
709 if(tail == NULL)
710 tail = this;
711 ::LeaveCriticalSection(&cs);
712 ::InterlockedIncrement(&RequestCount);
713
714 ::ReleaseSemaphore(request_semaphore, 1, NULL);
715 leave_system_critiacl_section(&lock);
716
717 if(blocking) {
718 ::WaitForSingleObject(blocker, INFINITE);
719
720 _result = result;
721
722 enter_system_critical_section(&lock);
723 delete this;
724 leave_system_critiacl_section(&lock);
725 }
726
727 if(cpustate == 0)
728 ena_int(0);
729
730 return _result;
731 }
732 };
733
734// typedef class EventDumpRequest EventRequest;
735 typedef class Request EventRequest; //イベントログ出力要求で使用されるリクエスト
736// typedef class Request DeviceRequest; //デバイス通信要求で使用されるリクエスト
737 typedef class ExclusiveDeviceRequest DeviceRequest; //デバイス通信要求で使用されるリクエスト
738
739 //==============================================================================
740
741 LONG Request::RequestCount = -1; //キューにつながっているリクエストの数
742 Request * Request::top = NULL; //リクエストキューのå…
743ˆé ­ (もっとも古いリクエスト)
744 Request * Request::tail = NULL; //リクエストキューの末尾 (もっとも新しいリクエスト)
745 CRITICAL_SECTION Request::cs; //排他キュー操作用危険領域オブジェクト
746
747 HANDLE EventDumpRequest::FileHandle = INVALID_HANDLE_VALUE; //CreateFile uses INVALID_HANDLE_VALUE for identifying an invalid instance
748 HANDLE ExclusiveDeviceRequest::blocker = NULL;
749
750 //==============================================================================
751
752 /*
753 * 作業スレッドが使用する作業関数の定義
754 */
755
756 //コネクションポイントへの接続
757 bool Advise(IUnknown * container, REFIID iid, IUnknown * sink, DWORD * cookie, IConnectionPoint ** p_cp = NULL)
758 {
759 IConnectionPointContainer * cp_container;
760 IConnectionPoint * cp;
761
762 if(container == 0 || sink == 0 || cookie == 0)
763 return false;
764
765 if(p_cp == 0)
766 p_cp = &cp;
767
768 //IUnknownインタフェースからIConnectionPointContainerへキャスト
769 container->QueryInterface(IID_IConnectionPointContainer, (void **)&cp_container);
770 if(cp_container == 0)
771 return false;
772
773 //ConnectionPointContainerから要求に合うConnectionPointを探す
774 cp_container->FindConnectionPoint(iid, p_cp);
775 cp_container->Release();
776 if(*p_cp == 0)
777 return false;
778
779 //コネクションポイント接続
780 if(FAILED((*p_cp)->Advise(sink, cookie)))
781 return false;
782
783 if(p_cp == &cp)
784 cp->Release();
785 return true;
786 }
787
788 //==============================================================================
789
790 /*
791 * PerformRequest : 要求の実行
792 * 返却値 : イベント処理を継続する(true) or 作業スレッドを停止させる(false)
793 */
794
795 bool PerformRequest(IKernel * manager)
796 {
797 Request * request;
798 bool succeeded;
799
800 //キューからリクエストを抜き取る
801 request = Request::GetRequest();
802 FatalAssertion(request != NULL,"");
803
804 //終了要求
805 if(request->getType() == Request::QuitThread)
806 {
807 if(!request->isBlockingRequest())
808 {
809 BOOL lock;
810
811 enter_system_critical_section(&lock);
812 delete request;
813 leave_system_critiacl_section(&lock);
814 }
815 return false;
816 }
817
818 //要求毎の処理
819 switch(request->getType())
820 {
821 case Request::Confirmation:
822 succeeded = true;
823 break;
824
825 case Request::DeviceRead:
826 succeeded = SUCCEEDED(manager->Read(request->getAddress(), request->getSize(), reinterpret_cast<char *>(request->getStorage())));
827 break;
828
829 case Request::DeviceWrite:
830 succeeded = SUCCEEDED(manager->Write(request->getAddress(), request->getSize(), reinterpret_cast<char *>(request->getStorage())));
831 break;
832
833 case Request::EventLog:
834 succeeded = SUCCEEDED(manager->OnLogEvent(request->getSize(), reinterpret_cast<unsigned char *>(request->getStorage())));
835
836 //シャットダウン中ならログをå…
837¨éƒ¨ã¯ãçµ‚るまで待
838ってもらう
839 ShutdownPostponementRequest = TRUE;
840 break;
841
842 default:
843 succeeded = false;
844 }
845
846 request->Finalize(succeeded);
847
848 return true;
849 }
850
851 /*
852 * COM通信を行うための作業スレッド 本体
853 */
854 DWORD WINAPI WorkerThreadProcess(LPVOID _param)
855 {
856 IKernel * manager;
857 IKernelEvents * sink;
858 IConnectionPoint * cp;
859 DWORD cookie;
860 BOOL Success;
861
862 kprintf(("WorkerThreadProcess : start\n"));
863
864 /* 初期化 */
865 ::CoInitialize(NULL);
866
867 // デバイスマネージャと接続
868 manager = 0;
869 if(FAILED(::CoCreateInstance(CLSID_Kernel, NULL, CLSCTX_ALL, IID_IKernel, (void **)&manager)))
870 goto _WorkerThreadProc_Cleanup;
871
872 cp = 0;
873 sink = new(std::nothrow) IKernelEvents;
874 if(!Advise(manager, IID_IKernelEvents, sink, &cookie,&cp))
875 {
876 if(sink != 0)
877 delete sink;
878 goto _WorkerThreadProc_Cleanup;
879 }
880
881 /* メインルーチン */
882 manager->IsValid(&Success);
883 if(Success != 0)
884 {
885 MSG msg;
886 DWORD work;
887 bool loop_flag = true;
888
889 do {
890 /*
891 * 外部からCOMをたたくとメッセージとして飛んでくるため、WaitForSingleObjectでセマフォを待
892つと外部からの要求を実行できなくなる。
893 * そのため、MsgWaitFor...を用い、メッセージが飛んできた場合はこれに対処できるようにする。
894 */
895
896 /*
897 * cygwin環境だとQS_ALLPOSTMESSAGEが定義されないので、これで対処
898 */
899#ifndef QS_ALLPOSTMESSAGE
900#define QS_ALLPOSTMESSAGE (0x0100)
901#endif
902
903 //要求待
904ち
905 work = ::MsgWaitForMultipleObjects(1, &request_semaphore, FALSE, INFINITE, QS_ALLPOSTMESSAGE);
906
907 switch(work) {
908
909 //処理要求の実行
910 case WAIT_OBJECT_0:
911 loop_flag = PerformRequest(manager);
912 break;
913
914 //外部からの要求 (割込みなど)
915 case WAIT_OBJECT_0 + 1:
916 GetMessage(&msg, 0, 0, 0);
917 TranslateMessage(&msg);
918 DispatchMessage(&msg);
919 break;
920
921 default:
922 loop_flag = false;
923 }
924
925 } while(loop_flag);
926 }
927
928 /*
929 * Finalize
930 */
931
932 if(cp != 0)
933 {
934 cp->Unadvise(cookie);
935 cp->Release();
936 cp = 0;
937 sink = 0;
938 }
939
940 _WorkerThreadProc_Cleanup:
941
942 if(manager != 0)
943 manager->Release();
944
945 CloseHandle(worker_thread_handle);
946 worker_thread_handle = NULL;
947 manager = 0l;
948 ::CoUninitialize();
949
950 /* キューを空にする (待
951ち解除) */
952
953 Request * request;
954 while((request = Request::GetRequest()) != 0)
955 request->Finalize(false);
956
957 kprintf(("WorkerThreadProcess : exit\n"));
958
959 return 0;
960 }
961}
962
963//==============================================================================
964
965/****************************************************
966 * *
967 * TOPPERS/JSP - Windowsシミュレーション環境 *
968 * COMを用いたデバイスエミュレーション機能 *
969 * *
970 ****************************************************/
971
972#ifdef DEVICE_ENABLE
973
974extern "C"
975int _cdecl DeviceRead(unsigned long address, unsigned long size, void * storage)
976{
977 if(!IsValid() || storage == NULL)
978 return -1;
979
980 return DeviceRequest::Create(Request::DeviceRead, true, size, storage, address)->invoke();
981}
982
983extern "C"
984int _cdecl DeviceWrite(unsigned long address, unsigned long size, void * storage)
985{
986 if(!IsValid() || storage == NULL)
987 return -1;
988
989 return DeviceRequest::Create(Request::DeviceWrite, true, size, storage, address)->invoke();
990}
991
992#endif
993
994
995/****************************************************
996 * *
997 * TOPPERS/JSP - Windowsシミュレーション環境 *
998 * COMを用いたカーネルログ取得機能 *
999 * *
1000 ****************************************************/
1001
1002#ifdef EVENTLOG_ENABLE
1003
1004 /* 多重ログ出力防止用セマフォ : 1を足した結果が1であったときだけ、ログを出力できる */
1005static LONG event_write_semaphore = 0;
1006
1007void event_write(unsigned int logtype, unsigned int valid, UINT bufsz, ... )
1008{
1009 EventRequest * event_request;
1010 DBIFLOG * log;
1011 va_list vl;
1012
1013 if(IsValid() && TlsGetValue(TLS_LOGMASK) == 0)
1014 {
1015 // リクエスト領域確保
1016 event_request = EventRequest::Create(EventRequest::EventLog, false, sizeof(T_RGLOG_HEADER) + bufsz);
1017 log = reinterpret_cast<DBIFLOG *>(event_request->getptr());
1018
1019 // ヘッダ生成
1020 log->header.logtype = logtype;
1021 log->header.logtim = _kernel_systim_offset + _kernel_current_time;
1022 log->header.valid = valid;
1023 log->header.bufsz = bufsz;
1024
1025 // 本体の格納
1026 va_start(vl, bufsz);
1027 for(unsigned int i=0;i<bufsz/sizeof(int);i++)
1028 *((int *)&log->body + i) = va_arg(vl, int);
1029
1030 // 要求の送付 (Non-blocking)
1031 event_request->invoke();
1032 }
1033}
1034
1035extern "C"
1036void event_write_svc_enter(int fncd, unsigned int params, ... )
1037{
1038 EventRequest * event_request;
1039 DBIFLOG * log;
1040 va_list vl;
1041 unsigned int i;
1042
1043 if(IsValid() && TlsGetValue(TLS_LOGMASK) == 0)
1044 {
1045 //領域確保 : 確保するサイズはパラメータ総数より一個分多い (呼び出しå…
1046ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’格納)
1047 event_request = EventRequest::Create(EventRequest::EventLog, false, sizeof(T_RGLOG_HEADER) + sizeof(T_RGLOG_SVC) + params * sizeof(VP_INT));
1048 log = reinterpret_cast<DBIFLOG *>(event_request->getptr());
1049
1050 //パケット生成
1051 log->header.logtype = LOG_TYPE_SVC;
1052 log->header.logtim = _kernel_systim_offset + _kernel_current_time;
1053 log->header.valid = 0x7fffffff >> (29 - params);
1054 log->header.bufsz = (params+3) * sizeof(int);
1055
1056 va_start(vl, params);
1057
1058 log->body.svc.fncno = fncd;
1059 log->body.svc.prmcnt = params;
1060
1061 /* 一回ループが多いのは最後に呼出å…
1062ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’積んでいるため */
1063 for(i=0;i<params+1;i++)
1064 log->body.svc.prmary[i] = va_arg(vl, VP_INT);
1065
1066 event_request->invoke();
1067 }
1068}
1069
1070extern "C"
1071void event_write_svc_leave(int fncd, unsigned int ercd, unsigned int retaddr)
1072{
1073 EventRequest * event_request;
1074 DBIFLOG * log;
1075
1076 if(IsValid() && TlsGetValue(TLS_LOGMASK) == 0)
1077 {
1078 //領域確保 : 確保するサイズはパラメータ総数(返却値のみなので1つ)より一個分多い (呼び出しå…
1079ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’格納)
1080 event_request = EventRequest::Create(EventRequest::EventLog, false, sizeof(T_RGLOG_HEADER) + sizeof(T_RGLOG_SVC) + sizeof(VP_INT));
1081 log = reinterpret_cast<DBIFLOG *>(event_request->getptr());
1082
1083 //ヘッダ部生成
1084 log->header.logtype = LOG_TYPE_SVC|LOG_LEAVE;
1085 log->header.logtim = _kernel_systim_offset + _kernel_current_time;
1086 log->header.valid = 0x7;
1087 log->header.bufsz = 4 * sizeof(int);
1088
1089 //ボディ部生成
1090 log->body.svc.fncno = fncd;
1091 log->body.svc.prmcnt = 1;
1092 log->body.svc.prmary[0] = (VP_INT)ercd;
1093 log->body.svc.prmary[1] = (VP_INT)retaddr;
1094
1095 event_request->invoke();
1096 }
1097}
1098
1099extern "C" void decode_taskstatus(void * tcb, int * tskid, unsigned int * tskstat, unsigned int * objtype, int * objid);
1100
1101extern "C"
1102void event_write_tskstat(void * tcb)
1103{
1104 EventRequest * event_request;
1105 DBIFLOG * log;
1106
1107 if(IsValid()) //これはカーネル操作なのでTLS_LOGMASKを見てはいけない
1108 {
1109 //領域確保
1110 event_request = EventRequest::Create(EventRequest::EventLog, false, sizeof(T_RGLOG_HEADER) + sizeof(T_RGLOG_TSKSTAT));
1111 log = reinterpret_cast<DBIFLOG *>(event_request->getptr());
1112
1113 log->header.logtype = LOG_TYPE_TSKSTAT;
1114 log->header.logtim = _kernel_systim_offset + _kernel_current_time;
1115 log->header.valid = 0xf;
1116 log->header.bufsz = 4 * sizeof(int);
1117
1118 decode_taskstatus(tcb, &log->body.tskstat.tskid, &log->body.tskstat.tskstat, &log->body.tskstat.tskwait, &log->body.tskstat.wobjid);
1119
1120 event_request->invoke();
1121 }
1122}
1123
1124#endif
1125
1126
1127static BOOL CALLBACK NotifyDialogProc(HWND hDlg,UINT Msg,WPARAM wParam,LPARAM lParam)
1128{
1129 switch(Msg)
1130 {
1131 case WM_INITDIALOG:
1132 {
1133 LONG count;
1134 HWND hCtrl;
1135
1136 hCtrl = ::GetDlgItem(hDlg, IDC_PROGRESS1);
1137 count = Request::getRequestCount();
1138
1139 ::SetWindowLong(hDlg, GWL_USERDATA, count);
1140 ::SendMessage(hCtrl, PBM_SETRANGE32, 0, count);
1141 ::SendMessage(hCtrl, PBM_SETPOS, count - Request::getRequestCount(), 0);
1142
1143 ::SetTimer(hDlg, 100, 200, NULL);
1144 break;
1145 }
1146
1147 case WM_TIMER:
1148 if(wParam == 100)
1149 {
1150 LONG count;
1151 HWND hCtrl;
1152
1153 hCtrl = ::GetDlgItem(hDlg, IDC_PROGRESS1);
1154 count = ::GetWindowLong(hDlg, GWL_USERDATA);
1155
1156 ::SendMessage(hCtrl, PBM_SETPOS, count - Request::getRequestCount(), 0);
1157
1158 if(Request::getRequestCount() <= 0)
1159 ::PostQuitMessage(0);
1160 }
1161 break;
1162 case WM_CLOSE:
1163 break;
1164
1165 default:
1166 return FALSE;
1167 }
1168 return TRUE;
1169}
1170
1171extern "C"
1172void _cdecl InitializeComSupportModule(void)
1173{
1174 kprintf(("InitializeComSupportModule()\n"));
1175
1176 Request::initialize();
1177 DeviceRequest::initialize();
1178 EventRequest::initialize();
1179
1180
1181 request_semaphore = ::CreateSemaphore(0, 0, 65536, 0);
1182 FatalAssertion(request_semaphore != NULL, "Object Creation Error : request_semaphore");
1183
1184 worker_thread_handle = ::CreateThread(0, 0, WorkerThreadProcess, 0, 0, 0);
1185 FatalAssertion(worker_thread_handle != NULL, "Object Creation Error : worker_thread");
1186
1187 Request * request = Request::Create(Request::Confirmation, true);
1188 request->invoke();
1189}
1190
1191extern "C"
1192void _cdecl FinalizeComSupportModule(void)
1193{
1194 kprintf(("FinalizeComSupportModule()\n"));
1195
1196 if(IsValid())
1197 {
1198 HWND hDlgitem;
1199 HWND NotifyDialog;
1200 MSG msg;
1201
1202 //ログが溜まりすぎるとログ吐きに時間がかかり、プログラムが暴走したように見えるので
1203 //「ログを吐いてるから待
1204て」と警告を出す。
1205 NotifyDialog = ::CreateDialog(ProcessInstance, MAKEINTRESOURCE(QUITNOTICEDIALOG), NULL, NotifyDialogProc);
1206 hDlgitem = ::GetDlgItem(NotifyDialog, IDC_NOTIFYMSG);
1207 ::SetWindowText(hDlgitem, "今 一生懸命カーネルのイベントログを出しているので、終るまで少し待
1208ってください");
1209 ::ShowWindow(NotifyDialog, SW_NORMAL);
1210
1211 Request * request = Request::Create(Request::QuitThread, false);
1212 request->invoke();
1213
1214 //終了ダイアログ用のメッセージポンプ
1215
1216 if(NotifyDialog != NULL) {
1217 while(GetMessage(&msg, NULL, 0, 0) != 0) {
1218 TranslateMessage(&msg);
1219 DispatchMessage(&msg);
1220 }
1221 }
1222
1223 //ちゃんとスレッドが終了するまで待
1224機
1225 if(worker_thread_handle != NULL)
1226 ::WaitForSingleObject(worker_thread_handle, INFINITE);
1227 ::CloseHandle(request_semaphore);
1228 request_semaphore = NULL;
1229
1230 EventRequest::finalize();
1231 DeviceRequest::finalize();
1232 Request::finalize();
1233
1234 ::DestroyWindow(NotifyDialog);
1235 }
1236}
1237
1238
1239#else // __COM_NOT_REQUIRED__
1240
1241extern "C"
1242void _cdecl InitializeComSupportModule(void)
1243{}
1244
1245extern "C"
1246void _cdecl FinalizeComSupportModule(void)
1247{}
1248
1249#endif // __COM_NOT_REQUIRED__
Note: See TracBrowser for help on using the repository browser.