/* ===== tls_alloc ================================================================ PUBLIC. Allocate a new TLS index. ================================================================================ */ status_t tls_alloc (int* pIndex) { int index ; status_t status; if (!pIndex) return B_BAD_VALUE ; // Check parameter. assert (pIndex != NULL) ; if (pIndex == NULL) return B_BAD_VALUE ; // Get a new index (using mutual exclusion). if ((status = tls_index_mutex_p ()) == B_NO_ERROR) { status = tls_create_index (&index) ; tls_index_mutex_v () ; } if (status != B_NO_ERROR) { // Set to an invalid index (ie: use without error checking will // resolve to errors). *pIndex = -1 ; return status ; } // Finish. *pIndex = index ; return B_NO_ERROR ; }
/* ===== tls_term ================================================================= PRIVATE. Terminate TLS management. Note: When its called, you should be sure that there is no more thread to call TLS services. ================================================================================ */ status_t tls_term () { status_t exit_value ; int i ; if (!gm_initOk) return B_NO_ERROR ; // Signal to monitoring thread that it must end, and waits for it. release_sem (gm_signalExit) ; wait_for_thread (gm_monitor, &exit_value) ; // Free monitor references. delete_sem (gm_signalExit) ; gm_signalExit = 0 ; gm_monitor = 0 ; // Remove entry and exit procs. while (gm_entry_proc_list && (B_NO_ERROR == tls_remove_entry_exit (PROC_ENTRY, gm_entry_proc_list->proc, gm_entry_proc_list->param))) ; while (gm_exit_proc_list && (B_NO_ERROR == tls_remove_entry_exit (PROC_EXIT, gm_exit_proc_list->proc, gm_exit_proc_list->param))) ; // Acquire resources to be released. if (gm_mutex_entries) tls_index_mutex_p () ; if (gm_mutex_indexs) tls_entries_mutex_p () ; if (gm_mutex_entry_exit) tls_entry_exit_mutex_p () ; // Free resources. delete_sem (gm_mutex_entries) ; gm_mutex_entries = 0 ; gm_mutex_entries_val = 1 ; for (i=0 ; i<THREAD_ENTRIES_RECENT_COUNT ; i++) gm_recent[i] = NULL ; delete_sem (gm_mutex_indexs) ; gm_mutex_indexs = 0 ; gm_mutex_indexs_val = 1 ; delete_sem (gm_mutex_entry_exit) ; gm_mutex_entry_exit = 0 ; gm_mutex_entry_exit_val = 1 ; // Note: memory is not freed, and counters are not reseted (can be reused as is). if (gm_indexs) memset (gm_indexs, 0, sizeof(bool)*gm_indexs_allocated_count) ; gm_initOk = false ; return B_NO_ERROR ; }
/* ===== tls_get ================================================================== PUBLIC. Get a TLS data at an index. ================================================================================ */ status_t tls_get (int index, tls_data_t* pData) { int indexOk ; _tls_thread_entry_t* e = NULL ; thread_id id ; status_t status ; // Check parameter. assert (pData != NULL) ; if (pData == NULL) return B_BAD_VALUE ; *pData = TLS_INVALID_DATA ; assert (index >= 0) ; if (index < 0) return B_BAD_VALUE ; // Check index value (verify index has been allocated). if ((status = tls_index_mutex_p ()) == B_NO_ERROR) { indexOk = tls_check_index (index) ; tls_index_mutex_v () ; } else return status ; if (!indexOk) return B_BAD_INDEX ; // Get the entry for the thread. id = find_thread (NULL) ; 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) ; tls_entries_mutex_v () ; } // Get it using the get_inproc function. if (status == B_NO_ERROR) return tls_get_inproc (index, pData, e) ; else return status ; }
/* ===== tls_free ================================================================= PUBLIC. Free TLS index. ================================================================================ */ status_t tls_free (int index) { status_t status ; // Check parameter. assert (index >= 0) ; if (index < 0) return B_BAD_INDEX ; // Request to free the index (using mutual exclusion). if ((status = tls_index_mutex_p ()) == B_NO_ERROR) { if (tls_check_index (index)) { tls_delete_index (index) ; } else status = B_BAD_INDEX ; tls_index_mutex_v () ; } // Finish. return status ; }