hackedteam/vector-ipa

View on GitHub
src/timer.c

Summary

Maintainability
Test Coverage
/*
    MODULE -- Timer hooking module

    Copyright (C) Alberto Ornaghi

    $Id: timer.c 2995 2010-10-07 14:42:52Z alor $
*/

#include <main.h>
#include <timer.h>
#include <threads.h>

static LIST_HEAD (, timer_entry) timer_list;

struct timer_entry {
   struct timer_hook th;
   time_t last;
   LIST_ENTRY (timer_entry) next;
};

/* proto */

int add_timer(struct timer_hook *th);
int del_timer(struct timer_hook *th);
static void timer_start(void);
MY_THREAD_FUNC(timer_thread);

/*******************************************/

int add_timer(struct timer_hook *th)
{
   struct timer_entry *e;
   struct timeval tv;

   DEBUG_MSG(D_INFO, "add_timer: [%d][%p]", (u_int32)th->sec, th->func);

   /* check if the timer thread must be created */
   if (LIST_EMPTY(&timer_list))
      timer_start();

   SAFE_CALLOC(e, 1, sizeof(struct timer_entry));

   memcpy(&e->th, th, sizeof(struct timer_hook));
   gettimeofday(&tv, 0);
   e->last = tv.tv_sec;

   LIST_INSERT_HEAD(&timer_list, e, next);

   return ESUCCESS;
}

int del_timer(struct timer_hook *th)
{
   struct timer_entry *e;

   DEBUG_MSG(D_INFO, "del_timer: [%d][%p]", (u_int32)th->sec, th->func);

   LIST_FOREACH(e, &timer_list, next) {
      if (th->sec == e->th.sec && th->func == e->th.func) {
         LIST_REMOVE(e, next);
         SAFE_FREE(e);
         return ESUCCESS;
      }
   }

   return -ENOTFOUND;
}

static void timer_start(void)
{
   pthread_t pid;

   DEBUG_MSG(D_DEBUG, "timer_start");

   pid = my_thread_getpid("timer");

   if (pthread_equal(pid, MY_PTHREAD_NULL))
      my_thread_new("timer", "timer hook module", &timer_thread, NULL);
   else
      DEBUG_MSG(D_DEBUG, "timer_start: already started");
}


MY_THREAD_FUNC(timer_thread)
{
   struct timer_entry *e;
   struct timeval tv;

   /* initialize the thread */
   my_thread_init();

   DEBUG_MSG(D_DEBUG, "timer_thread: activated");

   LOOP {

      gettimeofday(&tv, 0);

      LIST_FOREACH(e, &timer_list, next) {
         /* the timer is expired (now - last) */
         if (tv.tv_sec - e->last >= e->th.sec) {
            //DEBUG_MSG(D_VERBOSE, "timer_thread: executing %p", e->th.func);
            EXECUTE(e->th.func);
            e->last = tv.tv_sec;
            //DEBUG_MSG(D_VERBOSE, "timer_thread: execution of %p terminated", e->th.func);
         }
      }

      /* sleep the minimum quantum */
      sleep(1);

      /* update the keepalive */
      GBL_STATS->keepalive = time(NULL);
      /* update the trhoughput */
      GBL_STATS->throughput = (float)GBL_STATS->bytes * 8 / 1000000;
      GBL_STATS->bytes = 0;
   }

   return NULL;
}


struct timeval timeval_subtract (struct timeval *x, struct timeval *y)
{
   struct timeval result;

   /* Perform the carry for the later subtraction by updating y. */
   if (x->tv_usec < y->tv_usec) {
      int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
      y->tv_usec -= 1000000 * nsec;
      y->tv_sec += nsec;
   }
   if (x->tv_usec - y->tv_usec > 1000000) {
      int nsec = (x->tv_usec - y->tv_usec) / 1000000;
      y->tv_usec += 1000000 * nsec;
      y->tv_sec -= nsec;
   }

   /* Compute the time remaining to wait. tv_usec is certainly positive. */
   result.tv_sec = x->tv_sec - y->tv_sec;
   result.tv_usec = x->tv_usec - y->tv_usec;

   return result;
}

/* EOF */

// vim:ts=3:expandtab