1/* Implement tasking-related runtime actions for CHILL. 2 Copyright (C) 1992,1993 Free Software Foundation, Inc. 3 Author: Wilfried Moser 4 5This file is part of GNU CC. 6 7GNU CC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2, or (at your option) 10any later version. 11 12GNU CC is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GNU CC; see the file COPYING. If not, write to 19the Free Software Foundation, 59 Temple Place - Suite 330, 20Boston, 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 32extern void __cause_ex1 (char *ex, char *file, int lineno); 33 34EXCEPTION (delayfail); 35#define CAUSE_DELAYFAIL __cause_ex1 ("delayfail", filename, lineno) 36 37EXCEPTION (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 65int 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 */ 227extern void __print_event (); 228static EntryPoint pev = __print_event; 229