]> gcc.gnu.org Git - gcc.git/blame - libchill/rts.c
* Add library exception clause to the copyright notice for all
[gcc.git] / libchill / rts.c
CommitLineData
b79f73df
JL
1/* GNU CHILL compiler regression test file
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
502b941f
JL
20/* As a special exception, if you link this library with other files,
21 some of which are compiled with GCC, to produce an executable,
22 this library does not by itself cause the resulting executable
23 to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why
25 the executable file might be covered by the GNU General Public License. */
26
b79f73df
JL
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30#include <setjmp.h>
31#include <signal.h>
32
33#include "rts.h"
34
35
36/* some allocation/reallocation functions */
37
38static void *
39xmalloc (size)
40 int size;
41{
42 void *tmp = malloc (size);
43
44 if (!tmp)
45 {
46 fprintf (stderr, "Out of heap space.\n");
47 exit (1);
48 }
49 return (tmp);
50}
51
52static void *
53xrealloc (ptr, size)
54 void *ptr;
55 int size;
56{
57 void *tmp = realloc (ptr, size);
58
59 if (!tmp)
60 {
61 fprintf (stderr, "Out of heap space.\n");
62 exit (1);
63 }
64 return (tmp);
65}
66
67/* the necessary data */
68#define MAX_NUMBER 100
69typedef char UsedValues[MAX_NUMBER];
70
71#define MAX_COPIES 100
72
73#define MAX_PER_ITEM 20
74typedef struct TASKINGSTRUCTLIST
75{
76 struct TASKINGSTRUCTLIST *forward;
77 int num;
78 TaskingStruct *data[MAX_PER_ITEM];
79 char copies[MAX_COPIES];
80 jmp_buf where;
81} TaskingStructList;
82
83static TaskingStructList *task_array[LAST_AND_UNUSED];
84static UsedValues used_values[LAST_AND_UNUSED];
85
86static short
87get_next_free_number (vals)
88 UsedValues vals;
89{
90 short i;
91 for (i = 1; i < MAX_NUMBER; i++)
92 {
93 if (!vals[i])
94 {
95 vals[i] = 1;
96 return (i);
97 }
98 }
99 fprintf (stderr, "There are no more free numbers.\n");
100 exit (1);
101}
102
103/* function search for the next available copy number */
104static short
105get_next_copy_number (p)
106 TaskingStructList *p;
107{
108 short i;
109
110 for (i = 0; i < MAX_COPIES; i++)
111 {
112 if (!p->copies[i])
113 {
114 p->copies[i] = 1;
115 return (i);
116 }
117 }
118 fprintf (stderr, "No more copies available for \"%s\".\n",
119 p->data[0]->name);
120 exit (1);
121}
122
123/* function registers a tasking entry from a module and assign
124 a value to the type */
125
126void
127__register_tasking (t)
128 TaskingStruct *t;
129{
130 TaskingStructList *p;
131
132 /* check first if a value was provided and if it is in range */
133 if (t->value_defined && *t->value >= MAX_NUMBER)
134 {
135 fprintf (stderr, "Value %d out of range.\n", *t->value);
136 exit (1);
137 }
138
139 /* look for item defined */
140 p = task_array[t->type];
141 while (p)
142 {
143 if (!strcmp (p->data[0]->name, t->name))
144 /* have found it */
145 break;
146 p = p->forward;
147 }
148
149 if (!p)
150 {
151 TaskingStructList *wrk = (TaskingStructList *)&task_array[t->type];
152
153 /* this is a new one -- allocate space */
154 p = xmalloc (sizeof (TaskingStructList));
155 memset (p->copies, 0, sizeof (p->copies));
156 p->forward = 0;
157 p->num = 1;
158 p->data[0] = t;
159
160 /* queue it in */
161 while (wrk->forward)
162 wrk = wrk->forward;
163 wrk->forward = p;
164 }
165 else
166 {
167 if (p->num >= MAX_PER_ITEM)
168 {
169 fprintf (stderr, "Too many registrations of \"%s\".\n", t->name);
170 exit (1);
171 }
172 p->data[p->num++] = t;
173 }
174}
175\f
176/* define all the entries for the runtime system. They will be
177 needed by chillrt0.o */
178
179typedef char *(*fetch_names) ();
180typedef int (*fetch_numbers) ();
181
182static char tmp_for_fetch_name[100];
183
184char *
185__fetch_name (number)
186 int number;
187{
188 TaskingStructList *p = task_array[Process];
189
190 while (p)
191 {
192 if (*(p->data[0]->value) == number)
193 return (p->data[0]->name);
194 p = p->forward;
195 }
196 sprintf (tmp_for_fetch_name, "%d", number);
197 return (tmp_for_fetch_name);
198}
199fetch_names __RTS_FETCH_NAMES__ = __fetch_name;
200
201static int
202__fetch_number (name)
203 char *name;
204{
205 TaskingStructList *p = task_array[Process];
206
207 while (p)
208 {
209 if (!strcmp (p->data[0]->name, name))
210 return (*(p->data[0]->value));
211 p = p->forward;
212 }
213 return (-1);
214}
215fetch_numbers __RTS_FETCH_NUMBERS__ = __fetch_number;
216
217
218/* here we go to check all registered items */
219static void
220 __rts_init ()
221{
222 int i;
223 TaskingStructList *p;
224
225 for (i = Process; i <= Event; i++)
226 {
227 p = task_array[i];
228 while (p)
229 {
230 TaskingStruct *t = 0;
231 int j;
232 short val;
233
234 for (j = 0; j < p->num; j++)
235 {
236 if (p->data[j]->value_defined)
237 {
238 if (t)
239 {
240 if (*(t->value) != *(p->data[j]->value))
241 {
242 fprintf (stderr, "Different values (%d & %d) for \"%s\".",
243 *(t->value), *(p->data[j]->value), t->name);
244 exit (1);
245 }
246 }
247 else
248 t = p->data[j];
249 }
250 }
251
252 if (t)
253 {
254
255 val = *(t->value);
256
257 if (used_values[t->type][val])
258 {
259 fprintf (stderr, "Value %d for \"%s\" is already used.\n",
260 val, t->name);
261 exit (1);
262 }
263 used_values[t->type][val] = 1;
264 }
265 else
266 {
267 /* we have to create a new value */
268 val = get_next_free_number (used_values[p->data[0]->type]);
269 }
270
271 for (j = 0; j < p->num; j++)
272 {
273 p->data[j]->value_defined = 1;
274 *(p->data[j]->value) = val;
275 }
276
277 p = p->forward;
278 }
279 }
280}
281EntryPoint __RTS_INIT__ = __rts_init;
282\f
283/* define the start process queue */
284typedef struct STARTENTRY
285{
286 struct STARTENTRY *forward;
287 INSTANCE whoami;
288 EntryPoint entry;
289 void *data;
290 int datalen;
291} StartEntry;
292
293static StartEntry *start_queue = 0;
294static StartEntry *current_process = 0;
295
296/* the jump buffer for the main loop */
297static jmp_buf jump_buffer;
298static int jump_buffer_initialized = 0;
299
300/* look for entries in start_queue and start the process */
301static void
302__rts_main_loop ()
303{
304 StartEntry *s;
305
306 while (1)
307 {
308 if (setjmp (jump_buffer) == 0)
309 {
310 jump_buffer_initialized = 1;
311 s = start_queue;
312 while (s)
313 {
314 current_process = s;
315 start_queue = s->forward;
316
317 /* call the process */
318 (*s->entry) (s->data);
319 s = start_queue;
320 }
321 /* when queue empty we have finished */
322 return;
323 }
324 else
325 {
326 /* stop executed */
327 if (current_process->data)
328 free (current_process->data);
329 free (current_process);
330 current_process = 0;
331 }
332 }
333}
334EntryPoint __RTS_MAIN_LOOP__ = __rts_main_loop;
335
336
337void
338__start_process (ptype, pcopy, arg_size, args, ins)
339 short ptype;
340 short pcopy;
341 int arg_size;
342 void *args;
343 INSTANCE *ins;
344{
345 TaskingStructList *p = task_array[Process];
346 EntryPoint pc = 0;
347 int i;
348 short this_copy = pcopy;
349 StartEntry *s, *wrk;
350
351 /* search for the process */
352 while (p)
353 {
354 if (*(p->data[0]->value) == ptype)
355 break;
356 p = p->forward;
357 }
358 if (!p)
359 {
360 fprintf (stderr, "Cannot find a process with type %d.\n", ptype);
361 exit (1);
362 }
363
364 /* search for the entry point */
365 for (i = 0; i < p->num; i++)
366 {
367 if (p->data[i]->entry)
368 {
369 pc = p->data[i]->entry;
370 break;
371 }
372 }
373 if (!pc)
374 {
375 fprintf (stderr, "Process \"%s\" doesn't have an entry point.\n",
376 p->data[0]->name);
377 exit (1);
378 }
379
380 /* check the copy */
381 if (pcopy >= MAX_COPIES)
382 {
383 fprintf (stderr, "Copy number (%d) out of range.\n", pcopy);
384 exit (1);
385 }
386 if (pcopy == -1)
387 {
388 /* search for a copy number */
389 this_copy = get_next_copy_number (p);
390 }
391 else
392 {
393 if (p->copies[pcopy])
394 {
395 /* FIXME: should be exception 'startfail' */
396 fprintf (stderr, "Copy number %d already in use for \"%s\".\n",
397 pcopy, p->data[0]->name);
398 exit (1);
399 }
400 p->copies[this_copy = pcopy] = 1;
401 }
402
403 /* ready to build start_queue entry */
404 s = xmalloc (sizeof (StartEntry));
405 s->forward = 0;
406 s->whoami.pcopy = this_copy;
407 s->whoami.ptype = ptype;
408 s->entry = pc;
409 s->datalen = arg_size;
410 if (args)
411 {
412 s->data = xmalloc (arg_size);
413 memcpy (s->data, args, arg_size);
414 }
415 else
416 s->data = 0;
417
418 /* queue that stuff in */
419 wrk = (StartEntry *)&start_queue;
420 while (wrk->forward)
421 wrk = wrk->forward;
422 wrk->forward = s;
423
424 /* if we have a pointer to ins -- set it */
425 if (ins)
426 {
427 ins->ptype = ptype;
428 ins->pcopy = this_copy;
429 }
430}
431\f
432void
433__stop_process ()
434{
435 if (!jump_buffer_initialized)
436 {
437 fprintf (stderr, "STOP called before START.\n");
438 exit (1);
439 }
440 longjmp (jump_buffer, 1);
441}
442
443
444/* function returns INSTANCE of current process */
445INSTANCE
446__whoami ()
447{
448 INSTANCE whoami;
449 if (current_process)
450 whoami = current_process->whoami;
451 else
452 {
453 whoami.ptype = 0;
454 whoami.pcopy = 0;
455 }
456 return (whoami);
457}
458
459typedef struct
460{
461 short *sc;
462 int data_len;
463 void *data;
464} SignalDescr;
465
466typedef struct SIGNALQUEUE
467{
468 struct SIGNALQUEUE *forward;
469 short sc;
470 int data_len;
471 void *data;
472 INSTANCE to;
473 INSTANCE from;
474} SignalQueue;
475
476/* define the signal queue */
477static SignalQueue *msg_queue = 0;
478\f
479/* send a signal */
480void
481__send_signal (s, to, prio, with_len, with)
482 SignalDescr *s;
483 INSTANCE to;
484 int prio;
485 int with_len;
486 void *with;
487{
488 SignalQueue *wrk = (SignalQueue *)&msg_queue;
489 SignalQueue *p;
490 TaskingStructList *t = task_array[Process];
491
492 /* search for process is defined and running */
493 while (t)
494 {
495 if (*(t->data[0]->value) == to.ptype)
496 break;
497 t = t->forward;
498 }
499 if (!t || !t->copies[to.pcopy])
500 {
501 fprintf (stderr, "Can't find instance [%d,%d].\n",
502 to.ptype, to.pcopy);
503 exit (1);
504 }
505
506 /* go to the end of the msg_queue */
507 while (wrk->forward)
508 wrk = wrk->forward;
509
510 p = xmalloc (sizeof (SignalQueue));
511 p->sc = *(s->sc);
512 if (p->data_len = s->data_len)
513 {
514 p->data = xmalloc (s->data_len);
515 memcpy (p->data, s->data, s->data_len);
516 }
517 else
518 p->data = 0;
519 p->to = to;
520 p->from = __whoami ();
521 p->forward = 0;
522 wrk->forward = p;
523}
524\f
525void
526start_signal_timeout (i, s, j)
527 int i;
528 SignalDescr *s;
529 int j;
530{
531 __send_signal (s, __whoami (), 0, 0, 0);
532}
533
534
535/* receive a signal */
536int
537__wait_signal_timed (sig_got, nsigs, sigptr, datap,
538 datalen, ins, else_branche,
539 to, filename, lineno)
540 short *sig_got;
541 int nsigs;
542 short *sigptr[];
543 void *datap;
544 int datalen;
545 INSTANCE *ins;
546 int else_branche;
547 void *to;
548 char *filename;
549 int lineno;
550{
551 INSTANCE me = __whoami ();
552 SignalQueue *wrk, *p = msg_queue;
553 int i;
554 short sc;
555
556 /* search for a signal to `me' */
557 wrk = (SignalQueue *)&msg_queue;
558
559 while (p)
560 {
561 if (p->to.ptype == me.ptype
562 && p->to.pcopy == me.pcopy)
563 break;
564 wrk = p;
565 p = p->forward;
566 }
567
568 if (!p)
569 {
570 fprintf (stderr, "No signal for [%d,%d].\n",
571 me.ptype, me.pcopy);
572 exit (1);
573 }
574
575 /* queue the message out */
576 wrk->forward = p->forward;
577
578 /* now look for signal in list */
579 for (i = 0; i < nsigs; i++)
580 if (*(sigptr[i]) == p->sc)
581 break;
582
583 if (i >= nsigs && ! else_branche)
584 /* signal not in list and no ELSE in code */
585 __cause_exception ("signalfail", __FILE__, __LINE__);
586
587 if (i >= nsigs)
588 {
589 /* signal not in list */
590 sc = p->sc;
591 if (ins)
592 *ins = p->from;
593 if (p->data)
594 free (p->data);
595 free (p);
596 *sig_got = sc;
597 return (0);
598 }
599
600 /* we have found a signal in the list */
601 if (p->data_len)
602 {
603 if (datalen >= p->data_len
604 && datap)
605 memcpy (datap, p->data, p->data_len);
606 else
607 __cause_exception ("spacefail", __FILE__, __LINE__);
608 }
609
610 sc = p->sc;
611 if (ins)
612 *ins = p->from;
613 if (p->data)
614 free (p->data);
615 free (p);
616 *sig_got = sc;
617 return (0);
618}
619\f
620/* wait a certain amount of seconds */
621int
622__sleep_till (abstime, reltime, fname, lineno)
623 time_t abstime;
624 int reltime;
625 char *fname;
626 int lineno;
627{
628 sleep (reltime);
629 return 0;
630}
631\f
632/* set up an alarm */
633static int timeout_flag = 0;
634
635static void alarm_handler ()
636{
637 timeout_flag = 1;
638}
639
640int *
641__define_timeout (howlong, filename, lineno)
642 unsigned long howlong; /* comes in millisecs */
643 char *filename;
644 int lineno;
645{
646 unsigned int prev_alarm_value;
647
648 signal (SIGALRM, alarm_handler);
649 prev_alarm_value = alarm ((unsigned int)(howlong / 1000));
650 return &timeout_flag;
651}
652\f
653/* wait till timeout expires */
654void
655__wait_timeout (toid, filename, lineno)
656 volatile int *toid;
657 char *filename;
658 int lineno;
659{
660 while (! *toid) ;
661 *toid = 0;
662}
This page took 0.08373 seconds and 5 git commands to generate.