nuttx-apps/netutils/thttpd/timers.c
Xiang Xiao 857158451b Unify the void cast usage
1.Remove void cast for function because many place ignore the returned value witout cast
2.Replace void cast for variable with UNUSED macro

Change-Id: Ie644129a563244a6397036789c4c3ea83c4e9b09
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2020-01-02 23:21:01 +08:00

366 lines
8.7 KiB
C

/****************************************************************************
* netutils/thttpd/timers.c
* Simple Timer Routines
*
* Copyright (C) 2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Derived from the file of the same name in the original THTTPD package:
*
* Copyright © 1995,1998,2000 by Jef Poskanzer <jef@mail.acme.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <debug.h>
#include "thttpd_alloc.h"
#include "timers.h"
/****************************************************************************
* Pre-Processor Definitons
****************************************************************************/
#define HASH_SIZE 67
/****************************************************************************
* Private Data
****************************************************************************/
static Timer *timers[HASH_SIZE];
static Timer *free_timers;
/****************************************************************************
* Public Data
****************************************************************************/
ClientData JunkClientData;
/****************************************************************************
* Private Functions
****************************************************************************/
static unsigned int hash(Timer *tmr)
{
/* We can hash on the trigger time, even though it can change over the
* life of a timer via the periodic bit.
* This is because both of those guys call l_resort(), which * recomputes
* the hash and moves the timer to the appropriate list.
*/
return ((unsigned int)tmr->time.tv_sec ^
(unsigned int)tmr->time.tv_usec) % HASH_SIZE;
}
static void l_add(Timer *tmr)
{
int h = tmr->hash;
register Timer *tmr2;
register Timer *tmr2prev;
tmr2 = timers[h];
if (tmr2 == NULL)
{
/* The list is empty. */
timers[h] = tmr;
tmr->prev = tmr->next = NULL;
}
else
{
if (tmr->time.tv_sec < tmr2->time.tv_sec ||
(tmr->time.tv_sec == tmr2->time.tv_sec &&
tmr->time.tv_usec <= tmr2->time.tv_usec))
{
/* The new timer goes at the head of the list. */
timers[h] = tmr;
tmr->prev = NULL;
tmr->next = tmr2;
tmr2->prev = tmr;
}
else
{
/* Walk the list to find the insertion point. */
for (tmr2prev = tmr2, tmr2 = tmr2->next; tmr2 != NULL;
tmr2prev = tmr2, tmr2 = tmr2->next)
{
if (tmr->time.tv_sec < tmr2->time.tv_sec ||
(tmr->time.tv_sec == tmr2->time.tv_sec &&
tmr->time.tv_usec <= tmr2->time.tv_usec))
{
/* Found it. */
tmr2prev->next = tmr;
tmr->prev = tmr2prev;
tmr->next = tmr2;
tmr2->prev = tmr;
return;
}
}
/* Oops, got to the end of the list. Add to tail. */
tmr2prev->next = tmr;
tmr->prev = tmr2prev;
tmr->next = NULL;
}
}
}
static void l_remove(Timer *tmr)
{
int h = tmr->hash;
if (tmr->prev == NULL)
{
timers[h] = tmr->next;
}
else
{
tmr->prev->next = tmr->next;
}
if (tmr->next != NULL)
{
tmr->next->prev = tmr->prev;
}
}
static void l_resort(Timer *tmr)
{
/* Remove the timer from its old list. */
l_remove(tmr);
/* Recompute the hash. */
tmr->hash = hash(tmr);
/* And add it back in to its new list, sorted correctly. */
l_add(tmr);
}
/****************************************************************************
* Public Functions
****************************************************************************/
void tmr_init(void)
{
int h;
for (h = 0; h < HASH_SIZE; ++h)
{
timers[h] = NULL;
}
free_timers = NULL;
}
Timer *tmr_create(struct timeval *now, TimerProc *timer_proc,
ClientData client_data, long msecs, int periodic)
{
Timer *tmr;
if (free_timers != NULL)
{
tmr = free_timers;
free_timers = tmr->next;
}
else
{
tmr = (Timer*)httpd_malloc(sizeof(Timer));
if (!tmr)
{
return NULL;
}
}
tmr->timer_proc = timer_proc;
tmr->client_data = client_data;
tmr->msecs = msecs;
tmr->periodic = periodic;
if (now != NULL)
{
tmr->time = *now;
}
else
{
gettimeofday(&tmr->time, NULL);
}
tmr->time.tv_sec += msecs / 1000L;
tmr->time.tv_usec += (msecs % 1000L) * 1000L;
if (tmr->time.tv_usec >= 1000000L)
{
tmr->time.tv_sec += tmr->time.tv_usec / 1000000L;
tmr->time.tv_usec %= 1000000L;
}
tmr->hash = hash(tmr);
/* Add the new timer to the proper active list. */
l_add(tmr);
return tmr;
}
long tmr_mstimeout(struct timeval *now)
{
int h;
int gotone;
long msecs, m;
register Timer *tmr;
gotone = 0;
msecs = 0;
/* Since the lists are sorted, we only need to look at the * first timer on
* each one.
*/
for (h = 0; h < HASH_SIZE; ++h)
{
tmr = timers[h];
if (tmr != NULL)
{
m = (tmr->time.tv_sec - now->tv_sec) * 1000L +
(tmr->time.tv_usec - now->tv_usec) / 1000L;
if (!gotone)
{
msecs = m;
gotone = 1;
}
else if (m < msecs)
{
msecs = m;
}
}
}
if (!gotone)
{
return INFTIM;
}
if (msecs <= 0)
{
msecs = 0;
}
return msecs;
}
void tmr_run(struct timeval *now)
{
int h;
Timer *tmr;
Timer *next;
for (h = 0; h < HASH_SIZE; ++h)
{
for (tmr = timers[h]; tmr != NULL; tmr = next)
{
next = tmr->next;
/* Since the lists are sorted, as soon as we find a timer * that isn'tmr
* ready yet, we can go on to the next list
*/
if (tmr->time.tv_sec > now->tv_sec ||
(tmr->time.tv_sec == now->tv_sec && tmr->time.tv_usec > now->tv_usec))
{
break;
}
(tmr->timer_proc)(tmr->client_data, now);
if (tmr->periodic)
{
/* Reschedule. */
tmr->time.tv_sec += tmr->msecs / 1000L;
tmr->time.tv_usec += (tmr->msecs % 1000L) * 1000L;
if (tmr->time.tv_usec >= 1000000L)
{
tmr->time.tv_sec += tmr->time.tv_usec / 1000000L;
tmr->time.tv_usec %= 1000000L;
}
l_resort(tmr);
}
else
{
tmr_cancel(tmr);
}
}
}
}
void tmr_cancel(Timer *tmr)
{
/* Remove it from its active list. */
l_remove(tmr);
/* And put it on the free list. */
tmr->next = free_timers;
free_timers = tmr;
tmr->prev = NULL;
}
void tmr_cleanup(void)
{
Timer *tmr;
while (free_timers != NULL)
{
tmr = free_timers;
free_timers = tmr->next;
httpd_free((void*)tmr);
}
}
void tmr_destroy(void)
{
int h;
for (h = 0; h < HASH_SIZE; ++h)
{
while (timers[h] != NULL)
{
tmr_cancel(timers[h]);
}
}
tmr_cleanup();
}