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 DEFINE_MTYPE_STATIC(LIB
, THREAD
, "Thread")
36 DEFINE_MTYPE_STATIC(LIB
, THREAD_MASTER
, "Thread master")
37 DEFINE_MTYPE_STATIC(LIB
, THREAD_STATS
, "Thread stats")
39 #if defined(__APPLE__)
40 #include <mach/mach.h>
41 #include <mach/mach_time.h>
44 static pthread_mutex_t cpu_record_mtx
= PTHREAD_MUTEX_INITIALIZER
;
45 static struct hash
*cpu_record
= NULL
;
48 timeval_elapsed (struct timeval a
, struct timeval b
)
50 return (((a
.tv_sec
- b
.tv_sec
) * TIMER_SECOND_MICRO
)
51 + (a
.tv_usec
- b
.tv_usec
));
55 cpu_record_hash_key (struct cpu_thread_history
*a
)
57 return (uintptr_t) a
->func
;
61 cpu_record_hash_cmp (const struct cpu_thread_history
*a
,
62 const struct cpu_thread_history
*b
)
64 return a
->func
== b
->func
;
68 cpu_record_hash_alloc (struct cpu_thread_history
*a
)
70 struct cpu_thread_history
*new;
71 new = XCALLOC (MTYPE_THREAD_STATS
, sizeof (struct cpu_thread_history
));
73 new->funcname
= a
->funcname
;
78 cpu_record_hash_free (void *a
)
80 struct cpu_thread_history
*hist
= a
;
82 XFREE (MTYPE_THREAD_STATS
, hist
);
86 vty_out_cpu_thread_history(struct vty
* vty
,
87 struct cpu_thread_history
*a
)
89 vty_out(vty
, "%5d %10ld.%03ld %9d %8ld %9ld %8ld %9ld",
90 a
->total_active
, a
->cpu
.total
/1000, a
->cpu
.total
%1000, a
->total_calls
,
91 a
->cpu
.total
/a
->total_calls
, a
->cpu
.max
,
92 a
->real
.total
/a
->total_calls
, a
->real
.max
);
93 vty_out(vty
, " %c%c%c%c%c%c %s%s",
94 a
->types
& (1 << THREAD_READ
) ? 'R':' ',
95 a
->types
& (1 << THREAD_WRITE
) ? 'W':' ',
96 a
->types
& (1 << THREAD_TIMER
) ? 'T':' ',
97 a
->types
& (1 << THREAD_EVENT
) ? 'E':' ',
98 a
->types
& (1 << THREAD_EXECUTE
) ? 'X':' ',
99 a
->types
& (1 << THREAD_BACKGROUND
) ? 'B' : ' ',
100 a
->funcname
, VTY_NEWLINE
);
104 cpu_record_hash_print(struct hash_backet
*bucket
,
107 struct cpu_thread_history
*totals
= args
[0];
108 struct vty
*vty
= args
[1];
109 thread_type
*filter
= args
[2];
110 struct cpu_thread_history
*a
= bucket
->data
;
112 if ( !(a
->types
& *filter
) )
114 vty_out_cpu_thread_history(vty
,a
);
115 totals
->total_active
+= a
->total_active
;
116 totals
->total_calls
+= a
->total_calls
;
117 totals
->real
.total
+= a
->real
.total
;
118 if (totals
->real
.max
< a
->real
.max
)
119 totals
->real
.max
= a
->real
.max
;
120 totals
->cpu
.total
+= a
->cpu
.total
;
121 if (totals
->cpu
.max
< a
->cpu
.max
)
122 totals
->cpu
.max
= a
->cpu
.max
;
126 cpu_record_print(struct vty
*vty
, thread_type filter
)
128 struct cpu_thread_history tmp
;
129 void *args
[3] = {&tmp
, vty
, &filter
};
131 memset(&tmp
, 0, sizeof tmp
);
132 tmp
.funcname
= "TOTAL";
135 vty_out(vty
, "%21s %18s %18s%s",
136 "", "CPU (user+system):", "Real (wall-clock):", VTY_NEWLINE
);
137 vty_out(vty
, "Active Runtime(ms) Invoked Avg uSec Max uSecs");
138 vty_out(vty
, " Avg uSec Max uSecs");
139 vty_out(vty
, " Type Thread%s", VTY_NEWLINE
);
141 pthread_mutex_lock (&cpu_record_mtx
);
143 hash_iterate(cpu_record
,
144 (void(*)(struct hash_backet
*,void*))cpu_record_hash_print
,
147 pthread_mutex_unlock (&cpu_record_mtx
);
149 if (tmp
.total_calls
> 0)
150 vty_out_cpu_thread_history(vty
, &tmp
);
153 DEFUN (show_thread_cpu
,
155 "show thread cpu [FILTER]",
157 "Thread information\n"
159 "Display filter (rwtexb)\n")
163 thread_type filter
= (thread_type
) -1U;
168 while (argv
[idx_filter
]->arg
[i
] != '\0')
170 switch ( argv
[idx_filter
]->arg
[i
] )
174 filter
|= (1 << THREAD_READ
);
178 filter
|= (1 << THREAD_WRITE
);
182 filter
|= (1 << THREAD_TIMER
);
186 filter
|= (1 << THREAD_EVENT
);
190 filter
|= (1 << THREAD_EXECUTE
);
194 filter
|= (1 << THREAD_BACKGROUND
);
203 vty_out(vty
, "Invalid filter \"%s\" specified,"
204 " must contain at least one of 'RWTEXB'%s",
205 argv
[idx_filter
]->arg
, VTY_NEWLINE
);
210 cpu_record_print(vty
, filter
);
215 cpu_record_hash_clear (struct hash_backet
*bucket
,
218 thread_type
*filter
= args
;
219 struct cpu_thread_history
*a
= bucket
->data
;
221 if ( !(a
->types
& *filter
) )
224 pthread_mutex_lock (&cpu_record_mtx
);
226 hash_release (cpu_record
, bucket
->data
);
228 pthread_mutex_unlock (&cpu_record_mtx
);
232 cpu_record_clear (thread_type filter
)
234 thread_type
*tmp
= &filter
;
236 pthread_mutex_lock (&cpu_record_mtx
);
238 hash_iterate (cpu_record
,
239 (void (*) (struct hash_backet
*,void*)) cpu_record_hash_clear
,
242 pthread_mutex_unlock (&cpu_record_mtx
);
245 DEFUN (clear_thread_cpu
,
246 clear_thread_cpu_cmd
,
247 "clear thread cpu [FILTER]",
248 "Clear stored data\n"
249 "Thread information\n"
251 "Display filter (rwtexb)\n")
255 thread_type filter
= (thread_type
) -1U;
260 while (argv
[idx_filter
]->arg
[i
] != '\0')
262 switch ( argv
[idx_filter
]->arg
[i
] )
266 filter
|= (1 << THREAD_READ
);
270 filter
|= (1 << THREAD_WRITE
);
274 filter
|= (1 << THREAD_TIMER
);
278 filter
|= (1 << THREAD_EVENT
);
282 filter
|= (1 << THREAD_EXECUTE
);
286 filter
|= (1 << THREAD_BACKGROUND
);
295 vty_out(vty
, "Invalid filter \"%s\" specified,"
296 " must contain at least one of 'RWTEXB'%s",
297 argv
[idx_filter
]->arg
, VTY_NEWLINE
);
302 cpu_record_clear (filter
);
307 thread_cmd_init (void)
309 install_element (VIEW_NODE
, &show_thread_cpu_cmd
);
310 install_element (ENABLE_NODE
, &clear_thread_cpu_cmd
);
314 thread_timer_cmp(void *a
, void *b
)
316 struct thread
*thread_a
= a
;
317 struct thread
*thread_b
= b
;
319 if (timercmp (&thread_a
->u
.sands
, &thread_b
->u
.sands
, <))
321 if (timercmp (&thread_a
->u
.sands
, &thread_b
->u
.sands
, >))
327 thread_timer_update(void *node
, int actual_position
)
329 struct thread
*thread
= node
;
331 thread
->index
= actual_position
;
334 /* Allocate new thread master. */
335 struct thread_master
*
336 thread_master_create (void)
338 struct thread_master
*rv
;
341 getrlimit(RLIMIT_NOFILE
, &limit
);
343 pthread_mutex_lock (&cpu_record_mtx
);
345 if (cpu_record
== NULL
)
346 cpu_record
= hash_create ((unsigned int (*) (void *))cpu_record_hash_key
,
347 (int (*) (const void *, const void *))
348 cpu_record_hash_cmp
);
350 pthread_mutex_unlock (&cpu_record_mtx
);
352 rv
= XCALLOC (MTYPE_THREAD_MASTER
, sizeof (struct thread_master
));
356 pthread_mutex_init (&rv
->mtx
, NULL
);
358 rv
->fd_limit
= (int)limit
.rlim_cur
;
359 rv
->read
= XCALLOC (MTYPE_THREAD
, sizeof (struct thread
*) * rv
->fd_limit
);
360 if (rv
->read
== NULL
)
362 XFREE (MTYPE_THREAD_MASTER
, rv
);
366 rv
->write
= XCALLOC (MTYPE_THREAD
, sizeof (struct thread
*) * rv
->fd_limit
);
367 if (rv
->write
== NULL
)
369 XFREE (MTYPE_THREAD
, rv
->read
);
370 XFREE (MTYPE_THREAD_MASTER
, rv
);
374 /* Initialize the timer queues */
375 rv
->timer
= pqueue_create();
376 rv
->background
= pqueue_create();
377 rv
->timer
->cmp
= rv
->background
->cmp
= thread_timer_cmp
;
378 rv
->timer
->update
= rv
->background
->update
= thread_timer_update
;
380 rv
->handle_signals
= true;
382 #if defined(HAVE_POLL_CALL)
383 rv
->handler
.pfdsize
= rv
->fd_limit
;
384 rv
->handler
.pfdcount
= 0;
385 rv
->handler
.pfds
= XCALLOC (MTYPE_THREAD_MASTER
,
386 sizeof (struct pollfd
) * rv
->handler
.pfdsize
);
391 /* Add a new thread to the list. */
393 thread_list_add (struct thread_list
*list
, struct thread
*thread
)
396 thread
->prev
= list
->tail
;
398 list
->tail
->next
= thread
;
405 /* Delete a thread from the list. */
406 static struct thread
*
407 thread_list_delete (struct thread_list
*list
, struct thread
*thread
)
410 thread
->next
->prev
= thread
->prev
;
412 list
->tail
= thread
->prev
;
414 thread
->prev
->next
= thread
->next
;
416 list
->head
= thread
->next
;
417 thread
->next
= thread
->prev
= NULL
;
423 thread_delete_fd (struct thread
**thread_array
, struct thread
*thread
)
425 thread_array
[thread
->u
.fd
] = NULL
;
429 thread_add_fd (struct thread
**thread_array
, struct thread
*thread
)
431 thread_array
[thread
->u
.fd
] = thread
;
434 /* Thread list is empty or not. */
436 thread_empty (struct thread_list
*list
)
438 return list
->head
? 0 : 1;
441 /* Delete top of the list and return it. */
442 static struct thread
*
443 thread_trim_head (struct thread_list
*list
)
445 if (!thread_empty (list
))
446 return thread_list_delete (list
, list
->head
);
450 /* Move thread to unuse list. */
452 thread_add_unuse (struct thread_master
*m
, struct thread
*thread
)
454 assert (m
!= NULL
&& thread
!= NULL
);
455 assert (thread
->next
== NULL
);
456 assert (thread
->prev
== NULL
);
459 thread
->type
= THREAD_UNUSED
;
460 thread
->hist
->total_active
--;
461 thread_list_add (&m
->unuse
, thread
);
464 /* Free all unused thread. */
466 thread_list_free (struct thread_master
*m
, struct thread_list
*list
)
471 for (t
= list
->head
; t
; t
= next
)
474 XFREE (MTYPE_THREAD
, t
);
481 thread_array_free (struct thread_master
*m
, struct thread
**thread_array
)
486 for (index
= 0; index
< m
->fd_limit
; ++index
)
488 t
= thread_array
[index
];
491 thread_array
[index
] = NULL
;
492 XFREE (MTYPE_THREAD
, t
);
496 XFREE (MTYPE_THREAD
, thread_array
);
500 thread_queue_free (struct thread_master
*m
, struct pqueue
*queue
)
504 for (i
= 0; i
< queue
->size
; i
++)
505 XFREE(MTYPE_THREAD
, queue
->array
[i
]);
507 m
->alloc
-= queue
->size
;
508 pqueue_delete(queue
);
512 * thread_master_free_unused
514 * As threads are finished with they are put on the
515 * unuse list for later reuse.
516 * If we are shutting down, Free up unused threads
517 * So we can see if we forget to shut anything off
520 thread_master_free_unused (struct thread_master
*m
)
522 pthread_mutex_lock (&m
->mtx
);
525 while ((t
= thread_trim_head(&m
->unuse
)) != NULL
)
527 pthread_mutex_destroy (&t
->mtx
);
528 XFREE(MTYPE_THREAD
, t
);
531 pthread_mutex_unlock (&m
->mtx
);
534 /* Stop thread scheduler. */
536 thread_master_free (struct thread_master
*m
)
538 thread_array_free (m
, m
->read
);
539 thread_array_free (m
, m
->write
);
540 thread_queue_free (m
, m
->timer
);
541 thread_list_free (m
, &m
->event
);
542 thread_list_free (m
, &m
->ready
);
543 thread_list_free (m
, &m
->unuse
);
544 thread_queue_free (m
, m
->background
);
545 pthread_mutex_destroy (&m
->mtx
);
547 #if defined(HAVE_POLL_CALL)
548 XFREE (MTYPE_THREAD_MASTER
, m
->handler
.pfds
);
550 XFREE (MTYPE_THREAD_MASTER
, m
);
552 pthread_mutex_lock (&cpu_record_mtx
);
556 hash_clean (cpu_record
, cpu_record_hash_free
);
557 hash_free (cpu_record
);
561 pthread_mutex_unlock (&cpu_record_mtx
);
564 /* Return remain time in second. */
566 thread_timer_remain_second (struct thread
*thread
)
570 pthread_mutex_lock (&thread
->mtx
);
572 remain
= monotime_until(&thread
->u
.sands
, NULL
) / 1000000LL;
574 pthread_mutex_unlock (&thread
->mtx
);
576 return remain
< 0 ? 0 : remain
;
579 #define debugargdef const char *funcname, const char *schedfrom, int fromln
580 #define debugargpass funcname, schedfrom, fromln
583 thread_timer_remain(struct thread
*thread
)
585 struct timeval remain
;
586 pthread_mutex_lock (&thread
->mtx
);
588 monotime_until(&thread
->u
.sands
, &remain
);
590 pthread_mutex_unlock (&thread
->mtx
);
594 /* Get new thread. */
595 static struct thread
*
596 thread_get (struct thread_master
*m
, u_char type
,
597 int (*func
) (struct thread
*), void *arg
, debugargdef
)
599 struct thread
*thread
= thread_trim_head (&m
->unuse
);
600 struct cpu_thread_history tmp
;
604 thread
= XCALLOC (MTYPE_THREAD
, sizeof (struct thread
));
605 /* mutex only needs to be initialized at struct creation. */
606 pthread_mutex_init (&thread
->mtx
, NULL
);
611 thread
->add_type
= type
;
615 thread
->yield
= THREAD_YIELD_TIME_SLOT
; /* default */
618 * So if the passed in funcname is not what we have
619 * stored that means the thread->hist needs to be
620 * updated. We keep the last one around in unused
621 * under the assumption that we are probably
622 * going to immediately allocate the same
624 * This hopefully saves us some serious
627 if (thread
->funcname
!= funcname
||
628 thread
->func
!= func
)
631 tmp
.funcname
= funcname
;
632 pthread_mutex_lock (&cpu_record_mtx
);
634 thread
->hist
= hash_get (cpu_record
, &tmp
,
635 (void * (*) (void *))cpu_record_hash_alloc
);
637 pthread_mutex_unlock (&cpu_record_mtx
);
639 thread
->hist
->total_active
++;
641 thread
->funcname
= funcname
;
642 thread
->schedfrom
= schedfrom
;
643 thread
->schedfrom_line
= fromln
;
648 #if defined (HAVE_POLL_CALL)
650 #define fd_copy_fd_set(X) (X)
652 /* generic add thread function */
653 static struct thread
*
654 generic_thread_add(struct thread_master
*m
, int (*func
) (struct thread
*),
655 void *arg
, int fd
, int dir
, debugargdef
)
657 struct thread
*thread
;
662 if (dir
== THREAD_READ
)
664 event
= (POLLIN
| POLLHUP
);
669 event
= (POLLOUT
| POLLHUP
);
673 nfds_t queuepos
= m
->handler
.pfdcount
;
675 for (i
=0; i
<m
->handler
.pfdcount
; i
++)
676 if (m
->handler
.pfds
[i
].fd
== fd
)
682 /* is there enough space for a new fd? */
683 assert (queuepos
< m
->handler
.pfdsize
);
685 thread
= thread_get (m
, type
, func
, arg
, debugargpass
);
686 m
->handler
.pfds
[queuepos
].fd
= fd
;
687 m
->handler
.pfds
[queuepos
].events
|= event
;
688 if (queuepos
== m
->handler
.pfdcount
)
689 m
->handler
.pfdcount
++;
695 #define fd_copy_fd_set(X) (X)
699 fd_select (struct thread_master
*m
, int size
, thread_fd_set
*read
, thread_fd_set
*write
, thread_fd_set
*except
, struct timeval
*timer_wait
)
703 /* If timer_wait is null here, that means either select() or poll() should
704 * block indefinitely, unless the thread_master has overriden it. select()
705 * and poll() differ in the timeout values they interpret as an indefinite
706 * block; select() requires a null pointer, while poll takes a millisecond
709 * The thread_master owner has the option of overriding the default behavior
710 * by setting ->selectpoll_timeout. If the value is positive, it specifies
711 * the maximum number of milliseconds to wait. If the timeout is -1, it
712 * specifies that we should never wait and always return immediately even if
713 * no event is detected. If the value is zero, the behavior is default.
716 #if defined(HAVE_POLL_CALL)
719 if (timer_wait
!= NULL
&& m
->selectpoll_timeout
== 0) // use the default value
720 timeout
= (timer_wait
->tv_sec
*1000) + (timer_wait
->tv_usec
/1000);
721 else if (m
->selectpoll_timeout
> 0) // use the user's timeout
722 timeout
= m
->selectpoll_timeout
;
723 else if (m
->selectpoll_timeout
< 0) // effect a poll (return immediately)
726 num
= poll (m
->handler
.pfds
, m
->handler
.pfdcount
+ m
->handler
.pfdcountsnmp
, timeout
);
728 struct timeval timeout
;
730 if (m
->selectpoll_timeout
> 0) // use the user's timeout
732 timeout
.tv_sec
= m
->selectpoll_timeout
/ 1000;
733 timeout
.tv_usec
= (m
->selectpoll_timeout
% 1000) * 1000;
734 timer_wait
= &timeout
;
736 else if (m
->selectpoll_timeout
< 0) // effect a poll (return immediately)
740 timer_wait
= &timeout
;
742 num
= select (size
, read
, write
, except
, timer_wait
);
749 fd_is_set (struct thread
*thread
, thread_fd_set
*fdset
, int pos
)
751 #if defined(HAVE_POLL_CALL)
754 return FD_ISSET (THREAD_FD (thread
), fdset
);
759 fd_clear_read_write (struct thread
*thread
)
761 #if !defined(HAVE_POLL_CALL)
762 thread_fd_set
*fdset
= NULL
;
763 int fd
= THREAD_FD (thread
);
765 if (thread
->type
== THREAD_READ
)
766 fdset
= &thread
->master
->handler
.readfd
;
768 fdset
= &thread
->master
->handler
.writefd
;
770 if (!FD_ISSET (fd
, fdset
))
778 /* Add new read thread. */
780 funcname_thread_add_read_write (int dir
, struct thread_master
*m
,
781 int (*func
) (struct thread
*), void *arg
, int fd
, struct thread
**t_ptr
,
784 struct thread
*thread
= NULL
;
786 pthread_mutex_lock (&m
->mtx
);
788 if (t_ptr
&& *t_ptr
) // thread is already scheduled; don't reschedule
790 pthread_mutex_unlock (&m
->mtx
);
794 #if defined (HAVE_POLL_CALL)
795 thread
= generic_thread_add(m
, func
, arg
, fd
, dir
, debugargpass
);
797 if (fd
>= FD_SETSIZE
)
799 zlog_err ("File descriptor %d is >= FD_SETSIZE (%d). Please recompile"
800 "with --enable-poll=yes", fd
, FD_SETSIZE
);
801 assert (fd
< FD_SETSIZE
&& !"fd >= FD_SETSIZE");
803 thread_fd_set
*fdset
= NULL
;
804 if (dir
== THREAD_READ
)
805 fdset
= &m
->handler
.readfd
;
807 fdset
= &m
->handler
.writefd
;
809 if (FD_ISSET (fd
, fdset
))
811 zlog_warn ("There is already %s fd [%d]",
812 (dir
== THREAD_READ
) ? "read" : "write", fd
);
817 thread
= thread_get (m
, dir
, func
, arg
, debugargpass
);
823 pthread_mutex_lock (&thread
->mtx
);
826 if (dir
== THREAD_READ
)
827 thread_add_fd (m
->read
, thread
);
829 thread_add_fd (m
->write
, thread
);
831 pthread_mutex_unlock (&thread
->mtx
);
840 pthread_mutex_unlock (&m
->mtx
);
844 funcname_thread_add_timer_timeval (struct thread_master
*m
,
845 int (*func
) (struct thread
*), int type
, void *arg
,
846 struct timeval
*time_relative
, struct thread
**t_ptr
, debugargdef
)
848 struct thread
*thread
;
849 struct pqueue
*queue
;
853 assert (type
== THREAD_TIMER
|| type
== THREAD_BACKGROUND
);
854 assert (time_relative
);
856 pthread_mutex_lock (&m
->mtx
);
858 if (t_ptr
&& *t_ptr
) // thread is already scheduled; don't reschedule
860 pthread_mutex_unlock (&m
->mtx
);
864 queue
= ((type
== THREAD_TIMER
) ? m
->timer
: m
->background
);
865 thread
= thread_get (m
, type
, func
, arg
, debugargpass
);
867 pthread_mutex_lock (&thread
->mtx
);
869 monotime(&thread
->u
.sands
);
870 timeradd(&thread
->u
.sands
, time_relative
, &thread
->u
.sands
);
871 pqueue_enqueue(thread
, queue
);
873 pthread_mutex_unlock (&thread
->mtx
);
881 pthread_mutex_unlock (&m
->mtx
);
885 /* Add timer event thread. */
887 funcname_thread_add_timer (struct thread_master
*m
,
888 int (*func
) (struct thread
*), void *arg
, long timer
,
889 struct thread
**t_ptr
, debugargdef
)
898 return funcname_thread_add_timer_timeval (m
, func
, THREAD_TIMER
, arg
, &trel
,
899 t_ptr
, debugargpass
);
902 /* Add timer event thread with "millisecond" resolution */
904 funcname_thread_add_timer_msec (struct thread_master
*m
,
905 int (*func
) (struct thread
*), void *arg
, long timer
,
906 struct thread
**t_ptr
, debugargdef
)
912 trel
.tv_sec
= timer
/ 1000;
913 trel
.tv_usec
= 1000*(timer
% 1000);
915 funcname_thread_add_timer_timeval (m
, func
, THREAD_TIMER
, arg
, &trel
,
916 t_ptr
, debugargpass
);
919 /* Add timer event thread with "millisecond" resolution */
921 funcname_thread_add_timer_tv (struct thread_master
*m
,
922 int (*func
) (struct thread
*), void *arg
, struct timeval
*tv
,
923 struct thread
**t_ptr
, debugargdef
)
925 funcname_thread_add_timer_timeval (m
, func
, THREAD_TIMER
, arg
, tv
, t_ptr
,
929 /* Add a background thread, with an optional millisec delay */
931 funcname_thread_add_background (struct thread_master
*m
,
932 int (*func
) (struct thread
*), void *arg
, long delay
,
933 struct thread
**t_ptr
, debugargdef
)
941 trel
.tv_sec
= delay
/ 1000;
942 trel
.tv_usec
= 1000*(delay
% 1000);
950 funcname_thread_add_timer_timeval (m
, func
, THREAD_BACKGROUND
, arg
, &trel
,
951 t_ptr
, debugargpass
);
954 /* Add simple event thread. */
956 funcname_thread_add_event (struct thread_master
*m
,
957 int (*func
) (struct thread
*), void *arg
, int val
,
958 struct thread
**t_ptr
, debugargdef
)
960 struct thread
*thread
;
964 pthread_mutex_lock (&m
->mtx
);
966 if (t_ptr
&& *t_ptr
) // thread is already scheduled; don't reschedule
968 pthread_mutex_unlock (&m
->mtx
);
972 thread
= thread_get (m
, THREAD_EVENT
, func
, arg
, debugargpass
);
973 pthread_mutex_lock (&thread
->mtx
);
976 thread_list_add (&m
->event
, thread
);
978 pthread_mutex_unlock (&thread
->mtx
);
986 pthread_mutex_unlock (&m
->mtx
);
990 thread_cancel_read_or_write (struct thread
*thread
, short int state
)
992 #if defined(HAVE_POLL_CALL)
995 for (i
=0;i
<thread
->master
->handler
.pfdcount
;++i
)
996 if (thread
->master
->handler
.pfds
[i
].fd
== thread
->u
.fd
)
998 thread
->master
->handler
.pfds
[i
].events
&= ~(state
);
1000 /* remove thread fds from pfd list */
1001 if (thread
->master
->handler
.pfds
[i
].events
== 0)
1003 memmove(thread
->master
->handler
.pfds
+i
,
1004 thread
->master
->handler
.pfds
+i
+1,
1005 (thread
->master
->handler
.pfdsize
-i
-1) * sizeof(struct pollfd
));
1006 thread
->master
->handler
.pfdcount
--;
1012 fd_clear_read_write (thread
);
1016 * Cancel thread from scheduler.
1018 * This function is *NOT* MT-safe. DO NOT call it from any other pthread except
1019 * the one which owns thread->master.
1022 thread_cancel (struct thread
*thread
)
1024 struct thread_list
*list
= NULL
;
1025 struct pqueue
*queue
= NULL
;
1026 struct thread
**thread_array
= NULL
;
1028 pthread_mutex_lock (&thread
->master
->mtx
);
1029 pthread_mutex_lock (&thread
->mtx
);
1031 switch (thread
->type
)
1034 #if defined (HAVE_POLL_CALL)
1035 thread_cancel_read_or_write (thread
, POLLIN
| POLLHUP
);
1037 thread_cancel_read_or_write (thread
, 0);
1039 thread_array
= thread
->master
->read
;
1042 #if defined (HAVE_POLL_CALL)
1043 thread_cancel_read_or_write (thread
, POLLOUT
| POLLHUP
);
1045 thread_cancel_read_or_write (thread
, 0);
1047 thread_array
= thread
->master
->write
;
1050 queue
= thread
->master
->timer
;
1053 list
= &thread
->master
->event
;
1056 list
= &thread
->master
->ready
;
1058 case THREAD_BACKGROUND
:
1059 queue
= thread
->master
->background
;
1068 assert(thread
->index
>= 0);
1069 pqueue_remove (thread
, queue
);
1073 thread_list_delete (list
, thread
);
1075 else if (thread_array
)
1077 thread_delete_fd (thread_array
, thread
);
1081 assert(!"Thread should be either in queue or list or array!");
1085 *thread
->ref
= NULL
;
1087 thread_add_unuse (thread
->master
, thread
);
1090 pthread_mutex_unlock (&thread
->mtx
);
1091 pthread_mutex_unlock (&thread
->master
->mtx
);
1094 /* Delete all events which has argument value arg. */
1096 thread_cancel_event (struct thread_master
*m
, void *arg
)
1098 unsigned int ret
= 0;
1099 struct thread
*thread
;
1102 pthread_mutex_lock (&m
->mtx
);
1104 thread
= m
->event
.head
;
1108 pthread_mutex_lock (&t
->mtx
);
1115 thread_list_delete (&m
->event
, t
);
1118 thread_add_unuse (m
, t
);
1121 pthread_mutex_unlock (&t
->mtx
);
1124 /* thread can be on the ready list too */
1125 thread
= m
->ready
.head
;
1129 pthread_mutex_lock (&t
->mtx
);
1136 thread_list_delete (&m
->ready
, t
);
1139 thread_add_unuse (m
, t
);
1142 pthread_mutex_unlock (&t
->mtx
);
1145 pthread_mutex_unlock (&m
->mtx
);
1149 static struct timeval
*
1150 thread_timer_wait (struct pqueue
*queue
, struct timeval
*timer_val
)
1154 struct thread
*next_timer
= queue
->array
[0];
1155 monotime_until(&next_timer
->u
.sands
, timer_val
);
1161 static struct thread
*
1162 thread_run (struct thread_master
*m
, struct thread
*thread
,
1163 struct thread
*fetch
)
1166 thread_add_unuse (m
, thread
);
1171 thread_process_fds_helper (struct thread_master
*m
, struct thread
*thread
, thread_fd_set
*fdset
, short int state
, int pos
)
1173 struct thread
**thread_array
;
1178 if (thread
->type
== THREAD_READ
)
1179 thread_array
= m
->read
;
1181 thread_array
= m
->write
;
1183 if (fd_is_set (thread
, fdset
, pos
))
1185 fd_clear_read_write (thread
);
1186 thread_delete_fd (thread_array
, thread
);
1187 thread_list_add (&m
->ready
, thread
);
1188 thread
->type
= THREAD_READY
;
1189 #if defined(HAVE_POLL_CALL)
1190 thread
->master
->handler
.pfds
[pos
].events
&= ~(state
);
1197 #if defined(HAVE_POLL_CALL)
1199 /* check poll events */
1201 check_pollfds(struct thread_master
*m
, fd_set
*readfd
, int num
)
1205 for (i
= 0; i
< m
->handler
.pfdcount
&& ready
< num
; ++i
)
1207 /* no event for current fd? immideatly continue */
1208 if(m
->handler
.pfds
[i
].revents
== 0)
1213 /* POLLIN / POLLOUT process event */
1214 if (m
->handler
.pfds
[i
].revents
& POLLIN
)
1215 thread_process_fds_helper(m
, m
->read
[m
->handler
.pfds
[i
].fd
], NULL
, POLLIN
, i
);
1216 if (m
->handler
.pfds
[i
].revents
& POLLOUT
)
1217 thread_process_fds_helper(m
, m
->write
[m
->handler
.pfds
[i
].fd
], NULL
, POLLOUT
, i
);
1219 /* remove fd from list on POLLNVAL */
1220 if (m
->handler
.pfds
[i
].revents
& POLLNVAL
||
1221 m
->handler
.pfds
[i
].revents
& POLLHUP
)
1223 memmove(m
->handler
.pfds
+i
,
1224 m
->handler
.pfds
+i
+1,
1225 (m
->handler
.pfdsize
-i
-1) * sizeof(struct pollfd
));
1226 m
->handler
.pfdcount
--;
1230 m
->handler
.pfds
[i
].revents
= 0;
1236 thread_process_fds (struct thread_master
*m
, thread_fd_set
*rset
, thread_fd_set
*wset
, int num
)
1238 #if defined (HAVE_POLL_CALL)
1239 check_pollfds (m
, rset
, num
);
1241 int ready
= 0, index
;
1243 for (index
= 0; index
< m
->fd_limit
&& ready
< num
; ++index
)
1245 ready
+= thread_process_fds_helper (m
, m
->read
[index
], rset
, 0, 0);
1246 ready
+= thread_process_fds_helper (m
, m
->write
[index
], wset
, 0, 0);
1251 /* Add all timers that have popped to the ready list. */
1253 thread_timer_process (struct pqueue
*queue
, struct timeval
*timenow
)
1255 struct thread
*thread
;
1256 unsigned int ready
= 0;
1260 thread
= queue
->array
[0];
1261 if (timercmp (timenow
, &thread
->u
.sands
, <))
1263 pqueue_dequeue(queue
);
1264 thread
->type
= THREAD_READY
;
1265 thread_list_add (&thread
->master
->ready
, thread
);
1271 /* process a list en masse, e.g. for event thread lists */
1273 thread_process (struct thread_list
*list
)
1275 struct thread
*thread
;
1276 struct thread
*next
;
1277 unsigned int ready
= 0;
1279 for (thread
= list
->head
; thread
; thread
= next
)
1281 next
= thread
->next
;
1282 thread_list_delete (list
, thread
);
1283 thread
->type
= THREAD_READY
;
1284 thread_list_add (&thread
->master
->ready
, thread
);
1291 /* Fetch next ready thread. */
1293 thread_fetch (struct thread_master
*m
, struct thread
*fetch
)
1295 struct thread
*thread
;
1296 thread_fd_set readfd
;
1297 thread_fd_set writefd
;
1298 thread_fd_set exceptfd
;
1300 struct timeval timer_val
= { .tv_sec
= 0, .tv_usec
= 0 };
1301 struct timeval timer_val_bg
;
1302 struct timeval
*timer_wait
= &timer_val
;
1303 struct timeval
*timer_wait_bg
;
1309 /* Signals pre-empt everything */
1310 if (m
->handle_signals
)
1311 quagga_sigevent_process ();
1313 pthread_mutex_lock (&m
->mtx
);
1314 /* Drain the ready queue of already scheduled jobs, before scheduling
1317 if ((thread
= thread_trim_head (&m
->ready
)) != NULL
)
1319 fetch
= thread_run (m
, thread
, fetch
);
1322 pthread_mutex_unlock (&m
->mtx
);
1326 /* To be fair to all kinds of threads, and avoid starvation, we
1327 * need to be careful to consider all thread types for scheduling
1328 * in each quanta. I.e. we should not return early from here on.
1331 /* Normal event are the next highest priority. */
1332 thread_process (&m
->event
);
1334 /* Structure copy. */
1335 #if !defined(HAVE_POLL_CALL)
1336 readfd
= fd_copy_fd_set(m
->handler
.readfd
);
1337 writefd
= fd_copy_fd_set(m
->handler
.writefd
);
1338 exceptfd
= fd_copy_fd_set(m
->handler
.exceptfd
);
1341 /* Calculate select wait timer if nothing else to do */
1342 if (m
->ready
.count
== 0)
1344 timer_wait
= thread_timer_wait (m
->timer
, &timer_val
);
1345 timer_wait_bg
= thread_timer_wait (m
->background
, &timer_val_bg
);
1347 if (timer_wait_bg
&&
1348 (!timer_wait
|| (timercmp (timer_wait
, timer_wait_bg
, >))))
1349 timer_wait
= timer_wait_bg
;
1352 if (timer_wait
&& timer_wait
->tv_sec
< 0)
1354 timerclear(&timer_val
);
1355 timer_wait
= &timer_val
;
1358 num
= fd_select (m
, FD_SETSIZE
, &readfd
, &writefd
, &exceptfd
, timer_wait
);
1360 /* Signals should get quick treatment */
1365 pthread_mutex_unlock (&m
->mtx
);
1366 continue; /* signal received - process it */
1368 zlog_warn ("select() error: %s", safe_strerror (errno
));
1369 pthread_mutex_unlock (&m
->mtx
);
1373 /* Check foreground timers. Historically, they have had higher
1374 priority than I/O threads, so let's push them onto the ready
1375 list in front of the I/O threads. */
1377 thread_timer_process (m
->timer
, &now
);
1379 /* Got IO, process it */
1381 thread_process_fds (m
, &readfd
, &writefd
, num
);
1384 /* If any threads were made ready above (I/O or foreground timer),
1385 perhaps we should avoid adding background timers to the ready
1386 list at this time. If this is code is uncommented, then background
1387 timer threads will not run unless there is nothing else to do. */
1388 if ((thread
= thread_trim_head (&m
->ready
)) != NULL
)
1390 fetch
= thread_run (m
, thread
, fetch
);
1393 pthread_mutex_unlock (&m
->mtx
);
1398 /* Background timer/events, lowest priority */
1399 thread_timer_process (m
->background
, &now
);
1401 if ((thread
= thread_trim_head (&m
->ready
)) != NULL
)
1403 fetch
= thread_run (m
, thread
, fetch
);
1406 pthread_mutex_unlock (&m
->mtx
);
1410 pthread_mutex_unlock (&m
->mtx
);
1418 thread_consumed_time (RUSAGE_T
*now
, RUSAGE_T
*start
, unsigned long *cputime
)
1420 /* This is 'user + sys' time. */
1421 *cputime
= timeval_elapsed (now
->cpu
.ru_utime
, start
->cpu
.ru_utime
) +
1422 timeval_elapsed (now
->cpu
.ru_stime
, start
->cpu
.ru_stime
);
1423 return timeval_elapsed (now
->real
, start
->real
);
1426 /* We should aim to yield after yield milliseconds, which defaults
1427 to THREAD_YIELD_TIME_SLOT .
1428 Note: we are using real (wall clock) time for this calculation.
1429 It could be argued that CPU time may make more sense in certain
1430 contexts. The things to consider are whether the thread may have
1431 blocked (in which case wall time increases, but CPU time does not),
1432 or whether the system is heavily loaded with other processes competing
1433 for CPU time. On balance, wall clock time seems to make sense.
1434 Plus it has the added benefit that gettimeofday should be faster
1435 than calling getrusage. */
1437 thread_should_yield (struct thread
*thread
)
1440 pthread_mutex_lock (&thread
->mtx
);
1442 result
= monotime_since(&thread
->real
, NULL
) > (int64_t)thread
->yield
;
1444 pthread_mutex_unlock (&thread
->mtx
);
1449 thread_set_yield_time (struct thread
*thread
, unsigned long yield_time
)
1451 pthread_mutex_lock (&thread
->mtx
);
1453 thread
->yield
= yield_time
;
1455 pthread_mutex_unlock (&thread
->mtx
);
1459 thread_getrusage (RUSAGE_T
*r
)
1462 getrusage(RUSAGE_SELF
, &(r
->cpu
));
1465 struct thread
*thread_current
= NULL
;
1467 /* We check thread consumed time. If the system has getrusage, we'll
1468 use that to get in-depth stats on the performance of the thread in addition
1469 to wall clock time stats from gettimeofday. */
1471 thread_call (struct thread
*thread
)
1473 unsigned long realtime
, cputime
;
1474 RUSAGE_T before
, after
;
1476 GETRUSAGE (&before
);
1477 thread
->real
= before
.real
;
1479 thread_current
= thread
;
1480 (*thread
->func
) (thread
);
1481 thread_current
= NULL
;
1485 realtime
= thread_consumed_time (&after
, &before
, &cputime
);
1486 thread
->hist
->real
.total
+= realtime
;
1487 if (thread
->hist
->real
.max
< realtime
)
1488 thread
->hist
->real
.max
= realtime
;
1489 thread
->hist
->cpu
.total
+= cputime
;
1490 if (thread
->hist
->cpu
.max
< cputime
)
1491 thread
->hist
->cpu
.max
= cputime
;
1493 ++(thread
->hist
->total_calls
);
1494 thread
->hist
->types
|= (1 << thread
->add_type
);
1496 #ifdef CONSUMED_TIME_CHECK
1497 if (realtime
> CONSUMED_TIME_CHECK
)
1500 * We have a CPU Hog on our hands.
1501 * Whinge about it now, so we're aware this is yet another task
1504 zlog_warn ("SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
1506 (unsigned long) thread
->func
,
1507 realtime
/1000, cputime
/1000);
1509 #endif /* CONSUMED_TIME_CHECK */
1512 /* Execute thread */
1514 funcname_thread_execute (struct thread_master
*m
,
1515 int (*func
)(struct thread
*),
1520 struct cpu_thread_history tmp
;
1521 struct thread dummy
;
1523 memset (&dummy
, 0, sizeof (struct thread
));
1525 pthread_mutex_init (&dummy
.mtx
, NULL
);
1526 dummy
.type
= THREAD_EVENT
;
1527 dummy
.add_type
= THREAD_EXECUTE
;
1528 dummy
.master
= NULL
;
1532 tmp
.func
= dummy
.func
= func
;
1533 tmp
.funcname
= dummy
.funcname
= funcname
;
1534 pthread_mutex_lock (&cpu_record_mtx
);
1536 dummy
.hist
= hash_get (cpu_record
, &tmp
,
1537 (void * (*) (void *))cpu_record_hash_alloc
);
1539 pthread_mutex_unlock (&cpu_record_mtx
);
1541 dummy
.schedfrom
= schedfrom
;
1542 dummy
.schedfrom_line
= fromln
;
1544 thread_call (&dummy
);