1 /* Thread management routine
2 * Copyright (C) 1998, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
4 * This file is part of GNU Zebra.
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
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.
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
25 #include <sys/resource.h>
35 #if defined(__APPLE__)
36 #include <mach/mach.h>
37 #include <mach/mach_time.h>
40 /* Recent absolute time of day */
41 struct timeval recent_time;
42 static struct timeval last_recent_time;
43 /* Relative time, since startup */
44 static struct timeval relative_time;
45 static struct timeval relative_time_base;
47 static unsigned short timers_inited;
49 static struct hash *cpu_record = NULL;
51 /* Struct timeval's tv_usec one second value. */
52 #define TIMER_SECOND_MICRO 1000000L
54 /* Adjust so that tv_usec is in the range [0,TIMER_SECOND_MICRO).
55 And change negative values to 0. */
57 timeval_adjust (struct timeval a)
59 while (a.tv_usec >= TIMER_SECOND_MICRO)
61 a.tv_usec -= TIMER_SECOND_MICRO;
67 a.tv_usec += TIMER_SECOND_MICRO;
72 /* Change negative timeouts to 0. */
73 a.tv_sec = a.tv_usec = 0;
79 timeval_subtract (struct timeval a, struct timeval b)
83 ret.tv_usec = a.tv_usec - b.tv_usec;
84 ret.tv_sec = a.tv_sec - b.tv_sec;
86 return timeval_adjust (ret);
90 timeval_cmp (struct timeval a, struct timeval b)
92 return (a.tv_sec == b.tv_sec
93 ? a.tv_usec - b.tv_usec : a.tv_sec - b.tv_sec);
97 timeval_elapsed (struct timeval a, struct timeval b)
99 return (((a.tv_sec - b.tv_sec) * TIMER_SECOND_MICRO)
100 + (a.tv_usec - b.tv_usec));
103 #if !defined(HAVE_CLOCK_MONOTONIC) && !defined(__APPLE__)
105 quagga_gettimeofday_relative_adjust (void)
108 if (timeval_cmp (recent_time, last_recent_time) < 0)
110 relative_time.tv_sec++;
111 relative_time.tv_usec = 0;
115 diff = timeval_subtract (recent_time, last_recent_time);
116 relative_time.tv_sec += diff.tv_sec;
117 relative_time.tv_usec += diff.tv_usec;
118 relative_time = timeval_adjust (relative_time);
120 last_recent_time = recent_time;
122 #endif /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */
124 /* gettimeofday wrapper, to keep recent_time updated */
126 quagga_gettimeofday (struct timeval *tv)
132 if (!(ret = gettimeofday (&recent_time, NULL)))
137 relative_time_base = last_recent_time = recent_time;
140 /* avoid copy if user passed recent_time pointer.. */
141 if (tv != &recent_time)
149 quagga_get_relative (struct timeval *tv)
153 #ifdef HAVE_CLOCK_MONOTONIC
156 if (!(ret = clock_gettime (CLOCK_MONOTONIC, &tp)))
158 relative_time.tv_sec = tp.tv_sec;
159 relative_time.tv_usec = tp.tv_nsec / 1000;
162 #elif defined(__APPLE__)
166 static mach_timebase_info_data_t timebase_info;
168 ticks = mach_absolute_time();
169 if (timebase_info.denom == 0)
170 mach_timebase_info(&timebase_info);
172 useconds = ticks * timebase_info.numer / timebase_info.denom / 1000;
173 relative_time.tv_sec = useconds / 1000000;
174 relative_time.tv_usec = useconds % 1000000;
178 #else /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */
179 if (!(ret = quagga_gettimeofday (&recent_time)))
180 quagga_gettimeofday_relative_adjust();
181 #endif /* HAVE_CLOCK_MONOTONIC */
189 /* Get absolute time stamp, but in terms of the internal timer
190 * Could be wrong, but at least won't go back.
193 quagga_real_stabilised (struct timeval *tv)
195 *tv = relative_time_base;
196 tv->tv_sec += relative_time.tv_sec;
197 tv->tv_usec += relative_time.tv_usec;
198 *tv = timeval_adjust (*tv);
201 /* Exported Quagga timestamp function.
202 * Modelled on POSIX clock_gettime.
205 quagga_gettime (enum quagga_clkid clkid, struct timeval *tv)
209 case QUAGGA_CLK_REALTIME:
210 return quagga_gettimeofday (tv);
211 case QUAGGA_CLK_MONOTONIC:
212 return quagga_get_relative (tv);
213 case QUAGGA_CLK_REALTIME_STABILISED:
214 quagga_real_stabilised (tv);
222 /* time_t value in terms of stabilised absolute time.
223 * replacement for POSIX time()
226 quagga_time (time_t *t)
229 quagga_real_stabilised (&tv);
235 /* Public export of recent_relative_time by value */
237 recent_relative_time (void)
239 return relative_time;
243 cpu_record_hash_key (struct cpu_thread_history *a)
245 return (uintptr_t) a->func;
249 cpu_record_hash_cmp (const struct cpu_thread_history *a,
250 const struct cpu_thread_history *b)
252 return a->func == b->func;
256 cpu_record_hash_alloc (struct cpu_thread_history *a)
258 struct cpu_thread_history *new;
259 new = XCALLOC (MTYPE_THREAD_STATS, sizeof (struct cpu_thread_history));
261 new->funcname = a->funcname;
266 cpu_record_hash_free (void *a)
268 struct cpu_thread_history *hist = a;
270 XFREE (MTYPE_THREAD_STATS, hist);
274 vty_out_cpu_thread_history(struct vty* vty,
275 struct cpu_thread_history *a)
278 vty_out(vty, "%7ld.%03ld %9d %8ld %9ld %8ld %9ld",
279 a->cpu.total/1000, a->cpu.total%1000, a->total_calls,
280 a->cpu.total/a->total_calls, a->cpu.max,
281 a->real.total/a->total_calls, a->real.max);
283 vty_out(vty, "%7ld.%03ld %9d %8ld %9ld",
284 a->real.total/1000, a->real.total%1000, a->total_calls,
285 a->real.total/a->total_calls, a->real.max);
287 vty_out(vty, " %c%c%c%c%c%c %s%s",
288 a->types & (1 << THREAD_READ) ? 'R':' ',
289 a->types & (1 << THREAD_WRITE) ? 'W':' ',
290 a->types & (1 << THREAD_TIMER) ? 'T':' ',
291 a->types & (1 << THREAD_EVENT) ? 'E':' ',
292 a->types & (1 << THREAD_EXECUTE) ? 'X':' ',
293 a->types & (1 << THREAD_BACKGROUND) ? 'B' : ' ',
294 a->funcname, VTY_NEWLINE);
298 cpu_record_hash_print(struct hash_backet *bucket,
301 struct cpu_thread_history *totals = args[0];
302 struct vty *vty = args[1];
303 thread_type *filter = args[2];
304 struct cpu_thread_history *a = bucket->data;
307 if ( !(a->types & *filter) )
309 vty_out_cpu_thread_history(vty,a);
310 totals->total_calls += a->total_calls;
311 totals->real.total += a->real.total;
312 if (totals->real.max < a->real.max)
313 totals->real.max = a->real.max;
315 totals->cpu.total += a->cpu.total;
316 if (totals->cpu.max < a->cpu.max)
317 totals->cpu.max = a->cpu.max;
322 cpu_record_print(struct vty *vty, thread_type filter)
324 struct cpu_thread_history tmp;
325 void *args[3] = {&tmp, vty, &filter};
327 memset(&tmp, 0, sizeof tmp);
328 tmp.funcname = "TOTAL";
332 vty_out(vty, "%21s %18s %18s%s",
333 "", "CPU (user+system):", "Real (wall-clock):", VTY_NEWLINE);
335 vty_out(vty, "Runtime(ms) Invoked Avg uSec Max uSecs");
337 vty_out(vty, " Avg uSec Max uSecs");
339 vty_out(vty, " Type Thread%s", VTY_NEWLINE);
340 hash_iterate(cpu_record,
341 (void(*)(struct hash_backet*,void*))cpu_record_hash_print,
344 if (tmp.total_calls > 0)
345 vty_out_cpu_thread_history(vty, &tmp);
348 DEFUN(show_thread_cpu,
350 "show thread cpu [FILTER]",
352 "Thread information\n"
354 "Display filter (rwtexb)\n")
357 thread_type filter = (thread_type) -1U;
362 while (argv[0][i] != '\0')
364 switch ( argv[0][i] )
368 filter |= (1 << THREAD_READ);
372 filter |= (1 << THREAD_WRITE);
376 filter |= (1 << THREAD_TIMER);
380 filter |= (1 << THREAD_EVENT);
384 filter |= (1 << THREAD_EXECUTE);
388 filter |= (1 << THREAD_BACKGROUND);
397 vty_out(vty, "Invalid filter \"%s\" specified,"
398 " must contain at least one of 'RWTEXB'%s",
399 argv[0], VTY_NEWLINE);
404 cpu_record_print(vty, filter);
409 cpu_record_hash_clear (struct hash_backet *bucket,
412 thread_type *filter = args;
413 struct cpu_thread_history *a = bucket->data;
416 if ( !(a->types & *filter) )
419 hash_release (cpu_record, bucket->data);
423 cpu_record_clear (thread_type filter)
425 thread_type *tmp = &filter;
426 hash_iterate (cpu_record,
427 (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
431 DEFUN(clear_thread_cpu,
432 clear_thread_cpu_cmd,
433 "clear thread cpu [FILTER]",
434 "Clear stored data\n"
435 "Thread information\n"
437 "Display filter (rwtexb)\n")
440 thread_type filter = (thread_type) -1U;
445 while (argv[0][i] != '\0')
447 switch ( argv[0][i] )
451 filter |= (1 << THREAD_READ);
455 filter |= (1 << THREAD_WRITE);
459 filter |= (1 << THREAD_TIMER);
463 filter |= (1 << THREAD_EVENT);
467 filter |= (1 << THREAD_EXECUTE);
471 filter |= (1 << THREAD_BACKGROUND);
480 vty_out(vty, "Invalid filter \"%s\" specified,"
481 " must contain at least one of 'RWTEXB'%s",
482 argv[0], VTY_NEWLINE);
487 cpu_record_clear (filter);
492 thread_timer_cmp(void *a, void *b)
494 struct thread *thread_a = a;
495 struct thread *thread_b = b;
497 long cmp = timeval_cmp(thread_a->u.sands, thread_b->u.sands);
507 thread_timer_update(void *node, int actual_position)
509 struct thread *thread = node;
511 thread->index = actual_position;
514 /* Allocate new thread master. */
515 struct thread_master *
516 thread_master_create ()
518 struct thread_master *rv;
521 getrlimit(RLIMIT_NOFILE, &limit);
523 if (cpu_record == NULL)
525 = hash_create ((unsigned int (*) (void *))cpu_record_hash_key,
526 (int (*) (const void *, const void *))cpu_record_hash_cmp);
528 rv = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct thread_master));
534 rv->fd_limit = (int)limit.rlim_cur;
535 rv->read = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit);
536 if (rv->read == NULL)
538 XFREE (MTYPE_THREAD_MASTER, rv);
542 rv->write = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit);
543 if (rv->write == NULL)
545 XFREE (MTYPE_THREAD, rv->read);
546 XFREE (MTYPE_THREAD_MASTER, rv);
550 /* Initialize the timer queues */
551 rv->timer = pqueue_create();
552 rv->background = pqueue_create();
553 rv->timer->cmp = rv->background->cmp = thread_timer_cmp;
554 rv->timer->update = rv->background->update = thread_timer_update;
559 /* Add a new thread to the list. */
561 thread_list_add (struct thread_list *list, struct thread *thread)
564 thread->prev = list->tail;
566 list->tail->next = thread;
573 /* Delete a thread from the list. */
574 static struct thread *
575 thread_list_delete (struct thread_list *list, struct thread *thread)
578 thread->next->prev = thread->prev;
580 list->tail = thread->prev;
582 thread->prev->next = thread->next;
584 list->head = thread->next;
585 thread->next = thread->prev = NULL;
591 thread_delete_fd (struct thread **thread_array, struct thread *thread)
593 thread_array[thread->u.fd] = NULL;
597 thread_add_fd (struct thread **thread_array, struct thread *thread)
599 thread_array[thread->u.fd] = thread;
602 /* Move thread to unuse list. */
604 thread_add_unuse (struct thread_master *m, struct thread *thread)
606 assert (m != NULL && thread != NULL);
607 assert (thread->next == NULL);
608 assert (thread->prev == NULL);
609 assert (thread->type == THREAD_UNUSED);
610 thread_list_add (&m->unuse, thread);
613 /* Free all unused thread. */
615 thread_list_free (struct thread_master *m, struct thread_list *list)
620 for (t = list->head; t; t = next)
623 XFREE (MTYPE_THREAD, t);
630 thread_array_free (struct thread_master *m, struct thread **thread_array)
635 for (index = 0; index < m->fd_limit; ++index)
637 t = thread_array[index];
640 thread_array[index] = NULL;
641 XFREE (MTYPE_THREAD, t);
645 XFREE (MTYPE_THREAD, thread_array);
649 thread_queue_free (struct thread_master *m, struct pqueue *queue)
653 for (i = 0; i < queue->size; i++)
654 XFREE(MTYPE_THREAD, queue->array[i]);
656 m->alloc -= queue->size;
657 pqueue_delete(queue);
660 /* Stop thread scheduler. */
662 thread_master_free (struct thread_master *m)
664 thread_array_free (m, m->read);
665 thread_array_free (m, m->write);
666 thread_queue_free (m, m->timer);
667 thread_list_free (m, &m->event);
668 thread_list_free (m, &m->ready);
669 thread_list_free (m, &m->unuse);
670 thread_queue_free (m, m->background);
672 XFREE (MTYPE_THREAD_MASTER, m);
676 hash_clean (cpu_record, cpu_record_hash_free);
677 hash_free (cpu_record);
682 /* Thread list is empty or not. */
684 thread_empty (struct thread_list *list)
686 return list->head ? 0 : 1;
689 /* Delete top of the list and return it. */
690 static struct thread *
691 thread_trim_head (struct thread_list *list)
693 if (!thread_empty (list))
694 return thread_list_delete (list, list->head);
698 /* Return remain time in second. */
700 thread_timer_remain_second (struct thread *thread)
702 quagga_get_relative (NULL);
704 if (thread->u.sands.tv_sec - relative_time.tv_sec > 0)
705 return thread->u.sands.tv_sec - relative_time.tv_sec;
711 thread_timer_remain(struct thread *thread)
713 quagga_get_relative(NULL);
715 return timeval_subtract(thread->u.sands, relative_time);
718 #define debugargdef const char *funcname, const char *schedfrom, int fromln
719 #define debugargpass funcname, schedfrom, fromln
721 /* Get new thread. */
722 static struct thread *
723 thread_get (struct thread_master *m, u_char type,
724 int (*func) (struct thread *), void *arg, debugargdef)
726 struct thread *thread = thread_trim_head (&m->unuse);
730 thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread));
734 thread->add_type = type;
740 thread->funcname = funcname;
741 thread->schedfrom = schedfrom;
742 thread->schedfrom_line = fromln;
747 #define fd_copy_fd_set(X) (X)
750 fd_select (int size, thread_fd_set *read, thread_fd_set *write, thread_fd_set *except, struct timeval *t)
752 return(select(size, read, write, except, t));
756 fd_is_set (int fd, thread_fd_set *fdset)
758 return FD_ISSET (fd, fdset);
762 fd_clear_read_write (int fd, thread_fd_set *fdset)
764 if (!FD_ISSET (fd, fdset))
771 static struct thread *
772 funcname_thread_add_read_write (int dir, struct thread_master *m,
773 int (*func) (struct thread *), void *arg, int fd,
776 struct thread *thread = NULL;
777 thread_fd_set *fdset = NULL;
779 if (dir == THREAD_READ)
784 if (FD_ISSET (fd, fdset))
786 zlog (NULL, LOG_WARNING, "There is already %s fd [%d]",
787 (dir = THREAD_READ) ? "read" : "write", fd);
793 thread = thread_get (m, dir, func, arg, debugargpass);
795 if (dir == THREAD_READ)
796 thread_add_fd (m->read, thread);
798 thread_add_fd (m->write, thread);
803 /* Add new read thread. */
805 funcname_thread_add_read (struct thread_master *m,
806 int (*func) (struct thread *), void *arg, int fd,
809 return funcname_thread_add_read_write (THREAD_READ, m, func,
810 arg, fd, debugargpass);
813 /* Add new write thread. */
815 funcname_thread_add_write (struct thread_master *m,
816 int (*func) (struct thread *), void *arg, int fd,
819 return funcname_thread_add_read_write (THREAD_WRITE, m, func,
820 arg, fd, debugargpass);
823 static struct thread *
824 funcname_thread_add_timer_timeval (struct thread_master *m,
825 int (*func) (struct thread *),
828 struct timeval *time_relative,
831 struct thread *thread;
832 struct pqueue *queue;
833 struct timeval alarm_time;
837 assert (type == THREAD_TIMER || type == THREAD_BACKGROUND);
838 assert (time_relative);
840 queue = ((type == THREAD_TIMER) ? m->timer : m->background);
841 thread = thread_get (m, type, func, arg, debugargpass);
843 /* Do we need jitter here? */
844 quagga_get_relative (NULL);
845 alarm_time.tv_sec = relative_time.tv_sec + time_relative->tv_sec;
846 alarm_time.tv_usec = relative_time.tv_usec + time_relative->tv_usec;
847 thread->u.sands = timeval_adjust(alarm_time);
849 pqueue_enqueue(thread, queue);
854 /* Add timer event thread. */
856 funcname_thread_add_timer (struct thread_master *m,
857 int (*func) (struct thread *),
858 void *arg, long timer,
868 return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg,
869 &trel, debugargpass);
872 /* Add timer event thread with "millisecond" resolution */
874 funcname_thread_add_timer_msec (struct thread_master *m,
875 int (*func) (struct thread *),
876 void *arg, long timer,
883 trel.tv_sec = timer / 1000;
884 trel.tv_usec = 1000*(timer % 1000);
886 return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER,
887 arg, &trel, debugargpass);
890 /* Add timer event thread with "millisecond" resolution */
892 funcname_thread_add_timer_tv (struct thread_master *m,
893 int (*func) (struct thread *),
894 void *arg, struct timeval *tv,
897 return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER,
898 arg, tv, debugargpass);
901 /* Add a background thread, with an optional millisec delay */
903 funcname_thread_add_background (struct thread_master *m,
904 int (*func) (struct thread *),
905 void *arg, long delay,
914 trel.tv_sec = delay / 1000;
915 trel.tv_usec = 1000*(delay % 1000);
923 return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND,
924 arg, &trel, debugargpass);
927 /* Add simple event thread. */
929 funcname_thread_add_event (struct thread_master *m,
930 int (*func) (struct thread *), void *arg, int val,
933 struct thread *thread;
937 thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass);
939 thread_list_add (&m->event, thread);
944 /* Cancel thread from scheduler. */
946 thread_cancel (struct thread *thread)
948 struct thread_list *list = NULL;
949 struct pqueue *queue = NULL;
950 struct thread **thread_array = NULL;
952 switch (thread->type)
955 assert (fd_clear_read_write (thread->u.fd, &thread->master->readfd));
956 thread_array = thread->master->read;
959 assert (fd_clear_read_write (thread->u.fd, &thread->master->writefd));
960 thread_array = thread->master->write;
963 queue = thread->master->timer;
966 list = &thread->master->event;
969 list = &thread->master->ready;
971 case THREAD_BACKGROUND:
972 queue = thread->master->background;
981 assert(thread->index >= 0);
982 assert(thread == queue->array[thread->index]);
983 pqueue_remove_at(thread->index, queue);
987 thread_list_delete (list, thread);
989 else if (thread_array)
991 thread_delete_fd (thread_array, thread);
995 assert(!"Thread should be either in queue or list or array!");
998 thread->type = THREAD_UNUSED;
999 thread_add_unuse (thread->master, thread);
1002 /* Delete all events which has argument value arg. */
1004 thread_cancel_event (struct thread_master *m, void *arg)
1006 unsigned int ret = 0;
1007 struct thread *thread;
1009 thread = m->event.head;
1020 thread_list_delete (&m->event, t);
1021 t->type = THREAD_UNUSED;
1022 thread_add_unuse (m, t);
1026 /* thread can be on the ready list too */
1027 thread = m->ready.head;
1038 thread_list_delete (&m->ready, t);
1039 t->type = THREAD_UNUSED;
1040 thread_add_unuse (m, t);
1046 static struct timeval *
1047 thread_timer_wait (struct pqueue *queue, struct timeval *timer_val)
1051 struct thread *next_timer = queue->array[0];
1052 *timer_val = timeval_subtract (next_timer->u.sands, relative_time);
1058 static struct thread *
1059 thread_run (struct thread_master *m, struct thread *thread,
1060 struct thread *fetch)
1063 thread->type = THREAD_UNUSED;
1064 thread_add_unuse (m, thread);
1069 thread_process_fds_helper (struct thread_master *m, struct thread *thread, thread_fd_set *fdset)
1071 thread_fd_set *mfdset = NULL;
1072 struct thread **thread_array;
1077 if (thread->type == THREAD_READ)
1079 mfdset = &m->readfd;
1080 thread_array = m->read;
1084 mfdset = &m->writefd;
1085 thread_array = m->write;
1088 if (fd_is_set (THREAD_FD (thread), fdset))
1090 fd_clear_read_write (THREAD_FD (thread), mfdset);
1091 thread_delete_fd (thread_array, thread);
1092 thread_list_add (&m->ready, thread);
1093 thread->type = THREAD_READY;
1100 thread_process_fds (struct thread_master *m, thread_fd_set *rset, thread_fd_set *wset, int num)
1102 int ready = 0, index;
1104 for (index = 0; index < m->fd_limit && ready < num; ++index)
1106 ready += thread_process_fds_helper (m, m->read[index], rset);
1107 ready += thread_process_fds_helper (m, m->write[index], wset);
1112 /* Add all timers that have popped to the ready list. */
1114 thread_timer_process (struct pqueue *queue, struct timeval *timenow)
1116 struct thread *thread;
1117 unsigned int ready = 0;
1121 thread = queue->array[0];
1122 if (timeval_cmp (*timenow, thread->u.sands) < 0)
1124 pqueue_dequeue(queue);
1125 thread->type = THREAD_READY;
1126 thread_list_add (&thread->master->ready, thread);
1132 /* process a list en masse, e.g. for event thread lists */
1134 thread_process (struct thread_list *list)
1136 struct thread *thread;
1137 struct thread *next;
1138 unsigned int ready = 0;
1140 for (thread = list->head; thread; thread = next)
1142 next = thread->next;
1143 thread_list_delete (list, thread);
1144 thread->type = THREAD_READY;
1145 thread_list_add (&thread->master->ready, thread);
1152 /* Fetch next ready thread. */
1154 thread_fetch (struct thread_master *m, struct thread *fetch)
1156 struct thread *thread;
1157 thread_fd_set readfd;
1158 thread_fd_set writefd;
1159 thread_fd_set exceptfd;
1160 struct timeval timer_val = { .tv_sec = 0, .tv_usec = 0 };
1161 struct timeval timer_val_bg;
1162 struct timeval *timer_wait = &timer_val;
1163 struct timeval *timer_wait_bg;
1169 /* Signals pre-empt everything */
1170 quagga_sigevent_process ();
1172 /* Drain the ready queue of already scheduled jobs, before scheduling
1175 if ((thread = thread_trim_head (&m->ready)) != NULL)
1176 return thread_run (m, thread, fetch);
1178 /* To be fair to all kinds of threads, and avoid starvation, we
1179 * need to be careful to consider all thread types for scheduling
1180 * in each quanta. I.e. we should not return early from here on.
1183 /* Normal event are the next highest priority. */
1184 thread_process (&m->event);
1186 /* Structure copy. */
1187 readfd = fd_copy_fd_set(m->readfd);
1188 writefd = fd_copy_fd_set(m->writefd);
1189 exceptfd = fd_copy_fd_set(m->exceptfd);
1191 /* Calculate select wait timer if nothing else to do */
1192 if (m->ready.count == 0)
1194 quagga_get_relative (NULL);
1195 timer_wait = thread_timer_wait (m->timer, &timer_val);
1196 timer_wait_bg = thread_timer_wait (m->background, &timer_val_bg);
1198 if (timer_wait_bg &&
1199 (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0)))
1200 timer_wait = timer_wait_bg;
1203 num = fd_select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
1205 /* Signals should get quick treatment */
1209 continue; /* signal received - process it */
1210 zlog_warn ("select() error: %s", safe_strerror (errno));
1214 /* Check foreground timers. Historically, they have had higher
1215 priority than I/O threads, so let's push them onto the ready
1216 list in front of the I/O threads. */
1217 quagga_get_relative (NULL);
1218 thread_timer_process (m->timer, &relative_time);
1220 /* Got IO, process it */
1222 thread_process_fds (m, &readfd, &writefd, num);
1225 /* If any threads were made ready above (I/O or foreground timer),
1226 perhaps we should avoid adding background timers to the ready
1227 list at this time. If this is code is uncommented, then background
1228 timer threads will not run unless there is nothing else to do. */
1229 if ((thread = thread_trim_head (&m->ready)) != NULL)
1230 return thread_run (m, thread, fetch);
1233 /* Background timer/events, lowest priority */
1234 thread_timer_process (m->background, &relative_time);
1236 if ((thread = thread_trim_head (&m->ready)) != NULL)
1237 return thread_run (m, thread, fetch);
1242 thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime)
1245 /* This is 'user + sys' time. */
1246 *cputime = timeval_elapsed (now->cpu.ru_utime, start->cpu.ru_utime) +
1247 timeval_elapsed (now->cpu.ru_stime, start->cpu.ru_stime);
1250 #endif /* HAVE_RUSAGE */
1251 return timeval_elapsed (now->real, start->real);
1254 /* We should aim to yield after THREAD_YIELD_TIME_SLOT milliseconds.
1255 Note: we are using real (wall clock) time for this calculation.
1256 It could be argued that CPU time may make more sense in certain
1257 contexts. The things to consider are whether the thread may have
1258 blocked (in which case wall time increases, but CPU time does not),
1259 or whether the system is heavily loaded with other processes competing
1260 for CPU time. On balance, wall clock time seems to make sense.
1261 Plus it has the added benefit that gettimeofday should be faster
1262 than calling getrusage. */
1264 thread_should_yield (struct thread *thread)
1266 quagga_get_relative (NULL);
1267 unsigned long t = timeval_elapsed(relative_time, thread->real);
1268 return ((t > THREAD_YIELD_TIME_SLOT) ? t : 0);
1272 thread_getrusage (RUSAGE_T *r)
1274 quagga_get_relative (NULL);
1276 getrusage(RUSAGE_SELF, &(r->cpu));
1278 r->real = relative_time;
1280 #ifdef HAVE_CLOCK_MONOTONIC
1281 /* quagga_get_relative() only updates recent_time if gettimeofday
1282 * based, not when using CLOCK_MONOTONIC. As we export recent_time
1283 * and guarantee to update it before threads are run...
1285 quagga_gettimeofday(&recent_time);
1286 #endif /* HAVE_CLOCK_MONOTONIC */
1289 struct thread *thread_current = NULL;
1291 /* We check thread consumed time. If the system has getrusage, we'll
1292 use that to get in-depth stats on the performance of the thread in addition
1293 to wall clock time stats from gettimeofday. */
1295 thread_call (struct thread *thread)
1297 unsigned long realtime, cputime;
1298 RUSAGE_T before, after;
1300 /* Cache a pointer to the relevant cpu history thread, if the thread
1301 * does not have it yet.
1303 * Callers submitting 'dummy threads' hence must take care that
1304 * thread->cpu is NULL
1308 struct cpu_thread_history tmp;
1310 tmp.func = thread->func;
1311 tmp.funcname = thread->funcname;
1313 thread->hist = hash_get (cpu_record, &tmp,
1314 (void * (*) (void *))cpu_record_hash_alloc);
1317 GETRUSAGE (&before);
1318 thread->real = before.real;
1320 thread_current = thread;
1321 (*thread->func) (thread);
1322 thread_current = NULL;
1326 realtime = thread_consumed_time (&after, &before, &cputime);
1327 thread->hist->real.total += realtime;
1328 if (thread->hist->real.max < realtime)
1329 thread->hist->real.max = realtime;
1331 thread->hist->cpu.total += cputime;
1332 if (thread->hist->cpu.max < cputime)
1333 thread->hist->cpu.max = cputime;
1336 ++(thread->hist->total_calls);
1337 thread->hist->types |= (1 << thread->add_type);
1339 #ifdef CONSUMED_TIME_CHECK
1340 if (realtime > CONSUMED_TIME_CHECK)
1343 * We have a CPU Hog on our hands.
1344 * Whinge about it now, so we're aware this is yet another task
1347 zlog_warn ("SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
1349 (unsigned long) thread->func,
1350 realtime/1000, cputime/1000);
1352 #endif /* CONSUMED_TIME_CHECK */
1355 /* Execute thread */
1357 funcname_thread_execute (struct thread_master *m,
1358 int (*func)(struct thread *),
1363 struct thread dummy;
1365 memset (&dummy, 0, sizeof (struct thread));
1367 dummy.type = THREAD_EVENT;
1368 dummy.add_type = THREAD_EXECUTE;
1369 dummy.master = NULL;
1374 dummy.funcname = funcname;
1375 dummy.schedfrom = schedfrom;
1376 dummy.schedfrom_line = fromln;
1378 thread_call (&dummy);