Share the system heap between different address spaces. Made process

heap per-address space instead of per-process.
This commit is contained in:
Alexandre Julliard 2000-01-25 01:41:35 +00:00 committed by Alexandre Julliard
parent 2fe57779fb
commit 079fd72ca7
6 changed files with 175 additions and 21 deletions

View File

@ -22,6 +22,7 @@ extern LPSTR HEAP_strdupA( HANDLE heap, DWORD flags, LPCSTR str );
extern LPWSTR HEAP_strdupW( HANDLE heap, DWORD flags, LPCWSTR str ); extern LPWSTR HEAP_strdupW( HANDLE heap, DWORD flags, LPCWSTR str );
extern LPWSTR HEAP_strdupAtoW( HANDLE heap, DWORD flags, LPCSTR str ); extern LPWSTR HEAP_strdupAtoW( HANDLE heap, DWORD flags, LPCSTR str );
extern LPSTR HEAP_strdupWtoA( HANDLE heap, DWORD flags, LPCWSTR str ); extern LPSTR HEAP_strdupWtoA( HANDLE heap, DWORD flags, LPCWSTR str );
extern BOOL HEAP_CreateSystemHeap(void);
/* SEGPTR helper macros */ /* SEGPTR helper macros */
@ -41,5 +42,18 @@ static inline SEGPTR WINE_UNUSED SEGPTR_Get(LPCVOID ptr) {
#define SEGPTR_FREE(ptr) \ #define SEGPTR_FREE(ptr) \
(HIWORD(ptr) ? HeapFree( SegptrHeap, 0, (ptr) ) : 0) (HIWORD(ptr) ? HeapFree( SegptrHeap, 0, (ptr) ) : 0)
/* system heap private data */
/* you must lock the system heap before using this structure */
typedef struct
{
void *gdi; /* GDI heap */
void *user; /* USER handle table */
void *cursor; /* cursor information */
void *queue; /* message queues descriptor */
void *win; /* windows descriptor */
void *root; /* X11 root window */
} SYSTEM_HEAP_DESCR;
extern SYSTEM_HEAP_DESCR *SystemHeapDescr;
#endif /* __WINE_HEAP_H */ #endif /* __WINE_HEAP_H */

View File

@ -151,7 +151,7 @@ void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
extern DWORD WINAPI MapProcessHandle( HANDLE handle ); extern DWORD WINAPI MapProcessHandle( HANDLE handle );
/* scheduler/environ.c */ /* scheduler/environ.c */
extern BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env ); extern BOOL ENV_InheritEnvironment( LPCSTR env );
extern void ENV_FreeEnvironment( PDB *pdb ); extern void ENV_FreeEnvironment( PDB *pdb );
/* scheduler/process.c */ /* scheduler/process.c */

View File

