Re: TlsAlloc limitation in winxp mode

2005-03-18 Thread Jon Griffiths
Hi Michael,

 With the emulation mode set to winxp I can only TlsAlloc 64
 indexes, even though the MSDN docs say there should be at least
 20 million.

You're misreading that page, the limits are:
Win 2000/2003  XP - 1088 indexes per process
Win Me/98  - 80 indexes per process
Win NT and 95  - 64 indexes per process

So it seems that Me/98 add 16 on top of the original 64 limit, while
from Win2k onwards another 1024 indices were added.

You can almost certainly work around this if you have the source for
the app you are trying to run, unless your app has more than 64
threads running at once.

Just take all of the per-thread data you need and stick it into a
structure, store only the pointer to that for each thread (1 slot).
This adds a layer of indirection but means you are limited only by
the heap, provided you don't have more than 64 threads. See
dlls/msvcrt/thread.c for an implementation example.

Cheers,
Jon


Don't wait for the seas to part, or messiahs to come;
 Don't you sit around and waste this chance... - Live

[EMAIL PROTECTED]



__ 
Do you Yahoo!? 
Yahoo! Small Business - Try our new resources site!
http://smallbusiness.yahoo.com/resources/ 



Re: TlsAlloc limitation in winxp mode

2005-03-18 Thread Alexandre Julliard
Michael Ost [EMAIL PROTECTED] writes:

 With the emulation mode set to winxp I can only TlsAlloc 64 indexes,
 even though the MSDN docs say there should be at least 20 million.
 
 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/thread_local_storage.asp
 
 Has anyone done any work on this? Any workaround/hackarounds? ... mo

It's not 20 million, it's 1088 (64 + 1024). You need to use the TLS
expansion slots for the extra 1024, something like this (completely
untested):

Index: dlls/kernel/process.c
===
RCS file: /opt/cvs-commit/wine/dlls/kernel/process.c,v
retrieving revision 1.85
diff -u -p -r1.85 process.c
--- dlls/kernel/process.c   7 Mar 2005 19:24:44 -   1.85
+++ dlls/kernel/process.c   18 Mar 2005 11:24:53 -
@@ -2192,11 +2192,32 @@ UINT WINAPI SetErrorMode( UINT mode )
 DWORD WINAPI TlsAlloc( void )
 {
 DWORD index;
+PEB * const peb = NtCurrentTeb()-Peb;
 
 RtlAcquirePebLock();
-index = RtlFindClearBitsAndSet( NtCurrentTeb()-Peb-TlsBitmap, 1, 0 );
+index = RtlFindClearBitsAndSet( peb-TlsBitmap, 1, 0 );
 if (index != ~0UL) NtCurrentTeb()-TlsSlots[index] = 0; /* clear the value 
*/
-else SetLastError( ERROR_NO_MORE_ITEMS );
+else
+{
+index = RtlFindClearBitsAndSet( peb-TlsExpansionBitmap, 1, 0 );
+if (index != ~0UL)
+{
+if (!NtCurrentTeb()-TlsExpansionSlots 
+!(NtCurrentTeb()-TlsExpansionSlots = HeapAlloc( 
GetProcessHeap(), HEAP_ZERO_MEMORY,
+  
peb-TlsExpansionBitmap-SizeOfBitMap*sizeof(void*) )))
+{
+RtlClearBits( peb-TlsExpansionBitmap, index, 1 );
+index = ~0UL;
+SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+}
+else
+{
+NtCurrentTeb()-TlsExpansionSlots[index] = 0; /* clear the 
value */
+index += peb-TlsBitmap-SizeOfBitMap;
+}
+}
+else SetLastError( ERROR_NO_MORE_ITEMS );
+}
 RtlReleasePebLock();
 return index;
 }
