Skip to content
Snippets Groups Projects
Commit 079fd72c authored by Alexandre Julliard's avatar Alexandre Julliard Committed by Alexandre Julliard
Browse files

Share the system heap between different address spaces. Made process

heap per-address space instead of per-process.
parent 2fe57779
Branches
Tags
No related merge requests found
......@@ -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;
}
......
......@@ -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
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment