I wish to propose two changes that I currently have in my Solaris patchkit. I'll use two separate e-mails here to avoid confusion.
Both changes add environment variables controlling the way wine does things.
The first patch addresses a problem I have found where Windows applications under wine exceed the allocated stack. By default wine allocates the same 1MB stack that windows does but wine has a different stack consumption that does windows, adding the wine translation layers, possibly OGL then X calls on top of this.
The following patch allows an environment variable WINE_STACK to redefine the minimum stack to give applications and to add extra stack to that declared in the executables header to allow for additional stack consumption. Currently it works like this
if WINE_STACK is not set the default semantics are used just like wine does today
if WINE_STACK is set then wine allocates the maximum of the value given in the WINE_STACK env var or 1MB. 25% of the value specified in WINE_STACK is added to the value declared in the applications executable header to provide more headroom for wine/X calls.
Please excuse the primitive debugging included for now, it'll have to be removed for primetime.
Comments anyone ?
Index: dlls/ntdll/thread.c =================================================================== RCS file: /home/wine/wine/dlls/ntdll/thread.c,v retrieving revision 1.26 diff -u -3 -p -r1.26 thread.c --- dlls/ntdll/thread.c 27 Apr 2005 08:18:20 -0000 1.26 +++ dlls/ntdll/thread.c 6 May 2005 21:21:30 -0000 @@ -25,7 +25,7 @@ #ifdef HAVE_SYS_MMAN_H #include <sys/mman.h> #endif - +#include <stdio.h> #include "ntstatus.h" #include "thread.h" #include "winternl.h" @@ -221,6 +221,9 @@ NTSTATUS WINAPI RtlCreateUserThread( HAN ULONG size; int request_pipe[2]; NTSTATUS status; + unsigned long stack_min=1024*1024; + unsigned long stack_overhead=0; + char stack_mul=0;
if( ! is_current_process( process ) ) { @@ -273,23 +276,67 @@ NTSTATUS WINAPI RtlCreateUserThread( HAN MEM_SYSTEM, PAGE_EXECUTE_READWRITE ); info->pthread_info.teb_size = size; info->pthread_info.teb_sel = teb->teb_sel; - + + + /* Allocate the stack: + Allow the user to set an environment variable to specify the stack size + WINE_STACK, allow the user to use multiplier notation + eg K for kilobyts or M for Megabytes or M + example WINE_STCK=2048K or WINE_STACK=2M bithe specify 2 Megabytes + */ + + if(getenv("WINE_STACK")) { + sscanf(getenv("WINE_STACK")," %lu%c ",&stack_min,&stack_mul); + fprintf(stderr,"Got stack spec of %lu %c bytes from environment",stack_min,stack_mul); + } + + switch (stack_mul) { + case 'm': + case 'M': + stack_min=stack_min*1024*1024; + stack_overhead=stack_min/4; + break; + case 'b': + case 'B': + stack_overhead=stack_min/4; + break; + case 'k': + case 'K': + stack_min=stack_min*1024; + stack_overhead=stack_min/4; + break; + + default: + stack_min=1024*1024; + stack_overhead=0; + break; + } + + stack_min=max(stack_min,1024*1024); + fprintf(stderr,"Minimum Stack Set to %lu overhead allowance = %d\n",stack_min,stack_overhead); + /* Get the stack size recommendation from the program prefix (Executible header) + Because this is not "real windows" we have additional stack overheads particularly in xlib + where the user has specified a stack requirement (IE VIA WINE_STACK) add 25% of the minimum + stack over and above the value in the header to allow for this + */ if (!stack_reserve || !stack_commit) { IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); - if (!stack_reserve) stack_reserve = nt->OptionalHeader.SizeOfStackReserve; + if (!stack_reserve) stack_reserve = nt->OptionalHeader.SizeOfStackReserve+stack_overhead; if (!stack_commit) stack_commit = nt->OptionalHeader.SizeOfStackCommit; } if (stack_reserve < stack_commit) stack_reserve = stack_commit; stack_reserve = (stack_reserve + 0xffff) & ~0xffff; /* round to 64K boundary */ - if (stack_reserve < 1024 * 1024) stack_reserve = 1024 * 1024; /* Xlib needs a large stack */ + if (stack_reserve < stack_min) stack_reserve = stack_min; /* Xlib needs a large stack */
info->pthread_info.stack_base = NULL; info->pthread_info.stack_size = stack_reserve; info->pthread_info.entry = start_thread; info->entry_point = start; info->entry_arg = param; - + + fprintf(stderr,"Allocated thread at %lx Allocated stack of %lu Bytes\n",stack_commit,stack_reserve); + if (wine_pthread_create_thread( &info->pthread_info ) == -1) { status = STATUS_NO_MEMORY;