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