Commit 079fd72c authored by Alexandre Julliard's avatar Alexandre Julliard Committed by Alexandre Julliard

Share the system heap between different address spaces. Made process

heap per-address space instead of per-process.
parent 2fe57779
......@@ -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)
......@@ -1391,6 +1430,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
*
* Same as HeapAlloc(), but die on failure.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment