"Fossies" - the Fresh Open Source Software Archive

Member "open-fcoe-3.19/fcoe-utils/lib/sa_timer.c" (15 Apr 2015, 5094 Bytes) of package /linux/misc/open-fcoe-3.19.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 "sa_timer.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright(c) 2009 Intel Corporation. All rights reserved.
    3  *
    4  * This program is free software; you can redistribute it and/or modify it
    5  * under the terms and conditions of the GNU General Public License,
    6  * version 2, as published by the Free Software Foundation.
    7  *
    8  * This program is distributed in the hope it will be useful, but WITHOUT
    9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   11  * more details.
   12  *
   13  * You should have received a copy of the GNU General Public License along with
   14  * this program; if not, write to the Free Software Foundation, Inc.,
   15  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   16  *
   17  * Maintained at www.Open-FCoE.org
   18  */
   19 
   20 #include "fcoemon_utils.h"
   21 #include "net_types.h"
   22 #include "fc_types.h"
   23 
   24 #define SA_TIMER_HZ     (1000 * 1000 * 1000ULL) /* nanoseconds per second */
   25 #define SA_TIMER_FUZZ   (500 * 1000ULL) /* 500 microseconds is close enough */
   26 
   27 static struct sa_timer *sa_timer_head;  /* queue of scheduled events */
   28 static u_int64_t sa_timer_nsec;     /* nanoseconds since start */
   29 
   30 /*
   31  * Initialize a timer structure.  Set handler.
   32  */
   33 void
   34 sa_timer_init(struct sa_timer *tm, void (*handler)(void *), void *arg)
   35 {
   36     ASSERT(handler != NULL);
   37     memset(tm, 0, sizeof(*tm));
   38     tm->tm_handler = handler;
   39     tm->tm_handler_arg = arg;
   40 }
   41 
   42 /*
   43  * Allocate a timer structure.  Set handler.
   44  */
   45 struct sa_timer *
   46 sa_timer_alloc(void (*handler)(void *arg), void *arg)
   47 {
   48     struct sa_timer *tm;
   49 
   50     tm = malloc(sizeof(*tm));
   51     if (tm)
   52         sa_timer_init(tm, handler, arg);
   53     return tm;
   54 }
   55 
   56 u_int64_t
   57 sa_timer_get(void)
   58 {
   59     u_int64_t nsec;
   60 #ifndef _POSIX_TIMERS
   61     struct timeval tv;
   62 
   63     gettimeofday(&tv, NULL);    /* XXX want monotonic time, not TOD */
   64     nsec = tv.tv_sec * SA_TIMER_HZ + tv.tv_usec * 1000;
   65 #else /* _POSIX_TIMERS */
   66     struct timespec ts;
   67     int rc;
   68 
   69     rc = clock_gettime(CLOCK_MONOTONIC, &ts);
   70     ASSERT_NOTIMPL(rc == 0);
   71     nsec = ts.tv_sec * SA_TIMER_HZ + ts.tv_nsec;
   72 #endif /* _POSIX_TIMERS */
   73 
   74 #if 0 /* XXX */
   75     ASSERT(nsec >= sa_timer_nsec);  /* really must be monotonic */
   76 #else
   77     if (nsec < sa_timer_nsec)
   78         sa_log("sa_timer_get: negative time lapse "
   79             "old %qud new %qud diff %qd nsec\n",
   80             (long long unsigned int) sa_timer_nsec,
   81             (long long unsigned int) nsec,
   82             (long long int) (nsec - sa_timer_nsec));
   83 #endif
   84     sa_timer_nsec = nsec;
   85     return nsec;
   86 }
   87 
   88 /*
   89  * Get monotonic time since some arbitrary time in the past.
   90  * If _POSIX_MONOTONIC_CLOCK isn't available, we'll use time of day.
   91  */
   92 u_int
   93 sa_timer_get_secs(void)
   94 {
   95     u_int sec;
   96 
   97 #ifndef _POSIX_TIMERS
   98     struct timeval tv;
   99 
  100     gettimeofday(&tv, NULL); /* XXX want monotonic time, not TOD */
  101     sec = tv.tv_sec;
  102 #else /* _POSIX_TIMERS */
  103     struct timespec ts;
  104     int rc;
  105 
  106     rc = clock_gettime(CLOCK_MONOTONIC, &ts);
  107     ASSERT_NOTIMPL(rc == 0);
  108     sec = ts.tv_sec;
  109 #endif /* _POSIX_TIMERS */
  110     return sec;
  111 }
  112 
  113 /*
  114  * Set timer to fire.   Delta is in microseconds from now.
  115  */
  116 void
  117 sa_timer_set(struct sa_timer *tm, u_long delta_usec)
  118 {
  119     struct sa_timer *cur;
  120     struct sa_timer **prev;
  121 
  122     ASSERT(delta_usec != 0);
  123     ASSERT(tm->tm_handler != NULL);
  124     sa_timer_cancel(tm);
  125     ASSERT(sa_timer_active(tm) == 0);
  126     tm->tm_nsec =
  127         sa_timer_get() + delta_usec * SA_TIMER_HZ / SA_TIMER_UNITS;
  128     ASSERT(tm->tm_nsec != 0);
  129 
  130     /*
  131      * Insert timer into sorted linked list.
  132      * Find insertion point, before cur.
  133      */
  134     for (prev = &sa_timer_head;
  135          (cur = *prev) != NULL && cur->tm_nsec <= tm->tm_nsec;
  136          prev = &cur->tm_next)
  137         ;
  138     *prev = tm;
  139     tm->tm_next = cur;
  140 }
  141 
  142 /*
  143  * Cancel timer if it is active.
  144  */
  145 void
  146 sa_timer_cancel(struct sa_timer *tm)
  147 {
  148     struct sa_timer *cur;
  149     struct sa_timer **prev;
  150 
  151     if (sa_timer_active(tm)) {
  152         for (prev = &sa_timer_head; (cur = *prev) != NULL;
  153              prev = &cur->tm_next)
  154             if (cur == tm) {
  155                 tm->tm_nsec = 0;
  156                 *prev = tm->tm_next;
  157                 break;
  158             }
  159         ASSERT(cur == tm);
  160     }
  161 }
  162 
  163 /*
  164  * Free (and cancel) timer.
  165  */
  166 void
  167 sa_timer_free(struct sa_timer *tm)
  168 {
  169     if (sa_timer_active(tm))
  170         sa_timer_cancel(tm);
  171     free(tm);
  172 }
  173 
  174 /*
  175  * Handle timer checks.  Called from select loop or other periodic function.
  176  *
  177  * The struct timeval is set before returning to the maximum amount of time
  178  * that should elapse before the next call.
  179  *
  180  * Returns 1 if any timer functions were called, 0 otherwise.
  181  */
  182 int
  183 sa_timer_check(struct timeval *tv)
  184 {
  185     u_int64_t now = 0;
  186     u_int64_t next_due = 0;
  187     struct sa_timer *tm;
  188     int ret = 0;
  189 
  190     /*
  191      * Remember, the list may change during the handler.
  192      */
  193     for (;;) {
  194         now = sa_timer_get();
  195         tm = sa_timer_head;
  196         if (tm == NULL) {
  197             next_due = now;
  198             break;
  199         }
  200 
  201         next_due = tm->tm_nsec;
  202         if (next_due > now + SA_TIMER_FUZZ)
  203             break;
  204 
  205         /*
  206          * Remove this element from the list.
  207          */
  208         sa_timer_head = tm->tm_next;
  209         tm->tm_next = NULL;
  210 
  211         /*
  212          * Mark cancelled and call handler.
  213          */
  214         tm->tm_nsec = 0;
  215         ASSERT(tm->tm_handler != NULL);
  216         (*tm->tm_handler)(tm->tm_handler_arg);
  217         ret = 1;
  218     }
  219 
  220     ASSERT(next_due >= now);
  221     next_due -= now;
  222     tv->tv_sec = (time_t) (next_due / SA_TIMER_HZ);
  223     tv->tv_usec = (long) (next_due % SA_TIMER_HZ) / 1000;
  224 
  225     return ret;
  226 }