summaryrefslogtreecommitdiffstats
path: root/lib/libthr
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2012-02-07 02:57:36 +0000
committerdavidxu <davidxu@FreeBSD.org>2012-02-07 02:57:36 +0000
commitf738f62c3a5bfb5626074b81d3381913138229aa (patch)
tree901bfa2275da1c843393e11cbbf0d48ea651e9f2 /lib/libthr
parent89ff4dbd9e9ff21f537433984cfd47ea60d31f5d (diff)
downloadFreeBSD-src-f738f62c3a5bfb5626074b81d3381913138229aa.zip
FreeBSD-src-f738f62c3a5bfb5626074b81d3381913138229aa.tar.gz
Plug a memory leak. When a cached thread is reused, don't clear sleep
queue pointers, just reuse it. PR: 164828 MFC after: 1 week
Diffstat (limited to 'lib/libthr')
-rw-r--r--lib/libthr/thread/thr_list.c16
-rw-r--r--lib/libthr/thread/thr_private.h15
2 files changed, 19 insertions, 12 deletions
diff --git a/lib/libthr/thread/thr_list.c b/lib/libthr/thread/thr_list.c
index 249501c..5a2bc63 100644
--- a/lib/libthr/thread/thr_list.c
+++ b/lib/libthr/thread/thr_list.c
@@ -149,11 +149,16 @@ _thr_alloc(struct pthread *curthread)
if (total_threads > MAX_THREADS)
return (NULL);
atomic_fetchadd_int(&total_threads, 1);
- thread = malloc(sizeof(struct pthread));
+ thread = calloc(1, sizeof(struct pthread));
if (thread == NULL) {
atomic_fetchadd_int(&total_threads, -1);
return (NULL);
}
+ thread->sleepqueue = _sleepq_alloc();
+ thread->wake_addr = _thr_alloc_wake_addr();
+ } else {
+ bzero(&thread->_pthread_startzero,
+ __rangeof(struct pthread, _pthread_startzero, _pthread_endzero));
}
if (curthread != NULL) {
THR_LOCK_ACQUIRE(curthread, &tcb_lock);
@@ -163,10 +168,7 @@ _thr_alloc(struct pthread *curthread)
tcb = _tcb_ctor(thread, 1 /* initial tls */);
}
if (tcb != NULL) {
- memset(thread, 0, sizeof(*thread));
thread->tcb = tcb;
- thread->sleepqueue = _sleepq_alloc();
- thread->wake_addr = _thr_alloc_wake_addr();
} else {
thr_destroy(curthread, thread);
atomic_fetchadd_int(&total_threads, -1);
@@ -194,8 +196,6 @@ _thr_free(struct pthread *curthread, struct pthread *thread)
}
thread->tcb = NULL;
if ((curthread == NULL) || (free_thread_count >= MAX_CACHED_THREADS)) {
- _sleepq_free(thread->sleepqueue);
- _thr_release_wake_addr(thread->wake_addr);
thr_destroy(curthread, thread);
atomic_fetchadd_int(&total_threads, -1);
} else {
@@ -213,6 +213,10 @@ _thr_free(struct pthread *curthread, struct pthread *thread)
static void
thr_destroy(struct pthread *curthread __unused, struct pthread *thread)
{
+ if (thread->sleepqueue != NULL)
+ _sleepq_free(thread->sleepqueue);
+ if (thread->wake_addr != NULL)
+ _thr_release_wake_addr(thread->wake_addr);
free(thread);
}
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 9b9227b..7a9727f 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -343,6 +343,7 @@ struct pthread_key {
* Thread structure.
*/
struct pthread {
+#define _pthread_startzero tid
/* Kernel thread id. */
long tid;
#define TID_TERMINATED 1
@@ -506,12 +507,6 @@ struct pthread {
/* Event */
td_event_msg_t event_buf;
- struct wake_addr *wake_addr;
-#define WAKE_ADDR(td) ((td)->wake_addr)
-
- /* Sleep queue */
- struct sleepqueue *sleepqueue;
-
/* Wait channel */
void *wchan;
@@ -526,6 +521,14 @@ struct pthread {
/* Deferred threads from pthread_cond_signal. */
unsigned int *defer_waiters[MAX_DEFER_WAITERS];
+#define _pthread_endzero wake_addr
+
+ struct wake_addr *wake_addr;
+#define WAKE_ADDR(td) ((td)->wake_addr)
+
+ /* Sleep queue */
+ struct sleepqueue *sleepqueue;
+
};
#define THR_SHOULD_GC(thrd) \
OpenPOWER on IntegriCloud