OSDN Git Service

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