added code to handle timed semaphore singalling

This commit is contained in:
hyunghwan.chung 2016-03-22 14:18:07 +00:00
parent 00a4fd78d6
commit d6ee9e5b67
4 changed files with 439 additions and 100 deletions

View File

@ -57,13 +57,14 @@
#class Semaphore(Object)
{
#dcl count waiting_head waiting_tail heapIndex fireTime.
#dcl count waiting_head waiting_tail heapIndex fireTimeSec fireTimeNsec.
#method initialize
{
self.count := 0.
self.heapIndex := -1.
self.fireTime := 0.
self.fireTimeSec := 0.
self.fireTimeNsec := 0.
}
#method signal
@ -90,17 +91,17 @@
#method fireTime
{
^fireTime
^fireTimeSec
}
#method fireTime: anInteger
{
self.fireTime := anInteger.
self.fireTimeSec := anInteger.
}
#method youngerThan: aSemaphore
{
^self.fireTime < (aSemaphore fireTime)
^self.fireTimeSec < (aSemaphore fireTime)
}
}
@ -153,8 +154,19 @@
^top
}
#method updateAt: anIndex
#method updateAt: anIndex with: aSemaphore
{
| item |
item := self.arr at: anIndex.
item heapIndex: -1.
self.arr at: anIndex put: aSemaphore.
aSemaphore heapIndex: anIndex.
^(aSemaphore youngerThan: item)
ifTrue: [ self siftUp: anIndex ]
ifFalse: [ self siftDown: anIndex ].
}
#method deleteAt: anIndex
@ -333,6 +345,13 @@
#method signal: aSemaphore after: anInteger
{
self.sem_heap add: aSemaphore withTimeout: anInteger.
<primitive: #_processor_add_timed_semaphore>
self primitiveFailed.
}
#method signal: aSemaphore after: aSecond and: aNanoSecond
{
<primitive: #_processor_add_timed_semaphore>
self primitiveFailed.
}
}

View File

