OSDN Git Service

More address fixes.
[pf3gnuchains/gcc-fork.git] / libchill / rts.c
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
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
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
38 static void *
39 xmalloc (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
52 static void *
53 xrealloc (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
69 typedef char UsedValues[MAX_NUMBER];
70
71 #define MAX_COPIES 100
72
73 #define MAX_PER_ITEM 20
74 typedef 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
83 static TaskingStructList *task_array[LAST_AND_UNUSED];
84 static UsedValues used_values[LAST_AND_UNUSED];
85
86 static short
87 get_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 */
104 static short
105 get_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
126 void
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
179 typedef char *(*fetch_names) ();
180 typedef int (*fetch_numbers) ();
181
182 static char tmp_for_fetch_name[100];
183
184 char *
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 }
199 fetch_names     __RTS_FETCH_NAMES__ = __fetch_name;
200
201 static 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 }
215 fetch_numbers   __RTS_FETCH_NUMBERS__ = __fetch_number;
216
217
218 /* here we go to check all registered items */
219 static 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 }
281 EntryPoint      __RTS_INIT__ = __rts_init;
282 \f
283 /* define the start process queue */
284 typedef struct STARTENTRY
285 {
286   struct STARTENTRY *forward;
287   INSTANCE whoami;
288   EntryPoint entry;
289   void *data;
290   int datalen;
291 } StartEntry;
292
293 static StartEntry *start_queue = 0;
294 static StartEntry *current_process = 0;
295
296 /* the jump buffer for the main loop */
297 static jmp_buf jump_buffer;
298 static int jump_buffer_initialized = 0;
299
300 /* look for entries in start_queue and start the process */
301 static 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 }
334 EntryPoint      __RTS_MAIN_LOOP__ = __rts_main_loop;
335
336
337 void
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
432 void
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 */
445 INSTANCE
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
459 typedef struct
460 {
461   short *sc;
462   int    data_len;
463   void  *data;
464 } SignalDescr;
465
466 typedef 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 */
477 static SignalQueue *msg_queue = 0;
478 \f
479 /* send a signal */
480 void
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
525 void
526 start_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 */
536 int
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 */
621 int
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 */
633 static int timeout_flag = 0;
634
635 static void alarm_handler ()
636 {
637   timeout_flag = 1;
638 }
639
640 int *
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 */
654 void
655 __wait_timeout (toid, filename, lineno)
656      volatile int    *toid;
657      char   *filename;
658      int     lineno;
659 {
660   while (! *toid) ;
661   *toid = 0;
662 }