summaryrefslogtreecommitdiff
path: root/lib/thread.c
diff options
context:
space:
mode:
authorQuentin Young <qlyoung@users.noreply.github.com>2018-10-03 18:43:34 -0400
committerGitHub <noreply@github.com>2018-10-03 18:43:34 -0400
commit56f67d6870c6ab2c41b07c9a81874bcfd4a3e4f2 (patch)
tree080af23c552ab8de22228384b97587f196a48d5b /lib/thread.c
parent139221f25051db7a52ac64fed418d19125b7c3ae (diff)
parentc4345fbf71fcc7ef4b64d95979f252c613dd3ebf (diff)
Merge pull request #3087 from opensourcerouting/bfd-memleak
bfdd: fix memory leak and echo-mode start
Diffstat (limited to 'lib/thread.c')
-rw-r--r--lib/thread.c73
1 files changed, 45 insertions, 28 deletions
diff --git a/lib/thread.c b/lib/thread.c
index a81faae796..267dcd1cfc 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -58,6 +58,7 @@ pthread_key_t thread_current;
pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER;
static struct list *masters;
+static void thread_free(struct thread_master *master, struct thread *thread);
/* CLI start ---------------------------------------------------------------- */
static unsigned int cpu_record_hash_key(struct cpu_thread_history *a)
@@ -538,6 +539,8 @@ static struct thread *thread_trim_head(struct thread_list *list)
/* Move thread to unuse list. */
static void thread_add_unuse(struct thread_master *m, struct thread *thread)
{
+ pthread_mutex_t mtxc = thread->mtx;
+
assert(m != NULL && thread != NULL);
assert(thread->next == NULL);
assert(thread->prev == NULL);
@@ -546,10 +549,15 @@ static void thread_add_unuse(struct thread_master *m, struct thread *thread)
memset(thread, 0, sizeof(struct thread));
thread->type = THREAD_UNUSED;
- if (m->unuse.count < THREAD_UNUSED_DEPTH)
+ /* Restore the thread mutex context. */
+ thread->mtx = mtxc;
+
+ if (m->unuse.count < THREAD_UNUSED_DEPTH) {
thread_list_add(&m->unuse, thread);
- else
- XFREE(MTYPE_THREAD, thread);
+ return;
+ }
+
+ thread_free(m, thread);
}
/* Free all unused thread. */
@@ -560,9 +568,8 @@ static void thread_list_free(struct thread_master *m, struct thread_list *list)
for (t = list->head; t; t = next) {
next = t->next;
- XFREE(MTYPE_THREAD, t);
+ thread_free(m, t);
list->count--;
- m->alloc--;
}
}
@@ -576,8 +583,7 @@ static void thread_array_free(struct thread_master *m,
t = thread_array[index];
if (t) {
thread_array[index] = NULL;
- XFREE(MTYPE_THREAD, t);
- m->alloc--;
+ thread_free(m, t);
}
}
XFREE(MTYPE_THREAD_POLL, thread_array);
@@ -588,9 +594,8 @@ static void thread_queue_free(struct thread_master *m, struct pqueue *queue)
int i;
for (i = 0; i < queue->size; i++)
- XFREE(MTYPE_THREAD, queue->array[i]);
+ thread_free(m, queue->array[i]);
- m->alloc -= queue->size;
pqueue_delete(queue);
}
@@ -608,8 +613,7 @@ void thread_master_free_unused(struct thread_master *m)
{
struct thread *t;
while ((t = thread_trim_head(&m->unuse)) != NULL) {
- pthread_mutex_destroy(&t->mtx);
- XFREE(MTYPE_THREAD, t);
+ thread_free(m, t);
}
}
pthread_mutex_unlock(&m->mtx);
@@ -728,6 +732,17 @@ static struct thread *thread_get(struct thread_master *m, uint8_t type,
return thread;
}
+static void thread_free(struct thread_master *master, struct thread *thread)
+{
+ /* Update statistics. */
+ assert(master->alloc > 0);
+ master->alloc--;
+
+ /* Free allocated resources. */
+ pthread_mutex_destroy(&thread->mtx);
+ XFREE(MTYPE_THREAD, thread);
+}
+
static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize,
nfds_t count, const struct timeval *timer_wait)
{
@@ -1633,25 +1648,27 @@ void funcname_thread_execute(struct thread_master *m,
int (*func)(struct thread *), void *arg, int val,
debugargdef)
{
- struct cpu_thread_history tmp;
- struct thread dummy;
-
- memset(&dummy, 0, sizeof(struct thread));
+ struct thread *thread;
- pthread_mutex_init(&dummy.mtx, NULL);
- dummy.type = THREAD_EVENT;
- dummy.add_type = THREAD_EXECUTE;
- dummy.master = NULL;
- dummy.arg = arg;
- dummy.u.val = val;
+ /* Get or allocate new thread to execute. */
+ pthread_mutex_lock(&m->mtx);
+ {
+ thread = thread_get(m, THREAD_EVENT, func, arg, debugargpass);
- tmp.func = dummy.func = func;
- tmp.funcname = dummy.funcname = funcname;
- dummy.hist = hash_get(m->cpu_record, &tmp,
- (void *(*)(void *))cpu_record_hash_alloc);
+ /* Set its event value. */
+ pthread_mutex_lock(&thread->mtx);
+ {
+ thread->add_type = THREAD_EXECUTE;
+ thread->u.val = val;
+ thread->ref = &thread;
+ }
+ pthread_mutex_unlock(&thread->mtx);
+ }
+ pthread_mutex_unlock(&m->mtx);
- dummy.schedfrom = schedfrom;
- dummy.schedfrom_line = fromln;
+ /* Execute thread doing all accounting. */
+ thread_call(thread);
- thread_call(&dummy);
+ /* Give back or free thread. */
+ thread_add_unuse(m, thread);
}