Share the system heap between different address spaces. Made process
heap per-address space instead of per-process.
This commit is contained in:
parent
2fe57779fb
commit
079fd72ca7
|
@ -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_strdupAtoW( HANDLE heap, DWORD flags, LPCSTR str );
|
||||
extern LPSTR HEAP_strdupWtoA( HANDLE heap, DWORD flags, LPCWSTR str );
|
||||
extern BOOL HEAP_CreateSystemHeap(void);
|
||||
|
||||
/* SEGPTR helper macros */
|
||||
|
||||
|
@ -41,5 +42,18 @@ static inline SEGPTR WINE_UNUSED SEGPTR_Get(LPCVOID ptr) {
|
|||
#define SEGPTR_FREE(ptr) \
|
||||
(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 */
|
||||
|
|
|
@ -151,7 +151,7 @@ void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
|
|||
extern DWORD WINAPI MapProcessHandle( HANDLE handle );
|
||||
|
||||
/* scheduler/environ.c */
|
||||
extern BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env );
|
||||
extern BOOL ENV_InheritEnvironment( LPCSTR env );
|
||||
extern void ENV_FreeEnvironment( PDB *pdb );
|
||||
|
||||
/* scheduler/process.c */
|
||||
|
|
|
@ -117,6 +117,7 @@ typedef struct _SINGLE_LIST_ENTRY {
|
|||
#define HEAP_WINE_SEGPTR 0x01000000 /* 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_SHARED 0x08000000 /* Not a Win32 flag */
|
||||
|
||||
/* Processor feature flags. */
|
||||
#define PF_FLOATING_POINT_PRECISION_ERRATA 0
|
||||
|
|
|
@ -78,7 +78,7 @@ static BOOL ENV_BuildEnvironment( PDB *pdb )
|
|||
|
||||
/* 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;
|
||||
|
||||
/* 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
|
||||
* explicit environment.
|
||||
*/
|
||||
BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env )
|
||||
BOOL ENV_InheritEnvironment( LPCSTR env )
|
||||
{
|
||||
DWORD size;
|
||||
LPCSTR src;
|
||||
LPSTR dst;
|
||||
PDB *pdb = PROCESS_Current();
|
||||
|
||||
/* FIXME: should lock the parent environment */
|
||||
if (!env)
|
||||
|
@ -131,7 +132,7 @@ BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env )
|
|||
|
||||
/* Copy the environment */
|
||||
|
||||
if (!(pdb->env_db->environ = HeapAlloc( pdb->heap, 0, size )))
|
||||
if (!(pdb->env_db->environ = HeapAlloc( GetProcessHeap(), 0, size )))
|
||||
return FALSE;
|
||||
pdb->env_db->env_sel = SELECTOR_AllocBlock( pdb->env_db->environ,
|
||||
0x10000, SEGMENT_DATA,
|
||||
|
@ -162,7 +163,7 @@ void ENV_FreeEnvironment( PDB *pdb )
|
|||
if (!pdb->env_db) return;
|
||||
if (pdb->env_db->env_sel) SELECTOR_FreeBlock( pdb->env_db->env_sel, 1 );
|
||||
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();
|
||||
EnterCriticalSection( &pdb->env_db->section );
|
||||
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 );
|
||||
LeaveCriticalSection( &pdb->env_db->section );
|
||||
return pdb->env_db->cmd_lineW;
|
||||
|
@ -209,8 +210,8 @@ LPWSTR WINAPI GetEnvironmentStringsW(void)
|
|||
PDB *pdb = PROCESS_Current();
|
||||
|
||||
EnterCriticalSection( &pdb->env_db->section );
|
||||
size = HeapSize( pdb->heap, 0, pdb->env_db->environ );
|
||||
if ((ret = HeapAlloc( pdb->heap, 0, size * sizeof(WCHAR) )) != NULL)
|
||||
size = HeapSize( GetProcessHeap(), 0, pdb->env_db->environ );
|
||||
if ((ret = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )) != NULL)
|
||||
{
|
||||
LPSTR pA = pdb->env_db->environ;
|
||||
LPWSTR pW = ret;
|
||||
|
@ -323,13 +324,13 @@ BOOL WINAPI SetEnvironmentVariableA( LPCSTR name, LPCSTR value )
|
|||
|
||||
len = value ? strlen(name) + strlen(value) + 2 : 0;
|
||||
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)
|
||||
{
|
||||
LPSTR next = p + strlen(p) + 1; /* We know there is a next one */
|
||||
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;
|
||||
if (pdb->env_db->env_sel)
|
||||
SELECTOR_MoveBlock( pdb->env_db->env_sel, new_env );
|
||||
|
|
|
@ -206,7 +206,7 @@ HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
|
|||
size = (size + 0x1f) & ~0x1f;
|
||||
|
||||
/* Allocate the linear memory */
|
||||
ptr = HeapAlloc( SystemHeap, 0, size );
|
||||
ptr = HeapAlloc( GetProcessHeap(), 0, size );
|
||||
/* FIXME: free discardable blocks and try again? */
|
||||
if (!ptr) return 0;
|
||||
|
||||
|
@ -216,7 +216,7 @@ HGLOBAL16 GLOBAL_Alloc( UINT16 flags, DWORD size, HGLOBAL16 hOwner,
|
|||
isCode, is32Bit, isReadOnly, &shmdata);
|
||||
if (!handle)
|
||||
{
|
||||
HeapFree( SystemHeap, 0, ptr );
|
||||
HeapFree( GetProcessHeap(), 0, ptr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -276,7 +276,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
|
|||
if (!(pArena->flags & GA_MOVEABLE) ||
|
||||
!(pArena->flags & GA_DISCARDABLE) ||
|
||||
(pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
|
||||
HeapFree( SystemHeap, 0, (void *)pArena->base );
|
||||
HeapFree( GetProcessHeap(), 0, (void *)pArena->base );
|
||||
pArena->base = 0;
|
||||
|
||||
/* Note: we rely on the fact that SELECTOR_ReallocBlock won't
|
||||
|
@ -314,7 +314,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
|
|||
((char *)ptr <= DOSMEM_MemoryBase(0) + 0x100000))
|
||||
ptr = DOSMEM_ResizeBlock(0, ptr, size, NULL);
|
||||
else
|
||||
ptr = HeapReAlloc( SystemHeap, 0, ptr, size );
|
||||
ptr = HeapReAlloc( GetProcessHeap(), 0, ptr, size );
|
||||
if (!ptr)
|
||||
{
|
||||
SELECTOR_FreeBlock( sel, (oldsize + 0xffff) / 0x10000 );
|
||||
|
@ -327,7 +327,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
|
|||
sel = SELECTOR_ReallocBlock( sel, ptr, size );
|
||||
if (!sel)
|
||||
{
|
||||
HeapFree( SystemHeap, 0, ptr );
|
||||
HeapFree( GetProcessHeap(), 0, ptr );
|
||||
memset( pArena, 0, sizeof(GLOBALARENA) );
|
||||
return 0;
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
|
|||
|
||||
if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
|
||||
{
|
||||
HeapFree( SystemHeap, 0, ptr );
|
||||
HeapFree( GetProcessHeap(), 0, ptr );
|
||||
SELECTOR_FreeBlock( sel, selcount );
|
||||
return 0;
|
||||
}
|
||||
|
@ -376,7 +376,7 @@ HGLOBAL16 WINAPI GlobalFree16(
|
|||
|
||||
TRACE("%04x\n", handle );
|
||||
if (!GLOBAL_FreeBlock( handle )) return handle; /* failed */
|
||||
if (ptr) HeapFree( SystemHeap, 0, ptr );
|
||||
if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
146
memory/heap.c
146
memory/heap.c
|
@ -93,6 +93,7 @@ typedef struct tagHEAP
|
|||
CRITICAL_SECTION critSection; /* Critical section for serialization */
|
||||
DWORD flags; /* Heap flags */
|
||||
DWORD magic; /* Magic number */
|
||||
void *private; /* Private pointer for the user of the heap */
|
||||
} HEAP;
|
||||
|
||||
#define HEAP_MAGIC ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24)))
|
||||
|
@ -103,6 +104,14 @@ typedef struct tagHEAP
|
|||
HANDLE SystemHeap = 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 );
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -419,7 +428,7 @@ static void HEAP_MakeInUseBlockFree( SUBHEAP *subheap, ARENA_INUSE *pArena )
|
|||
|
||||
/* 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 */
|
||||
|
||||
if (flags & HEAP_WINE_SHARED)
|
||||
commitSize = totalSize; /* always commit everything in a shared heap */
|
||||
if (!VirtualAlloc(address, commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
|
||||
{
|
||||
WARN("Could not commit %08lx bytes for sub-heap %08lx\n",
|
||||
|
@ -1001,6 +1012,20 @@ HANDLE WINAPI HeapCreate(
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -1010,15 +1035,29 @@ HANDLE WINAPI HeapCreate(
|
|||
* TRUE: Success
|
||||
* FALSE: Failure
|
||||
*/
|
||||
BOOL WINAPI HeapDestroy(
|
||||
HANDLE heap /* [in] Handle of heap */
|
||||
) {
|
||||
BOOL WINAPI HeapDestroy( HANDLE heap /* [in] Handle of heap */ )
|
||||
{
|
||||
HEAP *heapPtr = HEAP_GetPtr( heap );
|
||||
SUBHEAP *subheap;
|
||||
|
||||
TRACE("%08x\n", heap );
|
||||
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 );
|
||||
subheap = &heapPtr->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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue