Date: Tue, 4 Jan 2005 12:44:53 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 68249 for review Message-ID: <200501041244.j04CirwN008554@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=68249 Change 68249 by davidxu@davidxu_tiger on 2005/01/04 12:44:47 merge thread list operations into thr_list.c Affected files ... .. //depot/projects/davidxu_thread/src/lib/libthread/thread/Makefile.inc#4 edit .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_find_thread.c#4 delete .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_fork.c#6 edit .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_init.c#6 edit .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_kern.c#9 edit .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_list.c#1 add .. //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_private.h#12 edit Differences ... ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/Makefile.inc#4 (text+ko) ==== @@ -23,6 +23,7 @@ thr_getschedparam.c \ thr_init.c \ thr_join.c \ + thr_list.c \ thr_kern.c \ thr_kill.c \ thr_main_np.c \ ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_fork.c#6 (text+ko) ==== @@ -87,13 +87,24 @@ /* Child process */ errsave = errno; + curthread->cancelflags &= ~THR_CANCEL_NEEDED; curthread->critical_count = 0; curthread->locklevel = 0; + /* clear other threads locked us. */ + umtx_init(&curthread->lock); + thr_self(&curthread->tid); + _thr_setthreaded(0); + _mutex_reinit(&_thr_atfork_mutex); - /* Reinitialize lib kernel. */ - _thr_single_thread(curthread); + /* reinitialize libc spinlocks, this includes __malloc_lock. */ + _thr_spinlock_init(); + TAILQ_INIT(&curthread->mutexq); + curthread->priority_mutex_count = 0; + + /* reinit library. */ + _libpthread_init(curthread); /* Restore signal mask. */ __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_init.c#6 (text+ko) ==== @@ -260,7 +260,6 @@ /* Initialize pthread private data. */ init_private(); - _thr_kern_init(); /* Set the initial thread. */ if (curthread == NULL) { @@ -367,8 +366,7 @@ size_t len; int mib[2]; - TAILQ_INIT(&_thread_list); - TAILQ_INIT(&_thread_gc_list); + _thr_list_init(); /* * Avoid reinitializing some things if they don't need to be, @@ -392,7 +390,6 @@ umtx_init(&_cond_static_lock); umtx_init(&_rwlock_static_lock); umtx_init(&_keytable_lock); - umtx_init(&_thread_list_lock); _thr_spinlock_init(); _pthread_mutex_init(&_thr_atfork_mutex, NULL); } else { @@ -401,7 +398,6 @@ umtx_init(&_cond_static_lock); umtx_init(&_rwlock_static_lock); umtx_init(&_keytable_lock); - umtx_init(&_thread_list_lock); /* reinitialized in thr_fork.c */ #if 0 _thr_spinlock_init(); @@ -409,8 +405,6 @@ #endif } - - /* Are we in M:N mode (default) or 1:1 mode? */ #ifdef SYSTEM_SCOPE_ONLY _thread_scope_system = 1; #else @@ -419,9 +413,5 @@ else if (getenv("LIBPTHREAD_PROCESS_SCOPE") != NULL) _thread_scope_system = -1; #endif - /* - * _thread_list_lock is initialized - * by _thr_init() - */ init_once = 1; } ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_kern.c#9 (text+ko) ==== @@ -30,16 +30,6 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <sys/types.h> -#include <sys/signalvar.h> -#include <sys/queue.h> - -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - #include "thr_private.h" #include "libc_private.h" @@ -51,103 +41,21 @@ #endif /* - * Define a high water mark for the maximum number of threads that - * will be cached. Once this level is reached, any extra threads - * will be free()'d. - */ -#define MAX_CACHED_THREADS 100 - -/* - * We've got to keep track of everything that is allocated, not only - * to have a speedy free list, but also so they can be deallocated - * after a fork(). - */ -static TAILQ_HEAD(, pthread) free_threadq; -static struct umtx free_thread_lock; -static int free_thread_count = 0; -static int inited = 0; -static u_int64_t next_uniqueid = 1; - -LIST_HEAD(thread_hash_head, pthread); -#define HASH_QUEUES 128 -static struct thread_hash_head thr_hashtable[HASH_QUEUES]; -#define THREAD_HASH(thrd) (((unsigned long)thrd >> 12) % HASH_QUEUES) - -/* Lock for thread tcb constructor/destructor */ -static struct umtx tcb_lock; - -static void thr_destroy(struct pthread *curthread, struct pthread *thread); -static void thread_gc(struct pthread *thread); - -/* - * This is called after a fork(). - * No locks need to be taken here since we are guaranteed to be - * single threaded. - * - * XXX - * POSIX says for threaded process, fork() function is used - * only to run new programs, and the effects of calling functions - * that require certain resources between the call to fork() and - * the call to an exec function are undefined. - * - * It is not safe to free memory after fork(), because these data - * structures may be in inconsistent state. - */ -void -_thr_single_thread(struct pthread *curthread) -{ - curthread->cancelflags &= ~THR_CANCEL_NEEDED; - /* clear other threads locked us. */ - umtx_init(&curthread->lock); - thr_self(&curthread->tid); - /* reinitialize libc spinlocks, this includes __malloc_lock. */ - _thr_spinlock_init(); - TAILQ_INIT(&curthread->mutexq); - curthread->priority_mutex_count = 0; - _libpthread_init(curthread); -#if 0 - if (__isthreaded) { - _thr_rtld_fini(); - } -#endif - __isthreaded = 0; -} - -/* - * This is used to initialize housekeeping and to initialize the - * KSD for the KSE. - */ -void -_thr_kern_init(void) -{ - TAILQ_INIT(&free_threadq); - _gc_count = 0; - if (inited == 0) { - umtx_init(&free_thread_lock); - umtx_init(&tcb_lock); - inited = 1; - } else { - umtx_init(&free_thread_lock); - umtx_init(&tcb_lock); - } -} - -/* * This is called when the first thread (other than the initial * thread) is created. */ int _thr_setthreaded(int threaded) { - if ((threaded != 0) && (__isthreaded == 0)) { -#if 0 - /* - * Locking functions in libc are required when there are - * threads other than the initial thread. - */ - _thr_rtld_init(); -#endif + if (((threaded == 0) ^ (__isthreaded == 0)) == 0) + return (0); + + if (threaded != 0) { +/* _thr_rtld_init(); */ __isthreaded = 1; + } else { + __isthreaded = 0; +/* _thr_rtld_fini(); */ } return (0); } @@ -166,275 +74,7 @@ } void -_thr_gc(struct pthread *curthread) -{ - thread_gc(curthread); -} - -static void -thread_gc(struct pthread *curthread) -{ - struct pthread *td, *td_next; - TAILQ_HEAD(, pthread) worklist; - - TAILQ_INIT(&worklist); - THREAD_LIST_LOCK(curthread); - - /* Check the threads waiting for GC. */ - for (td = TAILQ_FIRST(&_thread_gc_list); td != NULL; td = td_next) { - td_next = TAILQ_NEXT(td, gcle); - if ((td->tlflags & TLFLAGS_GC_SAFE) == 0) - continue; - else if (td->isdead == 0) { - /* make sure we are not still in userland */ - continue; - } - /* - * Remove the thread from the GC list. If the thread - * isn't yet detached, it will get added back to the - * GC list at a later time. - */ - THR_GCLIST_REMOVE(td); - DBG_MSG("Freeing thread %p stack\n", td); - /* - * We can free the thread stack since it's no longer - * in use. - */ - _thr_stack_free(&td->attr); - if (((td->tlflags & TLFLAGS_DETACHED) != 0) && - (td->refcount == 0)) { - /* - * The thread has detached and is no longer - * referenced. It is safe to remove all - * remnants of the thread. - */ - THR_LIST_REMOVE(td); - TAILQ_INSERT_HEAD(&worklist, td, gcle); - } - } - THREAD_LIST_UNLOCK(curthread); - - while ((td = TAILQ_FIRST(&worklist)) != NULL) { - TAILQ_REMOVE(&worklist, td, gcle); - /* - * XXX we don't free initial thread and its kse - * (if thread is a bound thread), because there might - * have some code referencing initial thread and kse. - */ - if (td == _thr_initial) { - DBG_MSG("Initial thread won't be freed\n"); - continue; - } - - DBG_MSG("Freeing thread %p\n", td); - _thr_free(curthread, td); - } -} - -struct pthread * -_thr_alloc(struct pthread *curthread) -{ - struct pthread *thread = NULL; - - if (curthread != NULL) { - if (GC_NEEDED()) - _thr_gc(curthread); - if (free_thread_count > 0) { - THR_LOCK_ACQUIRE(curthread, &free_thread_lock); - if ((thread = TAILQ_FIRST(&free_threadq)) != NULL) { - TAILQ_REMOVE(&free_threadq, thread, tle); - free_thread_count--; - } - THR_LOCK_RELEASE(curthread, &free_thread_lock); - } - } - if ((thread == NULL) && - ((thread = malloc(sizeof(struct pthread))) != NULL)) { - bzero(thread, sizeof(struct pthread)); - if (curthread) { - THR_LOCK_ACQUIRE(curthread, &tcb_lock); - thread->tcb = _tcb_ctor(thread, 0 /* not initial tls */); - THR_LOCK_RELEASE(curthread, &tcb_lock); - } else { - thread->tcb = _tcb_ctor(thread, 1 /* initial tls */); - } - if (thread->tcb == NULL) { - free(thread); - thread = NULL; - } else { - /* - * Initialize thread locking. - */ - umtx_init(&thread->lock); - } - } else if (thread != NULL) { - umtx_init(&thread->lock); - } - return (thread); -} - -void -_thr_free(struct pthread *curthread, struct pthread *thread) -{ - DBG_MSG("Freeing thread %p\n", thread); - if (thread->name) { - free(thread->name); - thread->name = NULL; - } - if ((curthread == NULL) || (free_thread_count >= MAX_CACHED_THREADS)) { - thr_destroy(curthread, thread); - } else { - /* Add the thread to the free thread list. */ - THR_LOCK_ACQUIRE(curthread, &free_thread_lock); - TAILQ_INSERT_TAIL(&free_threadq, thread, tle); - free_thread_count++; - THR_LOCK_RELEASE(curthread, &free_thread_lock); - } -} - -static void -thr_destroy(struct pthread *curthread, struct pthread *thread) -{ - if (curthread) { - THR_LOCK_ACQUIRE(curthread, &tcb_lock); - _tcb_dtor(thread->tcb); - THR_LOCK_RELEASE(curthread, &tcb_lock); - } else { - _tcb_dtor(thread->tcb); - } - free(thread); -} - -/* - * Add an active thread: - * - * o Assign the thread a unique id (which GDB uses to track - * threads. - * o Add the thread to the list of all threads and increment - * number of active threads. - */ -void -_thr_link(struct pthread *curthread, struct pthread *thread) -{ - THREAD_LIST_LOCK(curthread); - /* - * Initialize the unique id (which GDB uses to track - * threads), add the thread to the list of all threads, - * and - */ - thread->uniqueid = next_uniqueid++; - THR_LIST_ADD(thread); - if (thread->attr.flags & PTHREAD_DETACHED) - thread->tlflags |= TLFLAGS_DETACHED; - _thread_active_threads++; - THREAD_LIST_UNLOCK(curthread); -} - -/* - * Remove an active thread. - */ -void -_thr_unlink(struct pthread *curthread, struct pthread *thread) -{ - THREAD_LIST_LOCK(curthread); - THR_LIST_REMOVE(thread); - _thread_active_threads--; - THREAD_LIST_UNLOCK(curthread); -} - -void -_thr_hash_add(struct pthread *thread) -{ - struct thread_hash_head *head; - - head = &thr_hashtable[THREAD_HASH(thread)]; - LIST_INSERT_HEAD(head, thread, hle); -} - -void -_thr_hash_remove(struct pthread *thread) -{ - LIST_REMOVE(thread, hle); -} - -struct pthread * -_thr_hash_find(struct pthread *thread) -{ - struct pthread *td; - struct thread_hash_head *head; - - head = &thr_hashtable[THREAD_HASH(thread)]; - LIST_FOREACH(td, head, hle) { - if (td == thread) - return (thread); - } - return (NULL); -} - -/* - * Find a thread in the linked list of active threads and add a reference - * to it. Threads with positive reference counts will not be deallocated - * until all references are released. - */ -int -_thr_ref_add(struct pthread *curthread, struct pthread *thread, - int include_dead) -{ - int ret; - - if (thread == NULL) - /* Invalid thread: */ - return (EINVAL); - - THREAD_LIST_LOCK(curthread); - if ((ret = _thr_find_thread(curthread, thread, include_dead)) == 0) { - thread->refcount++; - if (curthread != NULL) - curthread->critical_count++; - } - THREAD_LIST_UNLOCK(curthread); - - /* Return zero if the thread exists: */ - return (ret); -} - -void -_thr_ref_delete(struct pthread *curthread, struct pthread *thread) -{ - if (thread != NULL) { - THREAD_LIST_LOCK(curthread); - thread->refcount--; - if (curthread != NULL) - curthread->critical_count--; - if ((thread->refcount == 0) && - (thread->tlflags & TLFLAGS_GC_SAFE) != 0) - THR_GCLIST_ADD(thread); - THREAD_LIST_UNLOCK(curthread); - } -} - -int -_thr_find_thread(struct pthread *curthread, struct pthread *thread, - int include_dead) -{ - struct pthread *pthread; - - if (thread == NULL) - /* Invalid thread: */ - return (EINVAL); - - pthread = _thr_hash_find(thread); - if (pthread) { - if (include_dead == 0 && pthread->state == PS_DEAD) - pthread = NULL; - } - - /* Return zero if the thread exists: */ - return ((pthread != NULL) ? 0 : ESRCH); -} - -void _thr_assert_lock_level() { - PANIC("lockleve <=0"); + PANIC("lockleve <= 0"); } ==== //depot/projects/davidxu_thread/src/lib/libthread/thread/thr_private.h#12 (text+ko) ==== @@ -686,7 +686,7 @@ * Function prototype definitions. */ __BEGIN_DECLS -void _thr_kern_init(); +void _thr_list_init(); void _thr_single_thread(struct pthread *); int _thr_setthreaded(int); int _mutex_cv_lock(pthread_mutex_t *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200501041244.j04CirwN008554>