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, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 extern void __cause_ex1 (char *ex, char *file, int lineno);
26 EXCEPTION (bufferinconsistency)
27 #define CAUSE_BUFFINCONS __cause_ex1 ("bufferinconsistency", filename, lineno)
28 EXCEPTION (spacefail);
29 #define CAUSE_SPACEFAIL __cause_ex1 ("spacefail", filename, lineno)
32 * function __wait_buffer
35 * buf_got pointer to location for writing the received buffer address
36 * nbuf number of buffers in RECEIVE CASE
37 * bufptr array of pointers to buffer descriptor
38 * datap pointer where to store data
39 * datalen length of data
40 * ins pointer to instance location or 0
41 * else_clause else specified or not
42 * to_loc pointer to timesupervision value
43 * filename source file name where function gets called
44 * lineno linenumber in source file
51 * bufferinconsistency if something's wrong in the buffer queue's
52 * spacefail out of heap space of datalength of receiver
53 * less then data avilable.
56 * implement the CHILL RECEIVE buffer CASE action.
60 __wait_buffer (buf_got, nbuf, bufptr, datap, datalen, ins,
61 else_clause, to, filename, lineno)
64 Buffer_Descr *bufptr[];
74 Buffer_Wait_Queue *start_list;
75 Buffer_Queue **retval;
76 Buffer_Queue **highprio;
79 /* look if there is a buffer already sent */
81 for (i = 0; i < nbuf; i++)
85 memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
86 if (bq != 0 && bq->sendqueue != 0)
90 Buffer_Queue *bsq = *highprio;
92 if (bq->sendqueue->priority > bsq->sendqueue->priority)
93 highprio = bufptr[i]->buf;
96 highprio = bufptr[i]->buf;
104 memcpy (&bq, highprio, sizeof (Buffer_Queue *));
105 if (bq != 0 && bq->sendqueue != 0)
107 Buffer_Send_Queue *bsq = bq->sendqueue;
108 Buffer_Send_Queue *tmp;
110 /* check data length */
111 if (datalen < bsq->datalen)
112 /* something's totaly wrong. Raise exception */
116 memcpy (datap, bsq->dataptr, bsq->datalen);
118 /* update instance, if present */
120 memcpy (ins, &bsq->this, sizeof (INSTANCE));
124 bq->sendqueue = tmp->forward;
128 /* there is an instance delayed on a send,
130 __continue_that (tmp->this, tmp->priority, filename, lineno);
133 /* return the buffer we have received from */
134 *buf_got = (void *)highprio;
138 /* just decrease sendqueue length */
139 bq->sendqueuelength--;
143 /* as we got an entry free, we should continue
144 an INSTANCE which is delayed on a send at this
151 bq->sendqueuelength++;
153 __continue_that (bsq->this, bsq->priority, filename, lineno);
158 /* return the buffer we have received from */
159 *buf_got = (void *)highprio;
164 /* if we come here, there is no buffer already sent */
165 if (else_clause != 0)
167 /* in that case we return immediately */
172 /* now we have to queue ourself to the wait queue(s) */
174 for (i = 0; i < nbuf; i++)
177 Buffer_Wait_Queue *wrk;
178 Buffer_Wait_Queue *bwq;
179 Buffer_Wait_Queue *prev_queue_entry = 0;
180 Buffer_Wait_Queue *prev_list_entry;
181 int j, have_done = 0;
183 for (j = 0; j < i; j++)
185 if (bufptr[i]->buf == bufptr[j]->buf)
194 memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
197 MALLOC (bq, sizeof (Buffer_Queue));
198 memset (bq, 0, sizeof (Buffer_Queue));
199 /* *(bufptr[i]->buf) = bq; may be unaligned */
200 memcpy (bufptr[i]->buf, &bq, sizeof (Buffer_Queue *));
202 MALLOC (wrk, sizeof (Buffer_Wait_Queue));
203 memset (wrk, 0, sizeof (Buffer_Wait_Queue));
204 bwq = (Buffer_Wait_Queue *)&bq->waitqueue;
207 wrk->datalen = datalen;
208 wrk->dataptr = datap;
209 wrk->bufferaddr = bufptr[i]->buf;
211 /* queue it at the end of buffer wait queue */
212 while (bwq->forward != 0)
214 wrk->forward = bwq->forward;
217 /* queue it into list */
218 wrk->startlist = start_list;
222 prev_list_entry = wrk;
223 wrk->startlist = start_list;
227 prev_list_entry->chain = wrk;
228 prev_list_entry = wrk;
231 /* increment wait queue count */
232 bq->waitqueuelength++;
235 /* tell runtime system to delay this process */
236 timed_out = __delay_this (wait_buffer_receive, to, filename, lineno);
239 /* remove all entries from buffer queues */
240 Buffer_Wait_Queue *listentry = start_list;
242 while (listentry != 0)
244 Buffer_Queue *bq = *(listentry->bufferaddr);
245 Buffer_Wait_Queue *prev_entry = (Buffer_Wait_Queue *)&bq->waitqueue;
246 Buffer_Wait_Queue *bwq = bq->waitqueue;
248 while (bwq != listentry)
254 prev_entry->forward = bwq->forward;
255 bq->waitqueuelength--;
256 listentry = listentry->chain;
260 /* someone has continued us, find which buffer got ready */
263 while (start_list != 0)
265 Buffer_Wait_Queue *tmp = start_list->chain;
267 if (start_list->is_sent)
269 /* this one has been sent */
270 /* save return value */
272 retval = start_list->bufferaddr;
274 /* more then one has been sent, that's wrong */
277 /* update instance, if present */
279 memcpy (ins, &start_list->who_sent, sizeof (INSTANCE));
285 /* now check if there was really a buffer got */
286 if (retval == 0 && !timed_out)
287 /* something's totally wrong, raise an exception */
291 *buf_got = (void *)retval;
295 /* force function __print_buffer to be linked */
296 extern void __print_buffer ();
297 static EntryPoint pev = __print_buffer;