Annotation of OpenXM_contrib2/windows/engine2000/io.c, Revision 1.8
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 */
127: recv_intr = 1;
1.8 ! noro 128: PulseEvent(hIntr_Ack);
1.1 noro 129: break;
130: case WAIT_OBJECT_0+1: /* hKill */
131: default:
132: terminate_debug_gui();
133: emergency = 1; /* XXX */
1.6 noro 134: asir_terminate(3);
1.1 noro 135: exit(0);
136: /* NOTREACHED */
137: break;
138: }
139: }
140: }
141:
142: void ox_watch_intr() {
143: HANDLE handle[3];
144: DWORD ret;
145:
146: handle[0] = hOxIntr; handle[1] = hOxReset; handle[2] = hOxKill;
147: while ( 1 ) {
148: ret = WaitForMultipleObjects(3,(CONST HANDLE *)handle,FALSE,(DWORD)-1);
149: switch ( ret ) {
150: case WAIT_OBJECT_0: /* hOxIntr */
151: ResetEvent(hOxIntr);
152: if ( doing_batch )
153: send_intr();
154: recv_intr = 1;
155: break;
156: case WAIT_OBJECT_0+1: /* hOxReset */
157: ResetEvent(hOxReset);
158: if ( doing_batch )
159: send_intr();
160: recv_intr = 2;
161: break;
162: case WAIT_OBJECT_0+2: /* hOxKill */
163: ResetEvent(hOxKill);
164: terminate_debug_gui();
165: emergency = 1; /* XXX */
1.6 noro 166: asir_terminate(3);
1.1 noro 167: /* NOTREACHED */
168: break;
169: }
170: }
171: }
172:
173: /*
174: setup the necessary events for communication between debug GUI and engine.
175: Then the debug GUI is invoked.
176: */
177:
178: int create_message_gui()
179: {
180: DWORD mypid,len;
181: HANDLE hR0,hW0,hR1,hW1;
182: SECURITY_ATTRIBUTES SecurityAttributes;
183: char remread[10],remwrite[10];
184: char notify[100],notify_ack[100];
185: char name[100];
186: char DebugGUI[100];
187: char *av[100];
188:
189: mypid = GetCurrentProcessId();
190: sprintf(notify,"message_notify_%d",mypid);
191: sprintf(notify_ack,"message_notify_ack_%d",mypid);
192: hNotify = hNotify0 = CreateEvent(NULL,TRUE,FALSE,notify);
193: hNotify_Ack = hNotify_Ack0 = CreateEvent(NULL,TRUE,FALSE,notify_ack);
194:
195: SecurityAttributes.nLength = sizeof(SecurityAttributes);
196: SecurityAttributes.lpSecurityDescriptor = NULL;
197: SecurityAttributes.bInheritHandle = TRUE;
198: CreatePipe(&hR0, &hW0, &SecurityAttributes, 65536);
199: CreatePipe(&hR1, &hW1, &SecurityAttributes, 65536);
200:
201: hRead = hRead0 = hR0;
202: hWrite = hWrite0 = hW1;
203: sprintf(remread,"%d",(DWORD)hR1);
204: sprintf(remwrite,"%d",(DWORD)hW0);
205: len = sizeof(name);
206: get_rootdir(name,len);
207: sprintf(DebugGUI,"%s\\bin\\asirgui.exe",name);
208: av[0] = "messagegui";
209: av[1] = remread;
210: av[2] = remwrite;
211: av[3] = notify;
212: av[4] = notify_ack;
213: av[5] = NULL;
214: hMessageProc = (HANDLE)_spawnv(_P_NOWAIT,DebugGUI,av);
215: if ( hMessageProc == (HANDLE)-1 ) {
216: fprintf(stderr,"%s not found",DebugGUI);
217: messagegui_is_present = 0;
218: return -1;
219: } else
220: messagegui_is_present = 1;
221: return 0;
222: }
223:
224: /*
225: setup the necessary events for communication between debug GUI and engine.
226: Then the debug GUI is invoked.
227: */
228:
229: int create_debug_gui()
230: {
231: DWORD mypid,len;
232: HANDLE hR0,hW0,hR1,hW1;
233: SECURITY_ATTRIBUTES SecurityAttributes;
234: char remread[10],remwrite[10];
235: char notify[100],notify_ack[100],intr[100],intr_ack[100],kill[100];
236: char name[100];
237: char DebugGUI[100];
238: char *av[100];
239:
240: mypid = GetCurrentProcessId();
241: sprintf(notify,"debug_notify_%d",mypid);
242: sprintf(notify_ack,"debug_notify_ack_%d",mypid);
243: sprintf(intr,"debug_intr_%d",mypid);
244: sprintf(intr_ack,"debug_intr_ack_%d",mypid);
245: sprintf(kill,"debug_kill_%d",mypid);
246: hDebugNotify = CreateEvent(NULL,TRUE,FALSE,notify);
247: hDebugNotify_Ack = CreateEvent(NULL,TRUE,FALSE,notify_ack);
248: hDebugIntr = CreateEvent(NULL,TRUE,FALSE,intr);
249: hDebugIntr_Ack = CreateEvent(NULL,TRUE,FALSE,intr_ack);
250: hDebugKill = CreateEvent(NULL,TRUE,FALSE,kill);
251:
252: SecurityAttributes.nLength = sizeof(SecurityAttributes);
253: SecurityAttributes.lpSecurityDescriptor = NULL;
254: SecurityAttributes.bInheritHandle = TRUE;
255: CreatePipe(&hR0, &hW0, &SecurityAttributes, 65536);
256: CreatePipe(&hR1, &hW1, &SecurityAttributes, 65536);
257:
258: hDebugRead = hR0;
259: hDebugWrite = hW1;
260: sprintf(remread,"%d",(DWORD)hR1);
261: sprintf(remwrite,"%d",(DWORD)hW0);
262: len = sizeof(name);
263: get_rootdir(name,len);
264: sprintf(DebugGUI,"%s\\bin\\asirgui.exe",name);
265: av[0] = "debuggui";
266: av[1] = remread;
267: av[2] = remwrite;
268: av[3] = notify;
269: av[4] = notify_ack;
270: av[5] = intr;
271: av[6] = intr_ack;
272: av[7] = kill;
273: av[8] = NULL;
274: hDebugProc = (HANDLE)_spawnv(_P_NOWAIT,DebugGUI,av);
275: if ( hDebugProc == (HANDLE)-1 ) {
276: fprintf(stderr,"%s not found",DebugGUI);
277: return -1;
278: }
279: return 0;
280: }
281:
282: /* if debug GUI is present, we have to terminate the process */
283:
284: void terminate_debug_gui()
285: {
286: if ( hDebugProc ) {
287: TerminateProcess(hDebugProc,0);
288: // hRead = hDebugRead; hWrite = hDebugWrite;
289: // hNotify = hDebugNotify; hNotify_Ack = hDebugNotify_Ack;
290: // hIntr = hDebugIntr;
291: // SendCmdSize(FROMASIR_EXIT,0);
292: hDebugProc = 0;
293: }
294: if ( hMessageProc ) {
295: TerminateProcess(hMessageProc,0);
296: // hRead = hRead0; hWrite = hWrite0;
297: // hNotify = hNotify0; hNotify_Ack = hNotify_Ack0;
298: // hIntr = hIntr0;
299: // SendCmdSize(FROMASIR_EXIT,0);
300: hMessageProc = 0;
301: }
302: }
303:
304: /* set the current active set of events */
305:
306: void set_debug_handles(int on)
307: {
308: if ( on ) {
309: if ( !debuggui_is_present ) {
310: hRead = hDebugRead; hWrite = hDebugWrite;
311: hNotify = hDebugNotify; hNotify_Ack = hDebugNotify_Ack;
312: hIntr = hDebugIntr;
313: SendCmdSize(FROMASIR_SHOW,0);
314: debuggui_is_present = 1;
315: }
316: } else {
317: if ( debuggui_is_present ) {
318: SendCmdSize(FROMASIR_HIDE,0);
319: hRead = hRead0; hWrite = hWrite0;
320: hNotify = hNotify0; hNotify_Ack = hNotify_Ack0;
321: hIntr = hIntr0;
322: debuggui_is_present = 0;
323: }
324: }
325: }
326:
1.7 noro 327: extern int wfep_mode;
328:
1.1 noro 329: void Init_IO()
330: {
331: _setargv();
1.7 noro 332: if ( !strncmp(__argv[0],"ox_asir",strlen("ox_asir")) ) {
333: /* ox_asir or ox_asir_wfep */
334: if ( !strcmp(__argv[0],"ox_asir_wfep") ) wfep_mode = 1;
1.1 noro 335: OxAsirMain(__argc,__argv);
336: exit(0);
337: } else if ( !strcmp(__argv[0],"ox_plot") )
338: OxPlotMain(__argc,__argv);
339: else if ( !strcmp(__argv[0],"ox_launch") ) {
340: launch_main(__argc,__argv);
341: exit(0);
342: } else {
343: AsirMain(__argc,__argv);
344: exit(0);
345: }
346: }
347:
348: void AsirMain(int argc, char **argv)
349: {
350: DWORD tid;
351:
352: hRead = (void *)atoi(__argv[1]);
353: hWrite = (void *)atoi(__argv[2]);
354: hNotify = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[3]);
355: hNotify_Ack = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[4]);
356: hIntr = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[5]);
357: hIntr_Ack = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[6]);
358: hKill = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[7]);
359: if ( !hRead || !hWrite || !hNotify || !hNotify_Ack || !hIntr || !hIntr_Ack || !hKill )
360: exit(0);
361: /* save the above handles */
362: hRead0 = hRead; hWrite0 = hWrite;
363: hNotify0 = hNotify; hNotify_Ack0 = hNotify_Ack;
364: hIntr0 = hIntr;
365:
366: hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)watch_intr,NULL,0,&tid);
367: if ( !hThread )
368: exit(0);
369: // ret = SetThreadPriority(hThread,THREAD_PRIORITY_BELOW_NORMAL);
370: // if ( !ret )
371: // exit(0);
372: /* messagegui is the asirgui main window. */
373: messagegui_is_present = 1;
374: /* The rest of the args are passed to Main(). */
375: /* XXX : process_args() increments argv. */
376: // ret = SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL);
377: // if ( !ret )
378: // exit(0);
379: Main(__argc-7,__argv+7);
380: }
381:
382: void OxAsirMain(int argc, char **argv)
383: {
384: int create_message;
385: int tid;
386:
387: ox_sock_id = atoi(__argv[1]);
388: create_message = atoi(__argv[2]);
389: hOxIntr = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[3]);
390: hOxReset = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[4]);
391: hOxKill = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[5]);
392: if ( create_message )
393: create_message_gui();
394: else
395: messagegui_is_present = 0;
396: if ( messagegui_is_present )
397: SendCmdSize(FROMASIR_SHOW,0);
398: hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_watch_intr,NULL,0,&tid);
399: // ret = SetThreadPriority(hThread,THREAD_PRIORITY_BELOW_NORMAL);
400: // if ( !ret )
401: // exit(0);
402: // ret = SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL);
403: // if ( !ret )
404: // exit(0);
405: /* XXX : process_args() increments argv. */
406: ox_main(__argc-5,__argv+5);
407: }
408:
409: int plot_argc;
410: char **plot_argv;
411:
412: void OxPlotMain(int argc, char **argv)
413: {
414: DWORD tid;
415: DWORD mypid;
416: char eventname[BUFSIZ];
417:
418: ox_sock_id = atoi(argv[1]);
419: do_message = atoi(argv[2]);
420: hOxIntr = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,argv[3]);
421: hOxReset = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,argv[4]);
422: hOxKill = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,argv[5]);
423:
424: if ( do_message )
425: create_message_gui();
426: else
427: messagegui_is_present = 0;
428: if ( messagegui_is_present )
429: SendCmdSize(FROMASIR_SHOW,0);
430:
431: mypid = GetCurrentProcessId();
432: sprintf(eventname,"stream_notify_%d",mypid);
433: hStreamNotify = CreateEvent(NULL,TRUE,FALSE,eventname);
434: sprintf(eventname,"stream_notify_ack_%d",mypid);
435: hStreamNotify_Ack = CreateEvent(NULL,TRUE,FALSE,eventname);
436: sprintf(eventname,"resize_notify_%d",mypid);
437: hResizeNotify = CreateEvent(NULL,TRUE,FALSE,eventname);
438: sprintf(eventname,"resize_notify_ack_%d",mypid);
439: hResizeNotify_Ack = CreateEvent(NULL,TRUE,FALSE,eventname);
1.4 noro 440: sprintf(eventname,"mainthreadready_%d",mypid);
441: hMainThreadReady = CreateEvent(NULL,TRUE,FALSE,eventname);
442: sprintf(eventname,"canvascreated_%d",mypid);
443: hCanvasCreated = CreateEvent(NULL,TRUE,FALSE,eventname);
1.1 noro 444:
445: hWatchStreamThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_watch_stream,NULL,0,&tid);
446: // ret = SetThreadPriority(hWatchStreamThread,THREAD_PRIORITY_BELOW_NORMAL);
447: // if ( !ret )
448: // exit(0);
449: hWatchIntrThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_watch_intr,NULL,0,&tid);
450: // ret = SetThreadPriority(hWatchIntrThread,THREAD_PRIORITY_BELOW_NORMAL);
451: // if ( !ret )
452: // exit(0);
453:
454: /* process_args() increments argv */
455: plot_argc = argc-5;
1.3 noro 456: plot_argv = argv+5;
1.1 noro 457: hComputingThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_plot_main,NULL,0,&tid);
458: // ret = SetThreadPriority(hComputingThread,THREAD_PRIORITY_ABOVE_NORMAL);
459: // if ( !ret )
460: // exit(0);
461: }
462:
463: void ox_watch_stream() {
464: fd_set r,w,e;
465:
466: /* wait for the completion of initalization in the computing thread */
467: WaitForSingleObject(hStreamNotify_Ack,(DWORD)-1);
468: ResetEvent(hStreamNotify_Ack);
469: while ( 1 ) {
470: FD_ZERO(&r);
471: FD_ZERO(&w);
472: FD_ZERO(&e);
473: FD_SET(ox_sock_id,&r);
474: select(FD_SETSIZE,&r,&w,&e,NULL);
475: SetEvent(hStreamNotify);
476: WaitForSingleObject(hStreamNotify_Ack,(DWORD)-1);
477: ResetEvent(hStreamNotify_Ack);
478: }
479: }
480:
481: /* get_line : used in Asir mode */
482:
483: int get_line(char *buf) {
484: DWORD len;
485: int size;
486:
487: ReadFile(hRead,&size,sizeof(int),&len,NULL);
488: ReadFile(hRead,buf,size,&len,NULL);
489: buf[size] = 0;
490: return 0;
491: }
492:
493: /* put_line : used in Asir mode */
494:
495: void put_line(char *buf) {
496: if ( debuggui_is_present || messagegui_is_present ) {
497: int size = strlen(buf);
498:
499: if ( size ) {
500: SendCmdSize(FROMASIR_TEXT,size);
501: SendBody(buf,size);
502: }
503: }
504: }
505:
506: /* common function for error exit */
507:
508: void ExitAsir() {
509: terminate_debug_gui();
510: /* if emergency != 0, asirgui may not exist */
511: if ( !emergency )
512: SendCmdSize(FROMASIR_EXIT,0);
513: ExitProcess(0);
514: }
515:
516: /* SendHeapSize : used in Asir mode */
517:
518: int get_heapsize();
519:
520: void SendHeapSize()
521: {
522: if ( messagegui_is_present || debuggui_is_present ) {
523: int h = get_heapsize();
524: SendCmdSize(FROMASIR_HEAPSIZE,sizeof(int));
525: SendBody(&h,sizeof(int));
526: }
527: }
528:
529: /* SendCmdSize : used in Asir mode */
530:
531: void SendCmdSize(unsigned int cmd,unsigned int size)
532: {
533: DWORD len;
534: unsigned int cmdsize;
535:
536: if ( hNotify ) {
537: SetEvent(hNotify);
538: WaitForSingleObject(hNotify_Ack,(DWORD)-1);
539: ResetEvent(hNotify_Ack);
540: cmdsize = (cmd<<16)|size;
541: WriteFile(hWrite,&cmdsize,sizeof(unsigned int),&len,NULL);
542: }
543: }
544:
545: /* SendBody : used in Asir mode */
546:
547: void SendBody(void *buf,unsigned int size)
548: {
549:
550: DWORD len;
551:
552: WriteFile(hWrite,buf,size,&len,NULL);
553: }
554:
555: /* send header + send progress data */
556:
557: void send_progress(short percentage,char *message)
558: {
559: }
560:
561: /* set error code, message, action in Errmsg. */
562:
563: void set_error(int id,char *reason,char *action)
564: {
565: }
566:
567: /* dummy functions */
1.3 noro 568: void reset_current_computation(){}
569: void set_selection(){}
570: void reset_selection(){}
571: void set_busy(){}
572: void reset_busy(){}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>