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