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