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