@ -117,6 +117,7 @@ typedef struct _SINGLE_LIST_ENTRY {
#define HEAP_WINE_SEGPTR 0x01000000 /* Not a Win32 flag */ #define HEAP_WINE_SEGPTR 0x01000000 /* Not a Win32 flag */
#define HEAP_WINE_CODESEG 0x02000000 /* Not a Win32 flag */ #define HEAP_WINE_CODESEG 0x02000000 /* Not a Win32 flag */
#define HEAP_WINE_CODE16SEG 0x04000000 /* Not a Win32 flag */ #define HEAP_WINE_CODE16SEG 0x04000000 /* Not a Win32 flag */
#define HEAP_WINE_SHARED 0x08000000 /* Not a Win32 flag */
/* Processor feature flags. */ /* Processor feature flags. */
#define PF_FLOATING_POINT_PRECISION_ERRATA 0 #define PF_FLOATING_POINT_PRECISION_ERRATA 0

View File

@ -78,7 +78,7 @@ static BOOL ENV_BuildEnvironment( PDB *pdb )
/* Now allocate the environment */ /* Now allocate the environment */
if (!(p = HeapAlloc( SystemHeap, 0, size ))) return FALSE; if (!(p = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE;
pdb->env_db->environ = p; pdb->env_db->environ = p;
/* And fill it with the Unix environment */ /* And fill it with the Unix environment */
@ -102,11 +102,12 @@ static BOOL ENV_BuildEnvironment( PDB *pdb )
* Make a process inherit the environment from its parent or from an * Make a process inherit the environment from its parent or from an
* explicit environment. * explicit environment.
*/ */
BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env ) BOOL ENV_InheritEnvironment( LPCSTR env )
{ {
DWORD size; DWORD size;
LPCSTR src; LPCSTR src;
LPSTR dst; LPSTR dst;
PDB *pdb = PROCESS_Current();
/* FIXME: should lock the parent environment */ /* FIXME: should lock the parent environment */
if (!env) if (!env)
@ -131,7 +132,7 @@ BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env )
/* Copy the environment */ /* Copy the environment */
if (!(pdb->env_db->environ = HeapAlloc( pdb->heap, 0, size ))) if (!(pdb->env_db->environ = HeapAlloc( GetProcessHeap(), 0, size )))
return FALSE; return FALSE;
pdb->env_db->env_sel = SELECTOR_AllocBlock( pdb->env_db->environ, pdb->env_db->env_sel = SELECTOR_AllocBlock( pdb->env_db->environ,
0x10000, SEGMENT_DATA, 0x10000, SEGMENT_DATA,
@ -162,7 +163,7 @@ void ENV_FreeEnvironment( PDB *pdb )
if (!pdb->env_db) return; if (!pdb->env_db) return;
if (pdb->env_db->env_sel) SELECTOR_FreeBlock( pdb->env_db->env_sel, 1 ); if (pdb->env_db->env_sel) SELECTOR_FreeBlock( pdb->env_db->env_sel, 1 );
DeleteCriticalSection( &pdb->env_db->section ); DeleteCriticalSection( &pdb->env_db->section );
HeapFree( pdb->heap, 0, pdb->env_db ); /* the storage will be deleted when the process heap is destroyed */
} }
@ -182,7 +183,7 @@ LPCWSTR WINAPI GetCommandLineW(void)
PDB *pdb = PROCESS_Current(); PDB *pdb = PROCESS_Current();
EnterCriticalSection( &pdb->env_db->section ); EnterCriticalSection( &pdb->env_db->section );
if (!pdb->env_db->cmd_lineW) if (!pdb->env_db->cmd_lineW)
pdb->env_db->cmd_lineW = HEAP_strdupAtoW( pdb->heap, 0, pdb->env_db->cmd_lineW = HEAP_strdupAtoW( GetProcessHeap(), 0,
pdb->env_db->cmd_line ); pdb->env_db->cmd_line );
LeaveCriticalSection( &pdb->env_db->section ); LeaveCriticalSection( &pdb->env_db->section );
return pdb->env_db->cmd_lineW; return pdb->env_db->cmd_lineW;
@ -209,8 +210,8 @@ LPWSTR WINAPI GetEnvironmentStringsW(void)
PDB *pdb = PROCESS_Current(); PDB *pdb = PROCESS_Current();
EnterCriticalSection( &pdb->env_db->section ); EnterCriticalSection( &pdb->env_db->section );
size = HeapSize( pdb->heap, 0, pdb->env_db->environ ); size = HeapSize( GetProcessHeap(), 0, pdb->env_db->environ );
if ((ret = HeapAlloc( pdb->heap, 0, size * sizeof(WCHAR) )) != NULL) if ((ret = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )) != NULL)
{ {
LPSTR pA = pdb->env_db->environ; LPSTR pA = pdb->env_db->environ;
LPWSTR pW = ret; LPWSTR pW = ret;
@ -323,13 +324,13 @@ BOOL WINAPI SetEnvironmentVariableA( LPCSTR name, LPCSTR value )
len = value ? strlen(name) + strlen(value) + 2 : 0; len = value ? strlen(name) + strlen(value) + 2 : 0;
if (*p) len -= strlen(p) + 1; /* The name already exists */ if (*p) len -= strlen(p) + 1; /* The name already exists */
old_size = HeapSize( pdb->heap, 0, env ); old_size = HeapSize( GetProcessHeap(), 0, env );
if (len < 0) if (len < 0)
{ {
LPSTR next = p + strlen(p) + 1; /* We know there is a next one */ LPSTR next = p + strlen(p) + 1; /* We know there is a next one */
memmove( next + len, next, old_size - (next - env) ); memmove( next + len, next, old_size - (next - env) );
} }
if (!(new_env = HeapReAlloc( pdb->heap, 0, env, old_size + len ))) if (!(new_env = HeapReAlloc( GetProcessHeap(), 0, env, old_size + len )))
goto done; goto done;
if (pdb->env_db->env_sel) if (pdb->env_db->env_sel)
SELECTOR_MoveBlock( pdb->env_db->env_sel, new_env ); SELECTOR_MoveBlock( pdb->env_db->env_sel, new_env );

View File

@ -206,7 +206,7 @@ HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
size = (size + 0x1f) & ~0x1f; size = (size + 0x1f) & ~0x1f;
/* Allocate the linear memory */ /* Allocate the linear memory */
ptr = HeapAlloc( SystemHeap, 0, size ); ptr = HeapAlloc( GetProcessHeap(), 0, size );
/* FIXME: free discardable blocks and try again? */ /* FIXME: free discardable blocks and try again? */
if (!ptr) return 0; if (!ptr) return 0;
@ -216,7 +216,7 @@ HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
isCode, is32Bit, isReadOnly, &shmdata); isCode, is32Bit, isReadOnly, &shmdata);
if (!handle) if (!handle)
{ {
HeapFree( SystemHeap, 0, ptr ); HeapFree( GetProcessHeap(), 0, ptr );
return 0; return 0;
} }
@ -276,7 +276,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
if (!(pArena->flags & GA_MOVEABLE) || if (!(pArena->flags & GA_MOVEABLE) ||
!(pArena->flags & GA_DISCARDABLE) || !(pArena->flags & GA_DISCARDABLE) ||
(pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0; (pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
HeapFree( SystemHeap, 0, (void *)pArena->base ); HeapFree( GetProcessHeap(), 0, (void *)pArena->base );
pArena->base = 0; pArena->base = 0;
/* Note: we rely on the fact that SELECTOR_ReallocBlock won't /* Note: we rely on the fact that SELECTOR_ReallocBlock won't
@ -314,7 +314,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
((char *)ptr <= DOSMEM_MemoryBase(0) + 0x100000)) ((char *)ptr <= DOSMEM_MemoryBase(0) + 0x100000))
ptr = DOSMEM_ResizeBlock(0, ptr, size, NULL); ptr = DOSMEM_ResizeBlock(0, ptr, size, NULL);
else else
ptr = HeapReAlloc( SystemHeap, 0, ptr, size ); ptr = HeapReAlloc( GetProcessHeap(), 0, ptr, size );
if (!ptr) if (!ptr)
{ {
SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 ); SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 );
@ -327,7 +327,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
sel = SELECTOR_ReallocBlock( sel, ptr, size ); sel = SELECTOR_ReallocBlock( sel, ptr, size );
if (!sel) if (!sel)
{ {
HeapFree( SystemHeap, 0, ptr ); HeapFree( GetProcessHeap(), 0, ptr );
memset( pArena, 0, sizeof(GLOBALARENA) ); memset( pArena, 0, sizeof(GLOBALARENA) );
return 0; return 0;
} }
@ -335,7 +335,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
if (!(pNewArena = GLOBAL_GetArena( sel, selcount ))) if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
{ {
HeapFree( SystemHeap, 0, ptr ); HeapFree( GetProcessHeap(), 0, ptr );
SELECTOR_FreeBlock( sel, selcount ); SELECTOR_FreeBlock( sel, selcount );
return 0; return 0;
} }
@ -376,7 +376,7 @@ HGLOBAL16 WINAPI GlobalFree16(
TRACE("%04x\n", handle ); TRACE("%04x\n", handle );
if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */ if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */
if (ptr) HeapFree( SystemHeap, 0, ptr ); if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
return 0; return 0;
} }

View File

@ -93,6 +93,7 @@ typedef struct tagHEAP
CRITICAL_SECTION critSection; /* Critical section for serialization */ CRITICAL_SECTION critSection; /* Critical section for serialization */
DWORD flags; /* Heap flags */ DWORD flags; /* Heap flags */
DWORD magic; /* Magic number */ DWORD magic; /* Magic number */
void *private; /* Private pointer for the user of the heap */
} HEAP; } HEAP;
#define HEAP_MAGIC ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24))) #define HEAP_MAGIC ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24)))
@ -103,6 +104,14 @@ typedef struct tagHEAP
HANDLE SystemHeap = 0; HANDLE SystemHeap = 0;
HANDLE SegptrHeap = 0; HANDLE SegptrHeap = 0;
SYSTEM_HEAP_DESCR *SystemHeapDescr = 0;
static HEAP *processHeap; /* main process heap */
static HEAP *firstHeap; /* head of secondary heaps list */
/* address where we try to map the system heap */
#define SYSTEM_HEAP_BASE ((void*)0x65430000)
static BOOL HEAP_IsRealArena( HANDLE heap, DWORD flags, LPCVOID block, BOOL quiet ); static BOOL HEAP_IsRealArena( HANDLE heap, DWORD flags, LPCVOID block, BOOL quiet );
#ifdef __GNUC__ #ifdef __GNUC__
@ -419,7 +428,7 @@ static void HEAP_MakeInUseBlockFree( SUBHEAP *subheap, ARENA_INUSE *pArena )
/* Decommit the end of the heap */ /* Decommit the end of the heap */
HEAP_Decommit( subheap, pFree + 1 ); if (!(subheap->heap->flags & HEAP_WINE_SHARED)) HEAP_Decommit( subheap, pFree + 1 );
} }
@ -458,6 +467,8 @@ static BOOL HEAP_InitSubHeap( HEAP *heap, LPVOID address, DWORD flags,
/* Commit memory */ /* Commit memory */
if (flags & HEAP_WINE_SHARED)
commitSize = totalSize; /* always commit everything in a shared heap */
if (!VirtualAlloc(address, commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) if (!VirtualAlloc(address, commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
{ {
WARN("Could not commit %08lx bytes for sub-heap %08lx\n", WARN("Could not commit %08lx bytes for sub-heap %08lx\n",
@ -1001,6 +1012,20 @@ HANDLE WINAPI HeapCreate(
return 0; return 0;
} }
/* link it into the per-process heap list */
if (processHeap)
{
HEAP *heapPtr = subheap->heap;
EnterCriticalSection( &processHeap->critSection );
heapPtr->next = firstHeap;
firstHeap = heapPtr;
LeaveCriticalSection( &processHeap->critSection );
}
else /* assume the first heap we create is the process main heap */
{
processHeap = subheap->heap;
}
return (HANDLE)subheap; return (HANDLE)subheap;
} }
@ -1010,15 +1035,29 @@ HANDLE WINAPI HeapCreate(
* TRUE: Success * TRUE: Success
* FALSE: Failure * FALSE: Failure
*/ */
BOOL WINAPI HeapDestroy( BOOL WINAPI HeapDestroy( HANDLE heap /* [in] Handle of heap */ )
HANDLE heap /* [in] Handle of heap */ {
) {
HEAP *heapPtr = HEAP_GetPtr( heap ); HEAP *heapPtr = HEAP_GetPtr( heap );
SUBHEAP *subheap; SUBHEAP *subheap;
TRACE("%08x\n", heap ); TRACE("%08x\n", heap );
if (!heapPtr) return FALSE; if (!heapPtr) return FALSE;
if (heapPtr == processHeap) /* cannot delete the main process heap */
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
else /* remove it from the per-process list */
{
HEAP **pptr;
EnterCriticalSection( &processHeap->critSection );
pptr = &firstHeap;
while (*pptr && *pptr != heapPtr) pptr = &(*pptr)->next;
if (*pptr) *pptr = (*pptr)->next;
LeaveCriticalSection( &processHeap->critSection );
}
DeleteCriticalSection( &heapPtr->critSection ); DeleteCriticalSection( &heapPtr->critSection );
subheap = &heapPtr->subheap; subheap = &heapPtr->subheap;
while (subheap) while (subheap)
@ -1390,6 +1429,105 @@ BOOL WINAPI HeapWalk(
} }
/***********************************************************************
* HEAP_CreateSystemHeap
*
* Create the system heap.
*/
BOOL HEAP_CreateSystemHeap(void)
{
SYSTEM_HEAP_DESCR *descr;
HANDLE heap;
HEAP *heapPtr;
int created;
HANDLE map = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE,
0, HEAP_DEF_SIZE, "__SystemHeap" );
if (!map) return FALSE;
created = (GetLastError() != ERROR_ALREADY_EXISTS);
if (!(heapPtr = MapViewOfFileEx( map, FILE_MAP_ALL_ACCESS, 0, 0, 0, SYSTEM_HEAP_BASE )))
{
/* pre-defined address not available, use any one */
fprintf( stderr, "Warning: system heap base address %p not available\n",
SYSTEM_HEAP_BASE );
if (!(heapPtr = MapViewOfFile( map, FILE_MAP_ALL_ACCESS, 0, 0, 0 )))
{
CloseHandle( map );
return FALSE;
}
}
heap = (HANDLE)heapPtr;
if (created) /* newly created heap */
{
HEAP_InitSubHeap( heapPtr, heapPtr, HEAP_WINE_SHARED, 0, HEAP_DEF_SIZE );
HeapLock( heap );
descr = heapPtr->private = HeapAlloc( heap, HEAP_ZERO_MEMORY, sizeof(*descr) );
assert( descr );
}
else
{
/* wait for the heap to be initialized */
while (!heapPtr->private) Sleep(1);
HeapLock( heap );
/* remap it to the right address if necessary */
if (heapPtr->subheap.heap != heapPtr)
{
void *base = heapPtr->subheap.heap;
HeapUnlock( heap );
UnmapViewOfFile( heapPtr );
if (!(heapPtr = MapViewOfFileEx( map, FILE_MAP_ALL_ACCESS, 0, 0, 0, base )))
{
fprintf( stderr, "Couldn't map system heap at the correct address (%p)\n", base );
CloseHandle( map );
return FALSE;
}
heap = (HANDLE)heapPtr;
HeapLock( heap );
}
descr = heapPtr->private;
assert( descr );
}
SystemHeap = heap;
SystemHeapDescr = descr;
HeapUnlock( heap );
CloseHandle( map );
return TRUE;
}
/***********************************************************************
* GetProcessHeap (KERNEL32.259)
*/
HANDLE WINAPI GetProcessHeap(void)
{
return (HANDLE)processHeap;
}
/***********************************************************************
* GetProcessHeaps (KERNEL32.376)
*/
DWORD WINAPI GetProcessHeaps( DWORD count, HANDLE *heaps )
{
DWORD total;
HEAP *ptr;
if (!processHeap) return 0; /* should never happen */
total = 1; /* main heap */
EnterCriticalSection( &processHeap->critSection );
for (ptr = firstHeap; ptr; ptr = ptr->next) total++;
if (total <= count)
{
*heaps++ = (HANDLE)processHeap;
for (ptr = firstHeap; ptr; ptr = ptr->next) *heaps++ = (HANDLE)ptr;
}
LeaveCriticalSection( &processHeap->critSection );
return total;
}
/*********************************************************************** /***********************************************************************
* HEAP_xalloc * HEAP_xalloc
* *