static void free_stack(struct pthread_attr *pattr) { struct kse *curkse; kse_critical_t crit; if ((pattr->flags & THR_STACK_USER) == 0) { crit = _kse_critical_enter(); curkse = _get_curkse(); KSE_LOCK_ACQUIRE(curkse, &_thread_list_lock); /* Stack routines don't use malloc/free. */ _thr_stack_free(pattr); KSE_LOCK_RELEASE(curkse, &_thread_list_lock); _kse_critical_leave(crit); } }
void _thr_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->terminated == 0) { /* make sure we are not still in userland */ continue; } _thr_stack_free(&td->attr); if (((td->tlflags & TLFLAGS_DETACHED) != 0) && (td->refcount == 0)) { THR_GCLIST_REMOVE(td); /* * 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, because there might * have some code referencing initial thread. */ if (td == _thr_initial) { DBG_MSG("Initial thread won't be freed\n"); continue; } _thr_free(curthread, td); } }