/* The main function of a freshly creating thread. It's a wrapper around the FUNC and ARG arguments passed to glthread_create_func. */ static unsigned int WINAPI wrapper_func (void *varg) { struct gl_thread_struct *thread = (struct gl_thread_struct *)varg; EnterCriticalSection (&thread->handle_lock); /* Create a new handle for the thread only if the parent thread did not yet fill in the handle. */ if (thread->handle == NULL) thread->handle = get_current_thread_handle (); LeaveCriticalSection (&thread->handle_lock); if (self_key == (DWORD)-1) init_self_key (); TlsSetValue (self_key, thread); /* Run the thread. Store the exit value if the thread was not terminated otherwise. */ thread->result = thread->func (thread->arg); return 0; }
EASYHOOK_NT_INTERNAL RhSetWakeUpThreadID(ULONG InThreadID) { /* Description: Used in conjunction with RhCreateAndInject(). If the given thread later is resumed in RhWakeUpProcess(), the injection target will start its usual execution. */ NTSTATUS NtStatus; if(!TlsSetValue(RhTlsIndex, (LPVOID)(size_t)InThreadID)) THROW(STATUS_INTERNAL_ERROR, L"Unable to set TLS value."); RETURN(STATUS_SUCCESS); THROW_OUTRO: FINALLY_OUTRO: return NtStatus; }
static unsigned long WINAPI _threadstart ( void * ptd ) { /* * Stash the pointer to the per-thread data stucture in TLS */ if ( !TlsSetValue(__tlsindex, ptd) ) _amsg_exit(_RT_THREAD); /* * Call fp initialization, if necessary */ if ( _FPmtinit != NULL ) (*_FPmtinit)(); /* * Guard call to user code with a _try - _except statement to * implement runtime errors and signal support */ __try { ( (void(__cdecl *)(void *))(((_ptiddata)ptd)->_initaddr) ) ( ((_ptiddata)ptd)->_initarg ); _endthread(); } __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) ) { /* * Should never reach here */ _exit( GetExceptionCode() ); } /* end of _try - _except */ /* * Never executed! */ return(0L); }
pthread_t pthread_self(void) { pthread_t t; _pthread_once_raw(&_pthread_tls_once, pthread_tls_init); t = (pthread_t)TlsGetValue(_pthread_tls); /* Main thread? */ if (!t) { t = (pthread_t)malloc(sizeof(struct _pthread_v)); /* If cannot initialize main thread, then the only thing we can do is abort */ if (!t) abort(); t->ret_arg = NULL; t->func = NULL; t->clean = NULL; t->cancelled = 0; t->p_state = PTHREAD_DEFAULT_ATTR; t->keymax = 0; t->keyval = NULL; t->h = GetCurrentThread(); /* Save for later */ TlsSetValue(_pthread_tls, t); if (setjmp(t->jb)) { /* Make sure we free ourselves if we are detached */ if (!t->h) free(t); /* Time to die */ _endthreadex(0); } } return t; }
static HDC getBitmapDC(void *imageData) { HDC hdc; HANDLE *mutex = (HANDLE*) TlsGetValue(tlsId); if(mutex == NULL) { mutex = (HANDLE*)malloc(sizeof(HANDLE)); if(mutex == NULL) { return NULL; } TlsSetValue(tlsId, mutex); *mutex = CreateMutex(0, JAVACALL_FALSE, "hPhoneBitmapMutex"); } if(lastImage != imageData) { if(hMemDC != NULL) { DeleteDC(hMemDC); } hdc = GetDC(hMainWindow); hMemDC = CreateCompatibleDC(hdc); ReleaseDC(hMainWindow, hdc); lastImage = imageData; } WaitForSingleObject(*mutex, INFINITE); if(imageData == NULL) { CHECK_RETURN(getBitmapDCtmp = SelectObject(hMemDC, hPhoneBitmap)); SetWindowOrgEx(hMemDC, -x_offset, -(Y_SCREEN_OFFSET), NULL); } else if(imageData == UNTRANSLATED_SCREEN_BITMAP) { CHECK_RETURN(getBitmapDCtmp = SelectObject(hMemDC, hPhoneBitmap)); } else { myBitmapStruct *bmp = (myBitmapStruct *)imageData; if(bmp->mutable) { getBitmapDCtmp = SelectObject(hMemDC, bmp->bitmap); } } return hMemDC; }
VOID _PrintExit(const CHAR *psz, ...) { DWORD dwErr = GetLastError(); LONG nIndent = 0; LONG nThread = 0; if (s_nTlsIndent >= 0) { nIndent = (LONG)TlsGetValue(s_nTlsIndent) - 1; ASSERT(nIndent >= 0); TlsSetValue(s_nTlsIndent, (PVOID)nIndent); } if (s_nTlsThread >= 0) { nThread = (LONG)TlsGetValue(s_nTlsThread); } if (s_bLog && psz) { CHAR szBuf[1024]; PCHAR pszBuf = szBuf; LONG nLen = (nIndent > 0) ? (nIndent < 35 ? nIndent * 2 : 70) : 0; *pszBuf++ = (CHAR)('0' + ((nThread / 100) % 10)); *pszBuf++ = (CHAR)('0' + ((nThread / 10) % 10)); *pszBuf++ = (CHAR)('0' + ((nThread / 1) % 10)); *pszBuf++ = ' '; while (nLen-- > 0) { *pszBuf++ = ' '; } va_list args; va_start(args, psz); while ((*pszBuf++ = *psz++) != 0) { // Copy characters. } SyelogV(SYELOG_SEVERITY_INFORMATION, szBuf, args); va_end(args); } SetLastError(dwErr); }
EXPORT TBOOL hal_initthread(struct THALBase *hal, struct THALObject *thread, TTASKENTRY void (*function)(struct TTask *task), TAPTR data) { struct HALThread *wth = THALNewObject(hal, thread, struct HALThread); if (wth) { wth->hth_SigEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (wth->hth_SigEvent) { #ifndef HAL_USE_ATOMICS InitializeCriticalSection(&wth->hth_SigLock); #endif wth->hth_SigState = 0; wth->hth_HALBase = hal; wth->hth_Data = data; wth->hth_Function = function; THALSetObject(thread, struct HALThread, wth); if (function) { wth->hth_Thread = (TAPTR) _beginthreadex(NULL, 0, hal_win32thread_entry, wth, 0, (HANDLE) &wth->hth_ThreadID); if (wth->hth_Thread) return TTRUE; } else { struct HALSpecific *hws = hal->hmb_Specific; TlsSetValue(hws->hsp_TLSIndex, wth); return TTRUE; } #ifndef HAL_USE_ATOMICS DeleteCriticalSection(&wth->hth_SigLock); #endif CloseHandle(wth->hth_SigEvent); } THALDestroyObject(hal, wth, struct HALThread); } TDBPRINTF(20,("could not create thread\n")); return TFALSE; }
void __cdecl _freeptd ( _ptiddata ptd ) { /* * Do nothing unless per-thread data has been allocated for this module! */ if ( __flsindex != 0xFFFFFFFF ) { /* * if parameter "ptd" is NULL, get the per-thread data pointer * Must NOT call _getptd because it will allocate one if none exists! * If FLS_GETVALUE is NULL then ptd could not have been set */ if ( ptd == NULL #ifndef _M_AMD64 && (FLS_GETVALUE != NULL) #endif /* _M_AMD64 */ ) ptd = FLS_GETVALUE(__flsindex); /* * Zero out the one pointer to the per-thread data block */ FLS_SETVALUE(__flsindex, (LPVOID)0); _freefls(ptd); } if ( __getvalueindex != 0xFFFFFFFF ) { /* * Zero out the FlsGetValue pointer */ TlsSetValue(__getvalueindex, (LPVOID)0); } }
/* static */ bool JsrtContext::TrySetCurrent(JsrtContext * context) { Assert(s_tlsSlot != TLS_OUT_OF_INDEXES); ThreadContext * threadContext; //We are not pinning the context after SetCurrentContext, so if the context is not pinned //it might be reclaimed half way during execution. In jsrtshell the runtime was optimized out //at time of JsrtContext::Run by the compiler. //The change is to pin the context at setconcurrentcontext, and unpin the previous one. In //JsDisposeRuntime we'll reject if current context is active, so that will make sure all //contexts are unpinned at time of JsDisposeRuntime. if (context != nullptr) { threadContext = context->GetScriptContext()->GetThreadContext(); if (!ThreadContextTLSEntry::TrySetThreadContext(threadContext)) { return false; } threadContext->GetRecycler()->RootAddRef((LPVOID)context); } else { if (!ThreadContextTLSEntry::ClearThreadContext(true)) { return false; } } JsrtContext* originalContext = (JsrtContext*) TlsGetValue(s_tlsSlot); if (originalContext != nullptr) { originalContext->GetScriptContext()->GetRecycler()->RootRelease((LPVOID) originalContext); } TlsSetValue(s_tlsSlot, context); return true; }
void iv_init(void) { struct iv_state *st; if (iv_state_index == -1) { iv_state_index = TlsAlloc(); if (iv_state_index == TLS_OUT_OF_INDEXES) iv_fatal("iv_init: failed to allocate TLS key"); } st = calloc(1, iv_tls_total_state_size()); TlsSetValue(iv_state_index, st); iv_handle_init(st); iv_task_init(st); iv_time_init(st); iv_timer_init(st); iv_event_init(st); iv_tls_thread_init(st); }
int virThreadLocalInit(virThreadLocalPtr l, virThreadLocalCleanup c) { if ((l->key = TlsAlloc()) == TLS_OUT_OF_INDEXES) { errno = ESRCH; return -1; } TlsSetValue(l->key, NULL); if (c) { virMutexLock(&virThreadLocalLock); if (VIR_REALLOC_N(virThreadLocalList, virThreadLocalCount + 1) < 0) return -1; virThreadLocalList[virThreadLocalCount].key = l->key; virThreadLocalList[virThreadLocalCount].cleanup = c; virThreadLocalCount++; virMutexUnlock(&virThreadLocalLock); } return 0; }
static TheCustomHeapType * initializeCustomHeap (void) { #if !defined(_WIN32) createKey(); assert (pthread_getspecific (theHeapKey) == NULL); #endif // Allocate a per-thread heap. TheCustomHeapType * heap; size_t sz = sizeof(TheCustomHeapType) + sizeof(double); void * mh = getMainHoardHeap()->malloc(sz); heap = new ((char *) mh) TheCustomHeapType (getMainHoardHeap()); // Store it in the appropriate thread-local area. #if defined(_WIN32) TlsSetValue (LocalTLABIndex, heap); #else int r = pthread_setspecific (theHeapKey, (void *) heap); assert (!r); #endif return heap; }
// Obtains a manager for the thread, with refcounting CMenuFocusManager * CMenuFocusManager::AcquireManager() { CMenuFocusManager * obj = NULL; if (!TlsIndex) { if ((TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return NULL; } obj = GetManager(); if (!obj) { obj = new CComObject<CMenuFocusManager>(); TlsSetValue(TlsIndex, obj); } obj->AddRef(); return obj; }
int async_fibre_init_dispatcher(async_fibre *fibre) { LPVOID dispatcher; dispatcher = (LPVOID)TlsGetValue(asyncwindispatch); if (dispatcher == NULL) { fibre->fibre = ConvertThreadToFiber(NULL); if (fibre->fibre == NULL) { fibre->converted = 0; fibre->fibre = GetCurrentFiber(); if (fibre->fibre == NULL) return 0; } else { fibre->converted = 1; } if (TlsSetValue(asyncwindispatch, (LPVOID)fibre->fibre) == 0) return 0; } else { fibre->fibre = dispatcher; } return 1; }
int stresscpu_thread_setspecific(stresscpu_thread_key_t key, const void * value) { int ret; if(key!=NULL && value != NULL) { EnterCriticalSection(&key->cs); ret = TlsSetValue(key->tls_index,(void *)value); LeaveCriticalSection(&key->cs); } if (ret == 0) { ret = EAGAIN; } else { ret = 0; } return ret; }
STDMETHODIMP_(VOID) DHContext::Release(SIZE_T cookie) { #if LOCK_TRACE // If we're tracing, enter a record into the list of currently held locks. vector<SIZE_T> *pCurrentLocks = reinterpret_cast<vector<SIZE_T>*>(TlsGetValue(m_dwTlsCurrentLocks)); if (pCurrentLocks) { _ASSERTE(!pCurrentLocks->empty() && "Expected a non-empty list"); if (pCurrentLocks->back() == cookie) { // This is the fast case (vector is constant time deletion from front/back). pCurrentLocks->pop_back(); } else { // Slow case, we must manually iterate through the list. for (vector<SIZE_T>::iterator currentWalker = pCurrentLocks->end(); currentWalker != pCurrentLocks->begin(); currentWalker--) { if (*currentWalker == cookie) { pCurrentLocks->erase(currentWalker); break; } } } // If the current list is empty, remove it from TLS and delete it. We will lazily // re-create it if necessary. if (pCurrentLocks->empty()) { TlsSetValue(m_dwTlsCurrentLocks, NULL); delete pCurrentLocks; } } #endif }
/* * Initialize a thread's errno */ static void Initialize_Thread_Errno(int *Errno_Pointer) { /* * Make sure we have a slot */ if (TLS_Errno_Slot == 0xffffffff) { /* * No: Get one */ TLS_Errno_Slot = (int)TlsAlloc(); if (TLS_Errno_Slot == 0xffffffff) ExitProcess(3); } /* * We can safely check for 0 threads, because * only the main thread will be initializing * at this point. Make sure the critical * section that protects the number of threads * is initialized */ if (Number_Of_Threads == 0) InitializeCriticalSection(&Number_Of_Threads_Critical_Section); /* * Store the errno pointer */ if (TlsSetValue(TLS_Errno_Slot, (LPVOID)Errno_Pointer) == 0) ExitProcess(3); /* * Bump the number of threads */ EnterCriticalSection(&Number_Of_Threads_Critical_Section); Number_Of_Threads++; if (Number_Of_Threads > 1) { /* * We have threads other than the main thread: * Use thread-local storage */ __WinCE_Errno_Pointer_Function = Get_Thread_Errno; } LeaveCriticalSection(&Number_Of_Threads_Critical_Section); }
/*----------------------------------------------------------------------------- -----------------------------------------------------------------------------*/ SECURITY_STATUS SchannelHook::InitializeSecurityContextW( PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR * pszTargetName, unsigned long fContextReq, unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned long * pfContextAttr, PTimeStamp ptsExpiry) { SECURITY_STATUS ret = SEC_E_INTERNAL_ERROR; fContextReq |= ISC_REQ_MANUAL_CRED_VALIDATION; if (_InitializeSecurityContextW) { ret = _InitializeSecurityContextW(phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); if (!phContext && phNewContext) { } } if (tlsIndex != TLS_OUT_OF_INDEXES) TlsSetValue(tlsIndex, phContext ? phContext : phNewContext); return ret; }
void *pa_tls_set(pa_tls *t, void *userdata) { void *r; assert(t); r = TlsGetValue(t->index); TlsSetValue(t->index, userdata); if (t->free_func) { struct pa_tls_monitor *m; PA_ONCE_BEGIN { monitor_tls = pa_tls_new(NULL); assert(monitor_tls); pa_tls_set(monitor_tls, NULL); } PA_ONCE_END; m = pa_tls_get(monitor_tls); if (!m) { HANDLE thread; m = pa_xnew(struct pa_tls_monitor, 1); DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &m->thread, 0, FALSE, DUPLICATE_SAME_ACCESS); m->free_func = t->free_func; pa_tls_set(monitor_tls, m); thread = CreateThread(NULL, 0, monitor_thread_func, m, 0, NULL); assert(thread); CloseHandle(thread); } m->data = userdata; }
/* Return the tls object. This function is guaranteed to return a valid non-NULL object. */ struct tls_space_s * get_tls (void) { struct tls_space_s *tls; tls = TlsGetValue (tls_index); if (!tls) { /* Called by a thread which existed before this DLL was loaded. Allocate the space. */ tls = LocalAlloc (LPTR, sizeof *tls); if (!tls) { /* No way to continue - commit suicide. */ abort (); } tls->gt_use_utf8 = 0; TlsSetValue (tls_index, tls); } return tls; }
DWORD Distributor::getframes(LPVOID param){ Thread* current_thread=(Thread*)param; Distributor* _this=current_thread->distributor; IScriptEnvironment** penv=&_this->_env; TlsSetValue(TlsIndex,new ScriptEnvironmentTLS()); while(true) { WaitForSingleObject(current_thread->begin,INFINITE); _RPT2(0,"Thread %d generating frame %d\n",GetCurrentThreadId(),current_thread->n); if(current_thread->endthread) break; current_thread->result=_this->child->GetFrame(current_thread->n,*penv); _RPT2(0,"Thread %d finished generating frame %d\n",GetCurrentThreadId(),current_thread->n); current_thread->status=Distributor::Thread::idle; SetEvent(current_thread->done); } delete((ScriptEnvironmentTLS*) TlsGetValue(TlsIndex)); ExitThread(0); return 0; }
static void set_error(const char * e) { char * s; char * old_s; size_t len; DWORD slot = get_tl_error_slot(); if (slot == TLS_OUT_OF_INDEXES) return; len = strlen(e) * sizeof(char) + sizeof(char); s = LocalAlloc(LMEM_FIXED, len); if (s == NULL) return; old_s = (char *) TlsGetValue(slot); TlsSetValue(slot, (LPVOID) s); if (old_s != NULL) LocalFree(old_s); }
CxContext* icxGetContext() { #ifdef CX_DLL #ifdef WIN32 CxContext* pContext = (CxContext*)TlsGetValue( g_TlsIndex ); if( !pContext ) { pContext = icxCreateContext(); if( !pContext ) { FatalAppExit( 0, "OpenCX. Problem to allocate memory for TLS OpenCX context." ); } TlsSetValue( g_TlsIndex, pContext ); } return pContext; #else CxContext* pContext = (CxContext*)pthread_getspecific( g_TlsIndex ); if( !pContext ) { pContext = icxCreateContext(); if( !pContext ) { fprintf(stderr,"OpenCX. Problem to allocate memory for OpenCX context."); exit(1); } pthread_setspecific( g_TlsIndex, pContext ); } return pContext; #endif #else /* CX_DLL */ static CxContext* pContext = 0; if( !pContext ) pContext = icxCreateContext(); return pContext; #endif }
/* Deinitialize libgpg-error. This function is only used in special circumstances. No gpg-error function should be used after this function has been called. A value of 0 passed for MODE deinitializes the entire libgpg-error, a value of 1 releases resources allocated for the current thread and only that thread may not anymore access libgpg-error after such a call. Under Windows this function may be called from the DllMain function of a DLL which statically links to libgpg-error. */ void _gpg_err_deinit (int mode) { #if defined (HAVE_W32_SYSTEM) && !defined(DLL_EXPORT) struct tls_space_s *tls; tls = TlsGetValue (tls_index); if (tls) { TlsSetValue (tls_index, NULL); LocalFree (tls); } if (mode == 0) { TlsFree (tls_index); tls_index = TLS_OUT_OF_INDEXES; } #else (void)mode; #endif }
BOOL WINAPI TLS_SetThread(fdcore::UpdateSystemThread* dw) { LPVOID lpvData; fdcore::UpdateSystemThread** pData; // The stored memory pointer lpvData = TlsGetValue(dwTlsIndex); if (lpvData == NULL) { lpvData = (LPVOID) LocalAlloc(LPTR, 256); if (lpvData == NULL) return FALSE; if (!TlsSetValue(dwTlsIndex, lpvData)) return FALSE; } pData = (fdcore::UpdateSystemThread**) lpvData; // Cast to my data type. // In this example, it is only a pointer to a DWORD // but it can be a structure pointer to contain more complicated data. (*pData) = dw; return TRUE; }
VOID WSAAPI WsThreadDelete(IN PWSTHREAD Thread) { /* Remove the blocking hook */ Thread->BlockingHook = NULL; /* Free our buffers */ if (Thread->Hostent) HeapFree(WsSockHeap, 0, Thread->Hostent); if (Thread->Servent) HeapFree(WsSockHeap, 0, Thread->Servent); if (Thread->ProtocolInfo) HeapFree(WsSockHeap, 0, Thread->ProtocolInfo); /* Clear the TLS */ TlsSetValue(TlsIndex, NULL); /* Close the WAH Handle */ WahCloseThread(Thread->AsyncHelper, &Thread->WahThreadId); /* Unlink the process and free us */ Thread->Process = NULL; HeapFree(WsSockHeap, 0, Thread); }
omni_thread::init_t::init_t(void) { if (count++ != 0) // only do it once however many objects get created. return; DB(cerr << "omni_thread::init: NT implementation initialising\n"); self_tls_index = TlsAlloc(); if (self_tls_index == 0xffffffff) throw omni_thread_fatal(GetLastError()); next_id_mutex = new omni_mutex; // // Create object for this (i.e. initial) thread. // omni_thread* t = new omni_thread; t->_state = STATE_RUNNING; if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &t->handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) throw omni_thread_fatal(GetLastError()); t->nt_id = GetCurrentThreadId(); DB(cerr << "initial thread " << t->id() << " NT thread id " << t->nt_id << endl); if (!TlsSetValue(self_tls_index, (LPVOID)t)) throw omni_thread_fatal(GetLastError()); if (!SetThreadPriority(t->handle, nt_priority(PRIORITY_NORMAL))) throw omni_thread_fatal(GetLastError()); }
void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex) { opj_cond_waiter_list_t* item; HANDLE hEvent = (HANDLE) TlsGetValue( TLSKey ); if (hEvent == NULL) { hEvent = CreateEvent(NULL, /* security attributes */ 0, /* manual reset = no */ 0, /* initial state = unsignaled */ NULL /* no name */); assert(hEvent); TlsSetValue( TLSKey, hEvent ); } /* Insert the waiter into the waiter list of the condition */ opj_mutex_lock(cond->internal_mutex); item = (opj_cond_waiter_list_t*)opj_malloc(sizeof(opj_cond_waiter_list_t)); assert(item != NULL); item->hEvent = hEvent; item->next = cond->waiter_list; cond->waiter_list = item; opj_mutex_unlock(cond->internal_mutex); /* Release the client mutex before waiting for the event being signaled */ opj_mutex_unlock(mutex); /* Ideally we would check that we do not get WAIT_FAILED but it is hard */ /* to report a failure. */ WaitForSingleObject(hEvent, INFINITE); /* Reacquire the client mutex */ opj_mutex_lock(mutex); }
/* * Disables the cache. */ void fscache_disable(void) { struct fscache *cache; if (!core_fscache) return; /* update the thread specific fscache initialization */ cache = fscache_getcache(); if (!cache) BUG("fscache_disable() called on a thread where fscache has not been initialized"); if (!cache->enabled) BUG("fscache_disable() called on an fscache that is already disabled"); cache->enabled--; if (!cache->enabled) { TlsSetValue(dwTlsIndex, NULL); trace_printf_key(&trace_fscache, "fscache_disable: lstat %u, opendir %u, " "total requests/misses %u/%u\n", cache->lstat_requests, cache->opendir_requests, cache->fscache_requests, cache->fscache_misses); mem_pool_discard(cache->mem_pool, 0); hashmap_free(&cache->map, 0); free(cache); } /* update the global fscache initialization */ EnterCriticalSection(&fscache_cs); initialized--; if (!initialized) { /* reset opendir and lstat to the original implementations */ opendir = dirent_opendir; lstat = mingw_lstat; } LeaveCriticalSection(&fscache_cs); trace_printf_key(&trace_fscache, "fscache: disable\n"); return; }
/* * This function should be called by the user whenever a thread ends, * to free the thread "virtual stack" storage */ ITT_EXTERN_C void JITAPI FinalizeThread() { if (threadLocalStorageHandle) { #if ITT_PLATFORM==ITT_PLATFORM_WIN pThreadStack threadStack = (pThreadStack)TlsGetValue (threadLocalStorageHandle); #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ pThreadStack threadStack = (pThreadStack)pthread_getspecific(threadLocalStorageHandle); #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ if (threadStack) { free (threadStack); threadStack = NULL; #if ITT_PLATFORM==ITT_PLATFORM_WIN TlsSetValue (threadLocalStorageHandle, threadStack); #else /* ITT_PLATFORM==ITT_PLATFORM_WIN */ pthread_setspecific(threadLocalStorageHandle, threadStack); #endif /* ITT_PLATFORM==ITT_PLATFORM_WIN */ } } }