/* ===== monitoring =============================================================== PRIVATE. Check in the thread entries list to detect ended threads. These threads see their entry deleted. ================================================================================ */ int32 monitoring (void* unused) { int i ; int numberDeleted ; thread_info info ; _tls_thread_entry_t* pEntry ; // We use semaphore time-outs to periodically wake up the monitoring thread, // with acquire_sem_etc returning B_TIMED_OUT. // When the term function is called, it set the semaphore and the thread // is immediatly resumed with acquire_sem_etc returning B_NO_ERROR. while (acquire_sem_etc (gm_signalExit, 1, B_TIMEOUT, 1000000LL) == B_TIMED_OUT) { // Must be reset at each iteration (ex-bug). numberDeleted = 0 ; tls_entries_mutex_p () ; { for (i=0 ; i<gm_entries_count ; i++) { pEntry = gm_sorted[i] ; // If not used, continue... if (pEntry->sign == SIGN_FREE) continue ; // Get thread info. If impossible... the thread should be down. if (B_NO_ERROR != get_thread_info (pEntry->ownerThread, &info)) { // As the entry is to be deleted, call the TLS exit procs. tls_call_entry_exit (pEntry->ownerThread, PROC_EXIT, pEntry) ; // Simply note it as free. pEntry->sign = SIGN_FREE ; numberDeleted++ ; } } // Update globals. if (numberDeleted != 0) { // Sort-it so deleted be moved at the end of the sorted array. assert (gm_sorted != NULL) ; assert (gm_entries_count >= 0) ; qsort (gm_sorted, gm_entries_count, sizeof (_tls_thread_entry_t*), qsort_comp_proc) ; // And decrement the number of elements. gm_entries_count -= numberDeleted ; } } tls_entries_mutex_v () ; } return 0 ; }
/* ===== tls_delete_entry ========================================================= PRIVATE. Delete an entry by its entry address. ================================================================================ */ status_t tls_delete_entry (_tls_thread_entry_t* pEntry) { // Internal check - must never occur. assert (pEntry != NULL) ; // As the entry is deleted, call the TLS exit procs. tls_call_entry_exit (pEntry->ownerThread, PROC_EXIT, pEntry) ; // Simply note it as free. pEntry->sign = SIGN_FREE ; // Sort-it so it be moved at the end of the sorted array. assert (gm_sorted != NULL) ; assert (gm_entries_count >= 0) ; qsort (gm_sorted, gm_entries_count, sizeof (_tls_thread_entry_t*), qsort_comp_proc) ; // And decrement the number of elements. gm_entries_count-- ; return B_NO_ERROR ; }
/* ===== tls_create_entry ========================================================= PRIVATE. Create an entry for a thread. ================================================================================ */ status_t tls_create_entry (thread_id id, _tls_thread_entry_t** ppEntry) { _tls_thread_entry_t* pEntry = NULL ; status_t status ; int i ; // Check parameters. if (id < 0) return B_BAD_VALUE ; if (ppEntry == NULL) return B_BAD_VALUE ; // Set to NULL so that a use without error checking will resolve into error too. *ppEntry = NULL ; // If no more room, reallocate more entries. if (gm_entries_count == gm_entries_allocated_count) { if ((status = tls_expand_entries (THREAD_ENTRIES_ADD_COUNT)) != B_NO_ERROR) return status ; } // Use next entry in the sorted array. // If data remain associated with the entry, erase it. pEntry = gm_sorted[gm_entries_count] ; pEntry->sign = SIGN_OK ; pEntry->ownerThread = id ; if (pEntry->datasCount) { for (i=0 ; i<pEntry->datasCount ; i++) pEntry->datas[i] = 0 ; } gm_entries_count++ ; // Sort the array with the new entry. assert (gm_sorted != NULL) ; assert (gm_entries_count >= 0) ; qsort (gm_sorted, gm_entries_count, sizeof (_tls_thread_entry_t*), qsort_comp_proc) ; // As a new entry is created for this thread, call the TLS entry procs. tls_call_entry_exit (id, PROC_ENTRY, pEntry) ; // Finish. *ppEntry = pEntry ; return B_NO_ERROR ; }
/* ===== tls_entering_procs ======================================================= PUBLIC. ================================================================================ */ status_t tls_entering_procs () { thread_id id = find_thread (NULL) ; _tls_thread_entry_t* e = NULL ; status_t status ; bool newlyCreated = false ; // Search for the thread entry. // If not founded, create it and dont call entry procs because tls_create_entry // automatically call them. // If founded, call entry procs. if ((status = tls_entries_mutex_p ()) == B_NO_ERROR) { if ((status = tls_get_entry (id, &e)) != B_NO_ERROR) status = tls_create_entry (id, &e) ; else tls_call_entry_exit (id, PROC_ENTRY, e) ; tls_entries_mutex_v () ; } if (status != B_NO_ERROR) return status ; // Finish return B_NO_ERROR ; }