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