Пример #1
0
/*	===== tls_exiting_procs ========================================================
	PUBLIC. 
	================================================================================	*/
status_t tls_exiting_procs () 
	{
	thread_id id = find_thread (NULL) ;
	_tls_thread_entry_t* e = NULL ;
	status_t status ;

	//	Search for the thread entry. 
	if ((status = tls_entries_mutex_p ()) == B_NO_ERROR)
		{
		status = tls_get_entry (id, &e) ;
		tls_entries_mutex_v () ;
		}

	//	If the thread has no entry, then we should not call its exit procs.
	if (status == B_NAME_NOT_FOUND) return B_NO_ERROR ;

	//	Other errors are... errors.
	if (status != B_NO_ERROR) return status ;

	//	Free the entry structure (avoid monitoring thread to have to do this at
	//	a bad time, in a bad thread). The entry deletion function will automatically 
	//	call exiting procs.
	if ((status = tls_entries_mutex_p ()) == B_NO_ERROR)
		{
		status = tls_delete_entry (e) ;
		tls_entries_mutex_v () ;
		}

	//	Finish.
	return status ;
	}
Пример #2
0
/*	===== 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 ;
	}
Пример #3
0
/*	===== 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 ;
	}
Пример #4
0
/*	===== 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 ;
	}
Пример #5
0
/*	===== 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 ;
	}
Пример #6
0
/*	===== 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 ;
	}