Annotation of OpenXM_contrib2/windows/engine2000/io.c, Revision 1.6
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:
326: void Init_IO()
327: {
328: _setargv();
329: if ( !strcmp(__argv[0],"ox_asir") ) {
330: OxAsirMain(__argc,__argv);
331: exit(0);
332: } else if ( !strcmp(__argv[0],"ox_plot") )
333: OxPlotMain(__argc,__argv);
334: else if ( !strcmp(__argv[0],"ox_launch") ) {
335: launch_main(__argc,__argv);
336: exit(0);
337: } else {
338: AsirMain(__argc,__argv);
339: exit(0);
340: }
341: }
342:
343: void AsirMain(int argc, char **argv)
344: {
345: DWORD tid;
346:
347: hRead = (void *)atoi(__argv[1]);
348: hWrite = (void *)atoi(__argv[2]);
349: hNotify = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[3]);
350: hNotify_Ack = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[4]);
351: hIntr = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[5]);
352: hIntr_Ack = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[6]);
353: hKill = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[7]);
354: if ( !hRead || !hWrite || !hNotify || !hNotify_Ack || !hIntr || !hIntr_Ack || !hKill )
355: exit(0);
356: /* save the above handles */
357: hRead0 = hRead; hWrite0 = hWrite;
358: hNotify0 = hNotify; hNotify_Ack0 = hNotify_Ack;
359: hIntr0 = hIntr;
360:
361: hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)watch_intr,NULL,0,&tid);
362: if ( !hThread )
363: exit(0);
364: // ret = SetThreadPriority(hThread,THREAD_PRIORITY_BELOW_NORMAL);
365: // if ( !ret )
366: // exit(0);
367: /* messagegui is the asirgui main window. */
368: messagegui_is_present = 1;
369: /* The rest of the args are passed to Main(). */
370: /* XXX : process_args() increments argv. */
371: // ret = SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL);
372: // if ( !ret )
373: // exit(0);
374: Main(__argc-7,__argv+7);
375: }
376:
377: void OxAsirMain(int argc, char **argv)
378: {
379: int create_message;
380: int tid;
381:
382: ox_sock_id = atoi(__argv[1]);
383: create_message = atoi(__argv[2]);
384: hOxIntr = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[3]);
385: hOxReset = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[4]);
386: hOxKill = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,__argv[5]);
387: if ( create_message )
388: create_message_gui();
389: else
390: messagegui_is_present = 0;
391: if ( messagegui_is_present )
392: SendCmdSize(FROMASIR_SHOW,0);
393: hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_watch_intr,NULL,0,&tid);
394: // ret = SetThreadPriority(hThread,THREAD_PRIORITY_BELOW_NORMAL);
395: // if ( !ret )
396: // exit(0);
397: // ret = SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL);
398: // if ( !ret )
399: // exit(0);
400: /* XXX : process_args() increments argv. */
401: ox_main(__argc-5,__argv+5);
402: }
403:
404: int plot_argc;
405: char **plot_argv;
406:
407: void OxPlotMain(int argc, char **argv)
408: {
409: DWORD tid;
410: DWORD mypid;
411: char eventname[BUFSIZ];
412:
413: ox_sock_id = atoi(argv[1]);
414: do_message = atoi(argv[2]);
415: hOxIntr = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,argv[3]);
416: hOxReset = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,argv[4]);
417: hOxKill = OpenEvent(EVENT_ALL_ACCESS|EVENT_MODIFY_STATE,TRUE,argv[5]);
418:
419: if ( do_message )
420: create_message_gui();
421: else
422: messagegui_is_present = 0;
423: if ( messagegui_is_present )
424: SendCmdSize(FROMASIR_SHOW,0);
425:
426: mypid = GetCurrentProcessId();
427: sprintf(eventname,"stream_notify_%d",mypid);
428: hStreamNotify = CreateEvent(NULL,TRUE,FALSE,eventname);
429: sprintf(eventname,"stream_notify_ack_%d",mypid);
430: hStreamNotify_Ack = CreateEvent(NULL,TRUE,FALSE,eventname);
431: sprintf(eventname,"resize_notify_%d",mypid);
432: hResizeNotify = CreateEvent(NULL,TRUE,FALSE,eventname);
433: sprintf(eventname,"resize_notify_ack_%d",mypid);
434: hResizeNotify_Ack = CreateEvent(NULL,TRUE,FALSE,eventname);
1.4 noro 435: sprintf(eventname,"mainthreadready_%d",mypid);
436: hMainThreadReady = CreateEvent(NULL,TRUE,FALSE,eventname);
437: sprintf(eventname,"canvascreated_%d",mypid);
438: hCanvasCreated = CreateEvent(NULL,TRUE,FALSE,eventname);
1.1 noro 439:
440: hWatchStreamThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_watch_stream,NULL,0,&tid);
441: // ret = SetThreadPriority(hWatchStreamThread,THREAD_PRIORITY_BELOW_NORMAL);
442: // if ( !ret )
443: // exit(0);
444: hWatchIntrThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_watch_intr,NULL,0,&tid);
445: // ret = SetThreadPriority(hWatchIntrThread,THREAD_PRIORITY_BELOW_NORMAL);
446: // if ( !ret )
447: // exit(0);
448:
449: /* process_args() increments argv */
450: plot_argc = argc-5;
1.3 noro 451: plot_argv = argv+5;
1.1 noro 452: hComputingThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ox_plot_main,NULL,0,&tid);
453: // ret = SetThreadPriority(hComputingThread,THREAD_PRIORITY_ABOVE_NORMAL);
454: // if ( !ret )
455: // exit(0);
456: }
457:
458: void ox_watch_stream() {
459: fd_set r,w,e;
460:
461: /* wait for the completion of initalization in the computing thread */
462: WaitForSingleObject(hStreamNotify_Ack,(DWORD)-1);
463: ResetEvent(hStreamNotify_Ack);
464: while ( 1 ) {
465: FD_ZERO(&r);
466: FD_ZERO(&w);
467: FD_ZERO(&e);
468: FD_SET(ox_sock_id,&r);
469: select(FD_SETSIZE,&r,&w,&e,NULL);
470: SetEvent(hStreamNotify);
471: WaitForSingleObject(hStreamNotify_Ack,(DWORD)-1);
472: ResetEvent(hStreamNotify_Ack);
473: }
474: }
475:
476: /* get_line : used in Asir mode */
477:
478: int get_line(char *buf) {
479: DWORD len;
480: int size;
481:
482: ReadFile(hRead,&size,sizeof(int),&len,NULL);
483: ReadFile(hRead,buf,size,&len,NULL);
484: buf[size] = 0;
485: return 0;
486: }
487:
488: /* put_line : used in Asir mode */
489:
490: void put_line(char *buf) {
491: if ( debuggui_is_present || messagegui_is_present ) {
492: int size = strlen(buf);
493:
494: if ( size ) {
495: SendCmdSize(FROMASIR_TEXT,size);
496: SendBody(buf,size);
497: }
498: }
499: }
500:
501: /* common function for error exit */
502:
503: void ExitAsir() {
504: terminate_debug_gui();
505: /* if emergency != 0, asirgui may not exist */
506: if ( !emergency )
507: SendCmdSize(FROMASIR_EXIT,0);
508: ExitProcess(0);
509: }
510:
511: /* SendHeapSize : used in Asir mode */
512:
513: int get_heapsize();
514:
515: void SendHeapSize()
516: {
517: if ( messagegui_is_present || debuggui_is_present ) {
518: int h = get_heapsize();
519: SendCmdSize(FROMASIR_HEAPSIZE,sizeof(int));
520: SendBody(&h,sizeof(int));
521: }
522: }
523:
524: /* SendCmdSize : used in Asir mode */
525:
526: void SendCmdSize(unsigned int cmd,unsigned int size)
527: {
528: DWORD len;
529: unsigned int cmdsize;
530:
531: if ( hNotify ) {
532: SetEvent(hNotify);
533: WaitForSingleObject(hNotify_Ack,(DWORD)-1);
534: ResetEvent(hNotify_Ack);
535: cmdsize = (cmd<<16)|size;
536: WriteFile(hWrite,&cmdsize,sizeof(unsigned int),&len,NULL);
537: }
538: }
539:
540: /* SendBody : used in Asir mode */
541:
542: void SendBody(void *buf,unsigned int size)
543: {
544:
545: DWORD len;
546:
547: WriteFile(hWrite,buf,size,&len,NULL);
548: }
549:
550: /* send header + send progress data */
551:
552: void send_progress(short percentage,char *message)
553: {
554: }
555:
556: /* set error code, message, action in Errmsg. */
557:
558: void set_error(int id,char *reason,char *action)
559: {
560: }
561:
562: /* dummy functions */
1.3 noro 563: void reset_current_computation(){}
564: void set_selection(){}
565: void reset_selection(){}
566: void set_busy(){}
567: void reset_busy(){}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>