* Makefile.in (rtlanal.o): Depend on $(TM_P_H).
[official-gcc.git] / libchill / rts.c
blobfd1878c6cfda14117747fadaabf16e9d04cc7bbf
1 /* GNU CHILL compiler regression test file
2 Copyright (C) 1992, 1993 Free Software Foundation, Inc.
4 This file is part of GNU CC.
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.
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.
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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* As a special exception, if you link this library with other files,
22 some of which are compiled with GCC, to produce an executable,
23 this library does not by itself cause the resulting executable
24 to be covered by the GNU General Public License.
25 This exception does not however invalidate any other reasons why
26 the executable file might be covered by the GNU General Public License. */
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <setjmp.h>
32 #include <signal.h>
34 #include "rts.h"
37 /* some allocation/reallocation functions */
39 static void *
40 xmalloc (size)
41 int size;
43 void *tmp = malloc (size);
45 if (!tmp)
47 fprintf (stderr, "Out of heap space.\n");
48 exit (1);
50 return (tmp);
53 static void *
54 xrealloc (ptr, size)
55 void *ptr;
56 int size;
58 void *tmp = realloc (ptr, size);
60 if (!tmp)
62 fprintf (stderr, "Out of heap space.\n");
63 exit (1);
65 return (tmp);
68 /* the necessary data */
69 #define MAX_NUMBER 100
70 typedef char UsedValues[MAX_NUMBER];
72 #define MAX_COPIES 100
74 #define MAX_PER_ITEM 20
75 typedef struct TASKINGSTRUCTLIST
77 struct TASKINGSTRUCTLIST *forward;
78 int num;
79 TaskingStruct *data[MAX_PER_ITEM];
80 char copies[MAX_COPIES];
81 jmp_buf where;
82 } TaskingStructList;
84 static TaskingStructList *task_array[LAST_AND_UNUSED];
85 static UsedValues used_values[LAST_AND_UNUSED];
87 static short
88 get_next_free_number (vals)
89 UsedValues vals;
91 short i;
92 for (i = 1; i < MAX_NUMBER; i++)
94 if (!vals[i])
96 vals[i] = 1;
97 return (i);
100 fprintf (stderr, "There are no more free numbers.\n");
101 exit (1);
104 /* function search for the next available copy number */
105 static short
106 get_next_copy_number (p)
107 TaskingStructList *p;
109 short i;
111 for (i = 0; i < MAX_COPIES; i++)
113 if (!p->copies[i])
115 p->copies[i] = 1;
116 return (i);
119 fprintf (stderr, "No more copies available for \"%s\".\n",
120 p->data[0]->name);
121 exit (1);
124 /* function registers a tasking entry from a module and assign
125 a value to the type */
127 void
128 __register_tasking (t)
129 TaskingStruct *t;
131 TaskingStructList *p;
133 /* check first if a value was provided and if it is in range */
134 if (t->value_defined && *t->value >= MAX_NUMBER)
136 fprintf (stderr, "Value %d out of range.\n", *t->value);
137 exit (1);
140 /* look for item defined */
141 p = task_array[t->type];
142 while (p)
144 if (!strcmp (p->data[0]->name, t->name))
145 /* have found it */
146 break;
147 p = p->forward;
150 if (!p)
152 TaskingStructList *wrk = (TaskingStructList *)&task_array[t->type];
154 /* this is a new one -- allocate space */
155 p = xmalloc (sizeof (TaskingStructList));
156 memset (p->copies, 0, sizeof (p->copies));
157 p->forward = 0;
158 p->num = 1;
159 p->data[0] = t;
161 /* queue it in */
162 while (wrk->forward)
163 wrk = wrk->forward;
164 wrk->forward = p;
166 else
168 if (p->num >= MAX_PER_ITEM)
170 fprintf (stderr, "Too many registrations of \"%s\".\n", t->name);
171 exit (1);
173 p->data[p->num++] = t;
177 /* define all the entries for the runtime system. They will be
178 needed by chillrt0.o */
180 typedef char *(*fetch_names) ();
181 typedef int (*fetch_numbers) ();
183 static char tmp_for_fetch_name[100];
185 char *
186 __fetch_name (number)
187 int number;
189 TaskingStructList *p = task_array[Process];
191 while (p)
193 if (*(p->data[0]->value) == number)
194 return (p->data[0]->name);
195 p = p->forward;
197 sprintf (tmp_for_fetch_name, "%d", number);
198 return (tmp_for_fetch_name);
200 fetch_names __RTS_FETCH_NAMES__ = __fetch_name;
202 static int
203 __fetch_number (name)
204 char *name;
206 TaskingStructList *p = task_array[Process];
208 while (p)
210 if (!strcmp (p->data[0]->name, name))
211 return (*(p->data[0]->value));
212 p = p->forward;
214 return (-1);
216 fetch_numbers __RTS_FETCH_NUMBERS__ = __fetch_number;
219 /* here we go to check all registered items */
220 static void
221 __rts_init ()
223 int i;
224 TaskingStructList *p;
226 for (i = Process; i <= Event; i++)
228 p = task_array[i];
229 while (p)
231 TaskingStruct *t = 0;
232 int j;
233 short val;
235 for (j = 0; j < p->num; j++)
237 if (p->data[j]->value_defined)
239 if (t)
241 if (*(t->value) != *(p->data[j]->value))
243 fprintf (stderr, "Different values (%d & %d) for \"%s\".",
244 *(t->value), *(p->data[j]->value), t->name);
245 exit (1);
248 else
249 t = p->data[j];
253 if (t)
256 val = *(t->value);
258 if (used_values[t->type][val])
260 fprintf (stderr, "Value %d for \"%s\" is already used.\n",
261 val, t->name);
262 exit (1);
264 used_values[t->type][val] = 1;
266 else
268 /* we have to create a new value */
269 val = get_next_free_number (used_values[p->data[0]->type]);
272 for (j = 0; j < p->num; j++)
274 p->data[j]->value_defined = 1;
275 *(p->data[j]->value) = val;
278 p = p->forward;
282 EntryPoint __RTS_INIT__ = __rts_init;
284 /* define the start process queue */
285 typedef struct STARTENTRY
287 struct STARTENTRY *forward;
288 INSTANCE whoami;
289 EntryPoint entry;
290 void *data;
291 int datalen;
292 } StartEntry;
294 static StartEntry *start_queue = 0;
295 static StartEntry *current_process = 0;
297 /* the jump buffer for the main loop */
298 static jmp_buf jump_buffer;
299 static int jump_buffer_initialized = 0;
301 /* look for entries in start_queue and start the process */
302 static void
303 __rts_main_loop ()
305 StartEntry *s;
307 while (1)
309 if (setjmp (jump_buffer) == 0)
311 jump_buffer_initialized = 1;
312 s = start_queue;
313 while (s)
315 current_process = s;
316 start_queue = s->forward;
318 /* call the process */
319 (*s->entry) (s->data);
320 s = start_queue;
322 /* when queue empty we have finished */
323 return;
325 else
327 /* stop executed */
328 if (current_process->data)
329 free (current_process->data);
330 free (current_process);
331 current_process = 0;
335 EntryPoint __RTS_MAIN_LOOP__ = __rts_main_loop;
338 void
339 __start_process (ptype, pcopy, arg_size, args, ins)
340 short ptype;
341 short pcopy;
342 int arg_size;
343 void *args;
344 INSTANCE *ins;
346 TaskingStructList *p = task_array[Process];
347 EntryPoint pc = 0;
348 int i;
349 short this_copy = pcopy;
350 StartEntry *s, *wrk;
352 /* search for the process */
353 while (p)
355 if (*(p->data[0]->value) == ptype)
356 break;
357 p = p->forward;
359 if (!p)
361 fprintf (stderr, "Cannot find a process with type %d.\n", ptype);
362 exit (1);
365 /* search for the entry point */
366 for (i = 0; i < p->num; i++)
368 if (p->data[i]->entry)
370 pc = p->data[i]->entry;
371 break;
374 if (!pc)
376 fprintf (stderr, "Process \"%s\" doesn't have an entry point.\n",
377 p->data[0]->name);
378 exit (1);
381 /* check the copy */
382 if (pcopy >= MAX_COPIES)
384 fprintf (stderr, "Copy number (%d) out of range.\n", pcopy);
385 exit (1);
387 if (pcopy == -1)
389 /* search for a copy number */
390 this_copy = get_next_copy_number (p);
392 else
394 if (p->copies[pcopy])
396 /* FIXME: should be exception 'startfail' */
397 fprintf (stderr, "Copy number %d already in use for \"%s\".\n",
398 pcopy, p->data[0]->name);
399 exit (1);
401 p->copies[this_copy = pcopy] = 1;
404 /* ready to build start_queue entry */
405 s = xmalloc (sizeof (StartEntry));
406 s->forward = 0;
407 s->whoami.pcopy = this_copy;
408 s->whoami.ptype = ptype;
409 s->entry = pc;
410 s->datalen = arg_size;
411 if (args)
413 s->data = xmalloc (arg_size);
414 memcpy (s->data, args, arg_size);
416 else
417 s->data = 0;
419 /* queue that stuff in */
420 wrk = (StartEntry *)&start_queue;
421 while (wrk->forward)
422 wrk = wrk->forward;
423 wrk->forward = s;
425 /* if we have a pointer to ins -- set it */
426 if (ins)
428 ins->ptype = ptype;
429 ins->pcopy = this_copy;
433 void
434 __stop_process ()
436 if (!jump_buffer_initialized)
438 fprintf (stderr, "STOP called before START.\n");
439 exit (1);
441 longjmp (jump_buffer, 1);
445 /* function returns INSTANCE of current process */
446 INSTANCE
447 __whoami ()
449 INSTANCE whoami;
450 if (current_process)
451 whoami = current_process->whoami;
452 else
454 whoami.ptype = 0;
455 whoami.pcopy = 0;
457 return (whoami);
460 typedef struct
462 short *sc;
463 int data_len;
464 void *data;
465 } SignalDescr;
467 typedef struct SIGNALQUEUE
469 struct SIGNALQUEUE *forward;
470 short sc;
471 int data_len;
472 void *data;
473 INSTANCE to;
474 INSTANCE from;
475 } SignalQueue;
477 /* define the signal queue */
478 static SignalQueue *msg_queue = 0;
480 /* send a signal */
481 void
482 __send_signal (s, to, prio, with_len, with)
483 SignalDescr *s;
484 INSTANCE to;
485 int prio;
486 int with_len;
487 void *with;
489 SignalQueue *wrk = (SignalQueue *)&msg_queue;
490 SignalQueue *p;
491 TaskingStructList *t = task_array[Process];
493 /* search for process is defined and running */
494 while (t)
496 if (*(t->data[0]->value) == to.ptype)
497 break;
498 t = t->forward;
500 if (!t || !t->copies[to.pcopy])
502 fprintf (stderr, "Can't find instance [%d,%d].\n",
503 to.ptype, to.pcopy);
504 exit (1);
507 /* go to the end of the msg_queue */
508 while (wrk->forward)
509 wrk = wrk->forward;
511 p = xmalloc (sizeof (SignalQueue));
512 p->sc = *(s->sc);
513 if (p->data_len = s->data_len)
515 p->data = xmalloc (s->data_len);
516 memcpy (p->data, s->data, s->data_len);
518 else
519 p->data = 0;
520 p->to = to;
521 p->from = __whoami ();
522 p->forward = 0;
523 wrk->forward = p;
526 void
527 start_signal_timeout (i, s, j)
528 int i;
529 SignalDescr *s;
530 int j;
532 __send_signal (s, __whoami (), 0, 0, 0);
536 /* receive a signal */
538 __wait_signal_timed (sig_got, nsigs, sigptr, datap,
539 datalen, ins, else_branche,
540 to, filename, lineno)
541 short *sig_got;
542 int nsigs;
543 short *sigptr[];
544 void *datap;
545 int datalen;
546 INSTANCE *ins;
547 int else_branche;
548 void *to;
549 char *filename;
550 int lineno;
552 INSTANCE me = __whoami ();
553 SignalQueue *wrk, *p = msg_queue;
554 int i;
555 short sc;
557 /* search for a signal to `me' */
558 wrk = (SignalQueue *)&msg_queue;
560 while (p)
562 if (p->to.ptype == me.ptype
563 && p->to.pcopy == me.pcopy)
564 break;
565 wrk = p;
566 p = p->forward;
569 if (!p)
571 fprintf (stderr, "No signal for [%d,%d].\n",
572 me.ptype, me.pcopy);
573 exit (1);
576 /* queue the message out */
577 wrk->forward = p->forward;
579 /* now look for signal in list */
580 for (i = 0; i < nsigs; i++)
581 if (*(sigptr[i]) == p->sc)
582 break;
584 if (i >= nsigs && ! else_branche)
585 /* signal not in list and no ELSE in code */
586 __cause_exception ("signalfail", __FILE__, __LINE__);
588 if (i >= nsigs)
590 /* signal not in list */
591 sc = p->sc;
592 if (ins)
593 *ins = p->from;
594 if (p->data)
595 free (p->data);
596 free (p);
597 *sig_got = sc;
598 return (0);
601 /* we have found a signal in the list */
602 if (p->data_len)
604 if (datalen >= p->data_len
605 && datap)
606 memcpy (datap, p->data, p->data_len);
607 else
608 __cause_exception ("spacefail", __FILE__, __LINE__);
611 sc = p->sc;
612 if (ins)
613 *ins = p->from;
614 if (p->data)
615 free (p->data);
616 free (p);
617 *sig_got = sc;
618 return (0);
621 /* wait a certain amount of seconds */
623 __sleep_till (abstime, reltime, fname, lineno)
624 time_t abstime;
625 int reltime;
626 char *fname;
627 int lineno;
629 sleep (reltime);
630 return 0;
633 /* set up an alarm */
634 static int timeout_flag = 0;
636 static void alarm_handler ()
638 timeout_flag = 1;
641 int *
642 __define_timeout (howlong, filename, lineno)
643 unsigned long howlong; /* comes in millisecs */
644 char *filename;
645 int lineno;
647 unsigned int prev_alarm_value;
649 signal (SIGALRM, alarm_handler);
650 prev_alarm_value = alarm ((unsigned int)(howlong / 1000));
651 return &timeout_flag;
654 /* wait till timeout expires */
655 void
656 __wait_timeout (toid, filename, lineno)
657 volatile int *toid;
658 char *filename;
659 int lineno;
661 while (! *toid) ;
662 *toid = 0;