@ -26,12 +26,29 @@
#include "stix-prv.h"
/* TODO: remove this header after having changed clock_gettime() to a
* platform independent function */
#include <time.h>
#define PROCESS_STATE_RUNNING 3
#define PROCESS_STATE_WAITING 2
#define PROCESS_STATE_RUNNABLE 1
#define PROCESS_STATE_SUSPENDED 0
#define PROCESS_STATE_TERMINATED -1
#define PROC_STATE_RUNNING 3
#define PROC_STATE_WAITING 2
#define PROC_STATE_RUNNABLE 1
#define PROC_STATE_SUSPENDED 0
#define PROC_STATE_TERMINATED -1
#define SEM_LIST_INC 256
#define SEM_HEAP_INC 256
#define SEM_LIST_MAX (SEM_LIST_INC * 1000)
#define SEM_HEAP_MAX (SEM_HEAP_INC * 1000)
#define SEM_HEAP_PARENT(x) (((x) - 1) / 2)
#define SEM_HEAP_LEFT(x) ((x) * 2 + 1)
#define SEM_HEAP_RIGHT(x) ((x) * 2 + 2)
#define SEM_HEAP_EARLIER_THAN(stx,x,y) ( \
(STIX_OOP_TO_SMOOI((x)->heap_ftime_sec) < STIX_OOP_TO_SMOOI((y)->heap_ftime_sec)) || \
(STIX_OOP_TO_SMOOI((x)->heap_ftime_sec) == STIX_OOP_TO_SMOOI((y)->heap_ftime_sec) && STIX_OOP_TO_SMOOI((x)->heap_ftime_nsec) < STIX_OOP_TO_SMOOI((y)->heap_ftime_nsec)) \
)
#if defined(USE_DYNCALL)
/* TODO: defined dcAllocMem and dcFreeMeme before builing the dynload and dyncall library */
@ -149,7 +166,7 @@ static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c)
stix_poptmp (stix);
if (!proc) return STIX_NULL;
proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED);
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED);
proc->initial_context = c;
proc->current_context = c;
proc->sp = STIX_SMOOI_TO_OOP(-1);
@ -166,8 +183,8 @@ static void switch_to_process (stix_t* stix, stix_oop_process_t proc, int new_st
STIX_ASSERT (stix->processor->active != proc);
/* the new process must be in the runnable state */
STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE) ||
proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_WAITING));
STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE) ||
proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_WAITING));
#if defined(STIX_DEBUG_PROCESSOR)
printf ("ACTUAL PROCESS SWITCHING BF...%d %p\n", (int)stix->ip, stix->active_context);
@ -183,11 +200,11 @@ printf ("ACTUAL PROCESS SWITCHING BF...%d %p\n", (int)stix->ip, stix->active_con
* it is the suspended context of the process to be suspended */
STIX_ASSERT ((stix_oop_t)stix->processor->active != stix->_nil);
stix->processor->active->current_context = stix->active_context;
/*stix->processor->active->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE);*/
/*stix->processor->active->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE);*/
stix->processor->active->state = STIX_SMOOI_TO_OOP(new_state_for_old_active);
/* activate the given process */
proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING);
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING);
stix->processor->active = proc;
#if defined(STIX_USE_PROCSTK)
@ -209,7 +226,7 @@ printf ("ACTUAL PROCESS SWITCHING AF...%d %p\n", (int)stix->ip, stix->active_con
static STIX_INLINE stix_oop_process_t find_next_runnable_process (stix_t* stix)
{
stix_oop_process_t npr;
STIX_ASSERT (stix->processor->active->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING));
STIX_ASSERT (stix->processor->active->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING));
npr = stix->processor->active->next;
if ((stix_oop_t)npr == stix->_nil) npr = stix->processor->runnable_head;
return npr;
@ -220,7 +237,7 @@ static STIX_INLINE void switch_to_next_runnable_process (stix_t* stix)
stix_oop_process_t nrp;
nrp = find_next_runnable_process (stix);
if (nrp != stix->processor->active) switch_to_process (stix, nrp, PROCESS_STATE_RUNNABLE);
if (nrp != stix->processor->active) switch_to_process (stix, nrp, PROC_STATE_RUNNABLE);
}
static STIX_INLINE int chain_into_processor (stix_t* stix, stix_oop_process_t proc)
@ -232,7 +249,7 @@ static STIX_INLINE int chain_into_processor (stix_t* stix, stix_oop_process_t pr
STIX_ASSERT ((stix_oop_t)proc->prev == stix->_nil);
STIX_ASSERT ((stix_oop_t)proc->next == stix->_nil);
STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED));
STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED));
tally = STIX_OOP_TO_SMOOI(stix->processor->tally);
@ -271,8 +288,8 @@ static STIX_INLINE void unchain_from_processor (stix_t* stix, stix_oop_process_t
{
stix_ooi_t tally;
STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING) ||
proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE));
STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING) ||
proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
tally = STIX_OOP_TO_SMOOI(stix->processor->tally);
STIX_ASSERT (tally > 0);
@ -327,12 +344,14 @@ static STIX_INLINE void unchain_from_semaphore (stix_t* stix, stix_oop_process_t
proc->prev = (stix_oop_process_t)stix->_nil;
proc->next = (stix_oop_process_t)stix->_nil;
proc->sem = (stix_oop_semaphore_t)stix->_nil;
}
static void terminate_process (stix_t* stix, stix_oop_process_t proc)
{
if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING) ||
proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE))
if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING) ||
proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE))
{
/* RUNNING/RUNNABLE ---> TERMINATED */
if (proc == stix->processor->active)
@ -342,7 +361,7 @@ static void terminate_process (stix_t* stix, stix_oop_process_t proc)
nrp = find_next_runnable_process (stix);
unchain_from_processor (stix, proc);
proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_TERMINATED);
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_TERMINATED);
proc->sp = STIX_SMOOI_TO_OOP(-1); /* invalidate the process stack */
proc->current_context = proc->initial_context; /* not needed but just in case */
@ -357,20 +376,20 @@ static void terminate_process (stix_t* stix, stix_oop_process_t proc)
}
else
{
switch_to_process (stix, nrp, PROCESS_STATE_TERMINATED);
switch_to_process (stix, nrp, PROC_STATE_TERMINATED);
}
}
else
{
unchain_from_processor (stix, proc);
proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_TERMINATED);
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_TERMINATED);
proc->sp = STIX_SMOOI_TO_OOP(-1); /* invalidate the process stack */
}
}
else if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED))
else if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED))
{
/* SUSPENDED ---> TERMINATED */
proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_TERMINATED);
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_TERMINATED);
proc->sp = STIX_SMOOI_TO_OOP(-1); /* invalidate the proce stack */
if ((stix_oop_t)proc->sem != stix->_nil)
@ -378,7 +397,7 @@ static void terminate_process (stix_t* stix, stix_oop_process_t proc)
unchain_from_semaphore (stix, proc);
}
}
else if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_WAITING))
else if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_WAITING))
{
/* WAITING ---> TERMINATED */
/* TODO: */
@ -388,35 +407,36 @@ static void terminate_process (stix_t* stix, stix_oop_process_t proc)
static void resume_process (stix_t* stix, stix_oop_process_t proc)
{
printf ("TO RESUME PROCESS = %p %d\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state));
if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED))
if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED))
{
/* SUSPENED ---> RUNNING */
printf ("TO RESUME PROCESS = %p %d SUSPENED ----> RUNNING\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state));
STIX_ASSERT ((stix_oop_t)proc->prev == stix->_nil);
STIX_ASSERT ((stix_oop_t)proc->next == stix->_nil);
chain_into_processor (stix, proc); /* TODO: error check */
/*proc->current_context = proc->initial_context;*/
proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE);
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE);
/*switch_to_process (stix, proc);*/
}
#if 0
else if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE))
else if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE))
{
/* RUNNABLE ---> RUNNING */
/* TODO: should i allow this? */
STIX_ASSERT (stix->processor->active != proc);
switch_to_process (stix, proc, PROCESS_STATE_RUNNABLE);
switch_to_process (stix, proc, PROC_STATE_RUNNABLE);
}
#endif
}
static void suspend_process (stix_t* stix, stix_oop_process_t proc)
{
if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING) ||
proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNABLE))
if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING) ||
proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE))
{
/* RUNNING/RUNNABLE ---> SUSPENDED */
@ -434,25 +454,25 @@ printf ("TO SUSPEND...%p %d\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state));
STIX_ASSERT (stix->processor->active == stix->nil_process);
printf ("NO RUNNABLE PROCESS AFTER SUPSENDISION\n");
proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED);
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED);
proc->current_context = stix->active_context;
}
else
{
switch_to_process (stix, nrp, PROCESS_STATE_SUSPENDED);
switch_to_process (stix, nrp, PROC_STATE_SUSPENDED);
}
}
else
{
unchain_from_processor (stix, proc);
proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_SUSPENDED);
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED);
}
}
}
static void yield_process (stix_t* stix, stix_oop_process_t proc)
{
if (proc->state == STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING))
if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING))
{
/* RUNNING --> RUNNABLE */
@ -465,19 +485,25 @@ static void yield_process (stix_t* stix, stix_oop_process_t proc)
* runnable process must be different from proc */
if (nrp != proc)
{
switch_to_process (stix, nrp, PROCESS_STATE_RUNNABLE);
switch_to_process (stix, nrp, PROC_STATE_RUNNABLE);
}
}
}
static int async_signal_semaphore (stix_t* stix, stix_oop_semaphore_t sem)
{
if (stix->sem_list_count >= SEM_LIST_MAX)
{
stix->errnum = STIX_ESLFULL;
return -1;
}
if (stix->sem_list_count >= stix->sem_list_capa)
{
stix_oow_t new_capa;
stix_oop_semaphore_t* tmp;
new_capa = stix->sem_list_capa * 2; /* TODO: overflow check.. */
new_capa = stix->sem_list_capa + SEM_LIST_INC; /* TODO: overflow check.. */
tmp = stix_reallocmem (stix, stix->sem_list, STIX_SIZEOF(stix_oop_semaphore_t) * new_capa);
if (!tmp) return -1;
@ -541,6 +567,152 @@ printf (">>>>>>>>>>>>>> AWAIT SEMAPHORE - SUEPENDING ACTIVE PROCESS.............
}
}
static void sift_up_sem_heap (stix_t* stix, stix_ooi_t index)
{
if (index > 0)
{
stix_ooi_t parent;
stix_oop_semaphore_t sem, parsem;
parent = SEM_HEAP_PARENT(index);
sem = stix->sem_heap[index];
parsem = stix->sem_heap[parent];
if (SEM_HEAP_EARLIER_THAN(stix, sem, parsem))
{
do
{
/* move down the parent to the current position */
parsem->heap_index = STIX_SMOOI_TO_OOP(index);
stix->sem_heap[index] = parsem;
/* traverse up */
index = parent;
if (index <= 0) break;
parent = SEM_HEAP_PARENT(parent);
parsem = stix->sem_heap[parent];
}
while (SEM_HEAP_EARLIER_THAN(stix, sem, parsem));
sem->heap_index = STIX_SMOOI_TO_OOP(index);
stix->sem_heap[index] = sem;
}
}
}
static void sift_down_sem_heap (stix_t* stix, stix_ooi_t index)
{
stix_ooi_t base = stix->sem_heap_count / 2;
if (index < base) /* at least 1 child is under the 'index' position */
{
stix_ooi_t left, right, child;
stix_oop_semaphore_t sem, chisem;
sem = stix->sem_heap[index];
do
{
left = SEM_HEAP_LEFT(index);
right = SEM_HEAP_RIGHT(index);
if (right < stix->sem_heap_count && SEM_HEAP_EARLIER_THAN(stix, stix->sem_heap[left], stix->sem_heap[right]))
{
child = right;
}
else
{
child = left;
}
chisem = stix->sem_heap[child];
if (SEM_HEAP_EARLIER_THAN(stix, sem, chisem)) break;
chisem->heap_index = STIX_SMOOI_TO_OOP(index);
stix->sem_heap[index ] = chisem;
index = child;
}
while (index < base);
sem->heap_index = STIX_SMOOI_TO_OOP(index);
stix->sem_heap[index] = sem;
}
}
static int add_to_sem_heap (stix_t* stix, stix_oop_semaphore_t sem)
{
stix_ooi_t index;
if (stix->sem_heap_count >= SEM_HEAP_MAX)
{
stix->errnum = STIX_ESHFULL;
return -1;
}
if (stix->sem_heap_count >= stix->sem_heap_capa)
{
stix_oow_t new_capa;
stix_oop_semaphore_t* tmp;
/* no overflow check when calculating the new capacity
* owing to SEM_HEAP_MAX check above */
new_capa = stix->sem_heap_capa + SEM_HEAP_INC;
tmp = stix_reallocmem (stix, stix->sem_heap, STIX_SIZEOF(stix_oop_semaphore_t) * new_capa);
if (!tmp) return -1;
stix->sem_heap = tmp;
stix->sem_heap_capa = new_capa;
}
STIX_ASSERT (stix->sem_heap_count <= STIX_SMOOI_MAX);
index = stix->sem_heap_count;
stix->sem_heap[index] = sem;
sem->heap_index = STIX_SMOOI_TO_OOP(index);
stix->sem_heap_count++;
sift_up_sem_heap (stix, index);
return 0;
}
static void delete_from_sem_heap (stix_t* stix, stix_ooi_t index)
{
stix_oop_semaphore_t sem, lastsem;
sem = stix->sem_heap[index];
sem->heap_index = STIX_SMOOI_TO_OOP(-1);
stix->sem_heap_count--;
if (stix->sem_heap_count > 0 && index != stix->sem_heap_count)
{
/* move the last item to the deletion position */
lastsem = stix->sem_heap[stix->sem_heap_count];
lastsem->heap_index = STIX_SMOOI_TO_OOP(index);
stix->sem_heap[index] = lastsem;
if (SEM_HEAP_EARLIER_THAN(stix, lastsem, sem))
sift_up_sem_heap (stix, index);
else
sift_down_sem_heap (stix, index);
}
}
static void update_sem_heap (stix_t* stix, stix_ooi_t index, stix_oop_semaphore_t newsem)
{
stix_oop_semaphore_t sem;
sem = stix->sem_heap[index];
sem->heap_index = STIX_SMOOI_TO_OOP(-1);
newsem->heap_index = STIX_SMOOI_TO_OOP(index);
stix->sem_heap[index] = newsem;
if (SEM_HEAP_EARLIER_THAN(stix, newsem, sem))
sift_up_sem_heap (stix, index);
else
sift_down_sem_heap (stix, index);
}
static stix_oop_process_t start_initial_process (stix_t* stix, stix_oop_context_t c)
{
stix_oop_process_t proc;
@ -553,7 +725,7 @@ static stix_oop_process_t start_initial_process (stix_t* stix, stix_oop_context_
if (!proc) return STIX_NULL;
if (chain_into_processor (stix, proc) <= -1) return STIX_NULL;
proc->state = STIX_SMOOI_TO_OOP(PROCESS_STATE_RUNNING); /* skip RUNNABLE and go to RUNNING */
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNING); /* skip RUNNABLE and go to RUNNING */
stix->processor->active = proc;
/* do somthing that resume_process() would do with less overhead */
@ -1478,6 +1650,101 @@ static int prim_processor_sleep (stix_t* stix, stix_ooi_t nargs)
return 0;
}
static int prim_processor_add_timed_semaphore (stix_t* stix, stix_ooi_t nargs)
{
stix_oop_t rcv, sec, nsec;
stix_oop_semaphore_t sem;
struct timespec ts, ft;
STIX_ASSERT (nargs >= 2 || nargs <= 3);
if (nargs == 3)
{
nsec = ACTIVE_STACK_GET (stix, stix->sp);
if (!STIX_OOP_IS_SMOOI(nsec)) return 0;
}
else nsec = STIX_SMOOI_TO_OOP(0);
sec = ACTIVE_STACK_GET(stix, stix->sp - nargs + 2);
sem = (stix_oop_semaphore_t)ACTIVE_STACK_GET(stix, stix->sp - nargs + 1);
rcv = ACTIVE_STACK_GET(stix, stix->sp - nargs);
if (rcv != (stix_oop_t)stix->processor) return 0;
if (STIX_CLASSOF(stix,sem) != stix->_semaphore) return 0;
if (!STIX_OOP_IS_SMOOI(sec)) return 0;
if (STIX_OOP_IS_SMOOI(sem->heap_index) &&
sem->heap_index != STIX_SMOOI_TO_OOP(-1))
{
delete_from_sem_heap (stix, STIX_OOP_TO_SMOOI(sem->heap_index));
STIX_ASSERT(sem->heap_index == STIX_SMOOI_TO_OOP(-1));
/*
Is this more desired???
ACTIVE_STACK_POPS (stix, nargs);
ACTIVE_STACK_SETTOP (stix, stix->_false);
return 1;
*/
}
/* TODO: make clock_gettime to be platform independent
*
* this code assumes that the monotonic clock returns a small value
* that can fit into a small integer, even after some addtions... */
if (clock_gettime (CLOCK_MONOTONIC, &ts) == -1)
{
/* TODO: soft error handling */
printf ("clock_gettime() failure....\n");
return 0;
}
ft.tv_nsec = ts.tv_nsec + STIX_OOP_TO_SMOOI(nsec);
ft.tv_sec = ts.tv_sec + STIX_OOP_TO_SMOOI(sec);
while (ft.tv_nsec >= 1000000000)
{
ft.tv_sec++;
ft.tv_nsec -= 1000000000;
}
if (ft.tv_sec < 0 || ft.tv_sec > STIX_SMOOI_MAX)
{
/* soft error - cannot represent the expiry time in
* a small integer. */
return 0;
}
sem->heap_ftime_sec = STIX_SMOOI_TO_OOP(ft.tv_sec);
sem->heap_ftime_nsec = STIX_SMOOI_TO_OOP(ft.tv_nsec);
if (add_to_sem_heap (stix, sem) <= -1) return -1;
ACTIVE_STACK_POPS (stix, nargs);
return 1;
}
static int prim_processor_del_time_semaphore (stix_t* stix, stix_ooi_t nargs)
{
stix_oop_t rcv;
stix_oop_semaphore_t sem;
STIX_ASSERT (nargs == 1);
sem = (stix_oop_semaphore_t)ACTIVE_STACK_GET(stix, stix->sp - 1);
rcv = ACTIVE_STACK_GET(stix, stix->sp);
if (rcv != (stix_oop_t)stix->processor) return 0;
if (STIX_CLASSOF(stix,sem) != stix->_semaphore) return 0;
if (STIX_OOP_IS_SMOOI(sem->heap_index) &&
sem->heap_index != STIX_SMOOI_TO_OOP(-1))
{
delete_from_sem_heap (stix, STIX_OOP_TO_SMOOI(sem));
STIX_ASSERT(sem->heap_index == STIX_SMOOI_TO_OOP(-1));
}
return 1;
}
static int prim_integer_add (stix_t* stix, stix_ooi_t nargs)
{
stix_oop_t rcv, arg, res;
@ -2123,10 +2390,11 @@ printf ("wrong function name...\n");
return 1;
}
#define MAX_NARGS STIX_TYPE_MAX(stix_ooi_t)
struct prim_t
{
stix_ooi_t nargs; /* expected number of arguments */
stix_ooi_t min_nargs; /* expected number of arguments */
stix_ooi_t max_nargs; /* expected number of arguments */
stix_prim_impl_t handler;
const char* name; /* the name is supposed to be 7-bit ascii only */
};
@ -2134,62 +2402,64 @@ typedef struct prim_t prim_t;
static prim_t primitives[] =
{
{ -1, prim_dump, "_dump" },
{ 1, prim_identical, "_identical" },
{ 1, prim_not_identical, "_not_identical" },
{ 0, prim_class, "_class" },
{ 0, MAX_NARGS, prim_dump, "_dump" },
{ 0, prim_basic_new, "_basic_new" },
{ 1, prim_basic_new_with_size, "_basic_new_with_size" },
{ 0, prim_ngc_new, "_ngc_new" },
{ 1, prim_ngc_new_with_size, "_ngc_new_with_size" },
{ 0, prim_ngc_dispose, "_ngc_dispose" },
{ 0, prim_shallow_copy, "_shallow_copy" },
{ 1, 1, prim_identical, "_identical" },
{ 1, 1, prim_not_identical, "_not_identical" },
{ 0, 0, prim_class, "_class" },
{ 0, prim_basic_size, "_basic_size" },
{ 1, prim_basic_at, "_basic_at" },
{ 2, prim_basic_at_put, "_basic_at_put" },
{ 0, 0, prim_basic_new, "_basic_new" },
{ 1, 1, prim_basic_new_with_size, "_basic_new_with_size" },
{ 0, 0, prim_ngc_new, "_ngc_new" },
{ 1, 1, prim_ngc_new_with_size, "_ngc_new_with_size" },
{ 0, 0, prim_ngc_dispose, "_ngc_dispose" },
{ 0, 0, prim_shallow_copy, "_shallow_copy" },
{ 0, 0, prim_basic_size, "_basic_size" },
{ 1, 1, prim_basic_at, "_basic_at" },
{ 2, 2, prim_basic_at_put, "_basic_at_put" },
{ -1, prim_block_value, "_block_value" },
{ -1, prim_block_new_process, "_block_new_process" },
{ 0, MAX_NARGS, prim_block_value, "_block_value" },
{ 0, MAX_NARGS, prim_block_new_process, "_block_new_process" },
{ 0, prim_process_resume, "_process_resume" },
{ 0, prim_process_terminate, "_process_terminate" },
{ 0, prim_process_yield, "_process_yield" },
{ 0, prim_semaphore_signal, "_semaphore_signal" },
{ 0, prim_semaphore_wait, "_semaphore_wait" },
{ 0, 0, prim_process_resume, "_process_resume" },
{ 0, 0, prim_process_terminate, "_process_terminate" },
{ 0, 0, prim_process_yield, "_process_yield" },
{ 0, 0, prim_semaphore_signal, "_semaphore_signal" },
{ 0, 0, prim_semaphore_wait, "_semaphore_wait" },
{ 1, prim_processor_schedule, "_processor_schedule" },
{ 1, prim_processor_remove, "_processor_remove" },
{ 1, prim_processor_sleep, "_processor_sleep" },
{ 1, 1, prim_processor_schedule, "_processor_schedule" },
{ 1, 1, prim_processor_remove, "_processor_remove" },
{ 1, 1, prim_processor_sleep, "_processor_sleep" },
{ 2, 3, prim_processor_add_timed_semaphore, "_processor_add_timed_semaphore" },
{ 1, prim_integer_add, "_integer_add" },
{ 1, prim_integer_sub, "_integer_sub" },
{ 1, prim_integer_mul, "_integer_mul" },
{ 1, prim_integer_quo, "_integer_quo" },
{ 1, prim_integer_rem, "_integer_rem" },
{ 1, prim_integer_quo2, "_integer_quo2" },
{ 1, prim_integer_rem2, "_integer_rem2" },
{ 0, prim_integer_negated, "_integer_negated" },
{ 1, prim_integer_bitat, "_integer_bitat" },
{ 1, prim_integer_bitand, "_integer_bitand" },
{ 1, prim_integer_bitor, "_integer_bitor" },
{ 1, prim_integer_bitxor, "_integer_bitxor" },
{ 0, prim_integer_bitinv, "_integer_bitinv" },
{ 1, prim_integer_bitshift, "_integer_bitshift" },
{ 1, prim_integer_eq, "_integer_eq" },
{ 1, prim_integer_ne, "_integer_ne" },
{ 1, prim_integer_lt, "_integer_lt" },
{ 1, prim_integer_gt, "_integer_gt" },
{ 1, prim_integer_le, "_integer_le" },
{ 1, prim_integer_ge, "_integer_ge" },
{ 1, prim_integer_inttostr, "_integer_inttostr" },
{ 1, 1, prim_integer_add, "_integer_add" },
{ 1, 1, prim_integer_sub, "_integer_sub" },
{ 1, 1, prim_integer_mul, "_integer_mul" },
{ 1, 1, prim_integer_quo, "_integer_quo" },
{ 1, 1, prim_integer_rem, "_integer_rem" },
{ 1, 1, prim_integer_quo2, "_integer_quo2" },
{ 1, 1, prim_integer_rem2, "_integer_rem2" },
{ 0, 0, prim_integer_negated, "_integer_negated" },
{ 1, 1, prim_integer_bitat, "_integer_bitat" },
{ 1, 1, prim_integer_bitand, "_integer_bitand" },
{ 1, 1, prim_integer_bitor, "_integer_bitor" },
{ 1, 1, prim_integer_bitxor, "_integer_bitxor" },
{ 0, 0, prim_integer_bitinv, "_integer_bitinv" },
{ 1, 1, prim_integer_bitshift, "_integer_bitshift" },
{ 1, 1, prim_integer_eq, "_integer_eq" },
{ 1, 1, prim_integer_ne, "_integer_ne" },
{ 1, 1, prim_integer_lt, "_integer_lt" },
{ 1, 1, prim_integer_gt, "_integer_gt" },
{ 1, 1, prim_integer_le, "_integer_le" },
{ 1, 1, prim_integer_ge, "_integer_ge" },
{ 1, 1, prim_integer_inttostr, "_integer_inttostr" },
{ 1, prim_ffi_open, "_ffi_open" },
{ 1, prim_ffi_close, "_ffi_close" },
{ 2, prim_ffi_getsym, "_ffi_getsym" },
{ 3, prim_ffi_call, "_ffi_call" }
{ 1, 1, prim_ffi_open, "_ffi_open" },
{ 1, 1, prim_ffi_close, "_ffi_close" },
{ 2, 2, prim_ffi_getsym, "_ffi_getsym" },
{ 3, 3, prim_ffi_call, "_ffi_call" }
};
@ -2478,7 +2748,7 @@ printf ("]\n");
DBGOUT_EXEC_1 ("METHOD_PREAMBLE_PRIMITIVE %d", (int)prim_no);
if (prim_no >= 0 && prim_no < STIX_COUNTOF(primitives) &&
(primitives[prim_no].nargs < 0 || primitives[prim_no].nargs == nargs))
(nargs >= primitives[prim_no].min_nargs && nargs <= primitives[prim_no].max_nargs))
{
int n;
@ -2568,8 +2838,43 @@ int stix_execute (stix_t* stix)
/* no more process in the system */
STIX_ASSERT (stix->processor->tally = STIX_SMOOI_TO_OOP(0));
printf ("NO MORE RUNNABLE PROCESS...\n");
if (stix->sem_heap_count > 0)
{
struct timespec now, ft;
clock_gettime (CLOCK_MONOTONIC, &now);
do
{
STIX_ASSERT (STIX_OOP_IS_SMOOI(stix->sem_heap[0]->heap_ftime_sec));
STIX_ASSERT (STIX_OOP_IS_SMOOI(stix->sem_heap[0]->heap_ftime_nsec));
ft.tv_sec = STIX_OOP_TO_SMOOI(stix->sem_heap[0]->heap_ftime_sec);
ft.tv_nsec = STIX_OOP_TO_SMOOI(stix->sem_heap[0]->heap_ftime_nsec);
if (ft.tv_sec < now.tv_sec || (ft.tv_sec == now.tv_sec && ft.tv_nsec <= now.tv_nsec))
{
signal_semaphore (stix, stix->sem_heap[0]);
delete_from_sem_heap (stix, 0);
}
else
{
/* THIS PART IS JUST EXPERIMENTAL... PROPER WAITING WITH IO MULTIPLEXER IS NEEDED ... */
sleep (ft.tv_sec - now.tv_sec);
signal_semaphore (stix, stix->sem_heap[0]);
delete_from_sem_heap (stix, 0);
goto carry_on_switching;
}
}
while (stix->sem_heap_count > 0);
}
break;
}
carry_on_switching:
/*
else if (stix->processor->active == stix->idle_process)
{
@ -2579,9 +2884,15 @@ IDLEING WAITING FOR PROCESS WAKE-UP...
while (stix->sem_list_count > 0)
{
/* handle async signals */
--stix->sem_list_count;
signal_semaphore (stix, stix->sem_list[stix->sem_list_count]);
}
/*
if (semaphore heap has pending request)
{
signal them...
}*/
/* TODO: implement different process switching scheme - time-slice or clock based??? */
if (!stix->proc_switched) { switch_to_next_runnable_process (stix); }

