diff options
| author | Quentin Young <qlyoung@cumulusnetworks.com> | 2017-04-24 22:33:25 +0000 |
|---|---|---|
| committer | Quentin Young <qlyoung@cumulusnetworks.com> | 2017-05-09 20:44:19 +0000 |
| commit | ffa2c8986d204f4a3e7204258fd6906af4a57c93 (patch) | |
| tree | 6242b8634bc2a264339a05dcfb20b94f63c252f4 /lib/thread.c | |
| parent | 7a78dea34d20e44539ccabb1b97e029003be4b40 (diff) | |
*: remove THREAD_ON macros, add nullity check
The way thread.c is written, a caller who wishes to be able to cancel a
thread or avoid scheduling it twice must keep a reference to the thread.
Typically this is done with a long lived pointer whose value is checked
for null in order to know if the thread is currently scheduled. The
check-and-schedule idiom is so common that several wrapper macros in
thread.h existed solely to provide it.
This patch removes those macros and adds a new parameter to all
thread_add_* functions which is a pointer to the struct thread * to
store the result of a scheduling call. If the value passed is non-null,
the thread will only be scheduled if the value is null. This helps with
consistency.
A Coccinelle spatch has been used to transform code of the form:
if (t == NULL)
t = thread_add_* (...)
to the form
thread_add_* (..., &t)
The THREAD_ON macros have also been transformed to the underlying
thread.c calls.
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'lib/thread.c')
| -rw-r--r-- | lib/thread.c | 79 |
1 files changed, 50 insertions, 29 deletions
diff --git a/lib/thread.c b/lib/thread.c index 3fb28bce26..37a71824d7 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -725,6 +725,7 @@ fd_select (struct thread_master *m, int size, thread_fd_set *read, thread_fd_set num = poll (m->handler.pfds, m->handler.pfdcount + m->handler.pfdcountsnmp, timeout); #else struct timeval timeout; + if (m->selectpoll_timeout > 0) // use the user's timeout { timeout.tv_sec = m->selectpoll_timeout / 1000; @@ -776,13 +777,19 @@ fd_clear_read_write (struct thread *thread) /* Add new read thread. */ struct thread * funcname_thread_add_read_write (int dir, struct thread_master *m, - int (*func) (struct thread *), void *arg, int fd, - debugargdef) + int (*func) (struct thread *), void *arg, int fd, struct thread **t_ptr, + debugargdef) { struct thread *thread = NULL; pthread_mutex_lock (&m->mtx); { + if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule + { + pthread_mutex_unlock (&m->mtx); + return NULL; + } + #if defined (HAVE_POLL_CALL) thread = generic_thread_add(m, func, arg, fd, dir, debugargpass); #else @@ -822,6 +829,9 @@ funcname_thread_add_read_write (int dir, struct thread_master *m, } pthread_mutex_unlock (&thread->mtx); } + + if (t_ptr) + *t_ptr = thread; } pthread_mutex_unlock (&m->mtx); @@ -830,11 +840,8 @@ funcname_thread_add_read_write (int dir, struct thread_master *m, static struct thread * funcname_thread_add_timer_timeval (struct thread_master *m, - int (*func) (struct thread *), - int type, - void *arg, - struct timeval *time_relative, - debugargdef) + int (*func) (struct thread *), int type, void *arg, + struct timeval *time_relative, struct thread **t_ptr, debugargdef) { struct thread *thread; struct pqueue *queue; @@ -846,6 +853,12 @@ funcname_thread_add_timer_timeval (struct thread_master *m, pthread_mutex_lock (&m->mtx); { + if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule + { + pthread_mutex_unlock (&m->mtx); + return NULL; + } + queue = ((type == THREAD_TIMER) ? m->timer : m->background); thread = thread_get (m, type, func, arg, debugargpass); @@ -856,6 +869,9 @@ funcname_thread_add_timer_timeval (struct thread_master *m, pqueue_enqueue(thread, queue); } pthread_mutex_unlock (&thread->mtx); + + if (t_ptr) + *t_ptr = thread; } pthread_mutex_unlock (&m->mtx); @@ -866,9 +882,8 @@ funcname_thread_add_timer_timeval (struct thread_master *m, /* Add timer event thread. */ struct thread * funcname_thread_add_timer (struct thread_master *m, - int (*func) (struct thread *), - void *arg, long timer, - debugargdef) + int (*func) (struct thread *), void *arg, long timer, + struct thread **t_ptr, debugargdef) { struct timeval trel; @@ -877,16 +892,15 @@ funcname_thread_add_timer (struct thread_master *m, trel.tv_sec = timer; trel.tv_usec = 0; - return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, - &trel, debugargpass); + return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel, + t_ptr, debugargpass); } /* Add timer event thread with "millisecond" resolution */ struct thread * funcname_thread_add_timer_msec (struct thread_master *m, - int (*func) (struct thread *), - void *arg, long timer, - debugargdef) + int (*func) (struct thread *), void *arg, long timer, + struct thread **t_ptr, debugargdef) { struct timeval trel; @@ -895,27 +909,25 @@ funcname_thread_add_timer_msec (struct thread_master *m, trel.tv_sec = timer / 1000; trel.tv_usec = 1000*(timer % 1000); - return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, - arg, &trel, debugargpass); + return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel, + t_ptr, debugargpass); } /* Add timer event thread with "millisecond" resolution */ struct thread * funcname_thread_add_timer_tv (struct thread_master *m, - int (*func) (struct thread *), - void *arg, struct timeval *tv, - debugargdef) + int (*func) (struct thread *), void *arg, struct timeval *tv, + struct thread **t_ptr, debugargdef) { - return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, - arg, tv, debugargpass); + return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, tv, + t_ptr, debugargpass); } /* Add a background thread, with an optional millisec delay */ struct thread * funcname_thread_add_background (struct thread_master *m, - int (*func) (struct thread *), - void *arg, long delay, - debugargdef) + int (*func) (struct thread *), void *arg, long delay, + struct thread **t_ptr, debugargdef) { struct timeval trel; @@ -932,15 +944,15 @@ funcname_thread_add_background (struct thread_master *m, trel.tv_usec = 0; } - return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND, - arg, &trel, debugargpass); + return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND, arg, + &trel, t_ptr, debugargpass); } /* Add simple event thread. */ struct thread * funcname_thread_add_event (struct thread_master *m, - int (*func) (struct thread *), void *arg, int val, - debugargdef) + int (*func) (struct thread *), void *arg, int val, + struct thread **t_ptr, debugargdef) { struct thread *thread; @@ -948,6 +960,12 @@ funcname_thread_add_event (struct thread_master *m, pthread_mutex_lock (&m->mtx); { + if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule + { + pthread_mutex_unlock (&m->mtx); + return NULL; + } + thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass); pthread_mutex_lock (&thread->mtx); { @@ -955,6 +973,9 @@ funcname_thread_add_event (struct thread_master *m, thread_list_add (&m->event, thread); } pthread_mutex_unlock (&thread->mtx); + + if (t_ptr) + *t_ptr = thread; } pthread_mutex_unlock (&m->mtx); |
