"Fossies" - the Fresh Open Source Software Archive

Member "httperf-0.9.0/src/timer.c" (7 Apr 2007, 4794 Bytes) of package /linux/www/old/httperf-0.9.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "timer.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2     httperf -- a tool for measuring web server performance
    3     Copyright 2000-2007 Hewlett-Packard Company and Contributors listed in
    4     AUTHORS file. Originally contributed by David Mosberger-Tang
    5 
    6     This file is part of httperf, a web server performance measurment
    7     tool.
    8 
    9     This program is free software; you can redistribute it and/or
   10     modify it under the terms of the GNU General Public License as
   11     published by the Free Software Foundation; either version 2 of the
   12     License, or (at your option) any later version.
   13     
   14     In addition, as a special exception, the copyright holders give
   15     permission to link the code of this work with the OpenSSL project's
   16     "OpenSSL" library (or with modified versions of it that use the same
   17     license as the "OpenSSL" library), and distribute linked combinations
   18     including the two.  You must obey the GNU General Public License in
   19     all respects for all of the code used other than "OpenSSL".  If you
   20     modify this file, you may extend this exception to your version of the
   21     file, but you are not obligated to do so.  If you do not wish to do
   22     so, delete this exception statement from your version.
   23 
   24     This program is distributed in the hope that it will be useful,
   25     but WITHOUT ANY WARRANTY; without even the implied warranty of
   26     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   27     General Public License for more details.
   28 
   29     You should have received a copy of the GNU General Public License
   30     along with this program; if not, write to the Free Software
   31     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
   32     02110-1301, USA
   33 */
   34 
   35 #include <assert.h>
   36 #include <errno.h>
   37 #include <stdio.h>
   38 #include <stdlib.h>
   39 #include <string.h>
   40 
   41 #include <sys/time.h>
   42 
   43 #include <httperf.h>
   44 #include <timer.h>
   45 
   46 #define WHEEL_SIZE  4096
   47 
   48 #if 1
   49 static Time now;
   50 #endif
   51 static Time next_tick;
   52 static Timer *timer_free_list = 0;
   53 static Timer *t_curr = 0;
   54 
   55 /* What a wheel is made of, no?  */
   56 static Timer_Queue wheel[WHEEL_SIZE], *curr = 0;
   57 
   58 static void
   59 done (Timer *t)
   60 {
   61   t->q.next = timer_free_list;
   62   t->q.prev = 0;
   63   timer_free_list = t;
   64 }
   65 
   66 Time
   67 timer_now_forced (void)
   68 {
   69   struct timeval tv;
   70 
   71   gettimeofday (&tv, 0);
   72   return tv.tv_sec + tv.tv_usec*1e-6;
   73 }
   74 
   75 Time
   76 timer_now (void)
   77 {
   78   return now;
   79 }
   80 
   81 void
   82 timer_init (void)
   83 {
   84   now = timer_now_forced ();
   85   memset (wheel, 0, sizeof (wheel));
   86   next_tick = timer_now () + TIMER_INTERVAL;
   87   curr = wheel;
   88 }
   89 
   90 void
   91 timer_tick (void)
   92 {
   93   Timer *t, *t_next;
   94 
   95   assert (!t_curr);
   96 
   97   now = timer_now_forced ();
   98 
   99   while (timer_now () >= next_tick)
  100     {
  101       for (t = curr->next; t && t->delta == 0; t = t_next)
  102     {
  103       t_curr = t;
  104       (*t->func) (t, t->arg);
  105       t_next = t->q.next;
  106       done (t);
  107     }
  108       t_curr = 0;
  109       curr->next = t;
  110       if (t)
  111     {
  112       t->q.prev = (Timer *) curr;
  113       --t->delta;
  114     }
  115       next_tick += TIMER_INTERVAL;
  116       if (++curr >= wheel + WHEEL_SIZE)
  117     curr = wheel;
  118     }
  119 }
  120 
  121 Timer*
  122 timer_schedule (Timer_Callback timeout, Any_Type arg, Time delay)
  123 {
  124   Timer_Queue *spoke;
  125   Timer *t, *p;
  126   u_long ticks;
  127   u_long delta;
  128   Time behind;
  129 
  130   if (timer_free_list)
  131     {
  132       t = timer_free_list;
  133       timer_free_list = t->q.next;
  134     }
  135   else
  136     {
  137       t = malloc (sizeof (*t));
  138       if (!t)
  139     {
  140       fprintf (stderr, "%s.timer_schedule: %s\n",
  141            prog_name, strerror (errno));
  142       return 0;
  143     }
  144     }
  145   memset (t, 0, sizeof (*t));
  146   t->func = timeout;
  147   t->arg = arg;
  148 
  149   behind = (timer_now () - next_tick);
  150   if (behind > 0.0)
  151     delay += behind;
  152 
  153   if (delay < 0.0)
  154     ticks = 1;
  155   else
  156     {
  157       ticks = (delay + TIMER_INTERVAL / 2.0) * (1.0 / TIMER_INTERVAL);
  158       if (!ticks)
  159     ticks = 1;          /* minimum delay is a tick */
  160     }
  161 
  162   spoke = curr + (ticks % WHEEL_SIZE);
  163   if (spoke >= wheel + WHEEL_SIZE)
  164     spoke -= WHEEL_SIZE;
  165 
  166   delta = ticks / WHEEL_SIZE;
  167   p = (Timer *) spoke;
  168   while (p->q.next && delta > p->q.next->delta)
  169     {
  170       delta -= p->q.next->delta;
  171       p = p->q.next;
  172     }
  173   t->q.next = p->q.next;
  174   t->q.prev = p;
  175   p->q.next = t;
  176   t->delta = delta;
  177   if (t->q.next)
  178     {
  179       t->q.next->q.prev = t;
  180       t->q.next->delta -= delta;
  181     }
  182 
  183   if (DBG > 2)
  184     fprintf (stderr, "timer_schedule: t=%p, delay=%gs, arg=%lx\n",
  185          t, delay, arg.l);
  186 
  187   return t;
  188 }
  189 
  190 void
  191 timer_cancel (Timer *t)
  192 {
  193   if (DBG > 2)
  194     fprintf (stderr, "timer_cancel: t=%p\n", t);
  195 
  196   assert (t->q.prev);
  197 
  198   /* A module MUST NOT call timer_cancel() for a timer that is
  199      currently being processed (whose timeout has expired).  */
  200   if (t_curr == t)
  201     {
  202       fprintf (stderr, "timer_cancel() called on currently active timer!\n");
  203       return;
  204     }
  205 
  206   if (t->q.next)
  207     {
  208       t->q.next->delta += t->delta;
  209       t->q.next->q.prev = t->q.prev;
  210     }
  211   t->q.prev->q.next = t->q.next;
  212   done (t);
  213 }