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 /* Relative time, since startup */
43 static struct timeval relative_time
;
45 static struct hash
*cpu_record
= NULL
;
47 /* Adjust so that tv_usec is in the range [0,TIMER_SECOND_MICRO).
48 And change negative values to 0. */
50 timeval_adjust (struct timeval a
)
52 while (a
.tv_usec
>= TIMER_SECOND_MICRO
)
54 a
.tv_usec
-= TIMER_SECOND_MICRO
;
60 a
.tv_usec
+= TIMER_SECOND_MICRO
;
65 /* Change negative timeouts to 0. */
66 a
.tv_sec
= a
.tv_usec
= 0;
72 timeval_subtract (struct timeval a
, struct timeval b
)
76 ret
.tv_usec
= a
.tv_usec
- b
.tv_usec
;
77 ret
.tv_sec
= a
.tv_sec
- b
.tv_sec
;
79 return timeval_adjust (ret
);
83 timeval_cmp (struct timeval a
, struct timeval b
)
85 return (a
.tv_sec
== b
.tv_sec
86 ? a
.tv_usec
- b
.tv_usec
: a
.tv_sec
- b
.tv_sec
);
90 timeval_elapsed (struct timeval a
, struct timeval b
)
92 return (((a
.tv_sec
- b
.tv_sec
) * TIMER_SECOND_MICRO
)
93 + (a
.tv_usec
- b
.tv_usec
));
96 /* gettimeofday wrapper, to keep recent_time updated */
98 quagga_gettimeofday (struct timeval
*tv
)
104 if (!(ret
= gettimeofday (&recent_time
, NULL
)))
106 /* avoid copy if user passed recent_time pointer.. */
107 if (tv
!= &recent_time
)
115 quagga_get_relative (struct timeval
*tv
)
119 #ifdef HAVE_CLOCK_MONOTONIC
122 if (!(ret
= clock_gettime (CLOCK_MONOTONIC
, &tp
)))
124 relative_time
.tv_sec
= tp
.tv_sec
;
125 relative_time
.tv_usec
= tp
.tv_nsec
/ 1000;
128 #elif defined(__APPLE__)
132 static mach_timebase_info_data_t timebase_info
;
134 ticks
= mach_absolute_time();
135 if (timebase_info
.denom
== 0)
136 mach_timebase_info(&timebase_info
);
138 useconds
= ticks
* timebase_info
.numer
/ timebase_info
.denom
/ 1000;
139 relative_time
.tv_sec
= useconds
/ 1000000;
140 relative_time
.tv_usec
= useconds
% 1000000;
144 #else /* !HAVE_CLOCK_MONOTONIC && !__APPLE__ */
145 #error no monotonic clock on this system
146 #endif /* HAVE_CLOCK_MONOTONIC */
154 /* Exported Quagga timestamp function.
155 * Modelled on POSIX clock_gettime.
158 quagga_gettime (enum quagga_clkid clkid
, struct timeval
*tv
)
162 case QUAGGA_CLK_MONOTONIC
:
163 return quagga_get_relative (tv
);
171 quagga_monotime (void)
174 quagga_get_relative(&tv
);
178 /* Public export of recent_relative_time by value */
180 recent_relative_time (void)
182 return relative_time
;
186 cpu_record_hash_key (struct cpu_thread_history
*a
)
188 return (uintptr_t) a
->func
;
192 cpu_record_hash_cmp (const struct cpu_thread_history
*a
,
193 const struct cpu_thread_history
*b
)
195 return a
->func
== b
->func
;
199 cpu_record_hash_alloc (struct cpu_thread_history
*a
)
201 struct cpu_thread_history
*new;
202 new = XCALLOC (MTYPE_THREAD_STATS
, sizeof (struct cpu_thread_history
));
204 new->funcname
= a
->funcname
;
209 cpu_record_hash_free (void *a
)
211 struct cpu_thread_history
*hist
= a
;
213 XFREE (MTYPE_THREAD_STATS
, hist
);
217 vty_out_cpu_thread_history(struct vty
* vty
,
218 struct cpu_thread_history
*a
)
221 vty_out(vty
, "%7ld.%03ld %9d %8ld %9ld %8ld %9ld",
222 a
->cpu
.total
/1000, a
->cpu
.total
%1000, a
->total_calls
,
223 a
->cpu
.total
/a
->total_calls
, a
->cpu
.max
,
224 a
->real
.total
/a
->total_calls
, a
->real
.max
);
226 vty_out(vty
, "%7ld.%03ld %9d %8ld %9ld",
227 a
->real
.total
/1000, a
->real
.total
%1000, a
->total_calls
,
228 a
->real
.total
/a
->total_calls
, a
->real
.max
);
230 vty_out(vty
, " %c%c%c%c%c%c %s%s",
231 a
->types
& (1 << THREAD_READ
) ? 'R':' ',
232 a
->types
& (1 << THREAD_WRITE
) ? 'W':' ',
233 a
->types
& (1 << THREAD_TIMER
) ? 'T':' ',
234 a
->types
& (1 << THREAD_EVENT
) ? 'E':' ',
235 a
->types
& (1 << THREAD_EXECUTE
) ? 'X':' ',
236 a
->types
& (1 << THREAD_BACKGROUND
) ? 'B' : ' ',
237 a
->funcname
, VTY_NEWLINE
);
241 cpu_record_hash_print(struct hash_backet
*bucket
,
244 struct cpu_thread_history
*totals
= args
[0];
245 struct vty
*vty
= args
[1];
246 thread_type
*filter
= args
[2];
247 struct cpu_thread_history
*a
= bucket
->data
;
249 if ( !(a
->types
& *filter
) )
251 vty_out_cpu_thread_history(vty
,a
);
252 totals
->total_calls
+= a
->total_calls
;
253 totals
->real
.total
+= a
->real
.total
;
254 if (totals
->real
.max
< a
->real
.max
)
255 totals
->real
.max
= a
->real
.max
;
257 totals
->cpu
.total
+= a
->cpu
.total
;
258 if (totals
->cpu
.max
< a
->cpu
.max
)
259 totals
->cpu
.max
= a
->cpu
.max
;
264 cpu_record_print(struct vty
*vty
, thread_type filter
)
266 struct cpu_thread_history tmp
;
267 void *args
[3] = {&tmp
, vty
, &filter
};
269 memset(&tmp
, 0, sizeof tmp
);
270 tmp
.funcname
= "TOTAL";
274 vty_out(vty
, "%21s %18s %18s%s",
275 "", "CPU (user+system):", "Real (wall-clock):", VTY_NEWLINE
);
277 vty_out(vty
, "Runtime(ms) Invoked Avg uSec Max uSecs");
279 vty_out(vty
, " Avg uSec Max uSecs");
281 vty_out(vty
, " Type Thread%s", VTY_NEWLINE
);
282 hash_iterate(cpu_record
,
283 (void(*)(struct hash_backet
*,void*))cpu_record_hash_print
,
286 if (tmp
.total_calls
> 0)
287 vty_out_cpu_thread_history(vty
, &tmp
);
290 DEFUN (show_thread_cpu
,
292 "show thread cpu [FILTER]",
294 "Thread information\n"
296 "Display filter (rwtexb)\n")
299 thread_type filter
= (thread_type
) -1U;
304 while (argv
[0][i
] != '\0')
306 switch ( argv
[0][i
] )
310 filter
|= (1 << THREAD_READ
);
314 filter
|= (1 << THREAD_WRITE
);
318 filter
|= (1 << THREAD_TIMER
);
322 filter
|= (1 << THREAD_EVENT
);
326 filter
|= (1 << THREAD_EXECUTE
);
330 filter
|= (1 << THREAD_BACKGROUND
);
339 vty_out(vty
, "Invalid filter \"%s\" specified,"
340 " must contain at least one of 'RWTEXB'%s",
341 argv
[0], VTY_NEWLINE
);
346 cpu_record_print(vty
, filter
);
351 cpu_record_hash_clear (struct hash_backet
*bucket
,
354 thread_type
*filter
= args
;
355 struct cpu_thread_history
*a
= bucket
->data
;
357 if ( !(a
->types
& *filter
) )
360 hash_release (cpu_record
, bucket
->data
);
364 cpu_record_clear (thread_type filter
)
366 thread_type
*tmp
= &filter
;
367 hash_iterate (cpu_record
,
368 (void (*) (struct hash_backet
*,void*)) cpu_record_hash_clear
,
372 DEFUN (clear_thread_cpu
,
373 clear_thread_cpu_cmd
,
374 "clear thread cpu [FILTER]",
375 "Clear stored data\n"
376 "Thread information\n"
378 "Display filter (rwtexb)\n")
381 thread_type filter
= (thread_type
) -1U;
386 while (argv
[0][i
] != '\0')
388 switch ( argv
[0][i
] )
392 filter
|= (1 << THREAD_READ
);
396 filter
|= (1 << THREAD_WRITE
);
400 filter
|= (1 << THREAD_TIMER
);
404 filter
|= (1 << THREAD_EVENT
);
408 filter
|= (1 << THREAD_EXECUTE
);
412 filter
|= (1 << THREAD_BACKGROUND
);
421 vty_out(vty
, "Invalid filter \"%s\" specified,"
422 " must contain at least one of 'RWTEXB'%s",
423 argv
[0], VTY_NEWLINE
);
428 cpu_record_clear (filter
);
433 thread_timer_cmp(void *a
, void *b
)
435 struct thread
*thread_a
= a
;
436 struct thread
*thread_b
= b
;
438 long cmp
= timeval_cmp(thread_a
->u
.sands
, thread_b
->u
.sands
);
448 thread_timer_update(void *node
, int actual_position
)
450 struct thread
*thread
= node
;
452 thread
->index
= actual_position
;
455 /* Allocate new thread master. */
456 struct thread_master
*
457 thread_master_create (void)
459 struct thread_master
*rv
;
462 getrlimit(RLIMIT_NOFILE
, &limit
);
464 if (cpu_record
== NULL
)
466 = hash_create ((unsigned int (*) (void *))cpu_record_hash_key
,
467 (int (*) (const void *, const void *))cpu_record_hash_cmp
);
469 rv
= XCALLOC (MTYPE_THREAD_MASTER
, sizeof (struct thread_master
));
475 rv
->fd_limit
= (int)limit
.rlim_cur
;
476 rv
->read
= XCALLOC (MTYPE_THREAD
, sizeof (struct thread
*) * rv
->fd_limit
);
477 if (rv
->read
== NULL
)
479 XFREE (MTYPE_THREAD_MASTER
, rv
);
483 rv
->write
= XCALLOC (MTYPE_THREAD
, sizeof (struct thread
*) * rv
->fd_limit
);
484 if (rv
->write
== NULL
)
486 XFREE (MTYPE_THREAD
, rv
->read
);
487 XFREE (MTYPE_THREAD_MASTER
, rv
);
491 /* Initialize the timer queues */
492 rv
->timer
= pqueue_create();
493 rv
->background
= pqueue_create();
494 rv
->timer
->cmp
= rv
->background
->cmp
= thread_timer_cmp
;
495 rv
->timer
->update
= rv
->background
->update
= thread_timer_update
;
497 #if defined(HAVE_POLL)
498 rv
->handler
.pfdsize
= rv
->fd_limit
;
499 rv
->handler
.pfdcount
= 0;
500 rv
->handler
.pfds
= (struct pollfd
*) malloc (sizeof (struct pollfd
) * rv
->handler
.pfdsize
);
501 memset (rv
->handler
.pfds
, 0, sizeof (struct pollfd
) * rv
->handler
.pfdsize
);
506 /* Add a new thread to the list. */
508 thread_list_add (struct thread_list
*list
, struct thread
*thread
)
511 thread
->prev
= list
->tail
;
513 list
->tail
->next
= thread
;
520 /* Delete a thread from the list. */
521 static struct thread
*
522 thread_list_delete (struct thread_list
*list
, struct thread
*thread
)
525 thread
->next
->prev
= thread
->prev
;
527 list
->tail
= thread
->prev
;
529 thread
->prev
->next
= thread
->next
;
531 list
->head
= thread
->next
;
532 thread
->next
= thread
->prev
= NULL
;
538 thread_delete_fd (struct thread
**thread_array
, struct thread
*thread
)
540 thread_array
[thread
->u
.fd
] = NULL
;
544 thread_add_fd (struct thread
**thread_array
, struct thread
*thread
)
546 thread_array
[thread
->u
.fd
] = thread
;
549 /* Thread list is empty or not. */
551 thread_empty (struct thread_list
*list
)
553 return list
->head
? 0 : 1;
556 /* Delete top of the list and return it. */
557 static struct thread
*
558 thread_trim_head (struct thread_list
*list
)
560 if (!thread_empty (list
))
561 return thread_list_delete (list
, list
->head
);
565 /* Move thread to unuse list. */
567 thread_add_unuse (struct thread_master
*m
, struct thread
*thread
)
569 assert (m
!= NULL
&& thread
!= NULL
);
570 assert (thread
->next
== NULL
);
571 assert (thread
->prev
== NULL
);
572 assert (thread
->type
== THREAD_UNUSED
);
573 thread_list_add (&m
->unuse
, thread
);
576 /* Free all unused thread. */
578 thread_list_free (struct thread_master
*m
, struct thread_list
*list
)
583 for (t
= list
->head
; t
; t
= next
)
586 XFREE (MTYPE_THREAD
, t
);
593 thread_array_free (struct thread_master
*m
, struct thread
**thread_array
)
598 for (index
= 0; index
< m
->fd_limit
; ++index
)
600 t
= thread_array
[index
];
603 thread_array
[index
] = NULL
;
604 XFREE (MTYPE_THREAD
, t
);
608 XFREE (MTYPE_THREAD
, thread_array
);
612 thread_queue_free (struct thread_master
*m
, struct pqueue
*queue
)
616 for (i
= 0; i
< queue
->size
; i
++)
617 XFREE(MTYPE_THREAD
, queue
->array
[i
]);
619 m
->alloc
-= queue
->size
;
620 pqueue_delete(queue
);
624 * thread_master_free_unused
626 * As threads are finished with they are put on the
627 * unuse list for later reuse.
628 * If we are shutting down, Free up unused threads
629 * So we can see if we forget to shut anything off
632 thread_master_free_unused (struct thread_master
*m
)
635 while ((t
= thread_trim_head(&m
->unuse
)) != NULL
)
637 XFREE(MTYPE_THREAD
, t
);
641 /* Stop thread scheduler. */
643 thread_master_free (struct thread_master
*m
)
645 thread_array_free (m
, m
->read
);
646 thread_array_free (m
, m
->write
);
647 thread_queue_free (m
, m
->timer
);
648 thread_list_free (m
, &m
->event
);
649 thread_list_free (m
, &m
->ready
);
650 thread_list_free (m
, &m
->unuse
);
651 thread_queue_free (m
, m
->background
);
653 #if defined(HAVE_POLL)
654 XFREE (MTYPE_THREAD_MASTER
, m
->handler
.pfds
);
656 XFREE (MTYPE_THREAD_MASTER
, m
);
660 hash_clean (cpu_record
, cpu_record_hash_free
);
661 hash_free (cpu_record
);
666 /* Return remain time in second. */
668 thread_timer_remain_second (struct thread
*thread
)
670 quagga_get_relative (NULL
);
672 if (thread
->u
.sands
.tv_sec
- relative_time
.tv_sec
> 0)
673 return thread
->u
.sands
.tv_sec
- relative_time
.tv_sec
;
678 #define debugargdef const char *funcname, const char *schedfrom, int fromln
679 #define debugargpass funcname, schedfrom, fromln
682 thread_timer_remain(struct thread
*thread
)
684 quagga_get_relative(NULL
);
686 return timeval_subtract(thread
->u
.sands
, relative_time
);
689 /* Get new thread. */
690 static struct thread
*
691 thread_get (struct thread_master
*m
, u_char type
,
692 int (*func
) (struct thread
*), void *arg
, debugargdef
)
694 struct thread
*thread
= thread_trim_head (&m
->unuse
);
698 thread
= XCALLOC (MTYPE_THREAD
, sizeof (struct thread
));
702 thread
->add_type
= type
;
707 thread
->yield
= THREAD_YIELD_TIME_SLOT
; /* default */
709 thread
->funcname
= funcname
;
710 thread
->schedfrom
= schedfrom
;
711 thread
->schedfrom_line
= fromln
;
716 #if defined (HAVE_POLL)
718 #define fd_copy_fd_set(X) (X)
720 /* generic add thread function */
721 static struct thread
*
722 generic_thread_add(struct thread_master
*m
, int (*func
) (struct thread
*),
723 void *arg
, int fd
, int dir
, debugargdef
)
725 struct thread
*thread
;
730 if (dir
== THREAD_READ
)
732 event
= (POLLIN
| POLLHUP
);
737 event
= (POLLOUT
| POLLHUP
);
741 nfds_t queuepos
= m
->handler
.pfdcount
;
743 for (i
=0; i
<m
->handler
.pfdcount
; i
++)
744 if (m
->handler
.pfds
[i
].fd
== fd
)
750 /* is there enough space for a new fd? */
751 assert (queuepos
< m
->handler
.pfdsize
);
753 thread
= thread_get (m
, type
, func
, arg
, debugargpass
);
754 m
->handler
.pfds
[queuepos
].fd
= fd
;
755 m
->handler
.pfds
[queuepos
].events
|= event
;
756 if (queuepos
== m
->handler
.pfdcount
)
757 m
->handler
.pfdcount
++;
763 #define fd_copy_fd_set(X) (X)
767 fd_select (struct thread_master
*m
, int size
, thread_fd_set
*read
, thread_fd_set
*write
, thread_fd_set
*except
, struct timeval
*timer_wait
)
770 #if defined(HAVE_POLL)
771 /* recalc timeout for poll. Attention NULL pointer is no timeout with
772 select, where with poll no timeount is -1 */
774 if (timer_wait
!= NULL
)
775 timeout
= (timer_wait
->tv_sec
*1000) + (timer_wait
->tv_usec
/1000);
777 num
= poll (m
->handler
.pfds
, m
->handler
.pfdcount
+ m
->handler
.pfdcountsnmp
, timeout
);
779 num
= select (size
, read
, write
, except
, timer_wait
);
786 fd_is_set (struct thread
*thread
, thread_fd_set
*fdset
, int pos
)
788 #if defined(HAVE_POLL)
791 return FD_ISSET (THREAD_FD (thread
), fdset
);
796 fd_clear_read_write (struct thread
*thread
)
798 #if !defined(HAVE_POLL)
799 thread_fd_set
*fdset
= NULL
;
800 int fd
= THREAD_FD (thread
);
802 if (thread
->type
== THREAD_READ
)
803 fdset
= &thread
->master
->handler
.readfd
;
805 fdset
= &thread
->master
->handler
.writefd
;
807 if (!FD_ISSET (fd
, fdset
))
815 /* Add new read thread. */
817 funcname_thread_add_read_write (int dir
, struct thread_master
*m
,
818 int (*func
) (struct thread
*), void *arg
, int fd
,
821 struct thread
*thread
= NULL
;
823 #if !defined(HAVE_POLL)
824 thread_fd_set
*fdset
= NULL
;
825 if (dir
== THREAD_READ
)
826 fdset
= &m
->handler
.readfd
;
828 fdset
= &m
->handler
.writefd
;
831 #if defined (HAVE_POLL)
832 thread
= generic_thread_add(m
, func
, arg
, fd
, dir
, debugargpass
);
837 if (FD_ISSET (fd
, fdset
))
839 zlog (NULL
, LOG_WARNING
, "There is already %s fd [%d]", (dir
= THREAD_READ
) ? "read" : "write", fd
);
844 thread
= thread_get (m
, dir
, func
, arg
, debugargpass
);
848 if (dir
== THREAD_READ
)
849 thread_add_fd (m
->read
, thread
);
851 thread_add_fd (m
->write
, thread
);
856 static struct thread
*
857 funcname_thread_add_timer_timeval (struct thread_master
*m
,
858 int (*func
) (struct thread
*),
861 struct timeval
*time_relative
,
864 struct thread
*thread
;
865 struct pqueue
*queue
;
866 struct timeval alarm_time
;
870 assert (type
== THREAD_TIMER
|| type
== THREAD_BACKGROUND
);
871 assert (time_relative
);
873 queue
= ((type
== THREAD_TIMER
) ? m
->timer
: m
->background
);
874 thread
= thread_get (m
, type
, func
, arg
, debugargpass
);
876 /* Do we need jitter here? */
877 quagga_get_relative (NULL
);
878 alarm_time
.tv_sec
= relative_time
.tv_sec
+ time_relative
->tv_sec
;
879 alarm_time
.tv_usec
= relative_time
.tv_usec
+ time_relative
->tv_usec
;
880 thread
->u
.sands
= timeval_adjust(alarm_time
);
882 pqueue_enqueue(thread
, queue
);
887 /* Add timer event thread. */
889 funcname_thread_add_timer (struct thread_master
*m
,
890 int (*func
) (struct thread
*),
891 void *arg
, long timer
,
901 return funcname_thread_add_timer_timeval (m
, func
, THREAD_TIMER
, arg
,
902 &trel
, debugargpass
);
905 /* Add timer event thread with "millisecond" resolution */
907 funcname_thread_add_timer_msec (struct thread_master
*m
,
908 int (*func
) (struct thread
*),
909 void *arg
, long timer
,
916 trel
.tv_sec
= timer
/ 1000;
917 trel
.tv_usec
= 1000*(timer
% 1000);
919 return funcname_thread_add_timer_timeval (m
, func
, THREAD_TIMER
,
920 arg
, &trel
, debugargpass
);
923 /* Add timer event thread with "millisecond" resolution */
925 funcname_thread_add_timer_tv (struct thread_master
*m
,
926 int (*func
) (struct thread
*),
927 void *arg
, struct timeval
*tv
,
930 return funcname_thread_add_timer_timeval (m
, func
, THREAD_TIMER
,
931 arg
, tv
, debugargpass
);
934 /* Add a background thread, with an optional millisec delay */
936 funcname_thread_add_background (struct thread_master
*m
,
937 int (*func
) (struct thread
*),
938 void *arg
, long delay
,
947 trel
.tv_sec
= delay
/ 1000;
948 trel
.tv_usec
= 1000*(delay
% 1000);
956 return funcname_thread_add_timer_timeval (m
, func
, THREAD_BACKGROUND
,
957 arg
, &trel
, debugargpass
);
960 /* Add simple event thread. */
962 funcname_thread_add_event (struct thread_master
*m
,
963 int (*func
) (struct thread
*), void *arg
, int val
,
966 struct thread
*thread
;
970 thread
= thread_get (m
, THREAD_EVENT
, func
, arg
, debugargpass
);
972 thread_list_add (&m
->event
, thread
);
978 thread_cancel_read_or_write (struct thread
*thread
, short int state
)
980 #if defined(HAVE_POLL)
983 for (i
=0;i
<thread
->master
->handler
.pfdcount
;++i
)
984 if (thread
->master
->handler
.pfds
[i
].fd
== thread
->u
.fd
)
986 thread
->master
->handler
.pfds
[i
].events
&= ~(state
);
988 /* remove thread fds from pfd list */
989 if (thread
->master
->handler
.pfds
[i
].events
== 0)
991 memmove(thread
->master
->handler
.pfds
+i
,
992 thread
->master
->handler
.pfds
+i
+1,
993 (thread
->master
->handler
.pfdsize
-i
-1) * sizeof(struct pollfd
));
994 thread
->master
->handler
.pfdcount
--;
1000 fd_clear_read_write (thread
);
1003 /* Cancel thread from scheduler. */
1005 thread_cancel (struct thread
*thread
)
1007 struct thread_list
*list
= NULL
;
1008 struct pqueue
*queue
= NULL
;
1009 struct thread
**thread_array
= NULL
;
1011 switch (thread
->type
)
1014 #if defined (HAVE_POLL)
1015 thread_cancel_read_or_write (thread
, POLLIN
| POLLHUP
);
1017 thread_cancel_read_or_write (thread
, 0);
1019 thread_array
= thread
->master
->read
;
1022 #if defined (HAVE_POLL)
1023 thread_cancel_read_or_write (thread
, POLLOUT
| POLLHUP
);
1025 thread_cancel_read_or_write (thread
, 0);
1027 thread_array
= thread
->master
->write
;
1030 queue
= thread
->master
->timer
;
1033 list
= &thread
->master
->event
;
1036 list
= &thread
->master
->ready
;
1038 case THREAD_BACKGROUND
:
1039 queue
= thread
->master
->background
;
1048 assert(thread
->index
>= 0);
1049 assert(thread
== queue
->array
[thread
->index
]);
1050 pqueue_remove_at(thread
->index
, queue
);
1054 thread_list_delete (list
, thread
);
1056 else if (thread_array
)
1058 thread_delete_fd (thread_array
, thread
);
1062 assert(!"Thread should be either in queue or list or array!");
1065 thread
->type
= THREAD_UNUSED
;
1066 thread_add_unuse (thread
->master
, thread
);
1069 /* Delete all events which has argument value arg. */
1071 thread_cancel_event (struct thread_master
*m
, void *arg
)
1073 unsigned int ret
= 0;
1074 struct thread
*thread
;
1076 thread
= m
->event
.head
;
1087 thread_list_delete (&m
->event
, t
);
1088 t
->type
= THREAD_UNUSED
;
1089 thread_add_unuse (m
, t
);
1093 /* thread can be on the ready list too */
1094 thread
= m
->ready
.head
;
1105 thread_list_delete (&m
->ready
, t
);
1106 t
->type
= THREAD_UNUSED
;
1107 thread_add_unuse (m
, t
);
1113 static struct timeval
*
1114 thread_timer_wait (struct pqueue
*queue
, struct timeval
*timer_val
)
1118 struct thread
*next_timer
= queue
->array
[0];
1119 *timer_val
= timeval_subtract (next_timer
->u
.sands
, relative_time
);
1125 static struct thread
*
1126 thread_run (struct thread_master
*m
, struct thread
*thread
,
1127 struct thread
*fetch
)
1130 thread
->type
= THREAD_UNUSED
;
1131 thread_add_unuse (m
, thread
);
1136 thread_process_fds_helper (struct thread_master
*m
, struct thread
*thread
, thread_fd_set
*fdset
, short int state
, int pos
)
1138 struct thread
**thread_array
;
1143 if (thread
->type
== THREAD_READ
)
1144 thread_array
= m
->read
;
1146 thread_array
= m
->write
;
1148 if (fd_is_set (thread
, fdset
, pos
))
1150 fd_clear_read_write (thread
);
1151 thread_delete_fd (thread_array
, thread
);
1152 thread_list_add (&m
->ready
, thread
);
1153 thread
->type
= THREAD_READY
;
1154 #if defined(HAVE_POLL)
1155 thread
->master
->handler
.pfds
[pos
].events
&= ~(state
);
1162 #if defined(HAVE_POLL)
1164 #if defined(HAVE_SNMP)
1165 /* add snmp fds to poll set */
1167 add_snmp_pollfds(struct thread_master
*m
, fd_set
*snmpfds
, int fdsetsize
)
1170 m
->handler
.pfdcountsnmp
= m
->handler
.pfdcount
;
1171 /* cycle trough fds and add neccessary fds to poll set */
1172 for (i
=0;i
<fdsetsize
;++i
)
1174 if (FD_ISSET(i
, snmpfds
))
1176 assert (m
->handler
.pfdcountsnmp
<= m
->handler
.pfdsize
);
1178 m
->handler
.pfds
[m
->handler
.pfdcountsnmp
].fd
= i
;
1179 m
->handler
.pfds
[m
->handler
.pfdcountsnmp
].events
= POLLIN
;
1180 m
->handler
.pfdcountsnmp
++;
1186 /* check poll events */
1188 check_pollfds(struct thread_master
*m
, fd_set
*readfd
, int num
)
1192 for (i
= 0; i
< m
->handler
.pfdcount
&& ready
< num
; ++i
)
1194 /* no event for current fd? immideatly continue */
1195 if(m
->handler
.pfds
[i
].revents
== 0)
1200 /* POLLIN / POLLOUT process event */
1201 if (m
->handler
.pfds
[i
].revents
& POLLIN
)
1202 thread_process_fds_helper(m
, m
->read
[m
->handler
.pfds
[i
].fd
], NULL
, POLLIN
, i
);
1203 if (m
->handler
.pfds
[i
].revents
& POLLOUT
)
1204 thread_process_fds_helper(m
, m
->write
[m
->handler
.pfds
[i
].fd
], NULL
, POLLOUT
, i
);
1206 /* remove fd from list on POLLNVAL */
1207 if (m
->handler
.pfds
[i
].revents
& POLLNVAL
||
1208 m
->handler
.pfds
[i
].revents
& POLLHUP
)
1210 memmove(m
->handler
.pfds
+i
,
1211 m
->handler
.pfds
+i
+1,
1212 (m
->handler
.pfdsize
-i
-1) * sizeof(struct pollfd
));
1213 m
->handler
.pfdcount
--;
1217 m
->handler
.pfds
[i
].revents
= 0;
1223 thread_process_fds (struct thread_master
*m
, thread_fd_set
*rset
, thread_fd_set
*wset
, int num
)
1225 #if defined (HAVE_POLL)
1226 check_pollfds (m
, rset
, num
);
1228 int ready
= 0, index
;
1230 for (index
= 0; index
< m
->fd_limit
&& ready
< num
; ++index
)
1232 ready
+= thread_process_fds_helper (m
, m
->read
[index
], rset
, 0, 0);
1233 ready
+= thread_process_fds_helper (m
, m
->write
[index
], wset
, 0, 0);
1238 /* Add all timers that have popped to the ready list. */
1240 thread_timer_process (struct pqueue
*queue
, struct timeval
*timenow
)
1242 struct thread
*thread
;
1243 unsigned int ready
= 0;
1247 thread
= queue
->array
[0];
1248 if (timeval_cmp (*timenow
, thread
->u
.sands
) < 0)
1250 pqueue_dequeue(queue
);
1251 thread
->type
= THREAD_READY
;
1252 thread_list_add (&thread
->master
->ready
, thread
);
1258 /* process a list en masse, e.g. for event thread lists */
1260 thread_process (struct thread_list
*list
)
1262 struct thread
*thread
;
1263 struct thread
*next
;
1264 unsigned int ready
= 0;
1266 for (thread
= list
->head
; thread
; thread
= next
)
1268 next
= thread
->next
;
1269 thread_list_delete (list
, thread
);
1270 thread
->type
= THREAD_READY
;
1271 thread_list_add (&thread
->master
->ready
, thread
);
1278 /* Fetch next ready thread. */
1280 thread_fetch (struct thread_master
*m
, struct thread
*fetch
)
1282 struct thread
*thread
;
1283 thread_fd_set readfd
;
1284 thread_fd_set writefd
;
1285 thread_fd_set exceptfd
;
1286 struct timeval timer_val
= { .tv_sec
= 0, .tv_usec
= 0 };
1287 struct timeval timer_val_bg
;
1288 struct timeval
*timer_wait
= &timer_val
;
1289 struct timeval
*timer_wait_bg
;
1295 /* Signals pre-empt everything */
1296 quagga_sigevent_process ();
1298 /* Drain the ready queue of already scheduled jobs, before scheduling
1301 if ((thread
= thread_trim_head (&m
->ready
)) != NULL
)
1302 return thread_run (m
, thread
, fetch
);
1304 /* To be fair to all kinds of threads, and avoid starvation, we
1305 * need to be careful to consider all thread types for scheduling
1306 * in each quanta. I.e. we should not return early from here on.
1309 /* Normal event are the next highest priority. */
1310 thread_process (&m
->event
);
1312 /* Structure copy. */
1313 #if !defined(HAVE_POLL)
1314 readfd
= fd_copy_fd_set(m
->handler
.readfd
);
1315 writefd
= fd_copy_fd_set(m
->handler
.writefd
);
1316 exceptfd
= fd_copy_fd_set(m
->handler
.exceptfd
);
1319 /* Calculate select wait timer if nothing else to do */
1320 if (m
->ready
.count
== 0)
1322 quagga_get_relative (NULL
);
1323 timer_wait
= thread_timer_wait (m
->timer
, &timer_val
);
1324 timer_wait_bg
= thread_timer_wait (m
->background
, &timer_val_bg
);
1326 if (timer_wait_bg
&&
1327 (!timer_wait
|| (timeval_cmp (*timer_wait
, *timer_wait_bg
) > 0)))
1328 timer_wait
= timer_wait_bg
;
1331 num
= fd_select (m
, FD_SETSIZE
, &readfd
, &writefd
, &exceptfd
, timer_wait
);
1333 /* Signals should get quick treatment */
1337 continue; /* signal received - process it */
1338 zlog_warn ("select() error: %s", safe_strerror (errno
));
1342 /* Check foreground timers. Historically, they have had higher
1343 priority than I/O threads, so let's push them onto the ready
1344 list in front of the I/O threads. */
1345 quagga_get_relative (NULL
);
1346 thread_timer_process (m
->timer
, &relative_time
);
1348 /* Got IO, process it */
1350 thread_process_fds (m
, &readfd
, &writefd
, num
);
1353 /* If any threads were made ready above (I/O or foreground timer),
1354 perhaps we should avoid adding background timers to the ready
1355 list at this time. If this is code is uncommented, then background
1356 timer threads will not run unless there is nothing else to do. */
1357 if ((thread
= thread_trim_head (&m
->ready
)) != NULL
)
1358 return thread_run (m
, thread
, fetch
);
1361 /* Background timer/events, lowest priority */
1362 thread_timer_process (m
->background
, &relative_time
);
1364 if ((thread
= thread_trim_head (&m
->ready
)) != NULL
)
1365 return thread_run (m
, thread
, fetch
);
1370 thread_consumed_time (RUSAGE_T
*now
, RUSAGE_T
*start
, unsigned long *cputime
)
1373 /* This is 'user + sys' time. */
1374 *cputime
= timeval_elapsed (now
->cpu
.ru_utime
, start
->cpu
.ru_utime
) +
1375 timeval_elapsed (now
->cpu
.ru_stime
, start
->cpu
.ru_stime
);
1378 #endif /* HAVE_RUSAGE */
1379 return timeval_elapsed (now
->real
, start
->real
);
1382 /* We should aim to yield after yield milliseconds, which defaults
1383 to THREAD_YIELD_TIME_SLOT .
1384 Note: we are using real (wall clock) time for this calculation.
1385 It could be argued that CPU time may make more sense in certain
1386 contexts. The things to consider are whether the thread may have
1387 blocked (in which case wall time increases, but CPU time does not),
1388 or whether the system is heavily loaded with other processes competing
1389 for CPU time. On balance, wall clock time seems to make sense.
1390 Plus it has the added benefit that gettimeofday should be faster
1391 than calling getrusage. */
1393 thread_should_yield (struct thread
*thread
)
1395 quagga_get_relative (NULL
);
1396 return (timeval_elapsed(relative_time
, thread
->real
) >
1401 thread_set_yield_time (struct thread
*thread
, unsigned long yield_time
)
1403 thread
->yield
= yield_time
;
1407 thread_getrusage (RUSAGE_T
*r
)
1409 quagga_get_relative (NULL
);
1411 getrusage(RUSAGE_SELF
, &(r
->cpu
));
1413 r
->real
= relative_time
;
1415 #ifdef HAVE_CLOCK_MONOTONIC
1416 /* quagga_get_relative() only updates recent_time if gettimeofday
1417 * based, not when using CLOCK_MONOTONIC. As we export recent_time
1418 * and guarantee to update it before threads are run...
1420 quagga_gettimeofday(&recent_time
);
1421 #endif /* HAVE_CLOCK_MONOTONIC */
1424 struct thread
*thread_current
= NULL
;
1426 /* We check thread consumed time. If the system has getrusage, we'll
1427 use that to get in-depth stats on the performance of the thread in addition
1428 to wall clock time stats from gettimeofday. */
1430 thread_call (struct thread
*thread
)
1432 unsigned long realtime
, cputime
;
1433 RUSAGE_T before
, after
;
1435 /* Cache a pointer to the relevant cpu history thread, if the thread
1436 * does not have it yet.
1438 * Callers submitting 'dummy threads' hence must take care that
1439 * thread->cpu is NULL
1443 struct cpu_thread_history tmp
;
1445 tmp
.func
= thread
->func
;
1446 tmp
.funcname
= thread
->funcname
;
1448 thread
->hist
= hash_get (cpu_record
, &tmp
,
1449 (void * (*) (void *))cpu_record_hash_alloc
);
1452 GETRUSAGE (&before
);
1453 thread
->real
= before
.real
;
1455 thread_current
= thread
;
1456 (*thread
->func
) (thread
);
1457 thread_current
= NULL
;
1461 realtime
= thread_consumed_time (&after
, &before
, &cputime
);
1462 thread
->hist
->real
.total
+= realtime
;
1463 if (thread
->hist
->real
.max
< realtime
)
1464 thread
->hist
->real
.max
= realtime
;
1466 thread
->hist
->cpu
.total
+= cputime
;
1467 if (thread
->hist
->cpu
.max
< cputime
)
1468 thread
->hist
->cpu
.max
= cputime
;
1471 ++(thread
->hist
->total_calls
);
1472 thread
->hist
->types
|= (1 << thread
->add_type
);
1474 #ifdef CONSUMED_TIME_CHECK
1475 if (realtime
> CONSUMED_TIME_CHECK
)
1478 * We have a CPU Hog on our hands.
1479 * Whinge about it now, so we're aware this is yet another task
1482 zlog_warn ("SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
1484 (unsigned long) thread
->func
,
1485 realtime
/1000, cputime
/1000);
1487 #endif /* CONSUMED_TIME_CHECK */
1490 /* Execute thread */
1492 funcname_thread_execute (struct thread_master
*m
,
1493 int (*func
)(struct thread
*),
1498 struct thread dummy
;
1500 memset (&dummy
, 0, sizeof (struct thread
));
1502 dummy
.type
= THREAD_EVENT
;
1503 dummy
.add_type
= THREAD_EXECUTE
;
1504 dummy
.master
= NULL
;
1509 dummy
.funcname
= funcname
;
1510 dummy
.schedfrom
= schedfrom
;
1511 dummy
.schedfrom_line
= fromln
;
1513 thread_call (&dummy
);