Annotation of OpenXM_contrib2/windows/engine2000/io.c, Revision 1.10
1.1 noro 1: /*
2: main.c
3:
4: Windows toplevel and functions for communication, error-handling.
5: WinMain() is the common toplevel function for several asir variants.
6: 'Main()' (the toplevel of the usual asir session) is called from WinMain().
7: Furthermore, a special GUI for debugging is created by create_debug_gui().
8:
9: There are two sets of events:
10: {Notify0, Notify0_Ack, Intr0, Intr0_Ack, Kill}
11: and
12: {DebugNotify, DebugNotify_Ack, DebugIntr, DebugIntr_Ack}.
13: These are used for the communication between Asir GUI and engine,
14: or debug GUI and engine respectively.
15:
16: Asir GUI <-- Notify0, Notify0_Ack, Kill --> engine
17: debug GUI <-- DebugNotify, DebugNotify_Ack --> engine
18:
19: Revision History:
20:
21: 99/04/27 noro the first official version
22: 99/07/27 noro
23: */
24:
25: #include <stdio.h>
26: #include <stdlib.h>
27: #include <windows.h>
28: #include <signal.h>
29: #include <io.h>
30: #include <fcntl.h>
31: #include <process.h>
1.2 noro 32: #include "ca.h"
1.1 noro 33:
34: /* error message structure */
35:
36: typedef struct ErrMsg {
37: int code;
38: char reason[BUFSIZ*5]; /* XXX : the size should coincide with that in GUI */
39: char action[BUFSIZ*5];
40: } ErrMsg;
41:
42: /* main thread id */
43: DWORD MainThread;
44:
45: /* pipe handles */
46: static HANDLE hRead,hWrite;
47: static HANDLE hRead0,hWrite0;
48: static HANDLE hDebugRead,hDebugWrite;
49:
50: /* event handles */
51: static HANDLE hOxIntr,hOxReset,hOxKill;
52: static HANDLE hNotify,hNotify_Ack,hIntr,hIntr_Ack,hKill;
53: static HANDLE hNotify0,hNotify_Ack0,hIntr0;
54: static HANDLE hDebugNotify,hDebugNotify_Ack,hDebugIntr,hDebugIntr_Ack,hDebugKill;
55:
56: HANDLE hResizeNotify,hResizeNotify_Ack; /* should be visible from another file */
1.4 noro 57: HANDLE hMainThreadReady,hCanvasCreated; /* notification for ox_plot */
1.1 noro 58:
59: /* XXX */
60: extern HANDLE hStreamNotify,hStreamNotify_Ack; /* declared in io/ox.c */
61:
62: /* process handle */
63: static HANDLE hDebugProc,hMessageProc;
64: static HANDLE hThread,hWatchIntrThread,hWatchStreamThread,hComputingThread;
65:
66: static struct ErrMsg Errmsg;
67:
68: /*
69: * recv_intr : flag for Asir
70: * interrupt_state : flag to distinguish an Asir error and a cancellation
71: */
72:
1.5 noro 73: int emergency;
1.1 noro 74: static int interrupt_state;
75: int debuggui_is_present;
76: int messagegui_is_present;
77:
78: extern int recv_intr,doing_batch;
79: extern int ox_sock_id, do_message;
80:
81: void get_rootdir(char *,int);
82: void ox_watch_stream();
83: void ox_plot_main();
84:
85: void send_intr();
86: void SendCmdSize(unsigned int,unsigned int);
87: void SendBody(void *buf,unsigned int);
88: void SendHeapSize();
89: void Main(int,char **);
90: void AsirMain(int,char **);
91: void OxAsirMain(int,char **);
92: void OxPlotMain(int,char **);
93:
94: void Init_Asir(int,char **);
95: int Call_Asir(char *,void *);
96: void int_handler(int);
97: void set_debug_handles(int);
98: int create_debug_gui();
99: void terminate_debug_gui();
100:
101: void _setargv();
102:
103: #define FROMASIR_EXIT 0
104: #define FROMASIR_TEXT 1
105: #define FROMASIR_HEAPSIZE 2
106: #define FROMASIR_SHOW 3
107: #define FROMASIR_HIDE 4
108:
109: static char Asir_Cmd[BUFSIZ*8];
110:
111: extern char LastError[];
112:
113: /* the watch threads */
114:
115: void watch_intr() {
116: HANDLE handle[2];
117: DWORD ret;
118:
119: handle[0] = hIntr0; handle[1] = hKill;
120: while ( 1 ) {
121: ret = WaitForMultipleObjects(2,(CONST HANDLE *)handle,FALSE,(DWORD)-1);
122: switch ( ret ) {
123: case WAIT_OBJECT_0: /* hIntr0 */
124: if ( doing_batch )
125: send_intr();
126: /* for Asir; recv_intr is reset to 0 in Asir */
1.9 ohara 127: enter_signal_cs();
1.1 noro 128: recv_intr = 1;
1.9 ohara 129: leave_signal_cs();
1.8 noro 130: PulseEvent(hIntr_Ack);
1.1 noro 131: break;
132: case WAIT_OBJECT_0+1: /* hKill */
133: default:
134: terminate_debug_gui();
135: emergency = 1; /* XXX */
1.6 noro 136: asir_terminate(3);
1.1 noro 137: exit(0);
138: /* NOTREACHED */
139: break;
140: }
141: }
142: }
143:
144: void ox_watch_intr() {
145: HANDLE handle[3];
146: DWORD ret;
147:
148: handle[0] = hOxIntr; handle[1] = hOxReset; handle[2] = hOxKill;
149: while ( 1 ) {
150: ret = WaitForMultipleObjects(3,(CONST HANDLE *)handle,FALSE,(DWORD)-1);
151: switch ( ret ) {
152: case WAIT_OBJECT_0: /* hOxIntr */
153: ResetEvent(hOxIntr);
154: if ( doing_batch )
155: send_intr();
1.9 ohara 156: enter_signal_cs();
1.1 noro 157: recv_intr = 1;
1.9 ohara 158: leave_signal_cs();
1.1 noro 159: break;
160: case WAIT_OBJECT_0+1: /* hOxReset */
161: ResetEvent(hOxReset);
162: if ( doing_batch )
163: send_intr();
1.9 ohara 164: enter_signal_cs();
1.1 noro 165: recv_intr = 2;
1.9 ohara 166: leave_signal_cs();
1.1 noro 167: break;
168: case WAIT_OBJECT_0+2: /* hOxKill */
169: ResetEvent(hOxKill);
170: terminate_debug_gui();
171: emergency = 1; /* XXX */
1.6 noro 172: asir_terminate(3);
1.1 noro 173: /* NOTREACHED */
174: break;
175: }
176: }
177: }
178:
179: /*
180: setup the necessary events for communication between debug GUI and engine.
181: Then the debug GUI is invoked.
182: */
183:
184: int create_message_gui()
185: {
186: DWORD mypid,len;
187: HANDLE hR0,hW0,hR1,hW1;
188: SECURITY_ATTRIBUTES SecurityAttributes;
189: char remread[10],remwrite[10];
190: char notify[100],notify_ack[100];
191: char name[100];
192: char DebugGUI[100];
193: char *av[100];
194:
195: mypid = GetCurrentProcessId();
196: sprintf(notify,"message_notify_%d",mypid);
197: sprintf(notify_ack,"message_notify_ack_%d",mypid);
198: hNotify = hNotify0 = CreateEvent(NULL,TRUE,FALSE,notify);
199: hNotify_Ack = hNotify_Ack0 = CreateEvent(NULL,TRUE,FALSE,notify_ack);
200:
201: SecurityAttributes.nLength = sizeof(SecurityAttributes);
202: SecurityAttributes.lpSecurityDescriptor = NULL;
203: SecurityAttributes.bInheritHandle = TRUE;
204: CreatePipe(&hR0, &hW0, &SecurityAttributes, 65536);
205: CreatePipe(&hR1, &hW1, &SecurityAttributes, 65536);
206:
207: hRead = hRead0 = hR0;
208: hWrite = hWrite0 = hW1;
209: sprintf(remread,"%d",(DWORD)hR1);
210: sprintf(remwrite,"%d",(DWORD)hW0);
211: len = sizeof(name);
212: get_rootdir(name,len);
213: sprintf(DebugGUI,"%s\\bin\\asirgui.exe",name);
214: av[0] = "messagegui";
215: av[1] = remread;
216: av[2] = remwrite;
217: av[3] = notify;
218: av[4] = notify_ack;
219: av[5] = NULL;
220: hMessageProc = (HANDLE)_spawnv(_P_NOWAIT,DebugGUI,av);
221: if ( hMessageProc == (HANDLE)-1 ) {
222: fprintf(stderr,"%s not found",DebugGUI);
223: messagegui_is_present = 0;
224: return -1;
225: } else
226: messagegui_is_present = 1;
227: return 0;
228: }
229:
230: /*
231: setup the necessary events for communication between debug GUI and engine.
232: Then the debug GUI is invoked.
233: */
234:
235: int create_debug_gui()
236: {
237: DWORD mypid,len;
238: HANDLE hR0,hW0,hR1,hW1;
239: SECURITY_ATTRIBUTES SecurityAttributes;
240: char remread[10],remwrite[10];
241: char notify[100],notify_ack[100],intr[100],intr_ack[100],kill[100];
242: char name[100];
243: char DebugGUI[100];
244: char *av[100];
245:
246: mypid = GetCurrentProcessId();
247: sprintf(notify,"debug_notify_%d",mypid);
248: sprintf(notify_ack,"debug_notify_ack_%d",mypid);
249: sprintf(intr,"debug_intr_%d",mypid);
250: sprintf(intr_ack,"debug_intr_ack_%d",mypid);
251: sprintf(kill,"debug_kill_%d",mypid);
252: hDebugNotify = CreateEvent(NULL,TRUE,FALSE,notify);
253: hDebugNotify_Ack = CreateEvent(NULL,TRUE,FALSE,notify_ack);
254: hDebugIntr = CreateEvent(NULL,TRUE,FALSE,intr);
255: hDebugIntr_Ack = CreateEvent(NULL,TRUE,FALSE,intr_ack);
256: hDebugKill = CreateEvent(NULL,TRUE,FALSE,kill);
257:
258: SecurityAttributes.nLength = sizeof(SecurityAttributes);
259: SecurityAttributes.lpSecurityDescriptor = NULL;
260: SecurityAttributes.bInheritHandle = TRUE;
261: CreatePipe(&hR0, &hW0, &SecurityAttributes, 65536);
262: CreatePipe(&hR1, &hW1, &SecurityAttributes, 65536);
263:
264: hDebugRead = hR0;
265: hDebugWrite = hW1;
266: sprintf(remread,"%d",(DWORD)hR1);
267: sprintf(remwrite,"%d",(DWORD)hW0);
268: len = sizeof(name);
269: get_rootdir(name,len);
270: sprintf(DebugGUI,"%s\\bin\\asirgui.exe",name);
271: av[0] = "debuggui";
272: av[1] = remread;
273: av[2] = remwrite;
274: av[3] = notify;
275: av[4] = notify_ack;
276: av[5] = intr;
277: av[6] = intr_ack;
278: av[7] = kill;
279: av[8] = NULL;
280: hDebugProc = (HANDLE)_spawnv(_P_NOWAIT,DebugGUI,av);
281: if ( hDebugProc == (HANDLE)-1 ) {
282: fprintf(stderr,"%s not found",DebugGUI);
283: return -1;
284: }
285: return 0;
286: }
287:
288: /* if debug GUI is present, we have to terminate the process */
289:
290: void terminate_debug_gui()
291: {
292: if ( hDebugProc ) {
293: TerminateProcess(hDebugProc,0);
294: // hRead = hDebugRead; hWrite = hDebugWrite;
295: // hNotify = hDebugNotify; hNotify_Ack = hDebugNotify_Ack;
296: // hIntr = hDebugIntr;
297: // SendCmdSize(FROMASIR_EXIT,0);
298: hDebugProc = 0;
299: }
300: if ( hMessageProc ) {
301: TerminateProcess(hMessageProc,0);
302: // hRead = hRead0; hWrite = hWrite0;
303: // hNotify = hNotify0; hNotify_Ack = hNotify_Ack0;
304: // hIntr = hIntr0;
305: // SendCmdSize(FROMASIR_EXIT,0);
306: hMessageProc = 0;
307: }
308: }
309:
310: /* set the current active set of events */
311:
312: void set_debug_handles(int on)
313: {
314: if ( on ) {
315: if ( !debuggui_is_present ) {
316: hRead = hDebugRead; hWrite = hDebugWrite;
317: hNotify = hDebugNotify; hNotify_Ack = hDebugNotify_Ack;
318: hIntr = hDebugIntr;
319: SendCmdSize(FROMASIR_SHOW,0);
320: debuggui_is_present = 1;
321: }
322: } else {
323: if ( debuggui_is_present ) {
324: SendCmdSize(FROMASIR_HIDE,0);
325: hRead = hRead0; hWrite = hWrite0;
326: hNotify = hNotify0; hNotify_Ack = hNotify_Ack0;
327: hIntr = hIntr0;
328: debuggui_is_present = 0;
329: }
330: }
331: }
332:
1.7 noro 333: extern int wfep_mode;
334:
1.1 noro 335: void Init_IO()
336: {
1.10 ! ohara 337: #if _MSC_VER < 1900
1.1 noro 338: _setargv();
1.10 ! ohara 339: #endif
1.7 noro 340: if ( !strncmp(__argv[0],"ox_asir",strlen("ox_asir")) ) {
341: /* ox_asir or ox_asir_wfep */
342: if ( !strcmp(__argv[0],"ox_asir_wfep") ) wfep_mode = 1;
1.1 noro 343: OxAsirMain(__argc,__argv);
344: exit(0);
345: } else if ( !strcmp(__argv[0],"ox_plot") )
346: OxPlotMain(__argc,__argv);
347: else if ( !strcmp(__argv[0],"ox_launch") ) {
348: launch_main(__argc,__argv);
349: exit(0);
350: } else {
351: AsirMain(__argc,__argv);
352: exit(0);
353: }
354: }
355:
356: void AsirMain(int argc, char **argv)
357: {
358: DWORD tid;
359:
360: hRead = (void *)atoi(__argv[1]);
361: hWrite = (void *)atoi(__argv[2]);
362: hNotify = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[3]);
363: hNotify_Ack = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[4]);
364: hIntr = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[5]);
365: hIntr_Ack = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[6]);
366: hKill = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[7]);
367: if ( !hRead || !hWrite || !hNotify || !hNotify_Ack || !hIntr || !hIntr_Ack || !hKill )
368: exit(0);
369: /* save the above handles */
370: hRead0 = hRead; hWrite0 = hWrite;
371: hNotify0 = hNotify; hNotify_Ack0 = hNotify_Ack;
372: hIntr0 = hIntr;
373:
374: hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)watch_intr,NULL,0,&tid);
375: if ( !hThread )
376: exit(0);
377: // ret = SetThreadPriority(hThread,THREAD_PRIORITY_BELOW_NORMAL);
378: // if ( !ret )
379: // exit(0);
380: /* messagegui is the asirgui main window. */
381: messagegui_is_present = 1;
382: /* The rest of the args are passed to Main(). */
383: /* XXX : process_args() increments argv. */
384: // ret = SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL);
385: // if ( !ret )
386: // exit(0);
387: Main(__argc-7,__argv+7);
388: }
389:
390: void OxAsirMain(int argc, char **argv)
391: {
392: int create_message;
393: int tid;
394:
395: ox_sock_id = atoi(__argv[1]);
396: create_message = atoi(__argv[2]);
397: hOxIntr = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[3]);
398: hOxReset = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[4]);
399: hOxKill = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[5]);
400: if ( create_message )
401: create_message_gui();
402: else
403: messagegui_is_present = 0;
404: if ( messagegui_is_present )
405: SendCmdSize(FROMASIR_SHOW,0);
406: hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_watch_intr,NULL,0,&tid);
407: // ret = SetThreadPriority(hThread,THREAD_PRIORITY_BELOW_NORMAL);
408: // if ( !ret )
409: // exit(0);
410: // ret = SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL);
411: // if ( !ret )
412: // exit(0);
413: /* XXX : process_args() increments argv. */
414: ox_main(__argc-5,__argv+5);
415: }
416:
417: int plot_argc;
418: char **plot_argv;
419:
420: void OxPlotMain(int argc, char **argv)
421: {
422: DWORD tid;
423: DWORD mypid;
424: char eventname[BUFSIZ];
425:
426: ox_sock_id = atoi(argv[1]);
427: do_message = atoi(argv[2]);
428: hOxIntr = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,argv[3]);
429: hOxReset = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,argv[4]);
430: hOxKill = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,argv[5]);
431:
432: if ( do_message )
433: create_message_gui();
434: else
435: messagegui_is_present = 0;
436: if ( messagegui_is_present )
437: SendCmdSize(FROMASIR_SHOW,0);
438:
439: mypid = GetCurrentProcessId();
440: sprintf(eventname,"stream_notify_%d",mypid);
441: hStreamNotify = CreateEvent(NULL,TRUE,FALSE,eventname);
442: sprintf(eventname,"stream_notify_ack_%d",mypid);
443: hStreamNotify_Ack = CreateEvent(NULL,TRUE,FALSE,eventname);
444: sprintf(eventname,"resize_notify_%d",mypid);
445: hResizeNotify = CreateEvent(NULL,TRUE,FALSE,eventname);
446: sprintf(eventname,"resize_notify_ack_%d",mypid);
447: hResizeNotify_Ack = CreateEvent(NULL,TRUE,FALSE,eventname);
1.4 noro 448: sprintf(eventname,"mainthreadready_%d",mypid);
449: hMainThreadReady = CreateEvent(NULL,TRUE,FALSE,eventname);
450: sprintf(eventname,"canvascreated_%d",mypid);
451: hCanvasCreated = CreateEvent(NULL,TRUE,FALSE,eventname);
1.1 noro 452:
453: hWatchStreamThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_watch_stream,NULL,0,&tid);
454: // ret = SetThreadPriority(hWatchStreamThread,THREAD_PRIORITY_BELOW_NORMAL);
455: // if ( !ret )
456: // exit(0);
457: hWatchIntrThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_watch_intr,NULL,0,&tid);
458: // ret = SetThreadPriority(hWatchIntrThread,THREAD_PRIORITY_BELOW_NORMAL);
459: // if ( !ret )
460: // exit(0);
461:
462: /* process_args() increments argv */
463: plot_argc = argc-5;
1.3 noro 464: plot_argv = argv+5;
1.1 noro 465: hComputingThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_plot_main,NULL,0,&tid);
466: // ret = SetThreadPriority(hComputingThread,THREAD_PRIORITY_ABOVE_NORMAL);
467: // if ( !ret )
468: // exit(0);
469: }
470:
471: void ox_watch_stream() {
472: fd_set r,w,e;
473:
474: /* wait for the completion of initalization in the computing thread */
475: WaitForSingleObject(hStreamNotify_Ack,(DWORD)-1);
476: ResetEvent(hStreamNotify_Ack);
477: while ( 1 ) {
478: FD_ZERO(&r);
479: FD_ZERO(&w);
480: FD_ZERO(&e);
481: FD_SET(ox_sock_id,&r);
482: select(FD_SETSIZE,&r,&w,&e,NULL);
483: SetEvent(hStreamNotify);
484: WaitForSingleObject(hStreamNotify_Ack,(DWORD)-1);
485: ResetEvent(hStreamNotify_Ack);
486: }
487: }
488:
489: /* get_line : used in Asir mode */
490:
491: int get_line(char *buf) {
492: DWORD len;
493: int size;
494:
495: ReadFile(hRead,&size,sizeof(int),&len,NULL);
496: ReadFile(hRead,buf,size,&len,NULL);
497: buf[size] = 0;
498: return 0;
499: }
500:
501: /* put_line : used in Asir mode */
502:
503: void put_line(char *buf) {
504: if ( debuggui_is_present || messagegui_is_present ) {
505: int size = strlen(buf);
506:
507: if ( size ) {
508: SendCmdSize(FROMASIR_TEXT,size);
509: SendBody(buf,size);
510: }
511: }
512: }
513:
514: /* common function for error exit */
515:
516: void ExitAsir() {
517: terminate_debug_gui();
518: /* if emergency != 0, asirgui may not exist */
519: if ( !emergency )
520: SendCmdSize(FROMASIR_EXIT,0);
521: ExitProcess(0);
522: }
523:
524: /* SendHeapSize : used in Asir mode */
525:
526: int get_heapsize();
527:
528: void SendHeapSize()
529: {
530: if ( messagegui_is_present || debuggui_is_present ) {
531: int h = get_heapsize();
532: SendCmdSize(FROMASIR_HEAPSIZE,sizeof(int));
533: SendBody(&h,sizeof(int));
534: }
535: }
536:
537: /* SendCmdSize : used in Asir mode */
538:
539: void SendCmdSize(unsigned int cmd,unsigned int size)
540: {
541: DWORD len;
542: unsigned int cmdsize;
543:
544: if ( hNotify ) {
545: SetEvent(hNotify);
546: WaitForSingleObject(hNotify_Ack,(DWORD)-1);
547: ResetEvent(hNotify_Ack);
548: cmdsize = (cmd<<16)|size;
549: WriteFile(hWrite,&cmdsize,sizeof(unsigned int),&len,NULL);
550: }
551: }
552:
553: /* SendBody : used in Asir mode */
554:
555: void SendBody(void *buf,unsigned int size)
556: {
557:
558: DWORD len;
559:
560: WriteFile(hWrite,buf,size,&len,NULL);
561: }
562:
563: /* send header + send progress data */
564:
565: void send_progress(short percentage,char *message)
566: {
567: }
568:
569: /* set error code, message, action in Errmsg. */
570:
571: void set_error(int id,char *reason,char *action)
572: {
573: }
574:
575: /* dummy functions */
1.3 noro 576: void reset_current_computation(){}
577: void set_selection(){}
578: void reset_selection(){}
579: void set_busy(){}
580: void reset_busy(){}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>