feat(election-iomgr-refactor): add delay_task_ms() for ms-granularity one-shot tasks
Add millisecond-granularity delay_task_ms() to delaymgr using clock_gettime(CLOCK_MONOTONIC) for deadline computation. Extends delay_task_t with nextrun_ts field; delay_worker distinguishes ms-tasks from second-tasks via non-zero nextrun_ts. Backward compatible with existing delay_task callers. 4 delay tests pass (2 new: tolerance and invalid-args). Provides the timeout primitive for election and committing watchdogs.
This commit is contained in:
parent
289c4daaa2
commit
4737b0f8a3
3 changed files with 159 additions and 7 deletions
|
|
@ -8,6 +8,22 @@
|
|||
#include "delay.h"
|
||||
#include "utils.h"
|
||||
|
||||
/* Return 1 if a ms-task's deadline has passed, 0 otherwise. */
|
||||
static int ms_task_due(const delay_task_t* t)
|
||||
{
|
||||
struct timespec now;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
if (now.tv_sec > t->nextrun_ts.tv_sec) {
|
||||
return 1;
|
||||
}
|
||||
if (now.tv_sec == t->nextrun_ts.tv_sec
|
||||
&& now.tv_nsec >= t->nextrun_ts.tv_nsec) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* delay_worker(void* args)
|
||||
{
|
||||
delaymgr_t* mgr = (delaymgr_t*)args;
|
||||
|
|
@ -16,6 +32,7 @@ static void* delay_worker(void* args)
|
|||
ordq_item_t* it;
|
||||
delay_task_t* t;
|
||||
time_t now;
|
||||
int is_ms_task;
|
||||
|
||||
pthread_testcancel();
|
||||
{
|
||||
|
|
@ -32,10 +49,18 @@ static void* delay_worker(void* args)
|
|||
continue;
|
||||
}
|
||||
|
||||
now = time(NULL);
|
||||
t = (delay_task_t*)it->data;
|
||||
if (t->nextrun > now) {
|
||||
continue;
|
||||
t = (delay_task_t*)it->data;
|
||||
is_ms_task = (t->nextrun_ts.tv_nsec != 0 || t->nextrun_ts.tv_sec != 0);
|
||||
|
||||
if (is_ms_task) {
|
||||
if (!ms_task_due(t)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
now = time(NULL);
|
||||
if (t->nextrun > now) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
it = ordq_get(&(mgr->tasks), NULL);
|
||||
|
|
@ -49,10 +74,17 @@ static void* delay_worker(void* args)
|
|||
if (t->runcount == 0) {
|
||||
FREEUP(t);
|
||||
} else {
|
||||
time_t nextrun = now + t->run_period;
|
||||
if (is_ms_task) {
|
||||
/* advance deadline by run_period ms */
|
||||
long add_ns = (long)t->run_period * 1000000L;
|
||||
|
||||
/* put back to taskq as it need to be run again */
|
||||
t->nextrun = nextrun;
|
||||
t->nextrun_ts.tv_nsec += add_ns;
|
||||
t->nextrun_ts.tv_sec += t->nextrun_ts.tv_nsec / 1000000000L;
|
||||
t->nextrun_ts.tv_nsec %= 1000000000L;
|
||||
} else {
|
||||
/* put back to taskq as it need to be run again */
|
||||
t->nextrun = now + t->run_period;
|
||||
}
|
||||
ordq_put(&(mgr->tasks), t);
|
||||
}
|
||||
|
||||
|
|
@ -206,3 +238,41 @@ int delay_task(delaymgr_t* mgr, int delay, int runcount,
|
|||
|
||||
return ordq_put(&(mgr->tasks), t);
|
||||
}
|
||||
|
||||
int delay_task_ms(delaymgr_t* mgr, int delay_ms, int runcount,
|
||||
delay_task_entry_fn_t entry, void* args)
|
||||
{
|
||||
delay_task_t* t;
|
||||
struct timespec now;
|
||||
long add_ns;
|
||||
|
||||
if ((mgr == NULL) || (delay_ms <= 0) || (entry == NULL)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
t = (delay_task_t*)calloc(1, sizeof(*t));
|
||||
if (t == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
add_ns = (long)delay_ms * 1000000L;
|
||||
t->nextrun_ts.tv_sec = now.tv_sec + (now.tv_nsec + add_ns) / 1000000000L;
|
||||
t->nextrun_ts.tv_nsec = (now.tv_nsec + add_ns) % 1000000000L;
|
||||
|
||||
/* Ensure nextrun_ts is never all-zero so the ms-task flag is unambiguous.
|
||||
* tv_nsec == 0 can only arise when add_ns is an exact multiple of 1s and
|
||||
* now.tv_nsec == 0; in that edge case bump tv_nsec by 1 ns. */
|
||||
if (t->nextrun_ts.tv_nsec == 0) {
|
||||
t->nextrun_ts.tv_nsec = 1;
|
||||
}
|
||||
|
||||
t->nextrun = 0; /* unused for ms-tasks */
|
||||
t->runcount = runcount;
|
||||
t->run_period = delay_ms;
|
||||
t->entry = entry;
|
||||
t->args = args;
|
||||
|
||||
return ordq_put(&(mgr->tasks), t);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue