added simple time calculation types/functiosn/macros.

fixed a bug in timed semaphore signalling
This commit is contained in:
hyunghwan.chung 2016-03-24 14:58:47 +00:00
parent 63ce721147
commit 6487143a59
3 changed files with 201 additions and 102 deletions

View File

@ -53,6 +53,15 @@
{
^sp.
}
#method sleep: seconds
{
| s |
s := Semaphore new.
Processor signal: s after: seconds.
## Processor activeProcess dump.
s wait.
}
}
#class Semaphore(Object)
@ -67,6 +76,8 @@
self.fireTimeNsec := 0.
}
## ==================================================================
#method signal
{
<primitive: #_semaphore_signal>
@ -79,6 +90,20 @@
self primitiveFailed.
}
#method waitWithTimeout: seconds
{
<primitive: #_semaphore_wait>
self primitiveFailed
}
#method waitWithTimeout: seconds and: nanoSeconds
{
<primitive: #_semaphore_wait>
self primitiveFailed
}
## ==================================================================
#method heapIndex
{
^heapIndex
@ -302,12 +327,6 @@
^self.active.
}
#method sleep: anInteger
{
<primitive: #_processor_sleep>
self primitiveFailed.
}
#method resume: aProcess
{
<primitive: #_processor_schedule>
@ -329,12 +348,6 @@
"
}
#method remove: aProcess
{
"<primitive: #_processor_remove>"
"TODO: "
}
"
#method yield
{
@ -354,4 +367,17 @@
<primitive: #_processor_add_timed_semaphore>
self primitiveFailed.
}
#method unsignal: aSemaphore
{
<primitive: #_processor_remove_semaphore>
self primitiveFailed.
}
"#method signal: aSemaphore onInput: file
{
}"
"#method signal: aSemaphore onOutput: file
{
}"
}

View File

