Reindented server/core/housekeeper.c

This commit is contained in:
Johan Wikman
2015-11-30 13:53:06 +02:00
parent 486f724dc1
commit 3189a47fc5
2 changed files with 215 additions and 198 deletions

View File

@ -36,9 +36,9 @@
* @verbatim * @verbatim
* Revision History * Revision History
* *
* Date Who Description * Date Who Description
* 29/08/14 Mark Riddoch Initial implementation * 29/08/14 Mark Riddoch Initial implementation
* 22/10/14 Mark Riddoch Addition of one-shot tasks * 22/10/14 Mark Riddoch Addition of one-shot tasks
* *
* @endverbatim * @endverbatim
*/ */
@ -46,16 +46,16 @@
/** /**
* List of all tasks that need to be run * List of all tasks that need to be run
*/ */
static HKTASK *tasks = NULL; static HKTASK *tasks = NULL;
/** /**
* Spinlock to protect the tasks list * Spinlock to protect the tasks list
*/ */
static SPINLOCK tasklock = SPINLOCK_INIT; static SPINLOCK tasklock = SPINLOCK_INIT;
static int do_shutdown = 0; static int do_shutdown = 0;
unsigned long hkheartbeat = 0; unsigned long hkheartbeat = 0;
static void hkthread(void *); static void hkthread(void *);
/** /**
* Initialise the housekeeper thread * Initialise the housekeeper thread
@ -63,7 +63,7 @@ static void hkthread(void *);
void void
hkinit() hkinit()
{ {
thread_start(hkthread, NULL); thread_start(hkthread, NULL);
} }
/** /**
@ -76,63 +76,64 @@ hkinit()
* *
* Task names must be unique. * Task names must be unique.
* *
* @param name The unique name for this housekeeper task * @param name The unique name for this housekeeper task
* @param taskfn The function to call for the task * @param taskfn The function to call for the task
* @param data Data to pass to the task function * @param data Data to pass to the task function
* @param frequency How often to run the task, expressed in seconds * @param frequency How often to run the task, expressed in seconds
* @return Return the time in seconds when the task will be first run if the task was added, otherwise 0 * @return Return the time in seconds when the task will be first run
* if the task was added, otherwise 0
*/ */
int int
hktask_add(char *name, void (*taskfn)(void *), void *data, int frequency) hktask_add(char *name, void (*taskfn)(void *), void *data, int frequency)
{ {
HKTASK *task, *ptr; HKTASK *task, *ptr;
if ((task = (HKTASK *)malloc(sizeof(HKTASK))) == NULL) if ((task = (HKTASK *)malloc(sizeof(HKTASK))) == NULL)
{ {
return 0; return 0;
} }
if ((task->name = strdup(name)) == NULL) if ((task->name = strdup(name)) == NULL)
{ {
free(task); free(task);
return 0; return 0;
} }
task->task = taskfn; task->task = taskfn;
task->data = data; task->data = data;
task->frequency = frequency; task->frequency = frequency;
task->type = HK_REPEATED; task->type = HK_REPEATED;
task->nextdue = time(0) + frequency; task->nextdue = time(0) + frequency;
task->next = NULL; task->next = NULL;
spinlock_acquire(&tasklock); spinlock_acquire(&tasklock);
ptr = tasks; ptr = tasks;
while (ptr && ptr->next) while (ptr && ptr->next)
{ {
if (strcmp(ptr->name, name) == 0) if (strcmp(ptr->name, name) == 0)
{ {
spinlock_release(&tasklock); spinlock_release(&tasklock);
free(task->name); free(task->name);
free(task); free(task);
return 0; return 0;
} }
ptr = ptr->next; ptr = ptr->next;
} }
if (ptr) if (ptr)
{ {
if (strcmp(ptr->name, name) == 0) if (strcmp(ptr->name, name) == 0)
{ {
spinlock_release(&tasklock); spinlock_release(&tasklock);
free(task->name); free(task->name);
free(task); free(task);
return 0; return 0;
} }
ptr->next = task; ptr->next = task;
} }
else else
{ {
tasks = task; tasks = task;
} }
spinlock_release(&tasklock); spinlock_release(&tasklock);
return task->nextdue; return task->nextdue;
} }
/** /**
@ -140,90 +141,99 @@ HKTASK *task, *ptr;
* *
* Task names must be unique. * Task names must be unique.
* *
* @param name The unique name for this housekeeper task * @param name The unique name for this housekeeper task
* @param taskfn The function to call for the task * @param taskfn The function to call for the task
* @param data Data to pass to the task function * @param data Data to pass to the task function
* @param when How many second until the task is executed * @param when How many second until the task is executed
* @return Return the time in seconds when the task will be first run if the task was added, otherwise 0 * @return Return the time in seconds when the task will be first run
* if the task was added, otherwise 0
* *
*/ */
int int
hktask_oneshot(char *name, void (*taskfn)(void *), void *data, int when) hktask_oneshot(char *name, void (*taskfn)(void *), void *data, int when)
{ {
HKTASK *task, *ptr; HKTASK *task, *ptr;
if ((task = (HKTASK *)malloc(sizeof(HKTASK))) == NULL) if ((task = (HKTASK *)malloc(sizeof(HKTASK))) == NULL)
{ {
return 0; return 0;
} }
if ((task->name = strdup(name)) == NULL) if ((task->name = strdup(name)) == NULL)
{ {
free(task); free(task);
return 0; return 0;
} }
task->task = taskfn; task->task = taskfn;
task->data = data; task->data = data;
task->frequency = 0; task->frequency = 0;
task->type = HK_ONESHOT; task->type = HK_ONESHOT;
task->nextdue = time(0) + when; task->nextdue = time(0) + when;
task->next = NULL; task->next = NULL;
spinlock_acquire(&tasklock); spinlock_acquire(&tasklock);
ptr = tasks; ptr = tasks;
while (ptr && ptr->next) while (ptr && ptr->next)
{ {
if (strcmp(ptr->name, name) == 0) if (strcmp(ptr->name, name) == 0)
{ {
spinlock_release(&tasklock); spinlock_release(&tasklock);
free(task->name); free(task->name);
free(task); free(task);
return 0; return 0;
} }
ptr = ptr->next; ptr = ptr->next;
} }
if (ptr) if (ptr)
ptr->next = task; {
else ptr->next = task;
tasks = task; }
spinlock_release(&tasklock); else
{
tasks = task;
}
spinlock_release(&tasklock);
return task->nextdue; return task->nextdue;
} }
/** /**
* Remove a named task from the housekeepers task list * Remove a named task from the housekeepers task list
* *
* @param name The task name to remove * @param name The task name to remove
* @return Returns 0 if the task could not be removed * @return Returns 0 if the task could not be removed
*/ */
int int
hktask_remove(char *name) hktask_remove(char *name)
{ {
HKTASK *ptr, *lptr = NULL; HKTASK *ptr, *lptr = NULL;
spinlock_acquire(&tasklock); spinlock_acquire(&tasklock);
ptr = tasks; ptr = tasks;
while (ptr && strcmp(ptr->name, name) != 0) while (ptr && strcmp(ptr->name, name) != 0)
{ {
lptr = ptr; lptr = ptr;
ptr = ptr->next; ptr = ptr->next;
} }
if (ptr && lptr) if (ptr && lptr)
lptr->next = ptr->next; {
else if (ptr) lptr->next = ptr->next;
tasks = ptr->next; }
spinlock_release(&tasklock); else if (ptr)
{
tasks = ptr->next;
}
spinlock_release(&tasklock);
if (ptr) if (ptr)
{ {
free(ptr->name); free(ptr->name);
free(ptr); free(ptr);
return 1; return 1;
} }
else else
{ {
return 0; return 0;
} }
} }
@ -240,48 +250,54 @@ HKTASK *ptr, *lptr = NULL;
* It is vital that the task->nextdue tiem is updated before the task * It is vital that the task->nextdue tiem is updated before the task
* is run. * is run.
* *
* @param data Unused, here to satisfy the thread system * @param data Unused, here to satisfy the thread system
*/ */
void void
hkthread(void *data) hkthread(void *data)
{ {
HKTASK *ptr; HKTASK *ptr;
time_t now; time_t now;
void (*taskfn)(void *); void (*taskfn)(void *);
void *taskdata; void *taskdata;
int i; int i;
for (;;) for (;;)
{ {
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
{ {
if (do_shutdown) if (do_shutdown)
return; {
thread_millisleep(100); return;
hkheartbeat++; }
} thread_millisleep(100);
now = time(0); hkheartbeat++;
spinlock_acquire(&tasklock); }
ptr = tasks; now = time(0);
while (ptr) spinlock_acquire(&tasklock);
{ ptr = tasks;
if (ptr->nextdue <= now) while (ptr)
{ {
ptr->nextdue = now + ptr->frequency; if (ptr->nextdue <= now)
taskfn = ptr->task; {
taskdata = ptr->data; ptr->nextdue = now + ptr->frequency;
spinlock_release(&tasklock); taskfn = ptr->task;
(*taskfn)(taskdata); taskdata = ptr->data;
if (ptr->type == HK_ONESHOT) spinlock_release(&tasklock);
hktask_remove(ptr->name); (*taskfn)(taskdata);
spinlock_acquire(&tasklock); if (ptr->type == HK_ONESHOT)
ptr = tasks; {
} hktask_remove(ptr->name);
else }
ptr = ptr->next; spinlock_acquire(&tasklock);
} ptr = tasks;
spinlock_release(&tasklock); }
} else
{
ptr = ptr->next;
}
}
spinlock_release(&tasklock);
}
} }
/** /**
@ -291,35 +307,35 @@ int i;
void void
hkshutdown() hkshutdown()
{ {
do_shutdown = 1; do_shutdown = 1;
} }
/** /**
* Show the tasks that are scheduled for the house keeper * Show the tasks that are scheduled for the house keeper
* *
* @param pdcb The DCB to send to output * @param pdcb The DCB to send to output
*/ */
void void
hkshow_tasks(DCB *pdcb) hkshow_tasks(DCB *pdcb)
{ {
HKTASK *ptr; HKTASK *ptr;
struct tm tm; struct tm tm;
char buf[40]; char buf[40];
dcb_printf(pdcb, "%-25s | Type | Frequency | Next Due\n", "Name"); dcb_printf(pdcb, "%-25s | Type | Frequency | Next Due\n", "Name");
dcb_printf(pdcb, "--------------------------+----------+-----------+-------------------------\n"); dcb_printf(pdcb, "--------------------------+----------+-----------+-------------------------\n");
spinlock_acquire(&tasklock); spinlock_acquire(&tasklock);
ptr = tasks; ptr = tasks;
while (ptr) while (ptr)
{ {
localtime_r(&ptr->nextdue, &tm); localtime_r(&ptr->nextdue, &tm);
asctime_r(&tm, buf); asctime_r(&tm, buf);
dcb_printf(pdcb, "%-25s | %-8s | %-9d | %s", dcb_printf(pdcb, "%-25s | %-8s | %-9d | %s",
ptr->name, ptr->name,
ptr->type == HK_REPEATED ? "Repeated" : "One-Shot", ptr->type == HK_REPEATED ? "Repeated" : "One-Shot",
ptr->frequency, ptr->frequency,
buf); buf);
ptr = ptr->next; ptr = ptr->next;
} }
spinlock_release(&tasklock); spinlock_release(&tasklock);
} }