View File

@ -341,7 +341,12 @@ printf ("STARTING GC curheap base %p ptr %p newheap base %p ptr %p\n",
for (i = 0; i < stix->sem_list_count; i++)
{
stix->sem_list[i] = stix_moveoop (stix, stix->sem_list[i]);
stix->sem_list[i] = (stix_oop_semaphore_t)stix_moveoop (stix, stix->sem_list[i]);
}
for (i = 0; i < stix->sem_heap_count; i++)
{
stix->sem_heap[i] = (stix_oop_semaphore_t)stix_moveoop (stix, stix->sem_heap[i]);
}
for (i = 0; i < stix->tmp_count; i++)

View File

@ -52,6 +52,8 @@ enum stix_errnum_t
STIX_ENOENT, /**< no matching entry */
STIX_EDFULL, /**< dictionary full */
STIX_EPFULL, /**< processor full */
STIX_ESHFULL, /**< semaphore heap full */
STIX_ESLFULL, /**< semaphore list full */
STIX_EDIVBY0, /**< divide by zero */
STIX_EIOERR, /**< I/O error */
STIX_EECERR, /**< encoding conversion error */
@ -544,7 +546,7 @@ struct stix_context_t
typedef struct stix_process_t stix_process_t;
typedef struct stix_process_t* stix_oop_process_t;
#define STIX_SEMAPHORE_NAMED_INSTVARS 5
#define STIX_SEMAPHORE_NAMED_INSTVARS 6
typedef struct stix_semaphore_t stix_semaphore_t;
typedef struct stix_semaphore_t* stix_oop_semaphore_t;
@ -572,8 +574,9 @@ struct stix_semaphore_t
stix_oop_t count; /* SmallInteger */
stix_oop_process_t waiting_head;
stix_oop_process_t waiting_tail;
stix_oop_t sempq_index;
stix_oop_t sempq_firing_time;
stix_oop_t heap_index; /* index to the heap */
stix_oop_t heap_ftime_sec; /* firing time */
stix_oop_t heap_ftime_nsec; /* firing time */
};
#define STIX_PROCESS_SCHEDULER_NAMED_INSTVARS 5
@ -775,11 +778,12 @@ struct stix_t
stix_oop_process_scheduler_t processor; /* instance of ProcessScheduler */
stix_oop_process_t nil_process; /* instance of Process */
/* pending asynchronous semaphores */
stix_oop_semaphore_t* sem_list;
stix_oow_t sem_list_count;
stix_oow_t sem_list_capa;
/* semaphores sorted according to expiry */
/* semaphores sorted according to time-out */
stix_oop_semaphore_t* sem_heap;
stix_oow_t sem_heap_count;
stix_oow_t sem_heap_capa;