From 07f1198eea5dd7464d972cb5166c3c7509e385d1 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 9 Jul 2003 22:31:34 +0000 Subject: [PATCH] Store window procedures in a static array instead of creating a heap. Only allocate the winproc selector when actually needed. --- dlls/user/user_main.c | 3 -- dlls/user/winproc.h | 1 - windows/winproc.c | 89 +++++++++++++++++++++++++++++++++++---------------- 3 files changed, 61 insertions(+), 32 deletions(-) diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c index b676d50baec..78dc823cf11 100644 --- a/dlls/user/user_main.c +++ b/dlls/user/user_main.c @@ -237,9 +237,6 @@ static BOOL process_attach(void) /* Setup palette function pointers */ palette_init(); - /* Initialize window procedures */ - if (!WINPROC_Init()) return FALSE; - /* Initialize built-in window classes */ controls_init(); diff --git a/dlls/user/winproc.h b/dlls/user/winproc.h index c5d43f9daa8..18e135cebd8 100644 --- a/dlls/user/winproc.h +++ b/dlls/user/winproc.h @@ -56,7 +56,6 @@ typedef struct struct tagWINDOWPROC; -extern BOOL WINPROC_Init(void); extern WNDPROC16 WINPROC_GetProc( WNDPROC proc, WINDOWPROCTYPE type ); extern BOOL WINPROC_SetProc( WNDPROC *pFirst, WNDPROC func, WINDOWPROCTYPE type, WINDOWPROCUSER user ); diff --git a/windows/winproc.c b/windows/winproc.c index 1bb9bb99962..f7f85677fec 100644 --- a/windows/winproc.c +++ b/windows/winproc.c @@ -31,7 +31,6 @@ #include "wine/winbase16.h" #include "wine/winuser16.h" #include "stackframe.h" -#include "selectors.h" #include "controls.h" #include "heap.h" #include "struct32.h" @@ -45,7 +44,7 @@ WINE_DECLARE_DEBUG_CHANNEL(msg); WINE_DECLARE_DEBUG_CHANNEL(relay); -WINE_DECLARE_DEBUG_CHANNEL(win); +WINE_DEFAULT_DEBUG_CHANNEL(win); #include "pshpack1.h" @@ -110,24 +109,60 @@ static LRESULT WINAPI WINPROC_CallProc32WTo16( WNDPROC16 func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ); -static HANDLE WinProcHeap; -static WORD WinProcSel; +#define MAX_WINPROCS (0x10000 / sizeof(WINDOWPROC)) +static WINDOWPROC winproc_array[MAX_WINPROCS]; +static WINDOWPROC *winproc_first_free; +static UINT winproc_used; +static CRITICAL_SECTION winproc_cs = CRITICAL_SECTION_INIT("winproc_cs"); -/********************************************************************** - * WINPROC_Init - */ -BOOL WINPROC_Init(void) +/* allocate a window procedure from the global array */ +static WINDOWPROC *alloc_winproc(void) +{ + WINDOWPROC *ret = NULL; + + EnterCriticalSection( &winproc_cs ); + if ((ret = winproc_first_free)) + winproc_first_free = ret->next; + else if (winproc_used < MAX_WINPROCS) + ret = &winproc_array[winproc_used++]; + LeaveCriticalSection( &winproc_cs ); + return ret; +} + +static void free_winproc( WINDOWPROC *proc ) +{ + EnterCriticalSection( &winproc_cs ); + proc->magic = 0; + proc->next = winproc_first_free; + winproc_first_free = proc; + LeaveCriticalSection( &winproc_cs ); +} + +static BOOL is_valid_winproc( WINDOWPROC *proc ) +{ + if (proc < winproc_array || proc >= winproc_array + MAX_WINPROCS) return FALSE; + if (proc != winproc_array + (proc - winproc_array)) return FALSE; + return (proc->magic == WINPROC_MAGIC); +} + +static WORD get_winproc_selector(void) { - WinProcHeap = HeapCreate( 0, 0x10000, 0x10000 ); - WinProcSel = SELECTOR_AllocBlock( (void *)WinProcHeap, 0x10000, - WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT ); - if (!WinProcHeap || !WinProcSel) + static LONG winproc_selector; + WORD ret; + + if (!(ret = winproc_selector)) { - WARN_(relay)("Unable to create winproc heap\n" ); - return FALSE; + LDT_ENTRY entry; + WORD sel = wine_ldt_alloc_entries(1); + wine_ldt_set_base( &entry, winproc_array ); + wine_ldt_set_limit( &entry, sizeof(winproc_array) - 1 ); + wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT ); + wine_ldt_set_entry( sel, &entry ); + if (!(ret = InterlockedCompareExchange( &winproc_selector, sel, 0 ))) ret = sel; + else wine_ldt_free_entries( sel, 1 ); /* somebody beat us to it */ } - return TRUE; + return ret; } @@ -279,12 +314,11 @@ static WINDOWPROC *WINPROC_GetPtr( WNDPROC handle ) ptr = (BYTE *)handle; /* First check if it is the jmp address */ proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->jmp); - if (HeapValidate( WinProcHeap, 0, proc ) && (proc->magic == WINPROC_MAGIC)) - return proc; + if (is_valid_winproc(proc)) return proc; + /* Now it must be the thunk address */ proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->thunk); - if (HeapValidate( WinProcHeap, 0, proc ) && (proc->magic == WINPROC_MAGIC)) - return proc; + if (is_valid_winproc(proc)) return proc; /* Check for a segmented pointer */ @@ -293,8 +327,7 @@ static WINDOWPROC *WINPROC_GetPtr( WNDPROC handle ) ptr = MapSL( (SEGPTR)handle ); /* It must be the thunk address */ proc = (WINDOWPROC *)(ptr - (int)&((WINDOWPROC *)0)->thunk); - if (HeapValidate( WinProcHeap, 0, proc ) && (proc->magic == WINPROC_MAGIC)) - return proc; + if (is_valid_winproc(proc)) return proc; } return NULL; @@ -315,7 +348,7 @@ static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC func, WINDOWPROCTYPE type, /* Allocate a window procedure */ - if (!(proc = HeapAlloc( WinProcHeap, 0, sizeof(WINDOWPROC) ))) return 0; + if (!(proc = alloc_winproc())) return 0; /* Check if the function is already a win proc */ @@ -374,7 +407,7 @@ static WINDOWPROC *WINPROC_AllocWinProc( WNDPROC func, WINDOWPROCTYPE type, proc->user = user; } proc->next = NULL; - TRACE_(win)("(%p,%d): returning %p\n", func, type, proc ); + TRACE("(%p,%d): returning %p\n", func, type, proc ); return proc; } @@ -394,7 +427,8 @@ WNDPROC16 WINPROC_GetProc( WNDPROC proc, WINDOWPROCTYPE type ) if (ptr->type == WIN_PROC_16) return ptr->thunk.t_from32.proc; else - return (WNDPROC16)MAKESEGPTR( WinProcSel, (char *)&ptr->thunk - (char *)WinProcHeap ); + return (WNDPROC16)MAKESEGPTR( get_winproc_selector(), + (char *)&ptr->thunk - (char *)winproc_array ); } else /* We want a 32-bit address */ { @@ -501,8 +535,7 @@ BOOL WINPROC_SetProc( WNDPROC *pFirst, WNDPROC func, /* Add the win proc at the head of the list */ - TRACE_(win)("(%08x,%08x,%d): res=%08x\n", - (UINT)*pFirst, (UINT)func, type, (UINT)proc ); + TRACE("(%p,%p,%d): res=%p\n", *pFirst, func, type, proc ); proc->next = *(WINDOWPROC **)pFirst; *(WINDOWPROC **)pFirst = proc; return TRUE; @@ -521,8 +554,8 @@ void WINPROC_FreeProc( WNDPROC proc, WINDOWPROCUSER user ) { WINDOWPROC *next = ptr->next; if (ptr->user != user) break; - TRACE_(win)("freeing %p (%d)\n", ptr, user); - HeapFree( WinProcHeap, 0, ptr ); + TRACE("freeing %p (%d)\n", ptr, user); + free_winproc( ptr ); ptr = next; } } -- 2.11.4.GIT