Fix for PR1654 - implement "movstrsi" pattern to copy simple blocks of memory.
[official-gcc.git] / libchill / waitbuffer.c
blob2e9d1583076a08ae43713641d63b058d03132cda
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* As a special exception, if you link this library with other files,
22 some of which are compiled with GCC, to produce an executable,
23 this library does not by itself cause the resulting executable
24 to be covered by the GNU General Public License.
25 This exception does not however invalidate any other reasons why
26 the executable file might be covered by the GNU General Public License. */
28 #include "rtltypes.h"
29 #include "rts.h"
31 extern void __cause_ex1 (char *ex, char *file, int lineno);
33 EXCEPTION (bufferinconsistency)
34 #define CAUSE_BUFFINCONS __cause_ex1 ("bufferinconsistency", filename, lineno)
35 EXCEPTION (spacefail);
36 #define CAUSE_SPACEFAIL __cause_ex1 ("spacefail", filename, lineno)
39 * function __wait_buffer
41 * parameters:
42 * buf_got pointer to location for writing the received buffer address
43 * nbuf number of buffers in RECEIVE CASE
44 * bufptr array of pointers to buffer descriptor
45 * datap pointer where to store data
46 * datalen length of data
47 * ins pointer to instance location or 0
48 * else_clause else specified or not
49 * to_loc pointer to timesupervision value
50 * filename source file name where function gets called
51 * lineno linenumber in source file
53 * returns:
54 * int 0 .. success
55 * 1 .. timed out
57 * exceptions:
58 * bufferinconsistency if something's wrong in the buffer queue's
59 * spacefail out of heap space of datalength of receiver
60 * less then data avilable.
62 * abstract:
63 * implement the CHILL RECEIVE buffer CASE action.
66 int
67 __wait_buffer (buf_got, nbuf, bufptr, datap, datalen, ins,
68 else_clause, to, filename, lineno)
69 void **buf_got;
70 int nbuf;
71 Buffer_Descr *bufptr[];
72 void *datap;
73 int datalen;
74 INSTANCE *ins;
75 int else_clause;
76 void *to;
77 char *filename;
78 int lineno;
80 int i;
81 Buffer_Wait_Queue *start_list;
82 Buffer_Queue **retval;
83 Buffer_Queue **highprio;
84 int timed_out;
86 /* look if there is a buffer already sent */
87 highprio = 0;
88 for (i = 0; i < nbuf; i++)
90 Buffer_Queue *bq;
92 memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
93 if (bq != 0 && bq->sendqueue != 0)
95 if (highprio != 0)
97 Buffer_Queue *bsq = *highprio;
99 if (bq->sendqueue->priority > bsq->sendqueue->priority)
100 highprio = bufptr[i]->buf;
102 else
103 highprio = bufptr[i]->buf;
107 if (highprio != 0)
109 Buffer_Queue *bq;
111 memcpy (&bq, highprio, sizeof (Buffer_Queue *));
112 if (bq != 0 && bq->sendqueue != 0)
114 Buffer_Send_Queue *bsq = bq->sendqueue;
115 Buffer_Send_Queue *tmp;
117 /* check data length */
118 if (datalen < bsq->datalen)
119 /* something's totaly wrong. Raise exception */
120 CAUSE_SPACEFAIL;
122 /* copy data out */
123 memcpy (datap, bsq->dataptr, bsq->datalen);
125 /* update instance, if present */
126 if (ins != 0)
127 memcpy (ins, &bsq->this, sizeof (INSTANCE));
129 /* dequeue entry */
130 tmp = bsq;
131 bq->sendqueue = tmp->forward;
133 if (tmp->is_delayed)
135 /* there is an instance delayed on a send,
136 continue it. */
137 __continue_that (tmp->this, tmp->priority, filename, lineno);
138 FREE (tmp);
140 /* return the buffer we have received from */
141 *buf_got = (void *)highprio;
142 return 0;
145 /* just decrease sendqueue length */
146 bq->sendqueuelength--;
148 FREE (tmp);
150 /* as we got an entry free, we should continue
151 an INSTANCE which is delayed on a send at this
152 buffer */
153 bsq = bq->sendqueue;
154 while (bsq != 0)
156 if (bsq->is_delayed)
158 bq->sendqueuelength++;
159 bsq->is_delayed = 0;
160 __continue_that (bsq->this, bsq->priority, filename, lineno);
161 break;
163 bsq = bsq->forward;
165 /* return the buffer we have received from */
166 *buf_got = (void *)highprio;
167 return 0;
171 /* if we come here, there is no buffer already sent */
172 if (else_clause != 0)
174 /* in that case we return immediately */
175 *buf_got = 0;
176 return 0;
179 /* now we have to queue ourself to the wait queue(s) */
180 start_list = 0;
181 for (i = 0; i < nbuf; i++)
183 Buffer_Queue *bq;
184 Buffer_Wait_Queue *wrk;
185 Buffer_Wait_Queue *bwq;
186 Buffer_Wait_Queue *prev_queue_entry = 0;
187 Buffer_Wait_Queue *prev_list_entry;
188 int j, have_done = 0;
190 for (j = 0; j < i; j++)
192 if (bufptr[i]->buf == bufptr[j]->buf)
194 have_done = 1;
195 break;
198 if (have_done)
199 continue;
201 memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
202 if (bq == 0)
204 MALLOC (bq, sizeof (Buffer_Queue));
205 memset (bq, 0, sizeof (Buffer_Queue));
206 /* *(bufptr[i]->buf) = bq; may be unaligned */
207 memcpy (bufptr[i]->buf, &bq, sizeof (Buffer_Queue *));
209 MALLOC (wrk, sizeof (Buffer_Wait_Queue));
210 memset (wrk, 0, sizeof (Buffer_Wait_Queue));
211 bwq = (Buffer_Wait_Queue *)&bq->waitqueue;
213 wrk->this = THIS;
214 wrk->datalen = datalen;
215 wrk->dataptr = datap;
216 wrk->bufferaddr = bufptr[i]->buf;
218 /* queue it at the end of buffer wait queue */
219 while (bwq->forward != 0)
220 bwq = bwq->forward;
221 wrk->forward = bwq->forward;
222 bwq->forward = wrk;
224 /* queue it into list */
225 wrk->startlist = start_list;
226 if (! start_list)
228 start_list = wrk;
229 prev_list_entry = wrk;
230 wrk->startlist = start_list;
232 else
234 prev_list_entry->chain = wrk;
235 prev_list_entry = wrk;
238 /* increment wait queue count */
239 bq->waitqueuelength++;
242 /* tell runtime system to delay this process */
243 timed_out = __delay_this (wait_buffer_receive, to, filename, lineno);
244 if (timed_out)
246 /* remove all entries from buffer queues */
247 Buffer_Wait_Queue *listentry = start_list;
249 while (listentry != 0)
251 Buffer_Queue *bq = *(listentry->bufferaddr);
252 Buffer_Wait_Queue *prev_entry = (Buffer_Wait_Queue *)&bq->waitqueue;
253 Buffer_Wait_Queue *bwq = bq->waitqueue;
255 while (bwq != listentry)
257 prev_entry = bwq;
258 bwq = bwq->forward;
260 /* dequeue it */
261 prev_entry->forward = bwq->forward;
262 bq->waitqueuelength--;
263 listentry = listentry->chain;
267 /* someone has continued us, find which buffer got ready */
268 retval = 0;
270 while (start_list != 0)
272 Buffer_Wait_Queue *tmp = start_list->chain;
274 if (start_list->is_sent)
276 /* this one has been sent */
277 /* save return value */
278 if (retval == 0)
279 retval = start_list->bufferaddr;
280 else
281 /* more then one has been sent, that's wrong */
282 CAUSE_BUFFINCONS;
284 /* update instance, if present */
285 if (ins != 0)
286 memcpy (ins, &start_list->who_sent, sizeof (INSTANCE));
288 FREE (start_list);
289 start_list = tmp;
292 /* now check if there was really a buffer got */
293 if (retval == 0 && !timed_out)
294 /* something's totally wrong, raise an exception */
295 CAUSE_BUFFINCONS;
297 if (!timed_out)
298 *buf_got = (void *)retval;
299 return timed_out;
302 /* force function __print_buffer to be linked */
303 extern void __print_buffer ();
304 static EntryPoint pev = __print_buffer;