summaryrefslogtreecommitdiff
path: root/libchill/rts.c
diff options
context:
space:
mode:
Diffstat (limited to 'libchill/rts.c')
-rw-r--r--libchill/rts.c655
1 files changed, 655 insertions, 0 deletions
diff --git a/libchill/rts.c b/libchill/rts.c
new file mode 100644
index 00000000000..b7602e970cc
--- /dev/null
+++ b/libchill/rts.c
@@ -0,0 +1,655 @@
+/* GNU CHILL compiler regression test file
+ Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <signal.h>
+
+#include "rts.h"
+
+
+/* some allocation/reallocation functions */
+
+static void *
+xmalloc (size)
+ int size;
+{
+ void *tmp = malloc (size);
+
+ if (!tmp)
+ {
+ fprintf (stderr, "Out of heap space.\n");
+ exit (1);
+ }
+ return (tmp);
+}
+
+static void *
+xrealloc (ptr, size)
+ void *ptr;
+ int size;
+{
+ void *tmp = realloc (ptr, size);
+
+ if (!tmp)
+ {
+ fprintf (stderr, "Out of heap space.\n");
+ exit (1);
+ }
+ return (tmp);
+}
+
+/* the necessary data */
+#define MAX_NUMBER 100
+typedef char UsedValues[MAX_NUMBER];
+
+#define MAX_COPIES 100
+
+#define MAX_PER_ITEM 20
+typedef struct TASKINGSTRUCTLIST
+{
+ struct TASKINGSTRUCTLIST *forward;
+ int num;
+ TaskingStruct *data[MAX_PER_ITEM];
+ char copies[MAX_COPIES];
+ jmp_buf where;
+} TaskingStructList;
+
+static TaskingStructList *task_array[LAST_AND_UNUSED];
+static UsedValues used_values[LAST_AND_UNUSED];
+
+static short
+get_next_free_number (vals)
+ UsedValues vals;
+{
+ short i;
+ for (i = 1; i < MAX_NUMBER; i++)
+ {
+ if (!vals[i])
+ {
+ vals[i] = 1;
+ return (i);
+ }
+ }
+ fprintf (stderr, "There are no more free numbers.\n");
+ exit (1);
+}
+
+/* function search for the next available copy number */
+static short
+get_next_copy_number (p)
+ TaskingStructList *p;
+{
+ short i;
+
+ for (i = 0; i < MAX_COPIES; i++)
+ {
+ if (!p->copies[i])
+ {
+ p->copies[i] = 1;
+ return (i);
+ }
+ }
+ fprintf (stderr, "No more copies available for \"%s\".\n",
+ p->data[0]->name);
+ exit (1);
+}
+
+/* function registers a tasking entry from a module and assign
+ a value to the type */
+
+void
+__register_tasking (t)
+ TaskingStruct *t;
+{
+ TaskingStructList *p;
+
+ /* check first if a value was provided and if it is in range */
+ if (t->value_defined && *t->value >= MAX_NUMBER)
+ {
+ fprintf (stderr, "Value %d out of range.\n", *t->value);
+ exit (1);
+ }
+
+ /* look for item defined */
+ p = task_array[t->type];
+ while (p)
+ {
+ if (!strcmp (p->data[0]->name, t->name))
+ /* have found it */
+ break;
+ p = p->forward;
+ }
+
+ if (!p)
+ {
+ TaskingStructList *wrk = (TaskingStructList *)&task_array[t->type];
+
+ /* this is a new one -- allocate space */
+ p = xmalloc (sizeof (TaskingStructList));
+ memset (p->copies, 0, sizeof (p->copies));
+ p->forward = 0;
+ p->num = 1;
+ p->data[0] = t;
+
+ /* queue it in */
+ while (wrk->forward)
+ wrk = wrk->forward;
+ wrk->forward = p;
+ }
+ else
+ {
+ if (p->num >= MAX_PER_ITEM)
+ {
+ fprintf (stderr, "Too many registrations of \"%s\".\n", t->name);
+ exit (1);
+ }
+ p->data[p->num++] = t;
+ }
+}
+
+/* define all the entries for the runtime system. They will be
+ needed by chillrt0.o */
+
+typedef char *(*fetch_names) ();
+typedef int (*fetch_numbers) ();
+
+static char tmp_for_fetch_name[100];
+
+char *
+__fetch_name (number)
+ int number;
+{
+ TaskingStructList *p = task_array[Process];
+
+ while (p)
+ {
+ if (*(p->data[0]->value) == number)
+ return (p->data[0]->name);
+ p = p->forward;
+ }
+ sprintf (tmp_for_fetch_name, "%d", number);
+ return (tmp_for_fetch_name);
+}
+fetch_names __RTS_FETCH_NAMES__ = __fetch_name;
+
+static int
+__fetch_number (name)
+ char *name;
+{
+ TaskingStructList *p = task_array[Process];
+
+ while (p)
+ {
+ if (!strcmp (p->data[0]->name, name))
+ return (*(p->data[0]->value));
+ p = p->forward;
+ }
+ return (-1);
+}
+fetch_numbers __RTS_FETCH_NUMBERS__ = __fetch_number;
+
+
+/* here we go to check all registered items */
+static void
+ __rts_init ()
+{
+ int i;
+ TaskingStructList *p;
+
+ for (i = Process; i <= Event; i++)
+ {
+ p = task_array[i];
+ while (p)
+ {
+ TaskingStruct *t = 0;
+ int j;
+ short val;
+
+ for (j = 0; j < p->num; j++)
+ {
+ if (p->data[j]->value_defined)
+ {
+ if (t)
+ {
+ if (*(t->value) != *(p->data[j]->value))
+ {
+ fprintf (stderr, "Different values (%d & %d) for \"%s\".",
+ *(t->value), *(p->data[j]->value), t->name);
+ exit (1);
+ }
+ }
+ else
+ t = p->data[j];
+ }
+ }
+
+ if (t)
+ {
+
+ val = *(t->value);
+
+ if (used_values[t->type][val])
+ {
+ fprintf (stderr, "Value %d for \"%s\" is already used.\n",
+ val, t->name);
+ exit (1);
+ }
+ used_values[t->type][val] = 1;
+ }
+ else
+ {
+ /* we have to create a new value */
+ val = get_next_free_number (used_values[p->data[0]->type]);
+ }
+
+ for (j = 0; j < p->num; j++)
+ {
+ p->data[j]->value_defined = 1;
+ *(p->data[j]->value) = val;
+ }
+
+ p = p->forward;
+ }
+ }
+}
+EntryPoint __RTS_INIT__ = __rts_init;
+
+/* define the start process queue */
+typedef struct STARTENTRY
+{
+ struct STARTENTRY *forward;
+ INSTANCE whoami;
+ EntryPoint entry;
+ void *data;
+ int datalen;
+} StartEntry;
+
+static StartEntry *start_queue = 0;
+static StartEntry *current_process = 0;
+
+/* the jump buffer for the main loop */
+static jmp_buf jump_buffer;
+static int jump_buffer_initialized = 0;
+
+/* look for entries in start_queue and start the process */
+static void
+__rts_main_loop ()
+{
+ StartEntry *s;
+
+ while (1)
+ {
+ if (setjmp (jump_buffer) == 0)
+ {
+ jump_buffer_initialized = 1;
+ s = start_queue;
+ while (s)
+ {
+ current_process = s;
+ start_queue = s->forward;
+
+ /* call the process */
+ (*s->entry) (s->data);
+ s = start_queue;
+ }
+ /* when queue empty we have finished */
+ return;
+ }
+ else
+ {
+ /* stop executed */
+ if (current_process->data)
+ free (current_process->data);
+ free (current_process);
+ current_process = 0;
+ }
+ }
+}
+EntryPoint __RTS_MAIN_LOOP__ = __rts_main_loop;
+
+
+void
+__start_process (ptype, pcopy, arg_size, args, ins)
+ short ptype;
+ short pcopy;
+ int arg_size;
+ void *args;
+ INSTANCE *ins;
+{
+ TaskingStructList *p = task_array[Process];
+ EntryPoint pc = 0;
+ int i;
+ short this_copy = pcopy;
+ StartEntry *s, *wrk;
+
+ /* search for the process */
+ while (p)
+ {
+ if (*(p->data[0]->value) == ptype)
+ break;
+ p = p->forward;
+ }
+ if (!p)
+ {
+ fprintf (stderr, "Cannot find a process with type %d.\n", ptype);
+ exit (1);
+ }
+
+ /* search for the entry point */
+ for (i = 0; i < p->num; i++)
+ {
+ if (p->data[i]->entry)
+ {
+ pc = p->data[i]->entry;
+ break;
+ }
+ }
+ if (!pc)
+ {
+ fprintf (stderr, "Process \"%s\" doesn't have an entry point.\n",
+ p->data[0]->name);
+ exit (1);
+ }
+
+ /* check the copy */
+ if (pcopy >= MAX_COPIES)
+ {
+ fprintf (stderr, "Copy number (%d) out of range.\n", pcopy);
+ exit (1);
+ }
+ if (pcopy == -1)
+ {
+ /* search for a copy number */
+ this_copy = get_next_copy_number (p);
+ }
+ else
+ {
+ if (p->copies[pcopy])
+ {
+ /* FIXME: should be exception 'startfail' */
+ fprintf (stderr, "Copy number %d already in use for \"%s\".\n",
+ pcopy, p->data[0]->name);
+ exit (1);
+ }
+ p->copies[this_copy = pcopy] = 1;
+ }
+
+ /* ready to build start_queue entry */
+ s = xmalloc (sizeof (StartEntry));
+ s->forward = 0;
+ s->whoami.pcopy = this_copy;
+ s->whoami.ptype = ptype;
+ s->entry = pc;
+ s->datalen = arg_size;
+ if (args)
+ {
+ s->data = xmalloc (arg_size);
+ memcpy (s->data, args, arg_size);
+ }
+ else
+ s->data = 0;
+
+ /* queue that stuff in */
+ wrk = (StartEntry *)&start_queue;
+ while (wrk->forward)
+ wrk = wrk->forward;
+ wrk->forward = s;
+
+ /* if we have a pointer to ins -- set it */
+ if (ins)
+ {
+ ins->ptype = ptype;
+ ins->pcopy = this_copy;
+ }
+}
+
+void
+__stop_process ()
+{
+ if (!jump_buffer_initialized)
+ {
+ fprintf (stderr, "STOP called before START.\n");
+ exit (1);
+ }
+ longjmp (jump_buffer, 1);
+}
+
+
+/* function returns INSTANCE of current process */
+INSTANCE
+__whoami ()
+{
+ INSTANCE whoami;
+ if (current_process)
+ whoami = current_process->whoami;
+ else
+ {
+ whoami.ptype = 0;
+ whoami.pcopy = 0;
+ }
+ return (whoami);
+}
+
+typedef struct
+{
+ short *sc;
+ int data_len;
+ void *data;
+} SignalDescr;
+
+typedef struct SIGNALQUEUE
+{
+ struct SIGNALQUEUE *forward;
+ short sc;
+ int data_len;
+ void *data;
+ INSTANCE to;
+ INSTANCE from;
+} SignalQueue;
+
+/* define the signal queue */
+static SignalQueue *msg_queue = 0;
+
+/* send a signal */
+void
+__send_signal (s, to, prio, with_len, with)
+ SignalDescr *s;
+ INSTANCE to;
+ int prio;
+ int with_len;
+ void *with;
+{
+ SignalQueue *wrk = (SignalQueue *)&msg_queue;
+ SignalQueue *p;
+ TaskingStructList *t = task_array[Process];
+
+ /* search for process is defined and running */
+ while (t)
+ {
+ if (*(t->data[0]->value) == to.ptype)
+ break;
+ t = t->forward;
+ }
+ if (!t || !t->copies[to.pcopy])
+ {
+ fprintf (stderr, "Can't find instance [%d,%d].\n",
+ to.ptype, to.pcopy);
+ exit (1);
+ }
+
+ /* go to the end of the msg_queue */
+ while (wrk->forward)
+ wrk = wrk->forward;
+
+ p = xmalloc (sizeof (SignalQueue));
+ p->sc = *(s->sc);
+ if (p->data_len = s->data_len)
+ {
+ p->data = xmalloc (s->data_len);
+ memcpy (p->data, s->data, s->data_len);
+ }
+ else
+ p->data = 0;
+ p->to = to;
+ p->from = __whoami ();
+ p->forward = 0;
+ wrk->forward = p;
+}
+
+void
+start_signal_timeout (i, s, j)
+ int i;
+ SignalDescr *s;
+ int j;
+{
+ __send_signal (s, __whoami (), 0, 0, 0);
+}
+
+
+/* receive a signal */
+int
+__wait_signal_timed (sig_got, nsigs, sigptr, datap,
+ datalen, ins, else_branche,
+ to, filename, lineno)
+ short *sig_got;
+ int nsigs;
+ short *sigptr[];
+ void *datap;
+ int datalen;
+ INSTANCE *ins;
+ int else_branche;
+ void *to;
+ char *filename;
+ int lineno;
+{
+ INSTANCE me = __whoami ();
+ SignalQueue *wrk, *p = msg_queue;
+ int i;
+ short sc;
+
+ /* search for a signal to `me' */
+ wrk = (SignalQueue *)&msg_queue;
+
+ while (p)
+ {
+ if (p->to.ptype == me.ptype
+ && p->to.pcopy == me.pcopy)
+ break;
+ wrk = p;
+ p = p->forward;
+ }
+
+ if (!p)
+ {
+ fprintf (stderr, "No signal for [%d,%d].\n",
+ me.ptype, me.pcopy);
+ exit (1);
+ }
+
+ /* queue the message out */
+ wrk->forward = p->forward;
+
+ /* now look for signal in list */
+ for (i = 0; i < nsigs; i++)
+ if (*(sigptr[i]) == p->sc)
+ break;
+
+ if (i >= nsigs && ! else_branche)
+ /* signal not in list and no ELSE in code */
+ __cause_exception ("signalfail", __FILE__, __LINE__);
+
+ if (i >= nsigs)
+ {
+ /* signal not in list */
+ sc = p->sc;
+ if (ins)
+ *ins = p->from;
+ if (p->data)
+ free (p->data);
+ free (p);
+ *sig_got = sc;
+ return (0);
+ }
+
+ /* we have found a signal in the list */
+ if (p->data_len)
+ {
+ if (datalen >= p->data_len
+ && datap)
+ memcpy (datap, p->data, p->data_len);
+ else
+ __cause_exception ("spacefail", __FILE__, __LINE__);
+ }
+
+ sc = p->sc;
+ if (ins)
+ *ins = p->from;
+ if (p->data)
+ free (p->data);
+ free (p);
+ *sig_got = sc;
+ return (0);
+}
+
+/* wait a certain amount of seconds */
+int
+__sleep_till (abstime, reltime, fname, lineno)
+ time_t abstime;
+ int reltime;
+ char *fname;
+ int lineno;
+{
+ sleep (reltime);
+ return 0;
+}
+
+/* set up an alarm */
+static int timeout_flag = 0;
+
+static void alarm_handler ()
+{
+ timeout_flag = 1;
+}
+
+int *
+__define_timeout (howlong, filename, lineno)
+ unsigned long howlong; /* comes in millisecs */
+ char *filename;
+ int lineno;
+{
+ unsigned int prev_alarm_value;
+
+ signal (SIGALRM, alarm_handler);
+ prev_alarm_value = alarm ((unsigned int)(howlong / 1000));
+ return &timeout_flag;
+}
+
+/* wait till timeout expires */
+void
+__wait_timeout (toid, filename, lineno)
+ volatile int *toid;
+ char *filename;
+ int lineno;
+{
+ while (! *toid) ;
+ *toid = 0;
+}