1 /* Implement tasking-related runtime actions for CHILL.
2 Copyright (C) 1992,1993 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License. */
32 extern void __cause_ex1 (char *ex
, char *file
, int lineno
);
34 EXCEPTION (bufferinconsistency
)
35 #define CAUSE_BUFFINCONS __cause_ex1 ("bufferinconsistency", filename, lineno)
36 EXCEPTION (spacefail
);
37 #define CAUSE_SPACEFAIL __cause_ex1 ("spacefail", filename, lineno)
40 * function __wait_buffer
43 * buf_got pointer to location for writing the received buffer address
44 * nbuf number of buffers in RECEIVE CASE
45 * bufptr array of pointers to buffer descriptor
46 * datap pointer where to store data
47 * datalen length of data
48 * ins pointer to instance location or 0
49 * else_clause else specified or not
50 * to_loc pointer to timesupervision value
51 * filename source file name where function gets called
52 * lineno linenumber in source file
59 * bufferinconsistency if something's wrong in the buffer queue's
60 * spacefail out of heap space of datalength of receiver
61 * less then data avilable.
64 * implement the CHILL RECEIVE buffer CASE action.
68 __wait_buffer (buf_got
, nbuf
, bufptr
, datap
, datalen
, ins
,
69 else_clause
, to
, filename
, lineno
)
72 Buffer_Descr
*bufptr
[];
82 Buffer_Wait_Queue
*start_list
;
83 Buffer_Queue
**retval
;
84 Buffer_Queue
**highprio
;
87 /* look if there is a buffer already sent */
89 for (i
= 0; i
< nbuf
; i
++)
93 memcpy (&bq
, bufptr
[i
]->buf
, sizeof (Buffer_Queue
*));
94 if (bq
!= 0 && bq
->sendqueue
!= 0)
98 Buffer_Queue
*bsq
= *highprio
;
100 if (bq
->sendqueue
->priority
> bsq
->sendqueue
->priority
)
101 highprio
= bufptr
[i
]->buf
;
104 highprio
= bufptr
[i
]->buf
;
112 memcpy (&bq
, highprio
, sizeof (Buffer_Queue
*));
113 if (bq
!= 0 && bq
->sendqueue
!= 0)
115 Buffer_Send_Queue
*bsq
= bq
->sendqueue
;
116 Buffer_Send_Queue
*tmp
;
118 /* check data length */
119 if (datalen
< bsq
->datalen
)
120 /* something's totaly wrong. Raise exception */
124 memcpy (datap
, bsq
->dataptr
, bsq
->datalen
);
126 /* update instance, if present */
128 memcpy (ins
, &bsq
->this, sizeof (INSTANCE
));
132 bq
->sendqueue
= tmp
->forward
;
136 /* there is an instance delayed on a send,
138 __continue_that (tmp
->this, tmp
->priority
, filename
, lineno
);
141 /* return the buffer we have received from */
142 *buf_got
= (void *)highprio
;
146 /* just decrease sendqueue length */
147 bq
->sendqueuelength
--;
151 /* as we got an entry free, we should continue
152 an INSTANCE which is delayed on a send at this
159 bq
->sendqueuelength
++;
161 __continue_that (bsq
->this, bsq
->priority
, filename
, lineno
);
166 /* return the buffer we have received from */
167 *buf_got
= (void *)highprio
;
172 /* if we come here, there is no buffer already sent */
173 if (else_clause
!= 0)
175 /* in that case we return immediately */
180 /* now we have to queue ourself to the wait queue(s) */
182 for (i
= 0; i
< nbuf
; i
++)
185 Buffer_Wait_Queue
*wrk
;
186 Buffer_Wait_Queue
*bwq
;
187 Buffer_Wait_Queue
*prev_queue_entry
= 0;
188 Buffer_Wait_Queue
*prev_list_entry
;
189 int j
, have_done
= 0;
191 for (j
= 0; j
< i
; j
++)
193 if (bufptr
[i
]->buf
== bufptr
[j
]->buf
)
202 memcpy (&bq
, bufptr
[i
]->buf
, sizeof (Buffer_Queue
*));
205 MALLOC (bq
, sizeof (Buffer_Queue
));
206 memset (bq
, 0, sizeof (Buffer_Queue
));
207 /* *(bufptr[i]->buf) = bq; may be unaligned */
208 memcpy (bufptr
[i
]->buf
, &bq
, sizeof (Buffer_Queue
*));
210 MALLOC (wrk
, sizeof (Buffer_Wait_Queue
));
211 memset (wrk
, 0, sizeof (Buffer_Wait_Queue
));
212 bwq
= (Buffer_Wait_Queue
*)&bq
->waitqueue
;
215 wrk
->datalen
= datalen
;
216 wrk
->dataptr
= datap
;
217 wrk
->bufferaddr
= bufptr
[i
]->buf
;
219 /* queue it at the end of buffer wait queue */
220 while (bwq
->forward
!= 0)
222 wrk
->forward
= bwq
->forward
;
225 /* queue it into list */
226 wrk
->startlist
= start_list
;
230 prev_list_entry
= wrk
;
231 wrk
->startlist
= start_list
;
235 prev_list_entry
->chain
= wrk
;
236 prev_list_entry
= wrk
;
239 /* increment wait queue count */
240 bq
->waitqueuelength
++;
243 /* tell runtime system to delay this process */
244 timed_out
= __delay_this (wait_buffer_receive
, to
, filename
, lineno
);
247 /* remove all entries from buffer queues */
248 Buffer_Wait_Queue
*listentry
= start_list
;
250 while (listentry
!= 0)
252 Buffer_Queue
*bq
= *(listentry
->bufferaddr
);
253 Buffer_Wait_Queue
*prev_entry
= (Buffer_Wait_Queue
*)&bq
->waitqueue
;
254 Buffer_Wait_Queue
*bwq
= bq
->waitqueue
;
256 while (bwq
!= listentry
)
262 prev_entry
->forward
= bwq
->forward
;
263 bq
->waitqueuelength
--;
264 listentry
= listentry
->chain
;
268 /* someone has continued us, find which buffer got ready */
271 while (start_list
!= 0)
273 Buffer_Wait_Queue
*tmp
= start_list
->chain
;
275 if (start_list
->is_sent
)
277 /* this one has been sent */
278 /* save return value */
280 retval
= start_list
->bufferaddr
;
282 /* more then one has been sent, that's wrong */
285 /* update instance, if present */
287 memcpy (ins
, &start_list
->who_sent
, sizeof (INSTANCE
));
293 /* now check if there was really a buffer got */
294 if (retval
== 0 && !timed_out
)
295 /* something's totally wrong, raise an exception */
299 *buf_got
= (void *)retval
;
303 /* force function __print_buffer to be linked */
304 extern void __print_buffer ();
305 static EntryPoint pev
= __print_buffer
;