@ -157,6 +157,21 @@
#endif
static STIX_INLINE void vm_gettime (stix_ntime_t* now)
{
struct timespec ts;
clock_gettime (CLOCK_MONOTONIC, &ts);
STIX_INITNTIME(now, ts.tv_sec, ts.tv_nsec);
}
static STIX_INLINE void vm_sleep (const stix_ntime_t* dur)
{
struct timespec ts;
ts.tv_sec = dur->sec;
ts.tv_nsec = dur->nsec;
nanosleep (&ts, STIX_NULL);
}
static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c)
{
stix_oop_process_t proc;
@ -415,12 +430,11 @@ 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(PROC_STATE_SUSPENDED))
{
/* SUSPENED ---> RUNNING */
printf ("TO RESUME PROCESS = %p %d SUSPENED ----> RUNNING\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state));
//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);
@ -429,7 +443,7 @@ printf ("TO RESUME PROCESS = %p %d SUSPENED ----> RUNNING\n", proc, (int)STIX_OO
/*proc->current_context = proc->initial_context;*/
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE);
/*switch_to_process (stix, proc);*/
/* don't switch to this process. just set the state to RUNNING */
}
#if 0
else if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE))
@ -455,11 +469,11 @@ static void suspend_process (stix_t* stix, stix_oop_process_t proc)
nrp = find_next_runnable_process (stix);
printf ("TO SUSPEND...%p %d\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state));
//printf ("TO SUSPEND...%p %d\n", proc, (int)STIX_OOP_TO_SMOOI(proc->state));
if (nrp == proc)
{
/* no runnable process after suspension */
printf ("NO RUNNABLE PROCESS AFTER SUPSENDISION\n");
//printf ("NO RUNNABLE PROCESS AFTER SUPSENDISION\n");
sleep_active_process (stix, PROC_STATE_RUNNABLE);
unchain_from_processor (stix, proc, PROC_STATE_SUSPENDED);
@ -470,7 +484,7 @@ printf ("NO RUNNABLE PROCESS AFTER SUPSENDISION\n");
}
else
{
printf ("SWITCHING TO XXXXXXXXXXXXXXXXXXXXx\n");
//printf ("SWITCHING TO XXXXXXXXXXXXXXXXXXXXx\n");
/* keep the unchained process at the runnable state for
* the immediate call to switch_to_process() below */
unchain_from_processor (stix, proc, PROC_STATE_RUNNABLE);
@ -535,25 +549,34 @@ static int async_signal_semaphore (stix_t* stix, stix_oop_semaphore_t sem)
return 0;
}
static void signal_semaphore (stix_t* stix, stix_oop_semaphore_t sem)
static stix_oop_process_t signal_semaphore (stix_t* stix, stix_oop_semaphore_t sem)
{
stix_oop_process_t proc;
stix_ooi_t count;
if ((stix_oop_t)sem->waiting_head == stix->_nil)
{
printf ("signal semaphore...1111\n");
//printf ("signal semaphore...1111\n");
/* no process is waiting on this semaphore */
count = STIX_OOP_TO_SMOOI(sem->count);
count++;
sem->count = STIX_SMOOI_TO_OOP(count);
/* no process has been resumed */
return stix->_nil;
}
else
{
printf ("signal semaphore...2222\n");
proc = sem->waiting_head;
/* [NOTE] no GC must occur as 'proc' isn't protected with stix_pushtmp(). */
unchain_from_semaphore (stix, proc);
resume_process (stix, proc); /* TODO: error check */
//printf ("signal semaphore...2222 DONE -> resumed process -> proc state %d\n", (int)STIX_OOP_TO_SMOOI(proc->state));
/* return the resumed process */
return proc;
}
}
@ -568,20 +591,23 @@ static void await_semaphore (stix_t* stix, stix_oop_semaphore_t sem)
/* it's already signalled */
count--;
sem->count = STIX_SMOOI_TO_OOP(count);
printf (">>>>>>>>>>>>>> AWAIT SEMAPHORE - NO SUSPENDING ...................\n");
//printf (">>>>>>>>>>>>>> AWAIT SEMAPHORE - NO SUSPENDING ...................\n");
}
else
{
/* not signaled. need to wait */
proc = stix->processor->active;
printf (">>>>>>>>>>>>>> AWAIT SEMAPHORE - SUEPENDING ACTIVE PROCESS...............\n");
//printf (">>>>>>>>>>>>>> AWAIT SEMAPHORE - SUEPENDING ACTIVE PROCESS..........state=>[%d].....PROC %p\n", (int)STIX_OOP_TO_SMOOI(proc->state), proc);
/* suspend the active process */
suspend_process (stix, proc);
/* link the suspened process to the semaphore's process list */
/* link the suspended process to the semaphore's process list */
chain_into_semaphore (stix, proc, sem);
STIX_ASSERT (sem->waiting_tail == proc);
//printf (">>>>>>>>>>>>>> AWAIT SEMAPHORE - SUEPENDING ACTIVE PROCESS....XX......state=>[%d]..PROC %p\n", (int)STIX_OOP_TO_SMOOI(proc->state), proc);
STIX_ASSERT (stix->processor->active != proc);
}
}
@ -709,6 +735,7 @@ static void delete_from_sem_heap (stix_t* stix, stix_ooi_t index)
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
@ -1657,23 +1684,11 @@ static int prim_processor_schedule (stix_t* stix, stix_ooi_t nargs)
return 1;
}
static int prim_processor_remove (stix_t* stix, stix_ooi_t nargs)
{
/* TODO: */
return 0;
}
static int prim_processor_sleep (stix_t* stix, stix_ooi_t nargs)
{
/* TODO: */
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_ntime_t now, ft;
STIX_ASSERT (nargs >= 2 || nargs <= 3);
@ -1710,30 +1725,17 @@ static int prim_processor_add_timed_semaphore (stix_t* stix, stix_ooi_t nargs)
*
* 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)
vm_gettime (&now);
STIX_ADDNTIMESNS (&ft, &now, STIX_OOP_TO_SMOOI(sec), STIX_OOP_TO_SMOOI(nsec));
if (ft.sec < 0 || ft.sec > STIX_SMOOI_MAX)
{
/* 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
/* soft error - cannot represent the e:xpiry 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);
sem->heap_ftime_sec = STIX_SMOOI_TO_OOP(ft.sec);
sem->heap_ftime_nsec = STIX_SMOOI_TO_OOP(ft.nsec);
if (add_to_sem_heap (stix, sem) <= -1) return -1;
@ -1741,15 +1743,20 @@ printf ("clock_gettime() failure....\n");
return 1;
}
static int prim_processor_del_time_semaphore (stix_t* stix, stix_ooi_t nargs)
static int prim_processor_remove_semaphore (stix_t* stix, stix_ooi_t nargs)
{
/* remove a semaphore from processor's signal scheduling */
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);
sem = (stix_oop_semaphore_t)ACTIVE_STACK_GET(stix, stix->sp);
rcv = ACTIVE_STACK_GET(stix, stix->sp - 1);
/* TODO: remove a semaphore from IO handler if it's registered...
* remove a semaphore from XXXXXXXXXXXXXX */
if (rcv != (stix_oop_t)stix->processor) return 0;
if (STIX_CLASSOF(stix,sem) != stix->_semaphore) return 0;
@ -1757,10 +1764,12 @@ static int prim_processor_del_time_semaphore (stix_t* stix, stix_ooi_t nargs)
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));
/* the semaphore is in the timed semaphore heap */
delete_from_sem_heap (stix, STIX_OOP_TO_SMOOI(sem->heap_index));
STIX_ASSERT(sem->heap_index == STIX_SMOOI_TO_OOP(-1));
}
ACTIVE_STACK_POPS (stix, nargs);
return 1;
}
@ -2449,9 +2458,8 @@ static prim_t primitives[] =
{ 0, 0, prim_semaphore_wait, "_semaphore_wait" },
{ 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, 1, prim_processor_remove_semaphore, "_processor_remove_semaphore" },
{ 1, 1, prim_integer_add, "_integer_add" },
{ 1, 1, prim_integer_sub, "_integer_sub" },
@ -2852,40 +2860,43 @@ int stix_execute (stix_t* stix)
while (1)
{
#if 0
if (stix->processor->active == stix->nil_process)
{
/* no more process in the system */
STIX_ASSERT (stix->processor->tally = STIX_SMOOI_TO_OOP(0));
printf ("NO MORE RUNNABLE PROCESS...\n");
}
#endif
if (stix->sem_heap_count > 0)
{
struct timespec now, ft;
clock_gettime (CLOCK_MONOTONIC, &now);
stix_ntime_t ft, now;
vm_gettime (&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);
STIX_INITNTIME (&ft,
STIX_OOP_TO_SMOOI(stix->sem_heap[0]->heap_ftime_sec),
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))
if (STIX_CMPNTIME(&ft, (stix_ntime_t*)&now) <= 0)
{
stix_oop_process_t proc;
proc = stix->sem_heap[0]->waiting_head;
/* waited long enough. signal the semaphore */
signal_semaphore (stix, stix->sem_heap[0]);
proc = signal_semaphore (stix, stix->sem_heap[0]);
/* [NOTE] no stix_pushtmp() on proc. no GC must occur
* in the following line until it's used for
* wake_new_process() below. */
delete_from_sem_heap (stix, 0);
if (stix->processor->active == stix->nil_process)
/* if no process is waiting on the semaphore,
* signal_semaphore() returns stix->_nil. */
if (stix->processor->active == stix->nil_process && (stix_oop_t)proc != stix->_nil)
{
/* this is the only runnable process.
* switch the process to the running state.
* it uses wake_new_process() instead of
* switch_to_process() as there is no running
* process at this moment */
STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE));
STIX_ASSERT (proc == stix->processor->runnable_head);
@ -2895,16 +2906,9 @@ STIX_ASSERT (proc == stix->processor->runnable_head);
}
else if (stix->processor->active == stix->nil_process)
{
/* THIS PART IS JUST EXPERIMENTAL... PROPER WAITING WITH IO MULTIPLEXER IS NEEDED ... */
ft.tv_sec -= now.tv_sec;
ft.tv_nsec -= now.tv_nsec;
while (ft.tv_nsec < 0)
{
ft.tv_sec--;
ft.tv_nsec += 1000000000;
}
nanosleep (&ft, STIX_NULL);
clock_gettime (CLOCK_MONOTONIC, &now);
STIX_SUBNTIME (&ft, &ft, (stix_ntime_t*)&now);
vm_sleep (&ft); /* TODO: change this to i/o multiplexer??? */
vm_gettime (&now);
}
else
{
@ -2921,13 +2925,6 @@ printf ("REALLY NO MORE RUNNABLE PROCESS...\n");
break;
}
/*
else if (stix->processor->active == stix->idle_process)
{
IDLEING WAITING FOR PROCESS WAKE-UP...
}
*/
while (stix->sem_list_count > 0)
{
/* handle async signals */
@ -3704,7 +3701,6 @@ printf ("TERMINATE A PROCESS RETURNING FROM BLOCK\n");
#endif
terminate_process (stix, stix->processor->active);
#if defined(STIX_DEBUG_EXEC_002)
printf ("TERMINATED A PROCESS RETURNING FROM BLOCK %lld new active_context %p\n", (long long int)stix->ip, stix->active_context);
#endif
}

View File

@ -316,6 +316,83 @@ typedef stix_ucs_t stix_oocs_t;
#define STIX_OOCH_IS_UCH
/* =========================================================================
* TIME-RELATED TYPES
* =========================================================================*/
#define STIX_MSECS_PER_SEC (1000)
#define STIX_MSECS_PER_MIN (STIX_MSECS_PER_SEC * STIX_SECS_PER_MIN)
#define STIX_MSECS_PER_HOUR (STIX_MSECS_PER_SEC * STIX_SECS_PER_HOUR)
#define STIX_MSECS_PER_DAY (STIX_MSECS_PER_SEC * STIX_SECS_PER_DAY)
#define STIX_USECS_PER_MSEC (1000)
#define STIX_NSECS_PER_USEC (1000)
#define STIX_NSECS_PER_MSEC (STIX_NSECS_PER_USEC * STIX_USECS_PER_MSEC)
#define STIX_USECS_PER_SEC (STIX_USECS_PER_MSEC * STIX_MSECS_PER_SEC)
#define STIX_NSECS_PER_SEC (STIX_NSECS_PER_USEC * STIX_USECS_PER_MSEC * STIX_MSECS_PER_SEC)
#define STIX_SECNSEC_TO_MSEC(sec,nsec) \
(((qse_long_t)(sec) * STIX_MSECS_PER_SEC) + ((qse_long_t)(nsec) / STIX_NSECS_PER_MSEC))
#define STIX_SECNSEC_TO_USEC(sec,nsec) \
(((qse_long_t)(sec) * STIX_USECS_PER_SEC) + ((qse_long_t)(nsec) / STIX_NSECS_PER_USEC))
#define STIX_SEC_TO_MSEC(sec) ((sec) * STIX_MSECS_PER_SEC)
#define STIX_MSEC_TO_SEC(sec) ((sec) / STIX_MSECS_PER_SEC)
#define STIX_USEC_TO_NSEC(usec) ((usec) * STIX_NSECS_PER_USEC)
#define STIX_NSEC_TO_USEC(nsec) ((nsec) / STIX_NSECS_PER_USEC)
#define STIX_MSEC_TO_NSEC(msec) ((msec) * STIX_NSECS_PER_MSEC)
#define STIX_NSEC_TO_MSEC(nsec) ((nsec) / STIX_NSECS_PER_MSEC)
#define STIX_SEC_TO_NSEC(sec) ((sec) * STIX_NSECS_PER_SEC)
#define STIX_NSEC_TO_SEC(nsec) ((nsec) / STIX_NSECS_PER_SEC)
#define STIX_SEC_TO_USEC(sec) ((sec) * STIX_USECS_PER_SEC)
#define STIX_USEC_TO_SEC(usec) ((usec) / STIX_USECS_PER_SEC)
typedef struct stix_ntime_t stix_ntime_t;
struct stix_ntime_t
{
stix_intptr_t sec;
stix_int32_t nsec; /* nanoseconds */
};
#define STIX_INITNTIME(c,s,ns) (((c)->sec = (s)), ((c)->nsec = (ns)))
#define STIX_CLEARNTIME(c) STIX_INITNTIME(c, 0, 0)
#define STIX_ADDNTIME(c,a,b) \
do { \
(c)->sec = (a)->sec + (b)->sec; \
(c)->nsec = (a)->nsec + (b)->nsec; \
while ((c)->nsec >= STIX_NSECS_PER_SEC) { (c)->sec++; (c)->nsec -= STIX_NSECS_PER_SEC; } \
} while(0)
#define STIX_ADDNTIMESNS(c,a,s,ns) \
do { \
(c)->sec = (a)->sec + (s); \
(c)->nsec = (a)->nsec + (ns); \
while ((c)->nsec >= STIX_NSECS_PER_SEC) { (c)->sec++; (c)->nsec -= STIX_NSECS_PER_SEC; } \
} while(0)
#define STIX_SUBNTIME(c,a,b) \
do { \
(c)->sec = (a)->sec - (b)->sec; \
(c)->nsec = (a)->nsec - (b)->nsec; \
while ((c)->nsec < 0) { (c)->sec--; (c)->nsec += STIX_NSECS_PER_SEC; } \
} while(0)
#define STIX_SUBNTIMESNS(c,a,s,ns) \
do { \
(c)->sec = (a)->sec - s; \
(c)->nsec = (a)->nsec - ns; \
while ((c)->nsec < 0) { (c)->sec--; (c)->nsec += STIX_NSECS_PER_SEC; } \
} while(0)
#define STIX_CMPNTIME(a,b) (((a)->sec == (b)->sec)? ((a)->nsec - (b)->nsec): ((a)->sec - (b)->sec))
/* =========================================================================
* PRIMITIVE MACROS
* ========================================================================= */