View File

@ -26,30 +26,30 @@
* @verbatim * @verbatim
* Revision History * Revision History
* *
* Date Who Description * Date Who Description
* 29/08/14 Mark Riddoch Initial implementation * 29/08/14 Mark Riddoch Initial implementation
* *
* @endverbatim * @endverbatim
*/ */
typedef enum { typedef enum
HK_REPEATED = 1, {
HK_ONESHOT HK_REPEATED = 1,
HK_ONESHOT
} HKTASK_TYPE; } HKTASK_TYPE;
/** /**
* The housekeeper task list * The housekeeper task list
*/ */
typedef struct hktask { typedef struct hktask
char *name; /*< A simple task name */ {
void (*task)(void *data); /*< The task to call */ char *name; /*< A simple task name */
void *data; /*< Data to pass the task */ void (*task)(void *data); /*< The task to call */
int frequency; /*< How often to call the tasks (seconds) */ void *data; /*< Data to pass the task */
time_t nextdue; /*< When the task should be next run */ int frequency; /*< How often to call the tasks (seconds) */
HKTASK_TYPE time_t nextdue; /*< When the task should be next run */
type; /*< The task type */ HKTASK_TYPE type; /*< The task type */
struct hktask struct hktask *next; /*< Next task in the list */
*next; /*< Next task in the list */
} HKTASK; } HKTASK;
extern void hkinit(); extern void hkinit();
@ -58,4 +58,5 @@ extern int hktask_oneshot(char *name, void (*task)(void *), void *data, int whe
extern int hktask_remove(char *name); extern int hktask_remove(char *name);
extern void hkshutdown(); extern void hkshutdown();
extern void hkshow_tasks(DCB *pdcb); extern void hkshow_tasks(DCB *pdcb);
#endif #endif