"Fossies" - the Fresh Open Source Software Archive

Member "pidentd-3.0.19/src/timeout.c" (20 Jan 1999, 4873 Bytes) of package /linux/misc/old/pidentd-3.0.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 "timeout.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2 ** timeout.c - Generic timeout code
    3 **
    4 ** Copyright (c) 1997 Peter Eriksson <pen@lysator.liu.se>
    5 **
    6 ** This program is free software; you can redistribute it and/or
    7 ** modify it as you wish - as long as you don't claim that you wrote
    8 ** it.
    9 **
   10 ** This program is distributed in the hope that it will be useful,
   11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   13 */
   14 
   15 #include "config.h"
   16 
   17 #include <stdio.h>
   18 #include <time.h>
   19 #include <syslog.h>
   20 
   21 #include "pidentd.h"
   22 
   23 #ifdef HAVE_THREADS
   24 
   25 
   26 static struct timeout_cb
   27 {
   28     pthread_mutex_t mtx;
   29     pthread_cond_t cv;
   30     pthread_t tid;
   31     
   32     int running;
   33 
   34     struct timeout *top;
   35 } tcb;
   36 
   37 
   38 
   39 static void *
   40 timeout_thread(void *misc)
   41 {
   42     struct timeout_cb *tcb = (struct timeout_cb *) misc;
   43     struct timeout *tp;
   44     time_t now;
   45 
   46     
   47     if (debug)
   48     fprintf(stderr, "timeout_thread() started\n");
   49         
   50     pthread_mutex_lock(&tcb->mtx);
   51     while (tcb->running)
   52     {
   53     time(&now);
   54 
   55     tp = tcb->top;
   56     while (tp && now >= tp->when)
   57     {
   58         tcb->top = tp->next;
   59         pthread_mutex_unlock(&tcb->mtx);
   60         
   61         if (tp->fun)
   62         tp->fun(tp->arg);
   63         
   64         pthread_mutex_lock(&tcb->mtx);
   65         tp = tcb->top;
   66     }
   67     
   68     if (tp == NULL)
   69         pthread_cond_wait(&tcb->cv, &tcb->mtx);
   70     else
   71     {
   72         struct timespec when;
   73 
   74         when.tv_sec = tp->when;
   75         when.tv_nsec = 0;
   76         
   77         pthread_cond_timedwait(&tcb->cv, &tcb->mtx, &when);
   78     }
   79     }
   80 
   81     if (debug)
   82     fprintf(stderr, "timeout_thread() terminating\n");
   83         
   84     return NULL;
   85 }
   86 
   87 
   88 int
   89 timeout_init(void)
   90 {
   91     pthread_mutex_init(&tcb.mtx, NULL);
   92     pthread_cond_init(&tcb.cv, NULL);
   93 
   94     tcb.top = NULL;
   95     tcb.running = 1;
   96     
   97     if (pthread_create(&tcb.tid, NULL, timeout_thread, &tcb))
   98     {
   99     syslog(LOG_ERR, "pthread_create(timeout_thread) failed: %m");
  100     tcb.running = 0;
  101     return -1;
  102     }
  103 
  104     return 0;
  105 }
  106 
  107 
  108 struct timeout *
  109 timeout_create(int timeout,
  110            void (*fun)(void *arg),
  111            void *arg)
  112 {
  113     struct timeout *tp;
  114     struct timeout **prev, *cur;
  115     
  116 
  117     tp = s_malloc(sizeof(*tp));
  118 
  119     if (debug)
  120     fprintf(stderr, "timeout_create(%d, ...) -> %08lx\n",
  121         timeout, (long) tp);
  122     
  123     tp->next = NULL;
  124     tp->when = time(NULL)+timeout;
  125 
  126     tp->fun = fun;
  127     tp->arg = arg;
  128 
  129 
  130     /*
  131     ** Insert the timeout into the correct slot in the time-sorted
  132     ** linked list
  133     */
  134     pthread_mutex_lock(&tcb.mtx);
  135     prev = &tcb.top;
  136     cur = tcb.top;
  137     while (cur != NULL && cur->when < tp->when)
  138     {
  139     prev = &cur->next;
  140     cur = cur->next;
  141     }
  142     *prev = tp;
  143     tp->next = cur;
  144     pthread_mutex_unlock(&tcb.mtx);
  145     pthread_cond_signal(&tcb.cv);
  146 
  147     return tp;
  148 }
  149 
  150 
  151 int
  152 timeout_reset(struct timeout *tp,
  153           int timeout)
  154 {
  155     struct timeout **prev, *cur;
  156     
  157     if (debug)
  158     fprintf(stderr, "timeout_reset(%08lx, %d)\n", (long) tp, timeout);
  159     
  160     pthread_mutex_lock(&tcb.mtx);
  161 
  162     tp->when = time(NULL)+timeout;
  163 
  164     /* Locate it in the timeout list */
  165     prev = &tcb.top;
  166     cur = tcb.top;
  167     while (cur != NULL && cur != tp)
  168     {
  169     prev = &cur->next;
  170     cur = cur->next;
  171     }
  172 
  173     /* Remove it from the list */
  174     if (cur == tp)
  175     *prev = cur->next;
  176     
  177     /* Reinsert it at the new position */
  178     prev = &tcb.top;
  179     cur = tcb.top;
  180     while (cur != NULL && cur->when < tp->when)
  181     {
  182     prev = &cur->next;
  183     cur = cur->next;
  184     }
  185     *prev = tp;
  186     tp->next = cur;
  187     
  188     pthread_mutex_unlock(&tcb.mtx);
  189     pthread_cond_signal(&tcb.cv);
  190     
  191     return 0;
  192 }
  193 
  194 
  195 int
  196 timeout_cancel(struct timeout *tp)
  197 {
  198     struct timeout **prev, *cur;
  199 
  200     
  201     if (debug)
  202     fprintf(stderr, "timeout_cancel(%08lx)\n", (long) tp);
  203     
  204     pthread_mutex_lock(&tcb.mtx);
  205 
  206     prev = &tcb.top;
  207     cur = tcb.top;
  208     while (cur != NULL && cur != tp)
  209     {
  210     prev = &cur->next;
  211     cur = cur->next;
  212     }
  213 
  214     if (cur == tp)
  215     {
  216     *prev = cur->next;
  217     pthread_mutex_unlock(&tcb.mtx);
  218     pthread_cond_signal(&tcb.cv);
  219     }
  220     else
  221     pthread_mutex_unlock(&tcb.mtx);
  222 
  223     s_free(tp);
  224     return 0;
  225 }
  226 
  227 
  228 #else /* No threads */
  229 
  230 #include <signal.h>
  231 
  232 /* UGLY version */
  233 
  234 static void (*saved_fun)(void *arg);
  235 static void *saved_arg;
  236 
  237 static RETSIGTYPE
  238 sigalarm_handler(int sig)
  239 {
  240     /* XXX: Shouldn't really do things like this in the signal
  241        handler, but... who cares :-) */
  242     
  243     (*saved_fun)(saved_arg);
  244 }
  245 
  246 
  247 int
  248 timeout_init(void)
  249 {
  250     signal(SIGALRM, SIG_IGN);
  251 }
  252 
  253 
  254 struct timeout *
  255 timeout_create(int timeout,
  256           void (*fun)(void *arg),
  257           void *arg)
  258 {
  259     saved_fun = fun;
  260     saved_arg = arg;
  261 
  262     if (debug)
  263     fprintf(stderr, "timeout_init(SIGALARM version) called\n");
  264     
  265     signal(SIGALRM, sigalarm_handler);
  266     alarm(timeout);
  267 }
  268 
  269 
  270 int
  271 timeout_reset(struct timeout *tp,
  272           int timeout)
  273 {
  274     signal(SIGALRM, sigalarm_handler);
  275     alarm(timeout);
  276 }
  277 
  278 
  279 int
  280 timeout_cancel(struct timeout *tp)
  281 {
  282     alarm(0);
  283     signal(SIGALRM, SIG_IGN);
  284 }
  285 
  286 #endif
  287