Source to ./ptask.c
/*
* Cisco router simulation platform.
* Copyright (c) 2005,2006 Christophe Fillot ([email protected])
*
* Periodic tasks centralization. Used for TX part of network devices.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include "ptask.h"
static pthread_t ptask_thread;
static pthread_mutex_t ptask_mutex = PTHREAD_MUTEX_INITIALIZER;
static ptask_t *ptask_list = NULL;
static ptask_id_t ptask_current_id = 0;
u_int ptask_sleep_time = 10;
#define PTASK_LOCK() pthread_mutex_lock(&ptask_mutex)
#define PTASK_UNLOCK() pthread_mutex_unlock(&ptask_mutex)
/* Periodic task thread */
static void *ptask_run(void *arg)
{
pthread_mutex_t umutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ucond = PTHREAD_COND_INITIALIZER;
ptask_t *task;
for(;;) {
PTASK_LOCK();
for(task=ptask_list;task;task=task->next)
task->cbk(task->object,task->arg);
PTASK_UNLOCK();
/* For testing! */
{
struct timespec t_spc;
m_tmcnt_t expire;
expire = m_gettime_usec() + (ptask_sleep_time * 1000);
pthread_mutex_lock(&umutex);
t_spc.tv_sec = expire / 1000000;
t_spc.tv_nsec = (expire % 1000000) * 1000;
pthread_cond_timedwait(&ucond,&umutex,&t_spc);
pthread_mutex_unlock(&umutex);
}
/* Old method... */
//usleep(ptask_sleep_time*1000);
}
return NULL;
}
/* Add a new task */
ptask_id_t ptask_add(ptask_callback cbk,void *object,void *arg)
{
ptask_t *task;
ptask_id_t id;
if (!(task = malloc(sizeof(*task)))) {
fprintf(stderr,"ptask_add: unable to add new task.\n");
return(-1);
}
memset(task,0,sizeof(*task));
task->cbk = cbk;
task->object = object;
task->arg = arg;
PTASK_LOCK();
id = ++ptask_current_id;
assert(id != 0);
task->id = id;
task->next = ptask_list;
ptask_list = task;
PTASK_UNLOCK();
return(id);
}
/* Remove a task */
int ptask_remove(ptask_id_t id)
{
ptask_t **task,*p;
int res = -1;
PTASK_LOCK();
for(task=&ptask_list;*task;task=&(*task)->next)
if ((*task)->id == id) {
p = *task;
*task = (*task)->next;
free(p);
res = 0;
break;
}
PTASK_UNLOCK();
return(res);
}
/* Initialize ptask module */
int ptask_init(u_int sleep_time)
{
if (sleep_time)
ptask_sleep_time = sleep_time;
if (pthread_create(&ptask_thread,NULL,ptask_run,NULL) != 0) {
fprintf(stderr,"ptask_init: unable to create thread.\n");
return(-1);
}
return(0);
}