Annotation of embedaddon/quagga/lib/thread.c, revision 1.1.1.1

1.1       misho       1: /* Thread management routine
                      2:  * Copyright (C) 1998, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
                      3:  *
                      4:  * This file is part of GNU Zebra.
                      5:  *
                      6:  * GNU Zebra is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2, or (at your option) any
                      9:  * later version.
                     10:  *
                     11:  * GNU Zebra is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU General Public License
                     17:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
                     18:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     19:  * 02111-1307, USA.  
                     20:  */
                     21: 
                     22: /* #define DEBUG */
                     23: 
                     24: #include <zebra.h>
                     25: 
                     26: #include "thread.h"
                     27: #include "memory.h"
                     28: #include "log.h"
                     29: #include "hash.h"
                     30: #include "command.h"
                     31: #include "sigevent.h"
                     32: 
                     33: /* Recent absolute time of day */
                     34: struct timeval recent_time;
                     35: static struct timeval last_recent_time;
                     36: /* Relative time, since startup */
                     37: static struct timeval relative_time;
                     38: static struct timeval relative_time_base;
                     39: /* init flag */
                     40: static unsigned short timers_inited;
                     41: 
                     42: static struct hash *cpu_record = NULL;
                     43: 
                     44: /* Struct timeval's tv_usec one second value.  */
                     45: #define TIMER_SECOND_MICRO 1000000L
                     46: 
                     47: /* Adjust so that tv_usec is in the range [0,TIMER_SECOND_MICRO).
                     48:    And change negative values to 0. */
                     49: static struct timeval
                     50: timeval_adjust (struct timeval a)
                     51: {
                     52:   while (a.tv_usec >= TIMER_SECOND_MICRO)
                     53:     {
                     54:       a.tv_usec -= TIMER_SECOND_MICRO;
                     55:       a.tv_sec++;
                     56:     }
                     57: 
                     58:   while (a.tv_usec < 0)
                     59:     {
                     60:       a.tv_usec += TIMER_SECOND_MICRO;
                     61:       a.tv_sec--;
                     62:     }
                     63: 
                     64:   if (a.tv_sec < 0)
                     65:       /* Change negative timeouts to 0. */
                     66:       a.tv_sec = a.tv_usec = 0;
                     67: 
                     68:   return a;
                     69: }
                     70: 
                     71: static struct timeval
                     72: timeval_subtract (struct timeval a, struct timeval b)
                     73: {
                     74:   struct timeval ret;
                     75: 
                     76:   ret.tv_usec = a.tv_usec - b.tv_usec;
                     77:   ret.tv_sec = a.tv_sec - b.tv_sec;
                     78: 
                     79:   return timeval_adjust (ret);
                     80: }
                     81: 
                     82: static long
                     83: timeval_cmp (struct timeval a, struct timeval b)
                     84: {
                     85:   return (a.tv_sec == b.tv_sec
                     86:          ? a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);
                     87: }
                     88: 
                     89: static unsigned long
                     90: timeval_elapsed (struct timeval a, struct timeval b)
                     91: {
                     92:   return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO)
                     93:          + (a.tv_usec - b.tv_usec));
                     94: }
                     95: 
                     96: #ifndef HAVE_CLOCK_MONOTONIC
                     97: static void
                     98: quagga_gettimeofday_relative_adjust (void)
                     99: {
                    100:   struct timeval diff;
                    101:   if (timeval_cmp (recent_time, last_recent_time) < 0)
                    102:     {
                    103:       relative_time.tv_sec++;
                    104:       relative_time.tv_usec = 0;
                    105:     }
                    106:   else
                    107:     {
                    108:       diff = timeval_subtract (recent_time, last_recent_time);
                    109:       relative_time.tv_sec += diff.tv_sec;
                    110:       relative_time.tv_usec += diff.tv_usec;
                    111:       relative_time = timeval_adjust (relative_time);
                    112:     }
                    113:   last_recent_time = recent_time;
                    114: }
                    115: #endif /* !HAVE_CLOCK_MONOTONIC */
                    116: 
                    117: /* gettimeofday wrapper, to keep recent_time updated */
                    118: static int
                    119: quagga_gettimeofday (struct timeval *tv)
                    120: {
                    121:   int ret;
                    122:   
                    123:   assert (tv);
                    124:   
                    125:   if (!(ret = gettimeofday (&recent_time, NULL)))
                    126:     {
                    127:       /* init... */
                    128:       if (!timers_inited)
                    129:         {
                    130:           relative_time_base = last_recent_time = recent_time;
                    131:           timers_inited = 1;
                    132:         }
                    133:       /* avoid copy if user passed recent_time pointer.. */
                    134:       if (tv != &recent_time)
                    135:         *tv = recent_time;
                    136:       return 0;
                    137:     }
                    138:   return ret;
                    139: }
                    140: 
                    141: static int
                    142: quagga_get_relative (struct timeval *tv)
                    143: {
                    144:   int ret;
                    145: 
                    146: #ifdef HAVE_CLOCK_MONOTONIC
                    147:   {
                    148:     struct timespec tp;
                    149:     if (!(ret = clock_gettime (CLOCK_MONOTONIC, &tp)))
                    150:       {
                    151:         relative_time.tv_sec = tp.tv_sec;
                    152:         relative_time.tv_usec = tp.tv_nsec / 1000;
                    153:       }
                    154:   }
                    155: #else /* !HAVE_CLOCK_MONOTONIC */
                    156:   if (!(ret = quagga_gettimeofday (&recent_time)))
                    157:     quagga_gettimeofday_relative_adjust();
                    158: #endif /* HAVE_CLOCK_MONOTONIC */
                    159: 
                    160:   if (tv)
                    161:     *tv = relative_time;
                    162: 
                    163:   return ret;
                    164: }
                    165: 
                    166: /* Get absolute time stamp, but in terms of the internal timer
                    167:  * Could be wrong, but at least won't go back.
                    168:  */
                    169: static void
                    170: quagga_real_stabilised (struct timeval *tv)
                    171: {
                    172:   *tv = relative_time_base;
                    173:   tv->tv_sec += relative_time.tv_sec;
                    174:   tv->tv_usec += relative_time.tv_usec;
                    175:   *tv = timeval_adjust (*tv);
                    176: }
                    177: 
                    178: /* Exported Quagga timestamp function.
                    179:  * Modelled on POSIX clock_gettime.
                    180:  */
                    181: int
                    182: quagga_gettime (enum quagga_clkid clkid, struct timeval *tv)
                    183: {
                    184:   switch (clkid)
                    185:     {
                    186:       case QUAGGA_CLK_REALTIME:
                    187:         return quagga_gettimeofday (tv);
                    188:       case QUAGGA_CLK_MONOTONIC:
                    189:         return quagga_get_relative (tv);
                    190:       case QUAGGA_CLK_REALTIME_STABILISED:
                    191:         quagga_real_stabilised (tv);
                    192:         return 0;
                    193:       default:
                    194:         errno = EINVAL;
                    195:         return -1;
                    196:     }
                    197: }
                    198: 
                    199: /* time_t value in terms of stabilised absolute time. 
                    200:  * replacement for POSIX time()
                    201:  */
                    202: time_t
                    203: quagga_time (time_t *t)
                    204: {
                    205:   struct timeval tv;
                    206:   quagga_real_stabilised (&tv);
                    207:   if (t)
                    208:     *t = tv.tv_sec;
                    209:   return tv.tv_sec;
                    210: }
                    211: 
                    212: /* Public export of recent_relative_time by value */
                    213: struct timeval
                    214: recent_relative_time (void)
                    215: {
                    216:   return relative_time;
                    217: }
                    218: 
                    219: static unsigned int
                    220: cpu_record_hash_key (struct cpu_thread_history *a)
                    221: {
                    222:   return (uintptr_t) a->func;
                    223: }
                    224: 
                    225: static int 
                    226: cpu_record_hash_cmp (const struct cpu_thread_history *a,
                    227:                     const struct cpu_thread_history *b)
                    228: {
                    229:   return a->func == b->func;
                    230: }
                    231: 
                    232: static void *
                    233: cpu_record_hash_alloc (struct cpu_thread_history *a)
                    234: {
                    235:   struct cpu_thread_history *new;
                    236:   new = XCALLOC (MTYPE_THREAD_STATS, sizeof (struct cpu_thread_history));
                    237:   new->func = a->func;
                    238:   new->funcname = XSTRDUP(MTYPE_THREAD_FUNCNAME, a->funcname);
                    239:   return new;
                    240: }
                    241: 
                    242: static void
                    243: cpu_record_hash_free (void *a)
                    244: {
                    245:   struct cpu_thread_history *hist = a;
                    246:  
                    247:   XFREE (MTYPE_THREAD_FUNCNAME, hist->funcname);
                    248:   XFREE (MTYPE_THREAD_STATS, hist);
                    249: }
                    250: 
                    251: static inline void 
                    252: vty_out_cpu_thread_history(struct vty* vty,
                    253:                           struct cpu_thread_history *a)
                    254: {
                    255: #ifdef HAVE_RUSAGE
                    256:   vty_out(vty, "%7ld.%03ld %9d %8ld %9ld %8ld %9ld",
                    257:          a->cpu.total/1000, a->cpu.total%1000, a->total_calls,
                    258:          a->cpu.total/a->total_calls, a->cpu.max,
                    259:          a->real.total/a->total_calls, a->real.max);
                    260: #else
                    261:   vty_out(vty, "%7ld.%03ld %9d %8ld %9ld",
                    262:          a->real.total/1000, a->real.total%1000, a->total_calls,
                    263:          a->real.total/a->total_calls, a->real.max);
                    264: #endif
                    265:   vty_out(vty, " %c%c%c%c%c%c %s%s",
                    266:          a->types & (1 << THREAD_READ) ? 'R':' ',
                    267:          a->types & (1 << THREAD_WRITE) ? 'W':' ',
                    268:          a->types & (1 << THREAD_TIMER) ? 'T':' ',
                    269:          a->types & (1 << THREAD_EVENT) ? 'E':' ',
                    270:          a->types & (1 << THREAD_EXECUTE) ? 'X':' ',
                    271:          a->types & (1 << THREAD_BACKGROUND) ? 'B' : ' ',
                    272:          a->funcname, VTY_NEWLINE);
                    273: }
                    274: 
                    275: static void
                    276: cpu_record_hash_print(struct hash_backet *bucket, 
                    277:                      void *args[])
                    278: {
                    279:   struct cpu_thread_history *totals = args[0];
                    280:   struct vty *vty = args[1];
                    281:   thread_type *filter = args[2];
                    282:   struct cpu_thread_history *a = bucket->data;
                    283:   
                    284:   a = bucket->data;
                    285:   if ( !(a->types & *filter) )
                    286:        return;
                    287:   vty_out_cpu_thread_history(vty,a);
                    288:   totals->total_calls += a->total_calls;
                    289:   totals->real.total += a->real.total;
                    290:   if (totals->real.max < a->real.max)
                    291:     totals->real.max = a->real.max;
                    292: #ifdef HAVE_RUSAGE
                    293:   totals->cpu.total += a->cpu.total;
                    294:   if (totals->cpu.max < a->cpu.max)
                    295:     totals->cpu.max = a->cpu.max;
                    296: #endif
                    297: }
                    298: 
                    299: static void
                    300: cpu_record_print(struct vty *vty, thread_type filter)
                    301: {
                    302:   struct cpu_thread_history tmp;
                    303:   void *args[3] = {&tmp, vty, &filter};
                    304: 
                    305:   memset(&tmp, 0, sizeof tmp);
                    306:   tmp.funcname = (char *)"TOTAL";
                    307:   tmp.types = filter;
                    308: 
                    309: #ifdef HAVE_RUSAGE
                    310:   vty_out(vty, "%21s %18s %18s%s",
                    311:          "", "CPU (user+system):", "Real (wall-clock):", VTY_NEWLINE);
                    312: #endif
                    313:   vty_out(vty, "Runtime(ms)   Invoked Avg uSec Max uSecs");
                    314: #ifdef HAVE_RUSAGE
                    315:   vty_out(vty, " Avg uSec Max uSecs");
                    316: #endif
                    317:   vty_out(vty, "  Type  Thread%s", VTY_NEWLINE);
                    318:   hash_iterate(cpu_record,
                    319:               (void(*)(struct hash_backet*,void*))cpu_record_hash_print,
                    320:               args);
                    321: 
                    322:   if (tmp.total_calls > 0)
                    323:     vty_out_cpu_thread_history(vty, &tmp);
                    324: }
                    325: 
                    326: DEFUN(show_thread_cpu,
                    327:       show_thread_cpu_cmd,
                    328:       "show thread cpu [FILTER]",
                    329:       SHOW_STR
                    330:       "Thread information\n"
                    331:       "Thread CPU usage\n"
                    332:       "Display filter (rwtexb)\n")
                    333: {
                    334:   int i = 0;
                    335:   thread_type filter = (thread_type) -1U;
                    336: 
                    337:   if (argc > 0)
                    338:     {
                    339:       filter = 0;
                    340:       while (argv[0][i] != '\0')
                    341:        {
                    342:          switch ( argv[0][i] )
                    343:            {
                    344:            case 'r':
                    345:            case 'R':
                    346:              filter |= (1 << THREAD_READ);
                    347:              break;
                    348:            case 'w':
                    349:            case 'W':
                    350:              filter |= (1 << THREAD_WRITE);
                    351:              break;
                    352:            case 't':
                    353:            case 'T':
                    354:              filter |= (1 << THREAD_TIMER);
                    355:              break;
                    356:            case 'e':
                    357:            case 'E':
                    358:              filter |= (1 << THREAD_EVENT);
                    359:              break;
                    360:            case 'x':
                    361:            case 'X':
                    362:              filter |= (1 << THREAD_EXECUTE);
                    363:              break;
                    364:            case 'b':
                    365:            case 'B':
                    366:              filter |= (1 << THREAD_BACKGROUND);
                    367:              break;
                    368:            default:
                    369:              break;
                    370:            }
                    371:          ++i;
                    372:        }
                    373:       if (filter == 0)
                    374:        {
                    375:          vty_out(vty, "Invalid filter \"%s\" specified,"
                    376:                   " must contain at least one of 'RWTEXB'%s",
                    377:                  argv[0], VTY_NEWLINE);
                    378:          return CMD_WARNING;
                    379:        }
                    380:     }
                    381: 
                    382:   cpu_record_print(vty, filter);
                    383:   return CMD_SUCCESS;
                    384: }
                    385: 
                    386: static void
                    387: cpu_record_hash_clear (struct hash_backet *bucket, 
                    388:                      void *args)
                    389: {
                    390:   thread_type *filter = args;
                    391:   struct cpu_thread_history *a = bucket->data;
                    392:   
                    393:   a = bucket->data;
                    394:   if ( !(a->types & *filter) )
                    395:        return;
                    396:   
                    397:   hash_release (cpu_record, bucket->data);
                    398: }
                    399: 
                    400: static void
                    401: cpu_record_clear (thread_type filter)
                    402: {
                    403:   thread_type *tmp = &filter;
                    404:   hash_iterate (cpu_record,
                    405:                (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
                    406:                tmp);
                    407: }
                    408: 
                    409: DEFUN(clear_thread_cpu,
                    410:       clear_thread_cpu_cmd,
                    411:       "clear thread cpu [FILTER]",
                    412:       "Clear stored data\n"
                    413:       "Thread information\n"
                    414:       "Thread CPU usage\n"
                    415:       "Display filter (rwtexb)\n")
                    416: {
                    417:   int i = 0;
                    418:   thread_type filter = (thread_type) -1U;
                    419: 
                    420:   if (argc > 0)
                    421:     {
                    422:       filter = 0;
                    423:       while (argv[0][i] != '\0')
                    424:        {
                    425:          switch ( argv[0][i] )
                    426:            {
                    427:            case 'r':
                    428:            case 'R':
                    429:              filter |= (1 << THREAD_READ);
                    430:              break;
                    431:            case 'w':
                    432:            case 'W':
                    433:              filter |= (1 << THREAD_WRITE);
                    434:              break;
                    435:            case 't':
                    436:            case 'T':
                    437:              filter |= (1 << THREAD_TIMER);
                    438:              break;
                    439:            case 'e':
                    440:            case 'E':
                    441:              filter |= (1 << THREAD_EVENT);
                    442:              break;
                    443:            case 'x':
                    444:            case 'X':
                    445:              filter |= (1 << THREAD_EXECUTE);
                    446:              break;
                    447:            case 'b':
                    448:            case 'B':
                    449:              filter |= (1 << THREAD_BACKGROUND);
                    450:              break;
                    451:            default:
                    452:              break;
                    453:            }
                    454:          ++i;
                    455:        }
                    456:       if (filter == 0)
                    457:        {
                    458:          vty_out(vty, "Invalid filter \"%s\" specified,"
                    459:                   " must contain at least one of 'RWTEXB'%s",
                    460:                  argv[0], VTY_NEWLINE);
                    461:          return CMD_WARNING;
                    462:        }
                    463:     }
                    464: 
                    465:   cpu_record_clear (filter);
                    466:   return CMD_SUCCESS;
                    467: }
                    468: 
                    469: /* List allocation and head/tail print out. */
                    470: static void
                    471: thread_list_debug (struct thread_list *list)
                    472: {
                    473:   printf ("count [%d] head [%p] tail [%p]\n",
                    474:          list->count, list->head, list->tail);
                    475: }
                    476: 
                    477: /* Debug print for thread_master. */
                    478: static void  __attribute__ ((unused))
                    479: thread_master_debug (struct thread_master *m)
                    480: {
                    481:   printf ("-----------\n");
                    482:   printf ("readlist  : ");
                    483:   thread_list_debug (&m->read);
                    484:   printf ("writelist : ");
                    485:   thread_list_debug (&m->write);
                    486:   printf ("timerlist : ");
                    487:   thread_list_debug (&m->timer);
                    488:   printf ("eventlist : ");
                    489:   thread_list_debug (&m->event);
                    490:   printf ("unuselist : ");
                    491:   thread_list_debug (&m->unuse);
                    492:   printf ("bgndlist : ");
                    493:   thread_list_debug (&m->background);
                    494:   printf ("total alloc: [%ld]\n", m->alloc);
                    495:   printf ("-----------\n");
                    496: }
                    497: 
                    498: /* Allocate new thread master.  */
                    499: struct thread_master *
                    500: thread_master_create ()
                    501: {
                    502:   if (cpu_record == NULL) 
                    503:     cpu_record 
                    504:       = hash_create_size (1011, (unsigned int (*) (void *))cpu_record_hash_key, 
                    505:                           (int (*) (const void *, const void *))cpu_record_hash_cmp);
                    506:     
                    507:   return (struct thread_master *) XCALLOC (MTYPE_THREAD_MASTER,
                    508:                                           sizeof (struct thread_master));
                    509: }
                    510: 
                    511: /* Add a new thread to the list.  */
                    512: static void
                    513: thread_list_add (struct thread_list *list, struct thread *thread)
                    514: {
                    515:   thread->next = NULL;
                    516:   thread->prev = list->tail;
                    517:   if (list->tail)
                    518:     list->tail->next = thread;
                    519:   else
                    520:     list->head = thread;
                    521:   list->tail = thread;
                    522:   list->count++;
                    523: }
                    524: 
                    525: /* Add a new thread just before the point.  */
                    526: static void
                    527: thread_list_add_before (struct thread_list *list, 
                    528:                        struct thread *point, 
                    529:                        struct thread *thread)
                    530: {
                    531:   thread->next = point;
                    532:   thread->prev = point->prev;
                    533:   if (point->prev)
                    534:     point->prev->next = thread;
                    535:   else
                    536:     list->head = thread;
                    537:   point->prev = thread;
                    538:   list->count++;
                    539: }
                    540: 
                    541: /* Delete a thread from the list. */
                    542: static struct thread *
                    543: thread_list_delete (struct thread_list *list, struct thread *thread)
                    544: {
                    545:   if (thread->next)
                    546:     thread->next->prev = thread->prev;
                    547:   else
                    548:     list->tail = thread->prev;
                    549:   if (thread->prev)
                    550:     thread->prev->next = thread->next;
                    551:   else
                    552:     list->head = thread->next;
                    553:   thread->next = thread->prev = NULL;
                    554:   list->count--;
                    555:   return thread;
                    556: }
                    557: 
                    558: /* Move thread to unuse list. */
                    559: static void
                    560: thread_add_unuse (struct thread_master *m, struct thread *thread)
                    561: {
                    562:   assert (m != NULL && thread != NULL);
                    563:   assert (thread->next == NULL);
                    564:   assert (thread->prev == NULL);
                    565:   assert (thread->type == THREAD_UNUSED);
                    566:   thread_list_add (&m->unuse, thread);
                    567:   /* XXX: Should we deallocate funcname here? */
                    568: }
                    569: 
                    570: /* Free all unused thread. */
                    571: static void
                    572: thread_list_free (struct thread_master *m, struct thread_list *list)
                    573: {
                    574:   struct thread *t;
                    575:   struct thread *next;
                    576: 
                    577:   for (t = list->head; t; t = next)
                    578:     {
                    579:       next = t->next;
                    580:       if (t->funcname)
                    581:         XFREE (MTYPE_THREAD_FUNCNAME, t->funcname);
                    582:       XFREE (MTYPE_THREAD, t);
                    583:       list->count--;
                    584:       m->alloc--;
                    585:     }
                    586: }
                    587: 
                    588: /* Stop thread scheduler. */
                    589: void
                    590: thread_master_free (struct thread_master *m)
                    591: {
                    592:   thread_list_free (m, &m->read);
                    593:   thread_list_free (m, &m->write);
                    594:   thread_list_free (m, &m->timer);
                    595:   thread_list_free (m, &m->event);
                    596:   thread_list_free (m, &m->ready);
                    597:   thread_list_free (m, &m->unuse);
                    598:   thread_list_free (m, &m->background);
                    599:   
                    600:   XFREE (MTYPE_THREAD_MASTER, m);
                    601: 
                    602:   if (cpu_record)
                    603:     {
                    604:       hash_clean (cpu_record, cpu_record_hash_free);
                    605:       hash_free (cpu_record);
                    606:       cpu_record = NULL;
                    607:     }
                    608: }
                    609: 
                    610: /* Thread list is empty or not.  */
                    611: static inline int
                    612: thread_empty (struct thread_list *list)
                    613: {
                    614:   return  list->head ? 0 : 1;
                    615: }
                    616: 
                    617: /* Delete top of the list and return it. */
                    618: static struct thread *
                    619: thread_trim_head (struct thread_list *list)
                    620: {
                    621:   if (!thread_empty (list))
                    622:     return thread_list_delete (list, list->head);
                    623:   return NULL;
                    624: }
                    625: 
                    626: /* Return remain time in second. */
                    627: unsigned long
                    628: thread_timer_remain_second (struct thread *thread)
                    629: {
                    630:   quagga_get_relative (NULL);
                    631:   
                    632:   if (thread->u.sands.tv_sec - relative_time.tv_sec > 0)
                    633:     return thread->u.sands.tv_sec - relative_time.tv_sec;
                    634:   else
                    635:     return 0;
                    636: }
                    637: 
                    638: /* Trim blankspace and "()"s */
                    639: static char *
                    640: strip_funcname (const char *funcname) 
                    641: {
                    642:   char buff[100];
                    643:   char tmp, *ret, *e, *b = buff;
                    644: 
                    645:   strncpy(buff, funcname, sizeof(buff));
                    646:   buff[ sizeof(buff) -1] = '\0';
                    647:   e = buff +strlen(buff) -1;
                    648: 
                    649:   /* Wont work for funcname ==  "Word (explanation)"  */
                    650: 
                    651:   while (*b == ' ' || *b == '(')
                    652:     ++b;
                    653:   while (*e == ' ' || *e == ')')
                    654:     --e;
                    655:   e++;
                    656: 
                    657:   tmp = *e;
                    658:   *e = '\0';
                    659:   ret  = XSTRDUP (MTYPE_THREAD_FUNCNAME, b);
                    660:   *e = tmp;
                    661: 
                    662:   return ret;
                    663: }
                    664: 
                    665: /* Get new thread.  */
                    666: static struct thread *
                    667: thread_get (struct thread_master *m, u_char type,
                    668:            int (*func) (struct thread *), void *arg, const char* funcname)
                    669: {
                    670:   struct thread *thread;
                    671: 
                    672:   if (!thread_empty (&m->unuse))
                    673:     {
                    674:       thread = thread_trim_head (&m->unuse);
                    675:       if (thread->funcname)
                    676:         XFREE(MTYPE_THREAD_FUNCNAME, thread->funcname);
                    677:     }
                    678:   else
                    679:     {
                    680:       thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread));
                    681:       m->alloc++;
                    682:     }
                    683:   thread->type = type;
                    684:   thread->add_type = type;
                    685:   thread->master = m;
                    686:   thread->func = func;
                    687:   thread->arg = arg;
                    688:   
                    689:   thread->funcname = strip_funcname(funcname);
                    690: 
                    691:   return thread;
                    692: }
                    693: 
                    694: /* Add new read thread. */
                    695: struct thread *
                    696: funcname_thread_add_read (struct thread_master *m, 
                    697:                 int (*func) (struct thread *), void *arg, int fd, const char* funcname)
                    698: {
                    699:   struct thread *thread;
                    700: 
                    701:   assert (m != NULL);
                    702: 
                    703:   if (FD_ISSET (fd, &m->readfd))
                    704:     {
                    705:       zlog (NULL, LOG_WARNING, "There is already read fd [%d]", fd);
                    706:       return NULL;
                    707:     }
                    708: 
                    709:   thread = thread_get (m, THREAD_READ, func, arg, funcname);
                    710:   FD_SET (fd, &m->readfd);
                    711:   thread->u.fd = fd;
                    712:   thread_list_add (&m->read, thread);
                    713: 
                    714:   return thread;
                    715: }
                    716: 
                    717: /* Add new write thread. */
                    718: struct thread *
                    719: funcname_thread_add_write (struct thread_master *m,
                    720:                 int (*func) (struct thread *), void *arg, int fd, const char* funcname)
                    721: {
                    722:   struct thread *thread;
                    723: 
                    724:   assert (m != NULL);
                    725: 
                    726:   if (FD_ISSET (fd, &m->writefd))
                    727:     {
                    728:       zlog (NULL, LOG_WARNING, "There is already write fd [%d]", fd);
                    729:       return NULL;
                    730:     }
                    731: 
                    732:   thread = thread_get (m, THREAD_WRITE, func, arg, funcname);
                    733:   FD_SET (fd, &m->writefd);
                    734:   thread->u.fd = fd;
                    735:   thread_list_add (&m->write, thread);
                    736: 
                    737:   return thread;
                    738: }
                    739: 
                    740: static struct thread *
                    741: funcname_thread_add_timer_timeval (struct thread_master *m,
                    742:                                    int (*func) (struct thread *), 
                    743:                                   int type,
                    744:                                   void *arg, 
                    745:                                   struct timeval *time_relative, 
                    746:                                   const char* funcname)
                    747: {
                    748:   struct thread *thread;
                    749:   struct thread_list *list;
                    750:   struct timeval alarm_time;
                    751:   struct thread *tt;
                    752: 
                    753:   assert (m != NULL);
                    754: 
                    755:   assert (type == THREAD_TIMER || type == THREAD_BACKGROUND);
                    756:   assert (time_relative);
                    757:   
                    758:   list = ((type == THREAD_TIMER) ? &m->timer : &m->background);
                    759:   thread = thread_get (m, type, func, arg, funcname);
                    760: 
                    761:   /* Do we need jitter here? */
                    762:   quagga_get_relative (NULL);
                    763:   alarm_time.tv_sec = relative_time.tv_sec + time_relative->tv_sec;
                    764:   alarm_time.tv_usec = relative_time.tv_usec + time_relative->tv_usec;
                    765:   thread->u.sands = timeval_adjust(alarm_time);
                    766: 
                    767:   /* Sort by timeval. */
                    768:   for (tt = list->head; tt; tt = tt->next)
                    769:     if (timeval_cmp (thread->u.sands, tt->u.sands) <= 0)
                    770:       break;
                    771: 
                    772:   if (tt)
                    773:     thread_list_add_before (list, tt, thread);
                    774:   else
                    775:     thread_list_add (list, thread);
                    776: 
                    777:   return thread;
                    778: }
                    779: 
                    780: 
                    781: /* Add timer event thread. */
                    782: struct thread *
                    783: funcname_thread_add_timer (struct thread_master *m,
                    784:                           int (*func) (struct thread *), 
                    785:                           void *arg, long timer, const char* funcname)
                    786: {
                    787:   struct timeval trel;
                    788: 
                    789:   assert (m != NULL);
                    790: 
                    791:   trel.tv_sec = timer;
                    792:   trel.tv_usec = 0;
                    793: 
                    794:   return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, 
                    795:                                             &trel, funcname);
                    796: }
                    797: 
                    798: /* Add timer event thread with "millisecond" resolution */
                    799: struct thread *
                    800: funcname_thread_add_timer_msec (struct thread_master *m,
                    801:                                 int (*func) (struct thread *), 
                    802:                                 void *arg, long timer, const char* funcname)
                    803: {
                    804:   struct timeval trel;
                    805: 
                    806:   assert (m != NULL);
                    807: 
                    808:   trel.tv_sec = timer / 1000;
                    809:   trel.tv_usec = 1000*(timer % 1000);
                    810: 
                    811:   return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, 
                    812:                                             arg, &trel, funcname);
                    813: }
                    814: 
                    815: /* Add a background thread, with an optional millisec delay */
                    816: struct thread *
                    817: funcname_thread_add_background (struct thread_master *m,
                    818:                                 int (*func) (struct thread *),
                    819:                                 void *arg, long delay, 
                    820:                                 const char *funcname)
                    821: {
                    822:   struct timeval trel;
                    823:   
                    824:   assert (m != NULL);
                    825:   
                    826:   if (delay)
                    827:     {
                    828:       trel.tv_sec = delay / 1000;
                    829:       trel.tv_usec = 1000*(delay % 1000);
                    830:     }
                    831:   else
                    832:     {
                    833:       trel.tv_sec = 0;
                    834:       trel.tv_usec = 0;
                    835:     }
                    836: 
                    837:   return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND,
                    838:                                             arg, &trel, funcname);
                    839: }
                    840: 
                    841: /* Add simple event thread. */
                    842: struct thread *
                    843: funcname_thread_add_event (struct thread_master *m,
                    844:                  int (*func) (struct thread *), void *arg, int val, const char* funcname)
                    845: {
                    846:   struct thread *thread;
                    847: 
                    848:   assert (m != NULL);
                    849: 
                    850:   thread = thread_get (m, THREAD_EVENT, func, arg, funcname);
                    851:   thread->u.val = val;
                    852:   thread_list_add (&m->event, thread);
                    853: 
                    854:   return thread;
                    855: }
                    856: 
                    857: /* Cancel thread from scheduler. */
                    858: void
                    859: thread_cancel (struct thread *thread)
                    860: {
                    861:   struct thread_list *list;
                    862:   
                    863:   switch (thread->type)
                    864:     {
                    865:     case THREAD_READ:
                    866:       assert (FD_ISSET (thread->u.fd, &thread->master->readfd));
                    867:       FD_CLR (thread->u.fd, &thread->master->readfd);
                    868:       list = &thread->master->read;
                    869:       break;
                    870:     case THREAD_WRITE:
                    871:       assert (FD_ISSET (thread->u.fd, &thread->master->writefd));
                    872:       FD_CLR (thread->u.fd, &thread->master->writefd);
                    873:       list = &thread->master->write;
                    874:       break;
                    875:     case THREAD_TIMER:
                    876:       list = &thread->master->timer;
                    877:       break;
                    878:     case THREAD_EVENT:
                    879:       list = &thread->master->event;
                    880:       break;
                    881:     case THREAD_READY:
                    882:       list = &thread->master->ready;
                    883:       break;
                    884:     case THREAD_BACKGROUND:
                    885:       list = &thread->master->background;
                    886:       break;
                    887:     default:
                    888:       return;
                    889:       break;
                    890:     }
                    891:   thread_list_delete (list, thread);
                    892:   thread->type = THREAD_UNUSED;
                    893:   thread_add_unuse (thread->master, thread);
                    894: }
                    895: 
                    896: /* Delete all events which has argument value arg. */
                    897: unsigned int
                    898: thread_cancel_event (struct thread_master *m, void *arg)
                    899: {
                    900:   unsigned int ret = 0;
                    901:   struct thread *thread;
                    902: 
                    903:   thread = m->event.head;
                    904:   while (thread)
                    905:     {
                    906:       struct thread *t;
                    907: 
                    908:       t = thread;
                    909:       thread = t->next;
                    910: 
                    911:       if (t->arg == arg)
                    912:         {
                    913:           ret++;
                    914:           thread_list_delete (&m->event, t);
                    915:           t->type = THREAD_UNUSED;
                    916:           thread_add_unuse (m, t);
                    917:         }
                    918:     }
                    919:   return ret;
                    920: }
                    921: 
                    922: static struct timeval *
                    923: thread_timer_wait (struct thread_list *tlist, struct timeval *timer_val)
                    924: {
                    925:   if (!thread_empty (tlist))
                    926:     {
                    927:       *timer_val = timeval_subtract (tlist->head->u.sands, relative_time);
                    928:       return timer_val;
                    929:     }
                    930:   return NULL;
                    931: }
                    932: 
                    933: static struct thread *
                    934: thread_run (struct thread_master *m, struct thread *thread,
                    935:            struct thread *fetch)
                    936: {
                    937:   *fetch = *thread;
                    938:   thread->type = THREAD_UNUSED;
                    939:   thread->funcname = NULL;  /* thread_call will free fetch's copied pointer */
                    940:   thread_add_unuse (m, thread);
                    941:   return fetch;
                    942: }
                    943: 
                    944: static int
                    945: thread_process_fd (struct thread_list *list, fd_set *fdset, fd_set *mfdset)
                    946: {
                    947:   struct thread *thread;
                    948:   struct thread *next;
                    949:   int ready = 0;
                    950:   
                    951:   assert (list);
                    952:   
                    953:   for (thread = list->head; thread; thread = next)
                    954:     {
                    955:       next = thread->next;
                    956: 
                    957:       if (FD_ISSET (THREAD_FD (thread), fdset))
                    958:         {
                    959:           assert (FD_ISSET (THREAD_FD (thread), mfdset));
                    960:           FD_CLR(THREAD_FD (thread), mfdset);
                    961:           thread_list_delete (list, thread);
                    962:           thread_list_add (&thread->master->ready, thread);
                    963:           thread->type = THREAD_READY;
                    964:           ready++;
                    965:         }
                    966:     }
                    967:   return ready;
                    968: }
                    969: 
                    970: /* Add all timers that have popped to the ready list. */
                    971: static unsigned int
                    972: thread_timer_process (struct thread_list *list, struct timeval *timenow)
                    973: {
                    974:   struct thread *thread;
                    975:   unsigned int ready = 0;
                    976:   
                    977:   for (thread = list->head; thread; thread = thread->next)
                    978:     {
                    979:       if (timeval_cmp (*timenow, thread->u.sands) < 0)
                    980:         return ready;
                    981:       thread_list_delete (list, thread);
                    982:       thread->type = THREAD_READY;
                    983:       thread_list_add (&thread->master->ready, thread);
                    984:       ready++;
                    985:     }
                    986:   return ready;
                    987: }
                    988: 
                    989: /* process a list en masse, e.g. for event thread lists */
                    990: static unsigned int
                    991: thread_process (struct thread_list *list)
                    992: {
                    993:   struct thread *thread;
                    994:   unsigned int ready = 0;
                    995:   
                    996:   for (thread = list->head; thread; thread = thread->next)
                    997:     {
                    998:       thread_list_delete (list, thread);
                    999:       thread->type = THREAD_READY;
                   1000:       thread_list_add (&thread->master->ready, thread);
                   1001:       ready++;
                   1002:     }
                   1003:   return ready;
                   1004: }
                   1005: 
                   1006: 
                   1007: /* Fetch next ready thread. */
                   1008: struct thread *
                   1009: thread_fetch (struct thread_master *m, struct thread *fetch)
                   1010: {
                   1011:   struct thread *thread;
                   1012:   fd_set readfd;
                   1013:   fd_set writefd;
                   1014:   fd_set exceptfd;
                   1015:   struct timeval timer_val = { .tv_sec = 0, .tv_usec = 0 };
                   1016:   struct timeval timer_val_bg;
                   1017:   struct timeval *timer_wait = &timer_val;
                   1018:   struct timeval *timer_wait_bg;
                   1019: 
                   1020:   while (1)
                   1021:     {
                   1022:       int num = 0;
                   1023:       
                   1024:       /* Signals pre-empt everything */
                   1025:       quagga_sigevent_process ();
                   1026:        
                   1027:       /* Drain the ready queue of already scheduled jobs, before scheduling
                   1028:        * more.
                   1029:        */
                   1030:       if ((thread = thread_trim_head (&m->ready)) != NULL)
                   1031:         return thread_run (m, thread, fetch);
                   1032:       
                   1033:       /* To be fair to all kinds of threads, and avoid starvation, we
                   1034:        * need to be careful to consider all thread types for scheduling
                   1035:        * in each quanta. I.e. we should not return early from here on.
                   1036:        */
                   1037:        
                   1038:       /* Normal event are the next highest priority.  */
                   1039:       thread_process (&m->event);
                   1040:       
                   1041:       /* Structure copy.  */
                   1042:       readfd = m->readfd;
                   1043:       writefd = m->writefd;
                   1044:       exceptfd = m->exceptfd;
                   1045:       
                   1046:       /* Calculate select wait timer if nothing else to do */
                   1047:       if (m->ready.count == 0)
                   1048:         {
                   1049:           quagga_get_relative (NULL);
                   1050:           timer_wait = thread_timer_wait (&m->timer, &timer_val);
                   1051:           timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg);
                   1052:           
                   1053:           if (timer_wait_bg &&
                   1054:               (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
                   1055:             timer_wait = timer_wait_bg;
                   1056:         }
                   1057:       
                   1058:       num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
                   1059:       
                   1060:       /* Signals should get quick treatment */
                   1061:       if (num < 0)
                   1062:         {
                   1063:           if (errno == EINTR)
                   1064:             continue; /* signal received - process it */
                   1065:           zlog_warn ("select() error: %s", safe_strerror (errno));
                   1066:             return NULL;
                   1067:         }
                   1068: 
                   1069:       /* Check foreground timers.  Historically, they have had higher
                   1070:          priority than I/O threads, so let's push them onto the ready
                   1071:         list in front of the I/O threads. */
                   1072:       quagga_get_relative (NULL);
                   1073:       thread_timer_process (&m->timer, &relative_time);
                   1074:       
                   1075:       /* Got IO, process it */
                   1076:       if (num > 0)
                   1077:         {
                   1078:           /* Normal priority read thead. */
                   1079:           thread_process_fd (&m->read, &readfd, &m->readfd);
                   1080:           /* Write thead. */
                   1081:           thread_process_fd (&m->write, &writefd, &m->writefd);
                   1082:         }
                   1083: 
                   1084: #if 0
                   1085:       /* If any threads were made ready above (I/O or foreground timer),
                   1086:          perhaps we should avoid adding background timers to the ready
                   1087:         list at this time.  If this is code is uncommented, then background
                   1088:         timer threads will not run unless there is nothing else to do. */
                   1089:       if ((thread = thread_trim_head (&m->ready)) != NULL)
                   1090:         return thread_run (m, thread, fetch);
                   1091: #endif
                   1092: 
                   1093:       /* Background timer/events, lowest priority */
                   1094:       thread_timer_process (&m->background, &relative_time);
                   1095:       
                   1096:       if ((thread = thread_trim_head (&m->ready)) != NULL)
                   1097:         return thread_run (m, thread, fetch);
                   1098:     }
                   1099: }
                   1100: 
                   1101: unsigned long
                   1102: thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime)
                   1103: {
                   1104: #ifdef HAVE_RUSAGE
                   1105:   /* This is 'user + sys' time.  */
                   1106:   *cputime = timeval_elapsed (now->cpu.ru_utime, start->cpu.ru_utime) +
                   1107:             timeval_elapsed (now->cpu.ru_stime, start->cpu.ru_stime);
                   1108: #else
                   1109:   *cputime = 0;
                   1110: #endif /* HAVE_RUSAGE */
                   1111:   return timeval_elapsed (now->real, start->real);
                   1112: }
                   1113: 
                   1114: /* We should aim to yield after THREAD_YIELD_TIME_SLOT milliseconds. 
                   1115:    Note: we are using real (wall clock) time for this calculation.
                   1116:    It could be argued that CPU time may make more sense in certain
                   1117:    contexts.  The things to consider are whether the thread may have
                   1118:    blocked (in which case wall time increases, but CPU time does not),
                   1119:    or whether the system is heavily loaded with other processes competing
                   1120:    for CPU time.  On balance, wall clock time seems to make sense. 
                   1121:    Plus it has the added benefit that gettimeofday should be faster
                   1122:    than calling getrusage. */
                   1123: int
                   1124: thread_should_yield (struct thread *thread)
                   1125: {
                   1126:   quagga_get_relative (NULL);
                   1127:   return (timeval_elapsed(relative_time, thread->ru.real) >
                   1128:          THREAD_YIELD_TIME_SLOT);
                   1129: }
                   1130: 
                   1131: void
                   1132: thread_getrusage (RUSAGE_T *r)
                   1133: {
                   1134:   quagga_get_relative (NULL);
                   1135: #ifdef HAVE_RUSAGE
                   1136:   getrusage(RUSAGE_SELF, &(r->cpu));
                   1137: #endif
                   1138:   r->real = relative_time;
                   1139: 
                   1140: #ifdef HAVE_CLOCK_MONOTONIC
                   1141:   /* quagga_get_relative() only updates recent_time if gettimeofday
                   1142:    * based, not when using CLOCK_MONOTONIC. As we export recent_time
                   1143:    * and guarantee to update it before threads are run...
                   1144:    */
                   1145:   quagga_gettimeofday(&recent_time);
                   1146: #endif /* HAVE_CLOCK_MONOTONIC */
                   1147: }
                   1148: 
                   1149: /* We check thread consumed time. If the system has getrusage, we'll
                   1150:    use that to get in-depth stats on the performance of the thread in addition
                   1151:    to wall clock time stats from gettimeofday. */
                   1152: void
                   1153: thread_call (struct thread *thread)
                   1154: {
                   1155:   unsigned long realtime, cputime;
                   1156:   RUSAGE_T ru;
                   1157: 
                   1158:  /* Cache a pointer to the relevant cpu history thread, if the thread
                   1159:   * does not have it yet.
                   1160:   *
                   1161:   * Callers submitting 'dummy threads' hence must take care that
                   1162:   * thread->cpu is NULL
                   1163:   */
                   1164:   if (!thread->hist)
                   1165:     {
                   1166:       struct cpu_thread_history tmp;
                   1167:       
                   1168:       tmp.func = thread->func;
                   1169:       tmp.funcname = thread->funcname;
                   1170:       
                   1171:       thread->hist = hash_get (cpu_record, &tmp, 
                   1172:                     (void * (*) (void *))cpu_record_hash_alloc);
                   1173:     }
                   1174: 
                   1175:   GETRUSAGE (&thread->ru);
                   1176: 
                   1177:   (*thread->func) (thread);
                   1178: 
                   1179:   GETRUSAGE (&ru);
                   1180: 
                   1181:   realtime = thread_consumed_time (&ru, &thread->ru, &cputime);
                   1182:   thread->hist->real.total += realtime;
                   1183:   if (thread->hist->real.max < realtime)
                   1184:     thread->hist->real.max = realtime;
                   1185: #ifdef HAVE_RUSAGE
                   1186:   thread->hist->cpu.total += cputime;
                   1187:   if (thread->hist->cpu.max < cputime)
                   1188:     thread->hist->cpu.max = cputime;
                   1189: #endif
                   1190: 
                   1191:   ++(thread->hist->total_calls);
                   1192:   thread->hist->types |= (1 << thread->add_type);
                   1193: 
                   1194: #ifdef CONSUMED_TIME_CHECK
                   1195:   if (realtime > CONSUMED_TIME_CHECK)
                   1196:     {
                   1197:       /*
                   1198:        * We have a CPU Hog on our hands.
                   1199:        * Whinge about it now, so we're aware this is yet another task
                   1200:        * to fix.
                   1201:        */
                   1202:       zlog_warn ("SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
                   1203:                 thread->funcname,
                   1204:                 (unsigned long) thread->func,
                   1205:                 realtime/1000, cputime/1000);
                   1206:     }
                   1207: #endif /* CONSUMED_TIME_CHECK */
                   1208: 
                   1209:   XFREE (MTYPE_THREAD_FUNCNAME, thread->funcname);
                   1210: }
                   1211: 
                   1212: /* Execute thread */
                   1213: struct thread *
                   1214: funcname_thread_execute (struct thread_master *m,
                   1215:                 int (*func)(struct thread *), 
                   1216:                 void *arg,
                   1217:                 int val,
                   1218:                const char* funcname)
                   1219: {
                   1220:   struct thread dummy; 
                   1221: 
                   1222:   memset (&dummy, 0, sizeof (struct thread));
                   1223: 
                   1224:   dummy.type = THREAD_EVENT;
                   1225:   dummy.add_type = THREAD_EXECUTE;
                   1226:   dummy.master = NULL;
                   1227:   dummy.func = func;
                   1228:   dummy.arg = arg;
                   1229:   dummy.u.val = val;
                   1230:   dummy.funcname = strip_funcname (funcname);
                   1231:   thread_call (&dummy);
                   1232: 
                   1233:   XFREE (MTYPE_THREAD_FUNCNAME, dummy.funcname);
                   1234: 
                   1235:   return NULL;
                   1236: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>