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. ^sp.
} }
#method sleep: seconds
{
| s |
s := Semaphore new.
Processor signal: s after: seconds.
## Processor activeProcess dump.
s wait.
}
} }
#class Semaphore(Object) #class Semaphore(Object)
@ -67,6 +76,8 @@
self.fireTimeNsec := 0. self.fireTimeNsec := 0.
} }
## ==================================================================
#method signal #method signal
{ {
<primitive: #_semaphore_signal> <primitive: #_semaphore_signal>
@ -79,6 +90,20 @@
self primitiveFailed. self primitiveFailed.
} }
#method waitWithTimeout: seconds
{
<primitive: #_semaphore_wait>
self primitiveFailed
}
#method waitWithTimeout: seconds and: nanoSeconds
{
<primitive: #_semaphore_wait>
self primitiveFailed
}
## ==================================================================
#method heapIndex #method heapIndex
{ {
^heapIndex ^heapIndex
@ -302,12 +327,6 @@
^self.active. ^self.active.
} }
#method sleep: anInteger
{
<primitive: #_processor_sleep>
self primitiveFailed.
}
#method resume: aProcess #method resume: aProcess
{ {
<primitive: #_processor_schedule> <primitive: #_processor_schedule>
@ -329,12 +348,6 @@
" "
} }
#method remove: aProcess
{
"<primitive: #_processor_remove>"
"TODO: "
}
" "
#method yield #method yield
{ {
@ -354,4 +367,17 @@
<primitive: #_processor_add_timed_semaphore> <primitive: #_processor_add_timed_semaphore>
self primitiveFailed. 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 #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) static stix_oop_process_t make_process (stix_t* stix, stix_oop_context_t c)
{ {
stix_oop_process_t proc; 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) 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)) if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_SUSPENDED))
{ {
/* SUSPENED ---> RUNNING */ /* 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->prev == stix->_nil);
STIX_ASSERT ((stix_oop_t)proc->next == 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->current_context = proc->initial_context;*/
proc->state = STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE); 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 #if 0
else if (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)) 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); 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) if (nrp == proc)
{ {
/* no runnable process after suspension */ /* 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); sleep_active_process (stix, PROC_STATE_RUNNABLE);
unchain_from_processor (stix, proc, PROC_STATE_SUSPENDED); unchain_from_processor (stix, proc, PROC_STATE_SUSPENDED);
@ -470,7 +484,7 @@ printf ("NO RUNNABLE PROCESS AFTER SUPSENDISION\n");
} }
else else
{ {
printf ("SWITCHING TO XXXXXXXXXXXXXXXXXXXXx\n"); //printf ("SWITCHING TO XXXXXXXXXXXXXXXXXXXXx\n");
/* keep the unchained process at the runnable state for /* keep the unchained process at the runnable state for
* the immediate call to switch_to_process() below */ * the immediate call to switch_to_process() below */
unchain_from_processor (stix, proc, PROC_STATE_RUNNABLE); 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; 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_oop_process_t proc;
stix_ooi_t count; stix_ooi_t count;
if ((stix_oop_t)sem->waiting_head == stix->_nil) 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 */ /* no process is waiting on this semaphore */
count = STIX_OOP_TO_SMOOI(sem->count); count = STIX_OOP_TO_SMOOI(sem->count);
count++; count++;
sem->count = STIX_SMOOI_TO_OOP(count); sem->count = STIX_SMOOI_TO_OOP(count);
/* no process has been resumed */
return stix->_nil;
} }
else else
{ {
printf ("signal semaphore...2222\n");
proc = sem->waiting_head; proc = sem->waiting_head;
/* [NOTE] no GC must occur as 'proc' isn't protected with stix_pushtmp(). */
unchain_from_semaphore (stix, proc); unchain_from_semaphore (stix, proc);
resume_process (stix, proc); /* TODO: error check */ 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 */ /* it's already signalled */
count--; count--;
sem->count = STIX_SMOOI_TO_OOP(count); sem->count = STIX_SMOOI_TO_OOP(count);
printf (">>>>>>>>>>>>>> AWAIT SEMAPHORE - NO SUSPENDING ...................\n"); //printf (">>>>>>>>>>>>>> AWAIT SEMAPHORE - NO SUSPENDING ...................\n");
} }
else else
{ {
/* not signaled. need to wait */ /* not signaled. need to wait */
proc = stix->processor->active; 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 the active process */
suspend_process (stix, proc); 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); 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); 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); lastsem->heap_index = STIX_SMOOI_TO_OOP(index);
stix->sem_heap[index] = lastsem; stix->sem_heap[index] = lastsem;
if (SEM_HEAP_EARLIER_THAN(stix, lastsem, sem)) if (SEM_HEAP_EARLIER_THAN(stix, lastsem, sem))
sift_up_sem_heap (stix, index); sift_up_sem_heap (stix, index);
else else
@ -1657,23 +1684,11 @@ static int prim_processor_schedule (stix_t* stix, stix_ooi_t nargs)
return 1; 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) static int prim_processor_add_timed_semaphore (stix_t* stix, stix_ooi_t nargs)
{ {
stix_oop_t rcv, sec, nsec; stix_oop_t rcv, sec, nsec;
stix_oop_semaphore_t sem; stix_oop_semaphore_t sem;
struct timespec ts, ft; stix_ntime_t now, ft;
STIX_ASSERT (nargs >= 2 || nargs <= 3); 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 * this code assumes that the monotonic clock returns a small value
* that can fit into a small integer, even after some addtions... */ * 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 */ /* soft error - cannot represent the e:xpiry time in
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. */ * a small integer. */
return 0; return 0;
} }
sem->heap_ftime_sec = STIX_SMOOI_TO_OOP(ft.tv_sec); sem->heap_ftime_sec = STIX_SMOOI_TO_OOP(ft.sec);
sem->heap_ftime_nsec = STIX_SMOOI_TO_OOP(ft.tv_nsec); sem->heap_ftime_nsec = STIX_SMOOI_TO_OOP(ft.nsec);
if (add_to_sem_heap (stix, sem) <= -1) return -1; if (add_to_sem_heap (stix, sem) <= -1) return -1;
@ -1741,15 +1743,20 @@ printf ("clock_gettime() failure....\n");
return 1; 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_t rcv;
stix_oop_semaphore_t sem; stix_oop_semaphore_t sem;
STIX_ASSERT (nargs == 1); STIX_ASSERT (nargs == 1);
sem = (stix_oop_semaphore_t)ACTIVE_STACK_GET(stix, stix->sp - 1); sem = (stix_oop_semaphore_t)ACTIVE_STACK_GET(stix, stix->sp);
rcv = 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 (rcv != (stix_oop_t)stix->processor) return 0;
if (STIX_CLASSOF(stix,sem) != stix->_semaphore) 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) && if (STIX_OOP_IS_SMOOI(sem->heap_index) &&
sem->heap_index != STIX_SMOOI_TO_OOP(-1)) 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)); STIX_ASSERT(sem->heap_index == STIX_SMOOI_TO_OOP(-1));
} }
ACTIVE_STACK_POPS (stix, nargs);
return 1; return 1;
} }
@ -2448,10 +2457,9 @@ static prim_t primitives[] =
{ 0, 0, prim_semaphore_signal, "_semaphore_signal" }, { 0, 0, prim_semaphore_signal, "_semaphore_signal" },
{ 0, 0, prim_semaphore_wait, "_semaphore_wait" }, { 0, 0, prim_semaphore_wait, "_semaphore_wait" },
{ 1, 1, prim_processor_schedule, "_processor_schedule" }, { 1, 1, prim_processor_schedule, "_processor_schedule" },
{ 1, 1, prim_processor_remove, "_processor_remove" }, { 2, 3, prim_processor_add_timed_semaphore, "_processor_add_timed_semaphore" },
{ 1, 1, prim_processor_sleep, "_processor_sleep" }, { 1, 1, prim_processor_remove_semaphore, "_processor_remove_semaphore" },
{ 2, 3, prim_processor_add_timed_semaphore, "_processor_add_timed_semaphore" },
{ 1, 1, prim_integer_add, "_integer_add" }, { 1, 1, prim_integer_add, "_integer_add" },
{ 1, 1, prim_integer_sub, "_integer_sub" }, { 1, 1, prim_integer_sub, "_integer_sub" },
@ -2852,42 +2860,45 @@ int stix_execute (stix_t* stix)
while (1) 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) if (stix->sem_heap_count > 0)
{ {
struct timespec now, ft; stix_ntime_t ft, now;
vm_gettime (&now);
clock_gettime (CLOCK_MONOTONIC, &now);
do 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_sec));
STIX_ASSERT (STIX_OOP_IS_SMOOI(stix->sem_heap[0]->heap_ftime_nsec)); 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); STIX_INITNTIME (&ft,
ft.tv_nsec = STIX_OOP_TO_SMOOI(stix->sem_heap[0]->heap_ftime_nsec); 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; 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); 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)
{ {
STIX_ASSERT (proc->state == STIX_SMOOI_TO_OOP(PROC_STATE_RUNNABLE)); /* this is the only runnable process.
STIX_ASSERT (proc == stix->processor->runnable_head); * 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);
wake_new_process (stix, proc); wake_new_process (stix, proc);
stix->proc_switched = 1; stix->proc_switched = 1;
@ -2895,16 +2906,9 @@ STIX_ASSERT (proc == stix->processor->runnable_head);
} }
else if (stix->processor->active == stix->nil_process) else if (stix->processor->active == stix->nil_process)
{ {
/* THIS PART IS JUST EXPERIMENTAL... PROPER WAITING WITH IO MULTIPLEXER IS NEEDED ... */ STIX_SUBNTIME (&ft, &ft, (stix_ntime_t*)&now);
ft.tv_sec -= now.tv_sec; vm_sleep (&ft); /* TODO: change this to i/o multiplexer??? */
ft.tv_nsec -= now.tv_nsec; vm_gettime (&now);
while (ft.tv_nsec < 0)
{
ft.tv_sec--;
ft.tv_nsec += 1000000000;
}
nanosleep (&ft, STIX_NULL);
clock_gettime (CLOCK_MONOTONIC, &now);
} }
else else
{ {
@ -2921,13 +2925,6 @@ printf ("REALLY NO MORE RUNNABLE PROCESS...\n");
break; break;
} }
/*
else if (stix->processor->active == stix->idle_process)
{
IDLEING WAITING FOR PROCESS WAKE-UP...
}
*/
while (stix->sem_list_count > 0) while (stix->sem_list_count > 0)
{ {
/* handle async signals */ /* handle async signals */
@ -3704,7 +3701,6 @@ printf ("TERMINATE A PROCESS RETURNING FROM BLOCK\n");
#endif #endif
terminate_process (stix, stix->processor->active); terminate_process (stix, stix->processor->active);
#if defined(STIX_DEBUG_EXEC_002) #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); printf ("TERMINATED A PROCESS RETURNING FROM BLOCK %lld new active_context %p\n", (long long int)stix->ip, stix->active_context);
#endif #endif
} }

View File

@ -316,6 +316,83 @@ typedef stix_ucs_t stix_oocs_t;
#define STIX_OOCH_IS_UCH #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 * PRIMITIVE MACROS
* ========================================================================= */ * ========================================================================= */