Move body of HARD_REGNO_MODE_OK into a function: arm_hard_regno_mode_ok
[official-gcc.git] / libchill / waitbuffer.c
blob2d967d93e4861d8b123fc3d2a7e5f0f033e9fb4c
1 /* Implement tasking-related runtime actions for CHILL.
2 Copyright (C) 1992,1993 Free Software Foundation, Inc.
3 Author: Wilfried Moser
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)
10 any later version.
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. */
29 #include <string.h>
30 #include "rtltypes.h"
31 #include "rts.h"
33 extern void __cause_ex1 (char *ex, char *file, int lineno);
35 EXCEPTION (bufferinconsistency)
36 #define CAUSE_BUFFINCONS __cause_ex1 ("bufferinconsistency", filename, lineno)
37 EXCEPTION (spacefail);
38 #define CAUSE_SPACEFAIL __cause_ex1 ("spacefail", filename, lineno)
41 * function __wait_buffer
43 * parameters:
44 * buf_got pointer to location for writing the received buffer address
45 * nbuf number of buffers in RECEIVE CASE
46 * bufptr array of pointers to buffer descriptor
47 * datap pointer where to store data
48 * datalen length of data
49 * ins pointer to instance location or 0
50 * else_clause else specified or not
51 * to_loc pointer to timesupervision value
52 * filename source file name where function gets called
53 * lineno linenumber in source file
55 * returns:
56 * int 0 .. success
57 * 1 .. timed out
59 * exceptions:
60 * bufferinconsistency if something's wrong in the buffer queue's
61 * spacefail out of heap space of datalength of receiver
62 * less than data avilable.
64 * abstract:
65 * implement the CHILL RECEIVE buffer CASE action.
68 int
69 __wait_buffer (buf_got, nbuf, bufptr, datap, datalen, ins,
70 else_clause, to, filename, lineno)
71 void **buf_got;
72 int nbuf;
73 Buffer_Descr *bufptr[];
74 void *datap;
75 int datalen;
76 INSTANCE *ins;
77 int else_clause;
78 void *to;
79 char *filename;
80 int lineno;
82 int i;
83 Buffer_Wait_Queue *start_list;
84 Buffer_Queue **retval;
85 Buffer_Queue **highprio;
86 int timed_out;
88 /* look if there is a buffer already sent */
89 highprio = 0;
90 for (i = 0; i < nbuf; i++)
92 Buffer_Queue *bq;
94 memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
95 if (bq != 0 && bq->sendqueue != 0)
97 if (highprio != 0)
99 Buffer_Queue *bsq = *highprio;
101 if (bq->sendqueue->priority > bsq->sendqueue->priority)
102 highprio = bufptr[i]->buf;
104 else
105 highprio = bufptr[i]->buf;
109 if (highprio != 0)
111 Buffer_Queue *bq;
113 memcpy (&bq, highprio, sizeof (Buffer_Queue *));
114 if (bq != 0 && bq->sendqueue != 0)
116 Buffer_Send_Queue *bsq = bq->sendqueue;
117 Buffer_Send_Queue *tmp;
119 /* check data length */
120 if (datalen < bsq->datalen)
121 /* something's totaly wrong. Raise exception */
122 CAUSE_SPACEFAIL;
124 /* copy data out */
125 memcpy (datap, bsq->dataptr, bsq->datalen);
127 /* update instance, if present */
128 if (ins != 0)
129 memcpy (ins, &bsq->this, sizeof (INSTANCE));
131 /* dequeue entry */
132 tmp = bsq;
133 bq->sendqueue = tmp->forward;
135 if (tmp->is_delayed)
137 /* there is an instance delayed on a send,
138 continue it. */
139 __continue_that (tmp->this, tmp->priority, filename, lineno);
140 FREE (tmp);
142 /* return the buffer we have received from */
143 *buf_got = (void *)highprio;
144 return 0;
147 /* just decrease sendqueue length */
148 bq->sendqueuelength--;
150 FREE (tmp);
152 /* as we got an entry free, we should continue
153 an INSTANCE which is delayed on a send at this
154 buffer */
155 bsq = bq->sendqueue;
156 while (bsq != 0)
158 if (bsq->is_delayed)
160 bq->sendqueuelength++;
161 bsq->is_delayed = 0;
162 __continue_that (bsq->this, bsq->priority, filename, lineno);
163 break;
165 bsq = bsq->forward;
167 /* return the buffer we have received from */
168 *buf_got = (void *)highprio;
169 return 0;
173 /* if we come here, there is no buffer already sent */
174 if (else_clause != 0)
176 /* in that case we return immediately */
177 *buf_got = 0;
178 return 0;
181 /* now we have to queue ourself to the wait queue(s) */
182 start_list = 0;
183 for (i = 0; i < nbuf; i++)
185 Buffer_Queue *bq;
186 Buffer_Wait_Queue *wrk;
187 Buffer_Wait_Queue *bwq;
188 Buffer_Wait_Queue *prev_queue_entry = 0;
189 Buffer_Wait_Queue *prev_list_entry;
190 int j, have_done = 0;
192 for (j = 0; j < i; j++)
194 if (bufptr[i]->buf == bufptr[j]->buf)
196 have_done = 1;
197 break;
200 if (have_done)
201 continue;
203 memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
204 if (bq == 0)
206 MALLOC (bq, sizeof (Buffer_Queue));
207 memset (bq, 0, sizeof (Buffer_Queue));
208 /* *(bufptr[i]->buf) = bq; may be unaligned */
209 memcpy (bufptr[i]->buf, &bq, sizeof (Buffer_Queue *));
211 MALLOC (wrk, sizeof (Buffer_Wait_Queue));
212 memset (wrk, 0, sizeof (Buffer_Wait_Queue));
213 bwq = (Buffer_Wait_Queue *)&bq->waitqueue;
215 wrk->this = THIS;
216 wrk->datalen = datalen;
217 wrk->dataptr = datap;
218 wrk->bufferaddr = bufptr[i]->buf;
220 /* queue it at the end of buffer wait queue */
221 while (bwq->forward != 0)
222 bwq = bwq->forward;
223 wrk->forward = bwq->forward;
224 bwq->forward = wrk;
226 /* queue it into list */
227 wrk->startlist = start_list;
228 if (! start_list)
230 start_list = wrk;
231 prev_list_entry = wrk;
232 wrk->startlist = start_list;
234 else
236 prev_list_entry->chain = wrk;
237 prev_list_entry = wrk;
240 /* increment wait queue count */
241 bq->waitqueuelength++;
244 /* tell runtime system to delay this process */
245 timed_out = __delay_this (wait_buffer_receive, to, filename, lineno);
246 if (timed_out)
248 /* remove all entries from buffer queues */
249 Buffer_Wait_Queue *listentry = start_list;
251 while (listentry != 0)
253 Buffer_Queue *bq = *(listentry->bufferaddr);
254 Buffer_Wait_Queue *prev_entry = (Buffer_Wait_Queue *)&bq->waitqueue;
255 Buffer_Wait_Queue *bwq = bq->waitqueue;
257 while (bwq != listentry)
259 prev_entry = bwq;
260 bwq = bwq->forward;
262 /* dequeue it */
263 prev_entry->forward = bwq->forward;
264 bq->waitqueuelength--;
265 listentry = listentry->chain;
269 /* someone has continued us, find which buffer got ready */
270 retval = 0;
272 while (start_list != 0)
274 Buffer_Wait_Queue *tmp = start_list->chain;
276 if (start_list->is_sent)
278 /* this one has been sent */
279 /* save return value */
280 if (retval == 0)
281 retval = start_list->bufferaddr;
282 else
283 /* more than one has been sent, that's wrong */
284 CAUSE_BUFFINCONS;
286 /* update instance, if present */
287 if (ins != 0)
288 memcpy (ins, &start_list->who_sent, sizeof (INSTANCE));
290 FREE (start_list);
291 start_list = tmp;
294 /* now check if there was really a buffer got */
295 if (retval == 0 && !timed_out)
296 /* something's totally wrong, raise an exception */
297 CAUSE_BUFFINCONS;
299 if (!timed_out)
300 *buf_got = (void *)retval;
301 return timed_out;
304 /* force function __print_buffer to be linked */
305 extern void __print_buffer ();
306 static EntryPoint pev = __print_buffer;