diff options
Diffstat (limited to 'libchill/rts.c')
-rw-r--r-- | libchill/rts.c | 655 |
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; +} |