OSDN Git Service

* gjavah.c (print_class_decls): Fix thinko in arglist
[pf3gnuchains/gcc-fork.git] / libchill / waitbuffer.c
1 /* Implement tasking-related runtime actions for CHILL.
2    Copyright (C) 1992,1993 Free Software Foundation, Inc.
3    Author: Wilfried Moser
4
5 This file is part of GNU CC.
6
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.
11
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.
16
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.  */
20
21 #include "rtltypes.h"
22 #include "rts.h"
23
24 extern void __cause_ex1 (char *ex, char *file, int lineno);
25
26 EXCEPTION (bufferinconsistency)
27 #define CAUSE_BUFFINCONS  __cause_ex1 ("bufferinconsistency", filename, lineno)
28 EXCEPTION (spacefail);
29 #define CAUSE_SPACEFAIL   __cause_ex1 ("spacefail", filename, lineno)
30     
31 /*
32  * function __wait_buffer
33  *
34  * parameters:
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
45  *
46  * returns:
47  *     int         0 .. success
48  *                 1 .. timed out
49  *
50  * exceptions:
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.
54  *
55  * abstract:
56  *     implement the CHILL RECEIVE buffer CASE action.
57  */
58
59 int
60 __wait_buffer (buf_got, nbuf, bufptr, datap, datalen, ins,
61                else_clause, to, filename, lineno)
62      void           **buf_got;
63      int              nbuf;
64      Buffer_Descr    *bufptr[];
65      void            *datap;
66      int              datalen;
67      INSTANCE        *ins;
68      int              else_clause;
69      void            *to;
70      char            *filename;
71      int              lineno;
72 {
73   int i;
74   Buffer_Wait_Queue     *start_list;
75   Buffer_Queue         **retval;
76   Buffer_Queue         **highprio;
77   int                    timed_out;
78   
79   /* look if there is a buffer already sent */
80   highprio = 0;
81   for (i = 0; i < nbuf; i++)
82     {
83       Buffer_Queue      *bq;
84
85       memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
86       if (bq != 0 && bq->sendqueue != 0)
87         {
88           if (highprio != 0)
89             {
90               Buffer_Queue      *bsq = *highprio;
91               
92               if (bq->sendqueue->priority > bsq->sendqueue->priority)
93                 highprio = bufptr[i]->buf;
94             }
95           else
96             highprio = bufptr[i]->buf;
97         }
98     }
99   
100   if (highprio != 0)
101     {
102       Buffer_Queue      *bq;
103
104       memcpy (&bq, highprio, sizeof (Buffer_Queue *));
105       if (bq != 0 && bq->sendqueue != 0)
106         {
107           Buffer_Send_Queue *bsq = bq->sendqueue;
108           Buffer_Send_Queue *tmp;
109
110           /* check data length */
111           if (datalen < bsq->datalen)
112             /* something's totaly wrong. Raise exception */
113             CAUSE_SPACEFAIL;
114
115           /* copy data out */
116           memcpy (datap, bsq->dataptr, bsq->datalen);
117
118           /* update instance, if present */
119           if (ins != 0)
120             memcpy (ins, &bsq->this, sizeof (INSTANCE));
121
122           /* dequeue entry */
123           tmp = bsq;
124           bq->sendqueue = tmp->forward;
125
126           if (tmp->is_delayed)
127             {
128               /* there is an instance delayed on a send,
129                  continue it. */
130               __continue_that (tmp->this, tmp->priority, filename, lineno);
131               FREE (tmp);
132
133               /* return the buffer we have received from */
134               *buf_got = (void *)highprio;
135               return 0;
136             }
137
138           /* just decrease sendqueue length */
139           bq->sendqueuelength--;
140
141           FREE (tmp);
142
143           /* as we got an entry free, we should continue
144              an INSTANCE which is delayed on a send at this
145              buffer */
146           bsq = bq->sendqueue;
147           while (bsq != 0)
148             {
149               if (bsq->is_delayed)
150                 {
151                   bq->sendqueuelength++;
152                   bsq->is_delayed = 0;
153                   __continue_that (bsq->this, bsq->priority, filename, lineno);
154                   break;
155                 }
156               bsq = bsq->forward;
157             }
158           /* return the buffer we have received from */
159           *buf_got = (void *)highprio;
160           return 0;
161         }
162       }
163
164   /* if we come here, there is no buffer already sent */
165   if (else_clause != 0)
166     {
167       /* in that case we return immediately */
168       *buf_got = 0;
169       return 0;
170     }
171   
172   /* now we have to queue ourself to the wait queue(s) */
173   start_list = 0;
174   for (i = 0; i < nbuf; i++)
175     {
176       Buffer_Queue      *bq;
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;
182       
183       for (j = 0; j < i; j++)
184         {
185           if (bufptr[i]->buf == bufptr[j]->buf)
186             {
187               have_done = 1;
188               break;
189             }
190         }
191       if (have_done)
192         continue;
193       
194       memcpy (&bq, bufptr[i]->buf, sizeof (Buffer_Queue *));
195       if (bq == 0)
196         {
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 *));
201         }
202       MALLOC (wrk, sizeof (Buffer_Wait_Queue));
203       memset (wrk, 0, sizeof (Buffer_Wait_Queue));
204       bwq = (Buffer_Wait_Queue *)&bq->waitqueue;
205       
206       wrk->this = THIS;
207       wrk->datalen = datalen;
208       wrk->dataptr = datap;
209       wrk->bufferaddr = bufptr[i]->buf;
210
211       /* queue it at the end of buffer wait queue */
212       while (bwq->forward != 0)
213           bwq = bwq->forward;
214       wrk->forward = bwq->forward;
215       bwq->forward = wrk;
216       
217       /* queue it into list */
218       wrk->startlist = start_list;
219       if (! start_list)
220         {
221           start_list = wrk;
222           prev_list_entry = wrk;
223           wrk->startlist = start_list;
224         }
225       else
226         {
227           prev_list_entry->chain = wrk;
228           prev_list_entry = wrk;
229         }
230       
231       /* increment wait queue count */
232       bq->waitqueuelength++;
233     }
234
235   /* tell runtime system to delay this process */
236   timed_out = __delay_this (wait_buffer_receive, to, filename, lineno);
237   if (timed_out)
238     {
239       /* remove all entries from buffer queues */
240       Buffer_Wait_Queue *listentry = start_list;
241       
242       while (listentry != 0)
243         {
244           Buffer_Queue *bq = *(listentry->bufferaddr);
245           Buffer_Wait_Queue *prev_entry = (Buffer_Wait_Queue *)&bq->waitqueue;
246           Buffer_Wait_Queue *bwq = bq->waitqueue;
247           
248           while (bwq != listentry)
249             {
250               prev_entry = bwq;
251               bwq = bwq->forward;
252             }
253           /* dequeue it */
254           prev_entry->forward = bwq->forward;
255           bq->waitqueuelength--;
256           listentry = listentry->chain;
257         }
258     }
259   
260   /* someone has continued us, find which buffer got ready */
261   retval = 0;
262
263   while (start_list != 0)
264     {
265       Buffer_Wait_Queue *tmp = start_list->chain;
266       
267       if (start_list->is_sent)
268         {
269           /* this one has been sent */
270           /* save return value */
271           if (retval == 0)
272               retval = start_list->bufferaddr;
273           else
274               /* more then one has been sent, that's wrong */
275               CAUSE_BUFFINCONS;
276           
277           /* update instance, if present */
278           if (ins != 0)
279             memcpy (ins, &start_list->who_sent, sizeof (INSTANCE));
280         }
281       FREE (start_list);
282       start_list = tmp;
283     }
284
285   /* now check if there was really a buffer got */
286   if (retval == 0 && !timed_out)
287     /* something's totally wrong, raise an exception  */
288     CAUSE_BUFFINCONS;
289
290   if (!timed_out)
291     *buf_got = (void *)retval;
292   return timed_out;
293 }
294
295 /* force function __print_buffer to be linked */
296 extern void __print_buffer ();
297 static EntryPoint pev = __print_buffer;