4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * Green Red Orange Magenta Azure Cyan Skyblue
29 static char *SRCID_idtio_c
= "$Id$";
32 * This module implements synchronous and asynchronous communication via the
33 * dual ported ram in the SPC-860 system.
35 * Protocol description:
37 * Sender and receiver must complete their previous transfer on the specified
38 * channel first (busy flag must be cleared for the channel) before they can
39 * start a new transfer. A large block of data is split up into a number of
40 * blocks which fit into the i/o buffer. A transfer is finished after all
41 * blocks have been transferred and the receiver has acknowledged the reception
44 * Step Sender Receiver
46 * 1 gmx_tx(),gmx_txs() gmx_rx(),gmx_rxs()
48 * 2 Copy memory to io buffer .
49 * signal buffer filled .
51 * 3 . Wait for buffer filled signal
53 * 4 Wait for buffer empty signal .
55 * 5 . Copy io buffer to memory
56 * . signal buffer empty
58 * 6 Buffer transfer done .
60 * 7 Repeat step 2 & 4 until Repeat step 3 & 5 until
61 * complete transfer done complete transfer done
65 * As is clear from the previous, the sender and the receiver need not to
66 * enter the communication routines at the same time. The sender as well as
67 * the receiver may invoke its routine at every moment. The protocol
68 * guarantuees that no data is lost. The only restriction is that the sender
69 * and receiver have the same transfer length. A message with length 0 (zero)
70 * is also communicated. Although no data transfer is necessary, the protocol
71 * is handled in the same way as a normal message and thus causes the channel
72 * to be used for synchronisation. The synchronous and asynchronous routines
73 * are interchangable between sender and receiver, so a sender may use the
74 * asynchronous version while the receiver uses the synchronous version and
75 * vice versa. Naturally both may use the same type of communication
78 * Due to the fact that DMA is not available, all data copying is done by
79 * the processor. Because interrupts aren't used for efficiency reasons,
80 * real asynchronous communication is not possible, messages are copied
81 * from and to the io buffers while within the communication routines. So
82 * an asynchronous communication is implemented by doing the nonblocking
83 * part in the setup and the blocking part in the gmx_wait() routines.
84 * Notice that while another asynchronous transfer is busy on the specified
85 * channel, starting a new one implies waiting for the previous to finish.
91 * +----------+ +------+ +----------+
92 * | 3ff 1023 | irq (self) | I860 | irq (other) | 7ff 2047 |
93 * +----------+ | | +----------+
94 * | 3fe 1022 | irq (other) | | irq (self) | 7fe 2046 |
95 * -+----------+-------------- | | --------------+----------+-
96 * | 3fd 1021 | rx cmd | | tx cmd | 7fd 2045 |
97 * +----------+ | | +----------+
98 * | 3fc 1020 | tx cmd | | rx cmd | 7fc 2044 |
99 * -+----------+-------------- | | --------------+----------+-------
100 * | 3fb 1019 | | | | 7fb 2043 | ^
101 * +----------+ | | +----------+ |
103 * +----------+ | | +----------+ |
104 * | 1fe 510 | rx buffer | | tx buffer | 5fe 1534 | v
105 * -+----------+-------------- | | --------------+----------+-------
106 * | 1fd 509 | | | | 5fd 1533 | ^
107 * +----------+ | | +----------+ |
109 * +----------+ | | +----------+ |
110 * | 000 0 | tx buffer | | rx buffer | 400 1024 | v
111 * +----------+ +------+ +----------+-------
113 * Numbers are offsets relative to IDT base address, names like tx and rx are
114 * local for this i860. The actual buffer size may be smaller (aligned for
115 * word size, 4 bytes) for speed, see also module inout.s.
131 #define SERVER_VERSION "SERVER_VERSION"
132 #define USE_VERSION1 "S860.1"
134 #define IDTNR 2 /* Number of available idt's. */
135 #define IDTLEFT 0x0 /* Offset of my idt. */
136 #define IDTRIGHT 0x400 /* Offset of neighbour processors idt. */
137 #define IDTSIZE 0x400 /* Total size of idt. */
138 #define IRQBASE 0x3fe /* Interrupt locations at the top of an idt */
139 #define BSIZE 510 /* Usable buffer size, see comment above */
140 #define TX 0 /* Index of sender status. */
141 #define RX 1 /* Index of receiver status. */
142 #define TXRXNR 2 /* Number of directions (sender & receiver). */
143 #define BUF_DONE 0x55 /* Signals buffer transfer is done. */
144 #define BUF_BUSY ((~(BUF_DONE))&0xff) /* Signals buffer is busy. */
145 #define LINE_WIDTH 16 /* Hex dump bytes per line. */
146 #define MIN(a,b) (((a)>(b))?(b):(a))
147 #define WORK_NAME(work) \
148 (((work)==buf_idle)?"buf_idle": \
149 ((((work)==buf_accept)?"buf_accept": \
150 ((((work)==buf_send)?"buf_send": \
151 ((((work)==buf_avail)?"buf_avail":(NULL))))))))
153 typedef struct t_stat
155 char *name
; /* Name of the channel (debugging). */
156 int cmd
; /* Offset of command byte in io ram. */
157 int buf
; /* Offset of buffer in io ram. */
158 int len
; /* Actual number of bytes to transfer. */
159 int bsize
; /* Actual usable buffer size */
160 int bcnt
; /* Total block count, part of rx/tx. */
161 int tcnt
; /* Total transfer count for tx/rx. */
162 int icnt
; /* Total idle count, incremented while waiting. */
163 char *data
; /* Pointer to data bytes in memory. */
164 void (*work
)(struct t_stat
* stat
); /* State of transfer. */
168 static int idt_busy
=0;
169 static char *stat_names
[IDTNR
][TXRXNR
]={{"txl","rxl"},{"txr","rxr"}};
170 static t_stat sys_stat
[IDTNR
][TXRXNR
];
172 static void buf_idle(t_stat
*stat
);
173 static void buf_accept(t_stat
*stat
);
174 static void buf_send(t_stat
*stat
);
175 static void buf_avail(t_stat
*stat
);
178 * Debug routines start
185 for (i=0; i<IDTNR; i++) \
186 for (j=0; j<TXRXNR; j++) \
189 (void) fprintf(fp,"%*s",COL_WIDTH-len,""); \
191 (void) fprintf(fp,"\n"); \
195 static void print_connections(FILE *fp
,t_stat stat
[IDTNR
][TXRXNR
])
199 for (i
=0; i
<IDTNR
; i
++)
200 for (j
=0; j
<TXRXNR
; j
++)
201 (void) fprintf(fp
,"cmd at %s (0x%x) should be connected to %s (0x%x)\n",
202 stat
[i
][j
].name
,stat
[i
][j
].cmd
,
203 stat
[IDTNR
-1-i
][TXRXNR
-1-j
].name
,
204 stat
[IDTNR
-1-i
][TXRXNR
-1-j
].cmd
);
205 for (i
=0; i
<IDTNR
; i
++)
206 for (j
=0; j
<TXRXNR
; j
++)
207 (void) fprintf(fp
,"data at %s (0x%x,%d) should be connected to %s "
209 stat
[i
][j
].name
,stat
[i
][j
].buf
,stat
[i
][j
].bsize
,
210 stat
[IDTNR
-1-i
][TXRXNR
-1-j
].name
,
211 stat
[IDTNR
-1-i
][TXRXNR
-1-j
].buf
,
212 stat
[IDTNR
-1-i
][TXRXNR
-1-j
].bsize
);
215 static void print_chars(FILE *fp
,char s
[],int len
)
221 for (i
=len
; i
<LINE_WIDTH
; i
++) (void) fprintf(fp
," ");
223 (void) fprintf(fp
," | %s\n",s
);
227 static int ascii(int b
)
229 if ((b
<' ')||(b
>'~')) return ('.'); else return b
;
232 static void idt_dump(FILE *fp
,char *title
,int offset
,int len
)
235 char s
[LINE_WIDTH
+1];
239 if (len
) (void) fprintf(fp
,"idtdump %s:\n",title
);
240 for (i
=0; i
<len
; i
++)
242 b
=peek_io_buf(IDT7130
,offset
);
243 if ((index
==0)||(index
==LINE_WIDTH
))
245 print_chars(fp
,s
,index
);
246 (void) fprintf(fp
,"%.8X :",offset
);
249 (void) fprintf(fp
," %.2X",b
);
253 print_chars(fp
,s
,index
);
256 static int fprintw(FILE *fp
,char *title
,void (*work
)(struct t_stat
* stat
))
260 if ((work_name
=WORK_NAME(work
))==NULL
)
261 return fprintf(fp
,"%s0x%x",title
,work
);
263 return fprintf(fp
,"%s%s",title
,work_name
);
266 static void clear_cnt(t_stat stat
[IDTNR
][TXRXNR
])
270 for (i
=0; i
<IDTNR
; i
++)
271 for (j
=0; j
<TXRXNR
; j
++)
280 static void print_status(FILE *fp
,int pid
,char *s
,
281 t_stat stat
[IDTNR
][TXRXNR
],t_stat
*mark
)
283 (void) fprintf(fp
,"idt pid: %d, %s\n",pid
,s
);
284 line(fprintf(fp
,"%s%s:",stat
[i
][j
].name
,(mark
==&stat
[i
][j
])?" (*)":""));
285 line(fprintf(fp
,"cmd = 0x%x",stat
[i
][j
].cmd
));
286 line(fprintf(fp
,"(cmd) = 0x%x",peek_io_buf(IDT7130
,stat
[i
][j
].cmd
)));
287 line(fprintf(fp
,"buf = 0x%x",stat
[i
][j
].buf
));
288 line(fprintf(fp
,"len = %d",stat
[i
][j
].len
));
289 line(fprintf(fp
,"bsize = %d",stat
[i
][j
].bsize
));
290 line(fprintf(fp
,"bcnt = %d",stat
[i
][j
].bcnt
));
291 line(fprintf(fp
,"tcnt = %d",stat
[i
][j
].tcnt
));
292 line(fprintf(fp
,"icnt = %d",stat
[i
][j
].icnt
));
293 line(fprintf(fp
,"data = 0x%x",stat
[i
][j
].data
));
294 line(fprintw(fp
,"work = ",stat
[i
][j
].work
));
299 static void init_buf(t_stat
*stat
,int data
)
303 for (i
=0; i
<stat
->bsize
; i
++) poke_io_buf(IDT7130
,stat
->buf
+i
,data
);
306 static void init_bufs(t_stat stat
[IDTNR
][TXRXNR
],int data
)
310 for (i
=0; i
<IDTNR
; i
++)
311 for (j
=0; j
<TXRXNR
; j
++)
312 init_buf(&stat
[i
][j
],data
);
315 static int check_buf(FILE *fp
,t_stat
*stat
,int data
)
320 for (i
=0; i
<stat
->bsize
; i
++)
321 if ((peeked
=peek_io_buf(IDT7130
,stat
->buf
+i
))!=data
)
324 (void) fprintf(fp
,"data at 0x%x in %s is 0x%x, should be 0x%x\n",
325 stat
->buf
+i
,stat
->name
,peeked
,data
);
330 static void init_cmd(t_stat stat
[IDTNR
][TXRXNR
],int cmd
)
334 for (i
=0; i
<IDTNR
; i
++)
335 for (j
=0; j
<TXRXNR
; j
++)
336 poke_io_buf(IDT7130
,stat
[i
][j
].cmd
,cmd
);
339 static void test_connectivity(FILE *fp
,t_stat stat
[IDTNR
][TXRXNR
])
344 print_connections(fp
,stat
);
345 (void) fprintf(fp
,"short circuit test:\ntesting initialisation ...");
347 init_cmd(stat
,BUF_DONE
);
348 for (i
=0; i
<IDTNR
; i
++)
349 for (j
=0; j
<TXRXNR
; j
++)
350 if ((init
=peek_io_buf(IDT7130
,stat
[i
][j
].cmd
))!=BUF_DONE
)
352 if (err
++==0) (void) printf("\n");
353 (void) fprintf(fp
,"cmd at %s (0x%x) is 0x%x, should be 0x%x\n",
354 stat
[i
][j
].name
,stat
[i
][j
].cmd
,init
,BUF_DONE
);
356 (void) fprintf(fp
," done\ntesting cmd connectivity ...");
358 for (i
=0; i
<IDTNR
; i
++)
359 for (j
=0; j
<TXRXNR
; j
++)
361 init_cmd(stat
,BUF_DONE
); /* All others should have wrong value */
362 poke_io_buf(IDT7130
,stat
[i
][j
].cmd
,BUF_BUSY
);
363 if ((init
=peek_io_buf(IDT7130
,stat
[IDTNR
-1-i
][TXRXNR
-1-j
].cmd
))!=
366 if (err
++==0) (void) printf("\n");
367 (void) fprintf(fp
,"cmd at %s (0x%x) should be connected to"
369 stat
[i
][j
].name
,stat
[i
][j
].cmd
,
370 stat
[IDTNR
-1-i
][TXRXNR
-1-j
].name
,
371 stat
[IDTNR
-1-i
][TXRXNR
-1-j
].cmd
);
372 (void) fprintf(fp
,"cmd at %s (0x%x) is 0x%x, should be 0x%x\n",
373 stat
[IDTNR
-1-i
][TXRXNR
-1-j
].name
,
374 stat
[IDTNR
-1-i
][TXRXNR
-1-j
].cmd
,
378 (void) fprintf(fp
," done\ntesting data connectivity ...");
380 for (i
=0; i
<IDTNR
; i
++)
381 for (j
=0; j
<TXRXNR
; j
++)
383 init_bufs(stat
,0); /* All others should have wrong value */
384 init_buf(&stat
[i
][j
],0xff);
385 err
+=check_buf(fp
,&stat
[IDTNR
-1-i
][TXRXNR
-1-j
],0xff);
386 init_bufs(stat
,0xff); /* All others should have wrong value */
387 init_buf(&stat
[i
][j
],0);
388 err
+=check_buf(fp
,&stat
[IDTNR
-1-i
][TXRXNR
-1-j
],0);
390 (void) fprintf(fp
," done\n%d error(s) detected\n",err
);
394 #define BUFSIZE 25000
396 static int com_test(FILE *fp
,char *title
,int src
,int dest
)
400 (void) fprintf(fp
,"%s, src=%d, dest=%d\n",title
,src
,dest
);
401 clear_buff(buf
[0],BUFSIZE
);
402 fill_buff(buf
[1],BUFSIZE
);
403 gmx_tx(dest
,array(buf
[1],BUFSIZE
));
404 gmx_rx(src
,array(buf
[0],BUFSIZE
));
407 return check_buff(fp
,"com_test",buf
[0],BUFSIZE
,1);
411 #define i860main_test i860main
414 int i860main_test(int argc
,char *argv
[],FILE *stdlog
,
415 int nprocs
,int pid
,int left
,int right
)
419 (void) fprintf(stdlog
,"in i860main nprocs=%d, pid=%d, left=%d, right=%d, "
420 "bufsize=%d\n",nprocs
,pid
,left
,right
,BUFSIZE
*sizeof(int));
421 if (nprocs
==1) test_connectivity(stdlog
,sys_stat
);
422 err
=com_test(stdlog
,"left to right",left
,right
);
423 err
+=com_test(stdlog
,"right to left",right
,left
);
424 (void) fprintf(stdlog
,"%d error(s)\n",err
);
435 static void print_stat(FILE *fp
,char *title
,t_stat
*stat
)
437 (void) fprintf(fp
,"%-35s (%s): cmd=%d, len=%6d, data=0x%x\n",
438 title
,stat
->name
,peek_io_buf(IDT7130
,stat
->cmd
),
439 stat
->len
,stat
->data
);
443 #define ENTER(where,stat) print_stat(stdlog,"enter "#where,stat)
444 #define LEAVE(where,stat) print_stat(stdlog,"leave "#where,stat)
446 #define ENTER(where,stat)
447 #define LEAVE(where,stat)
450 static void set_comm_led(int busy
)
454 if ((idt_busy
++)==0) put_led(COMM_LED
,1);
458 if ((--idt_busy
)==0) put_led(COMM_LED
,0);
462 static int compare_tags(int tag1
,int tag2
)
467 for (i
=-1; i
!=0; i
<<=1)
469 if ((tag1
&1)==(tag2
&1)) count
++;
476 void idtio_errstat(FILE *fp
,char *msg
,t_stat
*stat
,int dump
)
478 print_status(fp
,idt_id
,msg
,sys_stat
,stat
);
481 idt_dump(fp
,"idtio_stat left",IDTLEFT
,IRQBASE
);
482 idt_dump(fp
,"idtio_stat right",IDTRIGHT
,IRQBASE
);
487 static int repair(FILE *fp
,char *where
,t_stat
*stat
,int tag
)
489 int out_tag
,busy_tag
,done_tag
;
491 busy_tag
=compare_tags(tag
,BUF_BUSY
);
492 done_tag
=compare_tags(tag
,BUF_DONE
);
493 if (busy_tag
>done_tag
)
496 if (done_tag
>busy_tag
)
501 (void) fprintf(fp
,"could not repair tag 0x%.2x in %s (%s)\n",tag
,where
,
503 idtio_errstat(fp
,where
,stat
,1);
504 fatal_error(0,"received 0x%x as a tag on processor %d",tag
,idt_id
);
506 (void) fprintf(fp
,"repaired 0x%.2x in %s(%s) -> 0x%.2x\n",
507 tag
,where
,stat
->name
,out_tag
);
511 static void buf_done(t_stat
*stat
)
513 ENTER(buf_done
,stat
);
517 LEAVE(buf_done
,stat
);
520 static void buf_idle(t_stat
*stat
)
522 ENTER(buf_idle
,stat
);
523 LEAVE(buf_idle
,stat
);
526 static void buf_accept(t_stat
*stat
)
529 static void buf_send(t_stat
*stat
);
531 ENTER(buf_accept
,stat
);
532 tag
=peek_io_buf(IDT7130
,stat
->cmd
);
542 if (stat
->len
!=0) buf_send(stat
); else buf_done(stat
);
545 tag
=repair(stdlog
,"buf_accept",stat
,tag
);
551 LEAVE(buf_accept
,stat
);
554 static void buf_send(t_stat
*stat
)
558 ENTER(buf_send
,stat
);
559 len
=MIN(stat
->bsize
,stat
->len
);
560 put_io_buf(IDT7130
,stat
->buf
,stat
->data
,len
);
561 poke_io_buf(IDT7130
,stat
->cmd
,BUF_BUSY
);
565 stat
->work
=buf_accept
;
566 LEAVE(buf_send
,stat
);
569 static void buf_avail(t_stat
*stat
)
571 int tag
,len
,repaired
;
573 ENTER(buf_avail
,stat
);
574 tag
=peek_io_buf(IDT7130
,stat
->cmd
);
584 len
=MIN(stat
->bsize
,stat
->len
);
585 get_io_buf(IDT7130
,stat
->buf
,stat
->data
,len
);
586 poke_io_buf(IDT7130
,stat
->cmd
,BUF_DONE
);
590 if (stat
->len
==0) buf_done(stat
);
593 tag
=repair(stdlog
,"buf_avail",stat
,tag
);
599 LEAVE(buf_avail
,stat
);
602 static void communicate(t_stat stat
[IDTNR
][TXRXNR
])
606 for (i
=0; i
<IDTNR
; i
++)
607 for (j
=0; j
<TXRXNR
; j
++)
608 stat
[i
][j
].work(&stat
[i
][j
]);
611 static void chan_wait(t_stat stat
[IDTNR
][TXRXNR
],int chan
,int txrx
)
613 while (stat
[chan
][txrx
].work
!=buf_idle
) communicate(stat
);
616 static void fill_stat(t_stat
*stat
,void *bufptr
,int bufsize
,
617 void (*work
)(t_stat
*stat
))
619 ENTER(fill_stat
,stat
);
625 LEAVE(fill_stat
,stat
);
628 void idtio_tx(int chan
,void *bufptr
,int bufsize
)
630 ENTER(idtio_tx
,&sys_stat
[chan
][TX
]);
631 chan_wait(sys_stat
,chan
,TX
); /* Be sure that this channel is free for use */
632 fill_stat(&sys_stat
[chan
][TX
],bufptr
,bufsize
,buf_send
);
633 LEAVE(idtio_tx
,&sys_stat
[chan
][TX
]);
636 void idtio_rx(int chan
,void *bufptr
,int bufsize
)
638 ENTER(idtio_rx
,&sys_stat
[chan
][RX
]);
639 chan_wait(sys_stat
,chan
,RX
);
640 fill_stat(&sys_stat
[chan
][RX
],bufptr
,bufsize
,buf_avail
);
641 LEAVE(idtio_rx
,&sys_stat
[chan
][RX
]);
644 void idtio_tx_wait(int chan
)
646 ENTER(idtio_tx_wait
,&sys_stat
[chan
][TX
]);
647 chan_wait(sys_stat
,chan
,TX
);
648 LEAVE(idtio_tx_wait
,&sys_stat
[chan
][TX
]);
651 void idtio_rx_wait(int chan
)
653 ENTER(idtio_rx_wait
,&sys_stat
[chan
][RX
]);
654 chan_wait(sys_stat
,chan
,RX
);
655 LEAVE(idtio_rx_wait
,&sys_stat
[chan
][RX
]);
658 void idtio_txs(int chan
,void *bufptr
,int bufsize
)
660 ENTER(idtio_txs
,&sys_stat
[chan
][RX
]);
661 idtio_tx(chan
,bufptr
,bufsize
);
663 LEAVE(idtio_txs
,&sys_stat
[chan
][RX
]);
666 void idtio_rxs(int chan
,void *bufptr
,int bufsize
)
668 ENTER(idtio_rxs
,&sys_stat
[chan
][RX
]);
669 idtio_rx(chan
,bufptr
,bufsize
);
671 LEAVE(idtio_rxs
,&sys_stat
[chan
][RX
]);
674 static void init_stat(t_stat
*stat
,char *name
,int bsize
,int buf
,int cmd
)
686 LEAVE(init_stat
,stat
);
689 static void ring_wait(int pid
,int nprocs
)
691 * Wait for every processor to execute this function, assume that pid
692 * runs from 0 to nprocs - 1.
698 if ((sv
=getenv(SERVER_VERSION
))==NULL
)
701 newserver
=(strcmp(sv
,USE_VERSION1
)==0);
709 for (i
=1; i
<nprocs
; i
++) rdlinda1in(i
,-1,&ch
);
710 for (i
=1; i
<nprocs
; i
++) rdlinda1out(i
+nprocs
,1,&ch
);
714 rdlinda1out(pid
,1,&ch
);
715 rdlinda1in(pid
+nprocs
,-1,&ch
);
720 void idtio_init(int pid
,int nprocs
)
725 init_stat(&sys_stat
[LEFT
] [TX
],stat_names
[LEFT
][TX
],
726 BSIZE
&~0x3,IDTLEFT
, IDTLEFT
+2*BSIZE
);
727 init_stat(&sys_stat
[LEFT
] [RX
],stat_names
[LEFT
][RX
],
728 BSIZE
&~0x3,IDTLEFT
+BSIZE
, IDTLEFT
+2*BSIZE
+1);
729 init_stat(&sys_stat
[RIGHT
][TX
],stat_names
[RIGHT
][TX
],
730 BSIZE
&~0x3,IDTRIGHT
+BSIZE
,IDTRIGHT
+2*BSIZE
+1);
731 init_stat(&sys_stat
[RIGHT
][RX
],stat_names
[RIGHT
][RX
],
732 BSIZE
&~0x3,IDTRIGHT
,IDTRIGHT
+2*BSIZE
);
733 for (i
=0; i
<IRQBASE
; i
++) poke_io_buf(IDT7130
,IDTLEFT
+i
,0xff);
736 print_status(stdlog
,pid
,"idtio_init (1)",sys_stat
,NULL
);
737 ring_wait(pid
,nprocs
);
738 print_status(stdlog
,pid
,"idtio_init (2)",sys_stat
,NULL
);
740 ring_wait(pid
,nprocs
);
742 for (i
=0; i
<IDTNR
; i
++) poke_io_buf(IDT7130
,sys_stat
[i
][TX
].cmd
,BUF_DONE
);
743 ring_wait(pid
,nprocs
);
744 for (i
=0; i
<IDTNR
; i
++)
746 if (peek_io_buf(IDT7130
,sys_stat
[i
][RX
].cmd
)!=BUF_DONE
)
748 idtio_errstat(stdlog
,"idtio_init",&sys_stat
[i
][RX
],1);
749 fatal_error(0,"idt %s not initialised on processor %d",
750 sys_stat
[i
][RX
].name
,idt_id
);
754 print_status(stdlog
,pid
,"idtio_init(3)",sys_stat
,NULL
);
756 ring_wait(pid
,nprocs
);
759 void idtio_stat(FILE *fp
,char *msg
)
761 fprintf(fp
,"idtio_stat message: %s\n",msg
);
762 fprintf(fp
,"Idle Left Send: %d\n",sys_stat
[LEFT
][TX
].icnt
);
763 fprintf(fp
,"Idle Left Receive: %d\n",sys_stat
[LEFT
][TX
].icnt
);
764 fprintf(fp
,"Idle Right Send: %d\n",sys_stat
[RIGHT
][RX
].icnt
);
765 fprintf(fp
,"Idle Right Receive: %d\n",sys_stat
[RIGHT
][RX
].icnt
);
767 idtio_errstat(fp
,msg
,NULL
,0);
771 void idt_left_right(int nprocs
,int pid
,int *left
,int *right
)
777 void idt_reset_idle()
779 sys_stat
[LEFT
][TX
].icnt
=0;
780 sys_stat
[LEFT
][TX
].icnt
=0;
781 sys_stat
[RIGHT
][RX
].icnt
=0;
782 sys_stat
[RIGHT
][RX
].icnt
=0;