/* ===== 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_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 ; }
/* ===== tls_init ================================================================= PRIVATE. Initialise TLS management. Called at dynamic module loading. Note: as we use Benaphore like mutexs, the semaphores initial count are 0. ================================================================================ */ status_t tls_init (int clientVersion) { int i ; status_t status ; int semCreatedCount = 0 ; // Currently, the test is based on the same primary version number. if ((clientVersion & 0xFF000000) < (TLS_VERSION &0xFF000000)) return B_ERROR ; // Create entries mutex. If the mutex already exist, the init phase is already // done (or is running). In this case, we wait for the mutex to be released // by its current owner, and then return doing nothing. if (gm_mutex_entries != 0) { if ((status=tls_entries_mutex_p ()) != B_NO_ERROR) // Wait for the mutex. goto ERROR_LABEL ; tls_entries_mutex_v (); // Release it. return B_NO_ERROR ; // Consider init already done. } else { // Note: When the semaphore is created, gm_mutex_entries_val is with // a value 1 (not 0). So during init phase other threads will block on // semaphore. status = gm_mutex_entries = create_sem (0, "tls-entries") ; if (gm_mutex_entries < B_NO_ERROR) goto ERROR_LABEL ; semCreatedCount = 1 ; } // Create indexs mutex. status = gm_mutex_indexs = create_sem (0, "tls-indexs") ; if (gm_mutex_indexs < B_NO_ERROR) goto ERROR_LABEL ; semCreatedCount = 2 ; // Create entry/exit mutex. status = gm_mutex_entry_exit = create_sem (0, "tls-entry-exit") ; if (gm_mutex_indexs < B_NO_ERROR) goto ERROR_LABEL ; semCreatedCount = 3 ; // Initialize array of last recently used entries. for (i=0 ; i<THREAD_ENTRIES_RECENT_COUNT ; i++) gm_recent[i] = NULL ; // Create tls ended thread management. status = gm_signalExit = create_sem (0, "tls-monitor-exit") ; if (gm_signalExit < B_NO_ERROR) goto ERROR_LABEL ; semCreatedCount = 4 ; status = gm_monitor = spawn_thread (monitoring, "tls_monitor", B_LOW_PRIORITY, NULL) ; if (gm_monitor != B_NO_MORE_THREADS && gm_monitor != B_NO_MEMORY) resume_thread (gm_monitor) ; else goto ERROR_LABEL ; // Finish. tls_entries_mutex_v () ; tls_index_mutex_v () ; tls_entry_exit_mutex_v () ; gm_initOk = true ; return B_NO_ERROR ; ERROR_LABEL: // Error processing goes here. Release the resources that may have been allocated. gm_monitor = 0 ; if (semCreatedCount >= 4) { delete_sem (gm_signalExit) ; gm_signalExit = 0 ; } if (semCreatedCount >= 3) { delete_sem (gm_mutex_entry_exit) ; gm_mutex_entry_exit = 0 ; gm_mutex_entry_exit_val = 1 ; } if (semCreatedCount >= 2) { delete_sem (gm_mutex_indexs) ; gm_mutex_indexs = 0 ; gm_mutex_indexs_val = 1 ; } if (semCreatedCount >= 1) { delete_sem (gm_mutex_entries) ; gm_mutex_entries = 0 ; gm_mutex_entries_val = 1 ; } // Return the status got when the error was detected. return status ; }