source: trunk/src/kernel32/wintls.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 7.9 KB
RevLine 
[8886]1/* $Id: wintls.cpp,v 1.18 2002-07-18 11:58:46 achimha Exp $ */
[281]2/*
3 * Win32 TLS API functions
4 *
[3975]5 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
[281]6 *
[3975]7 * TODO: correct errors set for Tls* apis? (verify in NT)
[281]8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#include <os2win.h>
[956]13#include <string.h>
[21916]14#include "winimagebase.h"
[281]15#include <thread.h>
16#include <wprocess.h>
[617]17#include "exceptutil.h"
[281]18
[4285]19#define DBG_LOCALLOG DBG_wintls
[2802]20#include "dbglocal.h"
21
[281]22//******************************************************************************
[8886]23// Design information on TLS - AH 2002-07-18
24//
25// Windows TLS is very restricted in size. We implement it the same way as NT -
26// as part of the thread's TEB. We do not use the OS/2 TLS facilities directly.
27// The only part we use OS/2 TLS for is to store the thread's TEB pointer.
28// We fully support .tls sections in PE modules with this method.
[281]29//******************************************************************************
[8886]30
31//******************************************************************************
32//******************************************************************************
[4285]33void Win32ImageBase::tlsAlloc() //Allocate TLS index for this module
[281]34{
[4285]35 if(!tlsAddress)
[4298]36 return;
[281]37
38 tlsIndex = TlsAlloc();
39 if(tlsIndex >= TLS_MINIMUM_AVAILABLE) {
[4459]40 dprintf(("tlsAlloc: invalid tlsIndex %x!!!!", tlsIndex));
[4298]41 DebugInt3();
42 return;
[281]43 }
[956]44 dprintf(("Win32ImageBase::tlsAlloc (%d) for module %x", tlsIndex, hinstance));
[281]45}
46//******************************************************************************
47//******************************************************************************
[4285]48void Win32ImageBase::tlsDelete() //Free TLS index for this module
[281]49{
[4285]50 if(!tlsAddress)
[4298]51 return;
[281]52
53 if(tlsIndex >= TLS_MINIMUM_AVAILABLE) {
[4459]54 dprintf(("tlsDelete: invalid tlsIndex %x!!!!", tlsIndex));
[4298]55 DebugInt3();
56 return;
[281]57 }
[956]58 dprintf(("Win32ImageBase::tlsDestroy (%d) for module %x", tlsIndex, hinstance));
[281]59 TlsFree(tlsIndex);
60 tlsIndex = -1;
61}
62//******************************************************************************
63//******************************************************************************
[4285]64void Win32ImageBase::tlsAttachThread() //setup TLS structures for new thread
[281]65{
[3975]66 EXCEPTION_FRAME exceptFrame;
[281]67 PIMAGE_TLS_CALLBACK *pCallback;
[3975]68 LPVOID tibmem;
[281]69
[4285]70 if(!tlsAddress)
[4298]71 return;
[281]72
73 if(tlsIndex >= TLS_MINIMUM_AVAILABLE) {
[4298]74 dprintf(("tlsAttachThread: invalid tlsIndex %x!!!!", tlsIndex));
75 DebugInt3();
76 return;
[281]77 }
78
[956]79 dprintf(("Win32ImageBase::tlsAttachThread for module %x, thread id %x", hinstance, GetCurrentThreadId()));
[281]80 dprintf(("tlsAddress: %x", tlsAddress));
81 dprintf(("tlsInitSize: %x", tlsInitSize));
82 dprintf(("tlsTotalSize %x", tlsTotalSize));
83 dprintf(("tlsIndexAddr %x", tlsIndexAddr));
84 dprintf(("tlsCallbackAddr %x", tlsCallBackAddr));
[1853]85 dprintf(("*tlsCallbackAddr %x", (tlsCallBackAddr) ? *tlsCallBackAddr : 0));
[3975]86 tibmem = VirtualAlloc(0, tlsTotalSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
[281]87 if(tibmem == NULL) {
[4298]88 dprintf(("tlsAttachThread: tibmem == NULL!!!!"));
89 DebugInt3();
90 return;
[281]91 }
92 memset(tibmem, 0, tlsTotalSize);
93 memcpy(tibmem, tlsAddress, tlsInitSize);
94
[3975]95 TlsSetValue(tlsIndex, tibmem);
[281]96 *tlsIndexAddr = tlsIndex;
97
[21489]98 if(tlsCallBackAddr && (ULONG)*tlsCallBackAddr != 0)
[4481]99 {
[4298]100 pCallback = tlsCallBackAddr;
101 while(*pCallback) {
102 dprintf(("tlsAttachThread: calling TLS Callback %x", *pCallback));
[617]103
[4298]104 (*pCallback)((LPVOID)hinstance, DLL_THREAD_ATTACH, 0);
[617]105
[4298]106 dprintf(("tlsAttachThread: finished calling TLS Callback %x", *pCallback));
[4481]107 pCallback++;
[4298]108 }
[281]109 }
110 return;
111}
112//******************************************************************************
113//******************************************************************************
[4285]114void Win32ImageBase::tlsDetachThread() //destroy TLS structures
[281]115{
[3975]116 EXCEPTION_FRAME exceptFrame;
[281]117 PIMAGE_TLS_CALLBACK *pCallback;
[3975]118 LPVOID tlsmem;
[281]119
[4285]120 if(!tlsAddress)
[4298]121 return;
[281]122
[956]123 dprintf(("Win32ImageBase::tlsDetachThread for module %x, thread id %x", hinstance, GetCurrentThreadId()));
[281]124
[21489]125 if(tlsCallBackAddr && (ULONG)*tlsCallBackAddr != 0)
[4481]126 {
[4298]127 pCallback = tlsCallBackAddr;
128 while(*pCallback) {
129 dprintf(("tlsDetachThread: calling TLS Callback %x", *pCallback));
[617]130
[4298]131 (*pCallback)((LPVOID)hinstance, DLL_THREAD_DETACH, 0);
[617]132
[4298]133 dprintf(("tlsDetachThread: finished calling TLS Callback %x", *pCallback));
[4481]134 pCallback++;
[4298]135 }
[281]136 }
[3975]137 tlsmem = TlsGetValue(tlsIndex);
138 if(tlsmem) {
[4796]139 VirtualFree(tlsmem, 0, MEM_RELEASE);
[3975]140 }
141 else {
[4298]142 dprintf(("ERROR: tlsDetachThread: tlsmem == NULL!!!"));
[3975]143 }
144 TlsFree(tlsIndex);
[281]145}
146//******************************************************************************
147//******************************************************************************
148DWORD WIN32API TlsAlloc()
149{
[3975]150 DWORD index = -1;
[4658]151 TEB *teb;
[3975]152 PDB *pdb;
153 DWORD mask, tibidx;
154 int i;
155
[4658]156 teb = GetThreadTEB();
[3975]157 pdb = PROCESS_Current();
158
159 EnterCriticalSection(&pdb->crit_section);
160 tibidx = 0;
161 if(pdb->tls_bits[0] == 0xFFFFFFFF) {
[4298]162 if(pdb->tls_bits[1] == 0xFFFFFFFF) {
163 LeaveCriticalSection(&pdb->crit_section);
164 SetLastError(ERROR_NO_MORE_ITEMS); //TODO: correct error?
[21489]165 return TLS_OUT_OF_INDEXES;
[4298]166 }
167 tibidx = 1;
[3975]168 }
169 for(i=0;i<32;i++) {
[4298]170 mask = (1 << i);
171 if((pdb->tls_bits[tibidx] & mask) == 0) {
172 pdb->tls_bits[tibidx] |= mask;
173 index = (tibidx*32) + i;
174 break;
175 }
[3975]176 }
177 LeaveCriticalSection(&pdb->crit_section);
[4658]178 teb->tls_array[index] = 0;
[4481]179
[3615]180 dprintf(("KERNEL32: TlsAlloc returned %d", index));
181 return index;
[281]182}
183//******************************************************************************
184//******************************************************************************
185BOOL WIN32API TlsFree(DWORD index)
186{
[4658]187 TEB *teb;
[3975]188 PDB *pdb;
189 int tlsidx;
190 DWORD mask;
191
[4481]192 dprintf(("KERNEL32: TlsFree %d", index));
[3975]193 if(index >= TLS_MINIMUM_AVAILABLE)
194 {
195 SetLastError(ERROR_INVALID_PARAMETER);
196 return NULL;
197 }
198
[4658]199 teb = GetThreadTEB();
200 pdb = PROCESS_Current();
[3975]201
202 EnterCriticalSection(&pdb->crit_section);
203 tlsidx = 0;
204 if(index > 32) {
[4481]205 tlsidx++;
[3975]206 }
207 mask = (1 << index);
208 if(pdb->tls_bits[tlsidx] & mask) {
209 LeaveCriticalSection(&pdb->crit_section);
[4298]210 pdb->tls_bits[tlsidx] &= ~mask;
[4658]211 teb->tls_array[index] = 0;
[3975]212 SetLastError(ERROR_SUCCESS);
[4298]213 return TRUE;
[3975]214 }
215 LeaveCriticalSection(&pdb->crit_section);
216 SetLastError(ERROR_INVALID_PARAMETER); //TODO: correct error? (does NT even change the last error?)
217 return FALSE;
[281]218}
219//******************************************************************************
220//******************************************************************************
221LPVOID WIN32API TlsGetValue(DWORD index)
222{
223 LPVOID rc;
[4658]224 TEB *teb;
[281]225
[3975]226 if(index >= TLS_MINIMUM_AVAILABLE)
227 {
228 SetLastError(ERROR_INVALID_PARAMETER);
229 return NULL;
230 }
231 SetLastError(ERROR_SUCCESS);
232
[4658]233 teb = GetThreadTEB();
234 rc = teb->tls_array[index];
[4481]235
[3975]236 dprintf2(("KERNEL32: TlsGetValue %d returned %X\n", index, rc));
[281]237 return(rc);
238}
239//******************************************************************************
240//******************************************************************************
241BOOL WIN32API TlsSetValue(DWORD index, LPVOID val)
242{
[4658]243 TEB *teb;
[4481]244
[3975]245 dprintf2(("KERNEL32: TlsSetValue %d %x", index, val));
246 if(index >= TLS_MINIMUM_AVAILABLE)
247 {
248 SetLastError(ERROR_INVALID_PARAMETER);
249 return FALSE;
250 }
251 SetLastError(ERROR_SUCCESS);
252
[4658]253 teb = GetThreadTEB();
254 teb->tls_array[index] = val;
[3975]255 return TRUE;
[281]256}
257//******************************************************************************
258//******************************************************************************
Note: See TracBrowser for help on using the repository browser.