diff options
Diffstat (limited to 'cmt/timebase.c')
-rw-r--r-- | cmt/timebase.c | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/cmt/timebase.c b/cmt/timebase.c new file mode 100644 index 0000000..0bb1713 --- /dev/null +++ b/cmt/timebase.c @@ -0,0 +1,322 @@ +/* timebase.c -- management of calls, time bases and heaps for moxc */ + +/***************************************************************************** +* Change Log +* Date | Change +*-----------+----------------------------------------------------------------- +* 2-Apr-91 | JDW : further changes +* 21-Mar-92 | GWL : abort recovery +* 28-Apr-03 | DM : true->TRUE +*****************************************************************************/ + + +#include "stdio.h" +#include "cext.h" +#include "userio.h" +#include "midifns.h" +#include "timebase.h" +#include "moxc.h" + + +timebase_type timebase_queue = NULL; /* waiting to run timebase queue */ +call_type callfree = NULL; /* free list */ + +private void fatal(); + + +/**************************************************************************** +* timebase_create +* Inputs: +* maxsize is the initial size of the heap +* Outputs: +* returns an initialized timebase_type +****************************************************************************/ + +timebase_type timebase_create(maxsize) + int maxsize; +{ + static char *error_msg = "Out of memory in timebase_create()"; + timebase_type base = (timebase_type) memget(sizeof(timebase_node)); + if (!base) fatal(error_msg); + base->next = NULL; + base->next_time = MAXTIME; + base->virt_base = 0L; + base->real_base = 0L; + base->rate = 256L; + base->heap_size = 0; + base->heap_max = maxsize; + base->heap = (call_type *) memget(sizeof(call_type) * maxsize); + if (!base->heap) fatal(error_msg); + return base; +} + +/**************************************************************************** +* callinsert +* Inputs: +* timebase_type base: the time base and heap +* call_type call: the call to insert in heap +* Outputs: + none +* Implementation: +* linear insertion; to be changed to heap +****************************************************************************/ + +void callinsert(base, call) + timebase_type base; + call_type call; +{ + int i; + register call_type *heap = base->heap; + + /* handle overflow -- this should never be executed if the user + * gives the right initial heap size + */ + base->heap_size++; + if (base->heap_size >= base->heap_max) { + call_type *new_heap = (call_type *) + memget((base->heap_max << 1) * sizeof(call_type)); + int i; + call_type *oldptr; + call_type *newptr; + if (!new_heap) { + gprintf(TRANS, "Out of space, can't allocate new heap\n"); + EXIT(1); + } + + oldptr = base->heap; + newptr = new_heap; + + for (i = base->heap_max; i > 0; i--) *newptr++ = *oldptr++; + memfree((char *) heap, base->heap_max * sizeof(call_type)); + base->heap = heap = new_heap; + base->heap_max = (base->heap_max << 1); + } + + /* now do the heap insert */ + i = base->heap_size; + while (i > 1) { + int parent = i >> 1; + if (heap[parent]->u.e.time < call->u.e.time || + (heap[parent]->u.e.time == call->u.e.time && + heap[parent]->u.e.priority <= call->u.e.priority)) break; + heap[i] = heap[parent]; + i = parent; + } + heap[i] = call; + + /* if next_time might change, reinsert base into queue */ + if (heap[1] == call) { + remove_base(base); + insert_base(base); + } +} + +/**************************************************************************** +* callshow +* Inputs: +* calltype call: the call to show +* Effect: +* prints a description of call +* Assumes: +* call is not null +****************************************************************************/ +void callshow(call) + call_type call; +{ + int i; + gprintf(TRANS,"address: %lx\n", (ulong)call); + gprintf(TRANS,"time: %ld\n", call->u.e.time); + gprintf(TRANS,"routine: %lx\n", (ulong)call->u.e.routine); + gprintf(TRANS,"parameters:"); + for (i = 0; i < MAX_CALL_ARGS; i++) { + gprintf(TRANS, " %d", call->u.e.p.arg[i]); + } + gprintf(TRANS, "\n"); +} + +/*************************************************************** +* fatal +* +* Input : msg: a message to be displayed +* Effect: print message and exit program +***************************************************************/ + +private void fatal(msg) + char *msg; +{ + gprintf(FATAL, msg); + EXIT(1); +} + +/*************************************************************** +* timebase_free +* +* Input : a time base +* Effect: deallocate the time base +***************************************************************/ + +void timebase_free(timebase) + timebase_type timebase; +{ + remove_base(timebase); + if (timebase->heap) { + memfree((char *) timebase->heap, + (timebase->heap_max * sizeof(call_type))); + } + memfree((char *) timebase, sizeof(timebase_node)); +} + +/*************************************************************** +* insert_base +* +* Input : a time base not in the list +* Effect: insert timebase at the appropriate spot in the list +* computes the next_time field from the top of the heap +***************************************************************/ + +void insert_base(timebase) + timebase_type timebase; +{ + register timebase_type *ptr = &timebase_queue; + register time_type next_time = MAXTIME; + /* compute next_time */ + if (timebase->heap_size != 0) { + register call_type call = timebase->heap[1]; + /* virt to real calculation */ + next_time = (virt_to_real_256(timebase, call->u.e.time) & + 0xFFFFFF00) + call->u.e.priority; +/* gprintf(TRANS, + "insert next_time is %ld, vt %ld, rb %ld, vb %ld rt %ld\n", + next_time, timebase->heap[1]->u.e.time, + timebase->real_base, timebase->virt_base, timebase->rate); + */ + } + timebase->next_time = next_time; + + if (next_time != MAXTIME) { + /* insert into the list */ + while (TRUE) { + if (! *ptr) { + *ptr = timebase; + timebase->next = NULL; + return; + } else if ((*ptr)->next_time >= next_time) { + timebase->next = *ptr; + *ptr = timebase; + return; + } else ptr = &((*ptr)->next); + } + } +} + +/*************************************************************** +* remove_base +* +* Input : timebase +* Effect: if timebase is in the queue, remove it +***************************************************************/ + +void remove_base(timebase) + timebase_type timebase; +{ + timebase_type *ptr = &timebase_queue; + while (*ptr) { + if (*ptr == timebase) { + *ptr = timebase->next; + return; + } else ptr = &((*ptr)->next); + } +} + +/*************************************************************** +* remove_call +* +* Input : a timebase -- passed as a global +* Assumes: a_timebase->heap_size > 0 +* Returns: the earliest call in the queue +* Effect: removes the earliest call in the queue +***************************************************************/ + +call_type remove_call(timebase_type a_timebase) +{ + register call_type *heap = a_timebase->heap; + call_type result = heap[1]; + register call_type large; + int i = 1; + int child = i << 1;; + large = heap[a_timebase->heap_size--]; + while (child <= a_timebase->heap_size) { + if (child + 1 <= a_timebase->heap_size) { + if (heap[child + 1]->u.e.time < heap[child]->u.e.time || + (heap[child + 1]->u.e.time == heap[child]->u.e.time && + heap[child + 1]->u.e.priority < heap[child]->u.e.priority)) + child++; + } + /* child is now the index of the least child */ + if (large->u.e.time < heap[child]->u.e.time || + (large->u.e.time == heap[child]->u.e.time && + large->u.e.priority <= heap[child]->u.e.priority)) break; + /* swap */ + heap[i] = heap[child]; + i = child; + child = i << 1; + } + heap[i] = large; + return result; +} + +/*************************************************************** +* set_rate +* +* Input : timebase and new rate +* Effect: makes the current rate of timebase be rate +***************************************************************/ + +void set_rate(base, rate) + timebase_type base; + time_type rate; +{ + if (base == timebase) base->virt_base = virttime; + else base->virt_base = real_to_virt(base, eventtime); + base->real_base = eventtime; + base->rate = rate; +/* gprintf(TRANS, "new real_base %ld virt_base %ld\n", + base->real_base, base->virt_base); + */ + remove_base(base); + insert_base(base); +} + +/*************************************************************** +* set_virttime +* +* Input : virtual time +* Effect: makes the current virtual time of timebase be vtime +***************************************************************/ + +void set_virttime(base, vtime) + timebase_type base; + time_type vtime; +{ + base->real_base = eventtime; + base->virt_base = vtime; + if (base == timebase) virttime = vtime; + remove_base(base); + insert_base(base); +} + +/*************************************************************** +* timebase_use +* +* Input : a timebase to use for scheduling +* Effect: sets up globals: timebase, virttime +***************************************************************/ + +void timebase_use(base) + register timebase_type base; +{ + if (timebase != base) { + timebase = base; + virttime = real_to_virt(base, eventtime); + } +} |