mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 11:19:13 +00:00
Merge pull request #3170 from opensourcerouting/60-memleak-fix
6.0: backport memory leak fix
This commit is contained in:
commit
09fdff5654
73
lib/thread.c
73
lib/thread.c
@ -57,6 +57,7 @@ pthread_key_t thread_current;
|
|||||||
pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER;
|
pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static struct list *masters;
|
static struct list *masters;
|
||||||
|
|
||||||
|
static void thread_free(struct thread_master *master, struct thread *thread);
|
||||||
|
|
||||||
/* CLI start ---------------------------------------------------------------- */
|
/* CLI start ---------------------------------------------------------------- */
|
||||||
static unsigned int cpu_record_hash_key(struct cpu_thread_history *a)
|
static unsigned int cpu_record_hash_key(struct cpu_thread_history *a)
|
||||||
@ -537,6 +538,8 @@ static struct thread *thread_trim_head(struct thread_list *list)
|
|||||||
/* Move thread to unuse list. */
|
/* Move thread to unuse list. */
|
||||||
static void thread_add_unuse(struct thread_master *m, struct thread *thread)
|
static void thread_add_unuse(struct thread_master *m, struct thread *thread)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_t mtxc = thread->mtx;
|
||||||
|
|
||||||
assert(m != NULL && thread != NULL);
|
assert(m != NULL && thread != NULL);
|
||||||
assert(thread->next == NULL);
|
assert(thread->next == NULL);
|
||||||
assert(thread->prev == NULL);
|
assert(thread->prev == NULL);
|
||||||
@ -545,10 +548,15 @@ static void thread_add_unuse(struct thread_master *m, struct thread *thread)
|
|||||||
memset(thread, 0, sizeof(struct thread));
|
memset(thread, 0, sizeof(struct thread));
|
||||||
thread->type = THREAD_UNUSED;
|
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);
|
thread_list_add(&m->unuse, thread);
|
||||||
else
|
return;
|
||||||
XFREE(MTYPE_THREAD, thread);
|
}
|
||||||
|
|
||||||
|
thread_free(m, thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free all unused thread. */
|
/* Free all unused thread. */
|
||||||
@ -559,9 +567,8 @@ static void thread_list_free(struct thread_master *m, struct thread_list *list)
|
|||||||
|
|
||||||
for (t = list->head; t; t = next) {
|
for (t = list->head; t; t = next) {
|
||||||
next = t->next;
|
next = t->next;
|
||||||
XFREE(MTYPE_THREAD, t);
|
thread_free(m, t);
|
||||||
list->count--;
|
list->count--;
|
||||||
m->alloc--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,8 +582,7 @@ static void thread_array_free(struct thread_master *m,
|
|||||||
t = thread_array[index];
|
t = thread_array[index];
|
||||||
if (t) {
|
if (t) {
|
||||||
thread_array[index] = NULL;
|
thread_array[index] = NULL;
|
||||||
XFREE(MTYPE_THREAD, t);
|
thread_free(m, t);
|
||||||
m->alloc--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
XFREE(MTYPE_THREAD_POLL, thread_array);
|
XFREE(MTYPE_THREAD_POLL, thread_array);
|
||||||
@ -587,9 +593,8 @@ static void thread_queue_free(struct thread_master *m, struct pqueue *queue)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < queue->size; 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);
|
pqueue_delete(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -607,8 +612,7 @@ void thread_master_free_unused(struct thread_master *m)
|
|||||||
{
|
{
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
while ((t = thread_trim_head(&m->unuse)) != NULL) {
|
while ((t = thread_trim_head(&m->unuse)) != NULL) {
|
||||||
pthread_mutex_destroy(&t->mtx);
|
thread_free(m, t);
|
||||||
XFREE(MTYPE_THREAD, t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&m->mtx);
|
pthread_mutex_unlock(&m->mtx);
|
||||||
@ -727,6 +731,17 @@ static struct thread *thread_get(struct thread_master *m, uint8_t type,
|
|||||||
return thread;
|
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,
|
static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize,
|
||||||
nfds_t count, const struct timeval *timer_wait)
|
nfds_t count, const struct timeval *timer_wait)
|
||||||
{
|
{
|
||||||
@ -1630,25 +1645,27 @@ void funcname_thread_execute(struct thread_master *m,
|
|||||||
int (*func)(struct thread *), void *arg, int val,
|
int (*func)(struct thread *), void *arg, int val,
|
||||||
debugargdef)
|
debugargdef)
|
||||||
{
|
{
|
||||||
struct cpu_thread_history tmp;
|
struct thread *thread;
|
||||||
struct thread dummy;
|
|
||||||
|
|
||||||
memset(&dummy, 0, sizeof(struct thread));
|
/* Get or allocate new thread to execute. */
|
||||||
|
pthread_mutex_lock(&m->mtx);
|
||||||
|
{
|
||||||
|
thread = thread_get(m, THREAD_EVENT, func, arg, debugargpass);
|
||||||
|
|
||||||
pthread_mutex_init(&dummy.mtx, NULL);
|
/* Set its event value. */
|
||||||
dummy.type = THREAD_EVENT;
|
pthread_mutex_lock(&thread->mtx);
|
||||||
dummy.add_type = THREAD_EXECUTE;
|
{
|
||||||
dummy.master = NULL;
|
thread->add_type = THREAD_EXECUTE;
|
||||||
dummy.arg = arg;
|
thread->u.val = val;
|
||||||
dummy.u.val = val;
|
thread->ref = &thread;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&thread->mtx);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&m->mtx);
|
||||||
|
|
||||||
tmp.func = dummy.func = func;
|
/* Execute thread doing all accounting. */
|
||||||
tmp.funcname = dummy.funcname = funcname;
|
thread_call(thread);
|
||||||
dummy.hist = hash_get(m->cpu_record, &tmp,
|
|
||||||
(void *(*)(void *))cpu_record_hash_alloc);
|
|
||||||
|
|
||||||
dummy.schedfrom = schedfrom;
|
/* Give back or free thread. */
|
||||||
dummy.schedfrom_line = fromln;
|
thread_add_unuse(m, thread);
|
||||||
|
|
||||||
thread_call(&dummy);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user