Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
Glasgow Haskell Compiler
GHC
Commits
3fb074b5
Commit
3fb074b5
authored
Aug 13, 2010
by
Ian Lynagh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Return memory to the OS; trac
#698
parent
429dc9a0
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
132 additions
and
41 deletions
+132
-41
includes/rts/storage/MBlock.h
includes/rts/storage/MBlock.h
+2
-2
rts/Stats.c
rts/Stats.c
+1
-1
rts/posix/OSMem.c
rts/posix/OSMem.c
+10
-24
rts/sm/BlockAlloc.c
rts/sm/BlockAlloc.c
+34
-0
rts/sm/BlockAlloc.h
rts/sm/BlockAlloc.h
+1
-0
rts/sm/GC.c
rts/sm/GC.c
+13
-0
rts/sm/MBlock.c
rts/sm/MBlock.c
+34
-14
rts/sm/OSMem.h
rts/sm/OSMem.h
+1
-0
rts/win32/OSMem.c
rts/win32/OSMem.c
+36
-0
No files found.
includes/rts/storage/MBlock.h
View file @
3fb074b5
...
...
@@ -12,17 +12,17 @@
#ifndef RTS_STORAGE_MBLOCK_H
#define RTS_STORAGE_MBLOCK_H
extern
lnat
peak_mblocks_allocated
;
extern
lnat
mblocks_allocated
;
extern
void
initMBlocks
(
void
);
extern
void
*
getMBlock
(
void
);
extern
void
*
getMBlocks
(
nat
n
);
extern
void
freeMBlocks
(
void
*
addr
,
nat
n
);
extern
void
freeAllMBlocks
(
void
);
#ifdef DEBUG
extern
void
*
getFirstMBlock
(
void
);
extern
void
*
getNextMBlock
(
void
*
mblock
);
#endif
#ifdef THREADED_RTS
// needed for HEAP_ALLOCED below
...
...
rts/Stats.c
View file @
3fb074b5
...
...
@@ -741,7 +741,7 @@ stat_exit(int alloc)
AvgResidency
*
sizeof
(
W_
)
/
ResidencySamples
,
MaxResidency
*
sizeof
(
W_
),
ResidencySamples
,
(
unsigned
long
)(
mblocks_allocated
*
MBLOCK_SIZE
/
(
1024L
*
1024L
)),
(
unsigned
long
)(
peak_
mblocks_allocated
*
MBLOCK_SIZE
/
(
1024L
*
1024L
)),
TICK_TO_DBL
(
InitUserTime
),
TICK_TO_DBL
(
InitElapsedTime
),
TICK_TO_DBL
(
MutUserTime
),
TICK_TO_DBL
(
MutElapsedTime
),
TICK_TO_DBL
(
GC_tot_time
),
TICK_TO_DBL
(
GCe_tot_time
));
...
...
rts/posix/OSMem.c
View file @
3fb074b5
...
...
@@ -37,16 +37,7 @@
#include <mach/vm_map.h>
#endif
/* keep track of maps returned by my_mmap */
typedef
struct
_map_rec
{
char
*
base
;
/* base addr */
int
size
;
/* map size */
struct
_map_rec
*
next
;
/* next pointer */
}
map_rec
;
static
caddr_t
next_request
=
0
;
static
map_rec
*
mmap_rec
=
NULL
;
void
osMemInit
(
void
)
{
...
...
@@ -187,7 +178,6 @@ osGetMBlocks(nat n)
{
caddr_t
ret
;
lnat
size
=
MBLOCK_SIZE
*
(
lnat
)
n
;
map_rec
*
rec
;
if
(
next_request
==
0
)
{
// use gen_map_mblocks the first time.
...
...
@@ -209,11 +199,6 @@ osGetMBlocks(nat n)
ret
=
gen_map_mblocks
(
size
);
}
}
rec
=
(
map_rec
*
)
stgMallocBytes
(
sizeof
(
map_rec
),
"OSMem: osGetMBlocks"
);
rec
->
size
=
size
;
rec
->
base
=
ret
;
rec
->
next
=
mmap_rec
;
mmap_rec
=
rec
;
// Next time, we'll try to allocate right after the block we just got.
// ToDo: check that we haven't already grabbed the memory at next_request
next_request
=
ret
+
size
;
...
...
@@ -221,18 +206,19 @@ osGetMBlocks(nat n)
return
ret
;
}
void
osFree
All
MBlocks
(
void
)
void
osFreeMBlocks
(
char
*
addr
,
nat
n
)
{
m
ap_rec
*
tmp
=
mmap_rec
;
map_rec
*
next
=
NULL
;
m
unmap
(
addr
,
n
*
MBLOCK_SIZE
)
;
}
for
(;
tmp
!=
NULL
;)
{
if
(
munmap
(
tmp
->
base
,
tmp
->
size
))
barf
(
"osFreeAllMBlocks: munmap failed!"
)
;
void
osFreeAllMBlocks
(
void
)
{
void
*
mblock
;
next
=
tmp
->
next
;
stgFree
(
tmp
);
tmp
=
next
;
for
(
mblock
=
getFirstMBlock
();
mblock
!=
NULL
;
mblock
=
getNextMBlock
(
mblock
))
{
munmap
(
mblock
,
MBLOCK_SIZE
);
}
}
...
...
rts/sm/BlockAlloc.c
View file @
3fb074b5
...
...
@@ -21,6 +21,7 @@
#include "Storage.h"
#include "RtsUtils.h"
#include "BlockAlloc.h"
#include "OSMem.h"
#include <string.h>
...
...
@@ -671,6 +672,39 @@ countAllocdBlocks(bdescr *bd)
return
n
;
}
void
returnMemoryToOS
(
nat
n
/* megablocks */
)
{
static
bdescr
*
bd
;
nat
size
;
bd
=
free_mblock_list
;
while
((
n
>
0
)
&&
(
bd
!=
NULL
))
{
size
=
BLOCKS_TO_MBLOCKS
(
bd
->
blocks
);
if
(
size
>
n
)
{
nat
newSize
=
size
-
n
;
char
*
freeAddr
=
MBLOCK_ROUND_DOWN
(
bd
->
start
);
freeAddr
+=
newSize
*
MBLOCK_SIZE
;
bd
->
blocks
=
MBLOCK_GROUP_BLOCKS
(
newSize
);
freeMBlocks
(
freeAddr
,
n
);
n
=
0
;
}
else
{
char
*
freeAddr
=
MBLOCK_ROUND_DOWN
(
bd
->
start
);
n
-=
size
;
bd
=
bd
->
link
;
freeMBlocks
(
freeAddr
,
size
);
}
}
free_mblock_list
=
bd
;
IF_DEBUG
(
gc
,
if
(
n
!=
0
)
{
debugBelch
(
"Wanted to free %d more MBlocks than are freeable
\n
"
,
n
);
}
);
}
/* -----------------------------------------------------------------------------
Debugging
-------------------------------------------------------------------------- */
...
...
rts/sm/BlockAlloc.h
View file @
3fb074b5
...
...
@@ -15,6 +15,7 @@
extern
nat
countBlocks
(
bdescr
*
bd
);
extern
nat
countAllocdBlocks
(
bdescr
*
bd
);
extern
void
returnMemoryToOS
(
nat
n
);
#ifdef DEBUG
void
checkFreeListSanity
(
void
);
...
...
rts/sm/GC.c
View file @
3fb074b5
...
...
@@ -746,6 +746,19 @@ SET_GCT(gc_threads[0]);
scheduleFinalizers
(
cap
,
old_weak_ptr_list
);
ACQUIRE_SM_LOCK
;
if
(
major_gc
)
{
nat
need
,
got
;
need
=
BLOCKS_TO_MBLOCKS
(
n_alloc_blocks
);
got
=
mblocks_allocated
;
/* If the amount of data remains constant, next major GC we'll
require (F+1)*need. We leave (F+2)*need in order to reduce
repeated deallocation and reallocation. */
need
=
(
RtsFlags
.
GcFlags
.
oldGenFactor
+
2
)
*
need
;
if
(
got
>
need
)
{
returnMemoryToOS
(
got
-
need
);
}
}
// check sanity after GC
IF_DEBUG
(
sanity
,
checkSanity
(
rtsTrue
));
...
...
rts/sm/MBlock.c
View file @
3fb074b5
...
...
@@ -18,6 +18,7 @@
#include <string.h>
lnat
peak_mblocks_allocated
=
0
;
lnat
mblocks_allocated
=
0
;
lnat
mpc_misses
=
0
;
...
...
@@ -29,9 +30,9 @@ lnat mpc_misses = 0;
StgWord8
mblock_map
[
MBLOCK_MAP_SIZE
];
// initially all zeros
static
void
mark
HeapAlloced
(
void
*
p
)
set
HeapAlloced
(
void
*
p
,
StgWord8
i
)
{
mblock_map
[
MBLOCK_MAP_ENTRY
(
p
)]
=
1
;
mblock_map
[
MBLOCK_MAP_ENTRY
(
p
)]
=
i
;
}
#elif SIZEOF_VOID_P == 8
...
...
@@ -81,7 +82,7 @@ StgBool HEAP_ALLOCED_miss(StgWord mblock, void *p)
}
static
void
mark
HeapAlloced
(
void
*
p
)
set
HeapAlloced
(
void
*
p
,
StgWord8
i
)
{
MBlockMap
*
map
=
findMBlockMap
(
p
);
if
(
map
==
NULL
)
...
...
@@ -95,7 +96,7 @@ markHeapAlloced(void *p)
map
->
addrHigh32
=
(
StgWord32
)
(((
StgWord
)
p
)
>>
32
);
}
map
->
lines
[
MBLOCK_MAP_LINE
(
p
)]
=
1
;
map
->
lines
[
MBLOCK_MAP_LINE
(
p
)]
=
i
;
{
StgWord
mblock
;
...
...
@@ -103,19 +104,22 @@ markHeapAlloced(void *p)
mblock
=
(
StgWord
)
p
>>
MBLOCK_SHIFT
;
entry_no
=
mblock
&
(
MBC_ENTRIES
-
1
);
mblock_cache
[
entry_no
]
=
(
mblock
<<
1
)
+
1
;
mblock_cache
[
entry_no
]
=
(
mblock
<<
1
)
+
i
;
}
}
#endif
/* ----------------------------------------------------------------------------
Debugging code for traversing the allocated MBlocks
This is used for searching for lost blocks when a memory leak is
detected; see Blocks.c:findUnmarkedBlock().
------------------------------------------------------------------------ */
static
void
markHeapAlloced
(
void
*
p
)
{
setHeapAlloced
(
p
,
1
);
}
#ifdef DEBUG
static
void
markHeapUnalloced
(
void
*
p
)
{
setHeapAlloced
(
p
,
0
);
}
#if SIZEOF_VOID_P == 4
...
...
@@ -207,8 +211,6 @@ void * getFirstMBlock(void)
#endif // SIZEOF_VOID_P
#endif // DEBUG
/* -----------------------------------------------------------------------------
Allocate new mblock(s)
-------------------------------------------------------------------------- */
...
...
@@ -238,13 +240,31 @@ getMBlocks(nat n)
}
mblocks_allocated
+=
n
;
peak_mblocks_allocated
=
stg_max
(
peak_mblocks_allocated
,
mblocks_allocated
);
return
ret
;
}
void
freeMBlocks
(
void
*
addr
,
nat
n
)
{
nat
i
;
debugTrace
(
DEBUG_gc
,
"freeing %d megablock(s) at %p"
,
n
,
addr
);
mblocks_allocated
-=
n
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
markHeapUnalloced
(
(
StgWord8
*
)
addr
+
i
*
MBLOCK_SIZE
);
}
osFreeMBlocks
(
addr
,
n
);
}
void
freeAllMBlocks
(
void
)
{
debugTrace
(
DEBUG_gc
,
"freeing all megablocks"
);
osFreeAllMBlocks
();
}
...
...
rts/sm/OSMem.h
View file @
3fb074b5
...
...
@@ -13,6 +13,7 @@
void
osMemInit
(
void
);
void
*
osGetMBlocks
(
nat
n
);
void
osFreeMBlocks
(
char
*
addr
,
nat
n
);
void
osFreeAllMBlocks
(
void
);
lnat
getPageSize
(
void
);
void
setExecutable
(
void
*
p
,
lnat
len
,
rtsBool
exec
);
...
...
rts/win32/OSMem.c
View file @
3fb074b5
...
...
@@ -203,6 +203,42 @@ osGetMBlocks(nat n) {
return
ret
;
}
void
osFreeMBlocks
(
char
*
addr
,
nat
n
)
{
alloc_rec
*
p
;
lnat
nBytes
=
(
lnat
)
n
*
MBLOCK_SIZE
;
insertFree
(
addr
,
nBytes
);
p
=
allocs
;
while
((
p
!=
NULL
)
&&
(
addr
>=
(
p
->
base
+
p
->
size
)))
{
p
=
p
->
next
;
}
while
(
nBytes
>
0
)
{
if
((
p
==
NULL
)
||
(
p
->
base
>
addr
))
{
errorBelch
(
"Memory to be freed isn't allocated
\n
"
);
stg_exit
(
EXIT_FAILURE
);
}
if
(
p
->
base
+
p
->
size
>=
addr
+
nBytes
)
{
if
(
!
VirtualFree
(
addr
,
nBytes
,
MEM_DECOMMIT
))
{
sysErrorBelch
(
"osFreeMBlocks: VirtualFree MEM_DECOMMIT failed"
);
stg_exit
(
EXIT_FAILURE
);
}
nBytes
=
0
;
}
else
{
lnat
bytesToFree
=
p
->
base
+
p
->
size
-
addr
;
if
(
!
VirtualFree
(
addr
,
bytesToFree
,
MEM_DECOMMIT
))
{
sysErrorBelch
(
"osFreeMBlocks: VirtualFree MEM_DECOMMIT failed"
);
stg_exit
(
EXIT_FAILURE
);
}
addr
+=
bytesToFree
;
nBytes
-=
bytesToFree
;
p
=
p
->
next
;
}
}
}
void
osFreeAllMBlocks
(
void
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment