OSDN Git Service

* aclocal.m4 (gcc_AC_CHECK_PROG_VER): New macro.
[pf3gnuchains/gcc-fork.git] / libchill / delaycase.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 (delayfail);
35 #define CAUSE_DELAYFAIL     __cause_ex1 ("delayfail", filename, lineno)
36
37 EXCEPTION (notyetimplemented);
38 #define CAUSE_NOTIMPLEMENTED   __cause_ex1 ("notyetimplemeyed", filename, lineno)
39
40 /*
41  * function __delay_event
42  *
43  * parameters:
44  *     ev_got      pointer to location where to write the event got.
45  *     nevents     number of events in list
46  *     evptrs      array of event descriptors
47  *     priority    specified priority
48  *     insloc      pointer to resulting instance location
49  *     to          timeout value
50  *     filename    filename of caller
51  *     lineno      linenumber of caller
52  *
53  * returns:
54  *     int         0 .. success
55  *                 1 .. timed out
56  *
57  * exceptions:
58  *     delayfail
59  *
60  * abstract:
61  *     implement the CHILL DELAY and DELAY CASE actions.
62  *
63  */
64
65 int
66 __delay_event (ev_got, nevents, evptrs, priority, to, insloc, filename, lineno)
67      void         **ev_got;
68      int            nevents;
69      Event_Descr   *evptrs;
70      int            priority;
71      void          *to;
72      INSTANCE      *insloc;
73      char          *filename;
74      int            lineno;
75 {
76   int             i, already_done = 0;
77   Event_Queue    *start_list = 0;
78   Event_Queue   **retval = 0;
79   Event_Queue    *wrk;
80   int             timed_out = 0;
81   
82   /* check if all specified event queues have enough space left
83      to perform the delay */
84   for (i = 0; i < nevents; i++)
85     {
86       Event_Queue  *e;
87       unsigned long cnt = 0;
88       int j, have_done = 0;
89
90       if (evptrs[i].maxqueuelength == 0)
91         CAUSE_DELAYFAIL;
92       else if (evptrs[i].maxqueuelength == (unsigned long)-1L)
93         /* infinite length */
94         continue;
95
96       /* check if we already have processed this one, that means, this
97          event is mentioned more then once */
98       for (j = 0; j < i; j++)
99         {
100           if (evptrs[i].ev == evptrs[j].ev)
101             {
102               have_done = 1;
103               break;
104             }
105         }
106       if (have_done)
107         continue;
108       
109       memcpy (&e, evptrs[i].ev, sizeof (Event_Queue *));
110       while (e)
111         {
112           cnt++;
113           e = e->forward;
114         }
115       if (cnt >= evptrs[i].maxqueuelength)
116         CAUSE_DELAYFAIL;
117     }
118
119   for (i = 0; i < nevents; i++)
120     {
121       /* queue that stuff on each event */
122       Event_Queue      *wrk;
123       Event_Queue      *ev;
124       Event_Queue      *prev_queue_entry = 0;
125       Event_Queue      *prev_list_entry;
126       int               j, have_done = 0;
127       
128       /* check for this event already processed */
129       for (j = 0; j < i; j++)
130         {
131           if (evptrs[i].ev == evptrs[j].ev)
132             {
133               have_done = 1;
134               break;
135             }
136         }
137       if (have_done)
138         continue;
139
140       memcpy (&ev, &evptrs[i].ev, sizeof (Event_Queue *));
141       MALLOC (wrk, sizeof (Event_Queue));
142       memset (wrk, 0, sizeof (Event_Queue));
143
144       wrk->priority = priority;
145       wrk->this = THIS;
146       wrk->listhead = evptrs[i].ev;
147
148       /* search for the place to queue this entry in */
149       while (ev->forward != 0 && ev->priority >= priority)
150         {
151           prev_queue_entry = ev;
152           ev = ev->forward;
153         }
154
155       /* ready to put entry into queue */
156       if (ev->forward == 0 || prev_queue_entry == 0)
157         {
158           /* beginning or end of the list */
159           wrk->forward = ev->forward;
160           ev->forward = wrk;
161         }
162       else
163         {
164           /* this is somewhere in the middle */
165           wrk->forward = prev_queue_entry->forward;
166           prev_queue_entry->forward = wrk;
167         }
168
169       /* queue it into list */
170       wrk->startlist = start_list;
171       if (! start_list)
172         {
173           /* we are the first in the list */
174           start_list = wrk;
175           prev_list_entry = wrk;
176           wrk->startlist = start_list;
177         }
178       else
179         {
180           prev_list_entry->chain = wrk;
181           prev_list_entry = wrk;
182         }
183     }
184
185   /* tell runtime system to delay that process */
186   timed_out = __delay_this (wait_event_delay, to, filename, lineno);
187   if (timed_out)
188     {
189       /* we have to remove the entries from the queue's */
190       wrk = start_list;
191       while (wrk)
192         {
193           Event_Queue *tmp = (Event_Queue *)wrk->listhead;
194           
195           while (tmp->forward != wrk)
196             tmp = tmp->forward;
197           tmp->forward = wrk->forward;
198           wrk = wrk->chain;
199         }
200     }
201   
202   wrk = start_list;
203   while (wrk)
204     {
205       Event_Queue  *tmp;
206
207       if (wrk->is_continued && ! already_done)
208         {
209           already_done = 1;
210           retval = wrk->listhead;
211           if (insloc && !timed_out)
212             {
213               insloc->ptype = wrk->who_continued.ptype;
214               insloc->pcopy = wrk->who_continued.pcopy;
215             }
216         }
217       tmp = wrk->chain;
218       FREE (wrk);
219       wrk = tmp;
220     }
221   if (!timed_out && ev_got)
222     *ev_got = (void *)retval;
223   return timed_out;
224 }
225
226 /* force function print_event to be linked */
227 extern void __print_event ();
228 static EntryPoint pev = __print_event;