@@ -2215,14 +2236,21 @@ BOOL WINAPI TlsFree(
 DWORD index) /* [in] TLS Index to free */
 {
 BOOL ret;
+PEB * const peb = NtCurrentTeb()-Peb;
 
 RtlAcquirePebLock();
-ret = RtlAreBitsSet( NtCurrentTeb()-Peb-TlsBitmap, index, 1 );
-if (ret)
+if (index = peb-TlsBitmap-SizeOfBitMap)
 {
-RtlClearBits( NtCurrentTeb()-Peb-TlsBitmap, index, 1 );
-NtSetInformationThread( GetCurrentThread(), ThreadZeroTlsCell, index, 
sizeof(index) );
+DWORD exp_index = index - peb-TlsBitmap-SizeOfBitMap;
+ret = RtlAreBitsSet( peb-TlsExpansionBitmap, exp_index, 1 );
+if (ret) RtlClearBits( peb-TlsExpansionBitmap, exp_index, 1 );
 }
+else
+{
+ret = RtlAreBitsSet( peb-TlsBitmap, index, 1 );
+if (ret) RtlClearBits( peb-TlsBitmap, index, 1 );
+}
+if (ret) NtSetInformationThread( GetCurrentThread(), ThreadZeroTlsCell, 
index, sizeof(index) );
 else SetLastError( ERROR_INVALID_PARAMETER );
 RtlReleasePebLock();
 return TRUE;
@@ -2239,13 +2267,25 @@ BOOL WINAPI TlsFree(
 LPVOID WINAPI TlsGetValue(
 DWORD index) /* [in] TLS index to retrieve value for */
 {
-if (index = NtCurrentTeb()-Peb-TlsBitmap-SizeOfBitMap)
+LPVOID ret;
+
+if (index  NtCurrentTeb()-Peb-TlsBitmap-SizeOfBitMap)
 {
-SetLastError( ERROR_INVALID_PARAMETER );
-return NULL;
+ret = NtCurrentTeb()-TlsSlots[index];
+}
+else
+{
+index -= NtCurrentTeb()-Peb-TlsBitmap-SizeOfBitMap;
+if (index = NtCurrentTeb()-Peb-TlsExpansionBitmap-SizeOfBitMap)
+{
+SetLastError( ERROR_INVALID_PARAMETER );
+return NULL;
+}
+if (!NtCurrentTeb()-TlsExpansionSlots) ret = NULL;
+else ret = NtCurrentTeb()-TlsExpansionSlots[index];
 }
 SetLastError( ERROR_SUCCESS );
-return NtCurrentTeb()-TlsSlots[index];
+return ret;
 }
 
 
@@ -2260,12 +2300,29 @@ BOOL WINAPI TlsSetValue(
 DWORD index,  /* [in] TLS index to set value for */
 LPVOID value) /* [in] Value to be stored */
 {
-if (index = NtCurrentTeb()-Peb-TlsBitmap-SizeOfBitMap)
+PEB * const peb = NtCurrentTeb()-Peb;
+
+if (index  peb-TlsBitmap-SizeOfBitMap)
+{
+NtCurrentTeb()-TlsSlots[index] = value;
+}
+else
 {
-SetLastError( ERROR_INVALID_PARAMETER );
-return FALSE;
+index -= peb-TlsBitmap-SizeOfBitMap;
+if (index = peb-TlsExpansionBitmap-SizeOfBitMap)
+{
+SetLastError( ERROR_INVALID_PARAMETER );
+return FALSE;
+}
+if (!NtCurrentTeb()-TlsExpansionSlots 
+!(NtCurrentTeb()-TlsExpansionSlots = HeapAlloc( GetProcessHeap(), 
HEAP_ZERO_MEMORY,
+  
peb-TlsExpansionBitmap-SizeOfBitMap*sizeof(void*) )))
+  

Re: TlsAlloc limitation in winxp mode

2005-03-18 Thread Michael Ost
On Fri, 2005-03-18 at 03:30, Alexandre Julliard wrote:
 Michael Ost [EMAIL PROTECTED] writes:
 
  With the emulation mode set to winxp I can only TlsAlloc 64 indexes,
  even though the MSDN docs say there should be at least 20 million.
  
  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/thread_local_storage.asp
  
  Has anyone done any work on this? Any workaround/hackarounds? ... mo
 
 It's not 20 million, it's 1088 (64 + 1024). You need to use the TLS
 expansion slots for the extra 1024, something like this (completely
 untested):
snip patch

Thanks. I suspected that was the way to go. Should the TlsAlloc code, or
perhaps the thread init code, check on the windows emulation version and
allow the right number of slots... 64, 80 or 1088?

- mo

===
Michael Ost, Software Architect
Muse Research, Inc.
[EMAIL PROTECTED]