]> git.proxmox.com Git - mirror_frr.git/blob - lib/thread.c
Merge branch 'quagga' into google-bgp-multipath
[mirror_frr.git] / lib / thread.c
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 \f
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 \f
42 static struct hash *cpu_record = NULL;
43 \f
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 \f
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 \f
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 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 \f
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 \f
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 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 struct thread *next;
976 unsigned int ready = 0;
977
978 for (thread = list->head; thread; thread = next)
979 {
980 next = thread->next;
981 if (timeval_cmp (*timenow, thread->u.sands) < 0)
982 return ready;
983 thread_list_delete (list, thread);
984 thread->type = THREAD_READY;
985 thread_list_add (&thread->master->ready, thread);
986 ready++;
987 }
988 return ready;
989 }
990
991 /* process a list en masse, e.g. for event thread lists */
992 static unsigned int
993 thread_process (struct thread_list *list)
994 {
995 struct thread *thread;
996 struct thread *next;
997 unsigned int ready = 0;
998
999 for (thread = list->head; thread; thread = next)
1000 {
1001 next = thread->next;
1002 thread_list_delete (list, thread);
1003 thread->type = THREAD_READY;
1004 thread_list_add (&thread->master->ready, thread);
1005 ready++;
1006 }
1007 return ready;
1008 }
1009
1010
1011 /* Fetch next ready thread. */
1012 struct thread *
1013 thread_fetch (struct thread_master *m, struct thread *fetch)
1014 {
1015 struct thread *thread;
1016 fd_set readfd;
1017 fd_set writefd;
1018 fd_set exceptfd;
1019 struct timeval timer_val = { .tv_sec = 0, .tv_usec = 0 };
1020 struct timeval timer_val_bg;
1021 struct timeval *timer_wait = &timer_val;
1022 struct timeval *timer_wait_bg;
1023
1024 while (1)
1025 {
1026 int num = 0;
1027
1028 /* Signals pre-empt everything */
1029 quagga_sigevent_process ();
1030
1031 /* Drain the ready queue of already scheduled jobs, before scheduling
1032 * more.
1033 */
1034 if ((thread = thread_trim_head (&m->ready)) != NULL)
1035 return thread_run (m, thread, fetch);
1036
1037 /* To be fair to all kinds of threads, and avoid starvation, we
1038 * need to be careful to consider all thread types for scheduling
1039 * in each quanta. I.e. we should not return early from here on.
1040 */
1041
1042 /* Normal event are the next highest priority. */
1043 thread_process (&m->event);
1044
1045 /* Structure copy. */
1046 readfd = m->readfd;
1047 writefd = m->writefd;
1048 exceptfd = m->exceptfd;
1049
1050 /* Calculate select wait timer if nothing else to do */
1051 if (m->ready.count == 0)
1052 {
1053 quagga_get_relative (NULL);
1054 timer_wait = thread_timer_wait (&m->timer, &timer_val);
1055 timer_wait_bg = thread_timer_wait (&m->background, &timer_val_bg);
1056
1057 if (timer_wait_bg &&
1058 (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
1059 timer_wait = timer_wait_bg;
1060 }
1061
1062 num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
1063
1064 /* Signals should get quick treatment */
1065 if (num < 0)
1066 {
1067 if (errno == EINTR)
1068 continue; /* signal received - process it */
1069 zlog_warn ("select() error: %s", safe_strerror (errno));
1070 return NULL;
1071 }
1072
1073 /* Check foreground timers. Historically, they have had higher
1074 priority than I/O threads, so let's push them onto the ready
1075 list in front of the I/O threads. */
1076 quagga_get_relative (NULL);
1077 thread_timer_process (&m->timer, &relative_time);
1078
1079 /* Got IO, process it */
1080 if (num > 0)
1081 {
1082 /* Normal priority read thead. */
1083 thread_process_fd (&m->read, &readfd, &m->readfd);
1084 /* Write thead. */
1085 thread_process_fd (&m->write, &writefd, &m->writefd);
1086 }
1087
1088 #if 0
1089 /* If any threads were made ready above (I/O or foreground timer),
1090 perhaps we should avoid adding background timers to the ready
1091 list at this time. If this is code is uncommented, then background
1092 timer threads will not run unless there is nothing else to do. */
1093 if ((thread = thread_trim_head (&m->ready)) != NULL)
1094 return thread_run (m, thread, fetch);
1095 #endif
1096
1097 /* Background timer/events, lowest priority */
1098 thread_timer_process (&m->background, &relative_time);
1099
1100 if ((thread = thread_trim_head (&m->ready)) != NULL)
1101 return thread_run (m, thread, fetch);
1102 }
1103 }
1104
1105 unsigned long
1106 thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime)
1107 {
1108 #ifdef HAVE_RUSAGE
1109 /* This is 'user + sys' time. */
1110 *cputime = timeval_elapsed (now->cpu.ru_utime, start->cpu.ru_utime) +
1111 timeval_elapsed (now->cpu.ru_stime, start->cpu.ru_stime);
1112 #else
1113 *cputime = 0;
1114 #endif /* HAVE_RUSAGE */
1115 return timeval_elapsed (now->real, start->real);
1116 }
1117
1118 /* We should aim to yield after THREAD_YIELD_TIME_SLOT milliseconds.
1119 Note: we are using real (wall clock) time for this calculation.
1120 It could be argued that CPU time may make more sense in certain
1121 contexts. The things to consider are whether the thread may have
1122 blocked (in which case wall time increases, but CPU time does not),
1123 or whether the system is heavily loaded with other processes competing
1124 for CPU time. On balance, wall clock time seems to make sense.
1125 Plus it has the added benefit that gettimeofday should be faster
1126 than calling getrusage. */
1127 int
1128 thread_should_yield (struct thread *thread)
1129 {
1130 quagga_get_relative (NULL);
1131 return (timeval_elapsed(relative_time, thread->ru.real) >
1132 THREAD_YIELD_TIME_SLOT);
1133 }
1134
1135 void
1136 thread_getrusage (RUSAGE_T *r)
1137 {
1138 quagga_get_relative (NULL);
1139 #ifdef HAVE_RUSAGE
1140 getrusage(RUSAGE_SELF, &(r->cpu));
1141 #endif
1142 r->real = relative_time;
1143
1144 #ifdef HAVE_CLOCK_MONOTONIC
1145 /* quagga_get_relative() only updates recent_time if gettimeofday
1146 * based, not when using CLOCK_MONOTONIC. As we export recent_time
1147 * and guarantee to update it before threads are run...
1148 */
1149 quagga_gettimeofday(&recent_time);
1150 #endif /* HAVE_CLOCK_MONOTONIC */
1151 }
1152
1153 /* We check thread consumed time. If the system has getrusage, we'll
1154 use that to get in-depth stats on the performance of the thread in addition
1155 to wall clock time stats from gettimeofday. */
1156 void
1157 thread_call (struct thread *thread)
1158 {
1159 unsigned long realtime, cputime;
1160 RUSAGE_T ru;
1161
1162 /* Cache a pointer to the relevant cpu history thread, if the thread
1163 * does not have it yet.
1164 *
1165 * Callers submitting 'dummy threads' hence must take care that
1166 * thread->cpu is NULL
1167 */
1168 if (!thread->hist)
1169 {
1170 struct cpu_thread_history tmp;
1171
1172 tmp.func = thread->func;
1173 tmp.funcname = thread->funcname;
1174
1175 thread->hist = hash_get (cpu_record, &tmp,
1176 (void * (*) (void *))cpu_record_hash_alloc);
1177 }
1178
1179 GETRUSAGE (&thread->ru);
1180
1181 (*thread->func) (thread);
1182
1183 GETRUSAGE (&ru);
1184
1185 realtime = thread_consumed_time (&ru, &thread->ru, &cputime);
1186 thread->hist->real.total += realtime;
1187 if (thread->hist->real.max < realtime)
1188 thread->hist->real.max = realtime;
1189 #ifdef HAVE_RUSAGE
1190 thread->hist->cpu.total += cputime;
1191 if (thread->hist->cpu.max < cputime)
1192 thread->hist->cpu.max = cputime;
1193 #endif
1194
1195 ++(thread->hist->total_calls);
1196 thread->hist->types |= (1 << thread->add_type);
1197
1198 #ifdef CONSUMED_TIME_CHECK
1199 if (realtime > CONSUMED_TIME_CHECK)
1200 {
1201 /*
1202 * We have a CPU Hog on our hands.
1203 * Whinge about it now, so we're aware this is yet another task
1204 * to fix.
1205 */
1206 zlog_warn ("SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
1207 thread->funcname,
1208 (unsigned long) thread->func,
1209 realtime/1000, cputime/1000);
1210 }
1211 #endif /* CONSUMED_TIME_CHECK */
1212
1213 XFREE (MTYPE_THREAD_FUNCNAME, thread->funcname);
1214 }
1215
1216 /* Execute thread */
1217 struct thread *
1218 funcname_thread_execute (struct thread_master *m,
1219 int (*func)(struct thread *),
1220 void *arg,
1221 int val,
1222 const char* funcname)
1223 {
1224 struct thread dummy;
1225
1226 memset (&dummy, 0, sizeof (struct thread));
1227
1228 dummy.type = THREAD_EVENT;
1229 dummy.add_type = THREAD_EXECUTE;
1230 dummy.master = NULL;
1231 dummy.func = func;
1232 dummy.arg = arg;
1233 dummy.u.val = val;
1234 dummy.funcname = strip_funcname (funcname);
1235 thread_call (&dummy);
1236
1237 XFREE (MTYPE_THREAD_FUNCNAME, dummy.funcname);
1238
1239 return NULL;
1240 }