[m-rev.] For review: Make improvements to stack segments code.
Paul Bone
pbone at csse.unimelb.edu.au
Mon Jun 7 22:07:53 AEST 2010
On Mon, Jun 07, 2010 at 12:41:07AM +1000, Julien Fischer wrote:
>
> Hi Paul,
>
> Here are some initial comments on this change.
>
> On Thu, 27 May 2010, Paul Bone wrote:
>
>> MR_create_or_reuse_zone (formerly MR_create_zone) checks for a free zone
>> of at least the required size before allocating a new one. When zones are
>> released they are put on the free list. Garbage collection of free zones
>> is not yet implemented.
>
> Will the garbage collector still scan the memory zones on the free list?
> (Not free the zones could be problematic in trail segment grades because
> if part of the program does something that allocates a lot of trail
> segments, we may end up with a lot of memory zones sitting on the free
> list after the commit; this may tie up memory that may be needed by
> later parts of the program.)
Yes, Boehm will scan these memory segments. I will allow these to be freed in
a future change.
>> As above MR_create_zone is now MR_create_or_reuse_zone,
>>
>> MR_unget_zone is now MR_release_zone.
>>
>> MR_construct_zone has been removed.
>
> Say why, i.e. it is no longer required.
>
MR_construct_zone has been removed, it was only ever called by MR_create_or_reuse_zone. MR_create_or_reuse_zone now contains the code for
MR_construct_zone.
>> error handlers.
>>
>> Do better locking on the free_memory_zones and used_memory_zones lists.
>
> Better locking in what sense?
>
Updates to used_memory_zones now use a pthread mutex so that only one
thread may be updating the list at once. This lock is shared with the
free_memory_zones structure.
>> Make sure that list modification makes memory writes in a clear order so
>> that the lists are always well formed.
I re-wrote this:
Updates to used_memory_zones now use memory barriers to guarantee that
concurrent reads always read a consistent, but possibly incomplete,
data-structure. This is necessary because it is read from a signal handler
which cannot call pthread_mutex().
>> Index: runtime/mercury_memory_zones.c
>> ===================================================================
>> RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.c,v
>> retrieving revision 1.36
>> diff -u -p -b -r1.36 mercury_memory_zones.c
>> --- runtime/mercury_memory_zones.c 13 Feb 2010 07:29:10 -0000 1.36
>> +++ runtime/mercury_memory_zones.c 27 May 2010 01:31:04 -0000
>> @@ -63,8 +63,14 @@
>>
>> #ifdef MR_THREAD_SAFE
>> #include "mercury_thread.h"
>> + #include "mercury_atomic_ops.h"
>> #endif
>>
>> +#include "mercury_memory_handlers.h"
>> +
>> +/*
>> +** Why is this included here and not above with the other system includes?
>> +*/
>
> Did you leave out an XXX there?
Yes,
>> @@ -469,12 +553,92 @@ MR_unget_zone(MR_MemoryZone *zone)
>> } else {
>> prev->MR_zone_next = tmp->MR_zone_next;
>> }
>> + MR_UNLOCK(&memory_zones_lock, "remove_zone_frm_used_list");
>> +}
>> +
>> +static void
>> +MR_return_zone_to_free_list(MR_MemoryZone *zone)
>> +{
>> + MR_MemoryZonesFree *tmp_list;
>
> Please use a more meaningful name than tmp_list.
/* The current list in iterations over the list of free lists */
MR_MemoryZonesFree *cur_list;
>
>> + size_t size;
>> +
>> + size = get_zone_alloc_size(zone);
>> +
>> + MR_LOCK(&memory_zones_lock, "ireturn_zone_to_free_list");
>
> ireturn?
>
I must have typeod this and not spotted it.
>> -MR_MemoryZone *
>> -MR_construct_zone(const char *name, int id, MR_Word *base,
>> - size_t size, size_t offset, size_t redsize, MR_ZoneHandler handler)
>> +static MR_MemoryZone *
>> +MR_create_new_zone(size_t desired_size, size_t redzone_size)
>> {
>> + size_t offset;
>> MR_MemoryZone *zone;
>> + MR_Word *base;
>> size_t total_size;
>>
>> + offset = MR_next_offset();
>> + /*
>> + ** Ignore the offset if it is at least half the desired size of the zone.
>> + ** This should only happen for very small zones.
>> + */
>> + if ((offset * 2) > desired_size) {
>> + offset = 0;
>> + }
>> +
>> + /*
>> + ** The redzone must be page aligned and page multiple.
>
> Do you mean:
>
> ... and its size must be a multiple of the page size.
Yes,
Changed this.
>> + */
>> + redzone_size = MR_round_up(redzone_size, MR_page_size);
>> + /*
>> + ** Include an extra page size for the hardzone.
>> + */
>> + total_size = desired_size + redzone_size + MR_page_size;
>> + /*
>> + ** The total size must also be rounded to a page boundary, so that it can
>> + ** be allocated from mmap if we're using accurate GC.
>> + */
>> + total_size = MR_round_up(total_size, MR_page_size);
>> +
>> + base = (MR_Word *) MR_alloc_zone_memory(total_size);
>> if (base == NULL) {
>> - MR_fatal_error("MR_construct_zone called with NULL pointer");
>> + MR_fatal_error("Unable to allocate memory for zone");
>> }
>>
>> - zone = MR_get_zone();
>> + zone = MR_GC_NEW(MR_MemoryZone);
>>
>> - zone->MR_zone_name = name;
>> - zone->MR_zone_id = id;
>> - zone->MR_zone_desired_size = size;
>> - zone->MR_zone_redzone_size = redsize;
>> + zone->MR_zone_name = NULL;
>> +#ifdef MR_THREAD_SAFE
>> + zone->MR_zone_id = MR_atomic_add_and_fetch_uint(&MR_context_id_counter, 1);
>> +#else
>> + zone->MR_zone_id = ++MR_context_id_counter;
>> +#endif
>> + zone->MR_zone_desired_size = desired_size;
>> + zone->MR_zone_redzone_size = redzone_size;
>>
>> #ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
>> - zone->MR_zone_handler = handler;
>> + zone->MR_zone_handler = NULL;
>> #endif /* MR_CHECK_OVERFLOW_VIA_MPROTECT */
>>
>> - /*
>> - ** XXX If `zone' is pulled off the free-list (rather than newly allocated)
>> - ** then zone->MR_zone_bottom will be pointing to a previously allocated
>> - ** memory region. Setting it to point to `base' therefore causes a memory
>> - ** leak. `base' should not be allocated in the first place if `zone' is
>> - ** to be reused. See also the workaround in MR_unget_zone().
>> - */
>> zone->MR_zone_bottom = base;
>>
>> -#ifdef MR_PROTECTPAGE
>> - total_size = size + MR_unit;
>> -#else
>> - total_size = size;
>> -#endif /* MR_PROTECTPAGE */
>> -
>> zone->MR_zone_top = (MR_Word *) ((char *) base + total_size);
>> zone->MR_zone_min = (MR_Word *) ((char *) base + offset);
>> #ifdef MR_LOWLEVEL_DEBUG
>> @@ -593,6 +795,9 @@ MR_extend_zone(MR_MemoryZone *zone, size
>> MR_fatal_error("MR_extend_zone called with NULL pointer");
>> }
>>
>> + /*
>> + ** Why use this value for new_total_size?
>> + */
>
> XXX?
>
Yes. I've added this.
>> #ifdef MR_PROTECTPAGE
>> new_total_size = new_size + 2 * MR_unit;
>> #else
>> @@ -645,25 +850,34 @@ MR_extend_zone(MR_MemoryZone *zone, size
>> return base_incr;
>> }
>> Index: runtime/mercury_memory_zones.h
>> ===================================================================
>> RCS file: /home/mercury1/repository/mercury/runtime/mercury_memory_zones.h,v
>> retrieving revision 1.20
>> diff -u -p -b -r1.20 mercury_memory_zones.h
>> --- runtime/mercury_memory_zones.h 5 Sep 2008 11:19:33 -0000 1.20
>> +++ runtime/mercury_memory_zones.h 26 May 2010 07:54:44 -0000
>> @@ -134,6 +135,22 @@ struct MR_MemoryZones_Struct {
>> MR_MemoryZones *MR_zones_tail;
>> };
>>
>> +/*
>> +** Free memory zones are arranged in a list of lists, The outer list (below)
>> +** associates a size of the zones in each inner list. It is to be kept in
>> +** sorted order from smallest to largest. So that a traversal of this list
>> +** returns the zones that are the 'best fit' as the 'first fit'. The inner
>> +** lists (using the MR_zone_next field of the zones contain zones of all the
>> +** same size.
>> +*/
>
> Elsewhere you refer to the outer list as the major list, and the inner
> list as the minor list.
>
I've made the other comments conformant with this comment.
>> +typedef struct MR_MemoryZonesFree_Struct MR_MemoryZonesFree;
>> +
>> +struct MR_MemoryZonesFree_Struct {
>> + size_t MR_zonesfree_size;
>> + MR_MemoryZone *MR_zonesfree_head;
>> + MR_MemoryZonesFree *MR_zonesfree_tail;
>> +};
>> +
>> /*
>> ** MR_zone_end specifies the end of the area accessible without
>> ** a page fault. It is used by MR_clear_zone_for_GC().
>> Index: runtime/mercury_misc.c
>> ===================================================================
>> RCS file: /home/mercury1/repository/mercury/runtime/mercury_misc.c,v
>> retrieving revision 1.28
>> diff -u -p -b -r1.28 mercury_misc.c
>> --- runtime/mercury_misc.c 14 Nov 2006 00:15:40 -0000 1.28
>> +++ runtime/mercury_misc.c 26 May 2010 07:54:44 -0000
>> @@ -88,9 +88,13 @@ void
>> MR_fatal_error(const char *fmt, ...)
>> {
>> va_list args;
>> + int error = errno;
>>
>> fflush(stdout); /* in case stdout and stderr are the same */
>>
>> + if (error != 0) {
>> + fprintf(stderr, "Errno: %s\n", strerror(error));
>> + }
>
> I suggest also printing errno itself there, sometimes the description
> won't be that useful, e.g. when it's something like "Unknown error".
>
There was a presentation about this at LCA this year. It was pretty amusing.
Abstract: http://www.lca2010.org.nz/programme/schedule/view_talk/50260?day=wednesday
Code: http://libexplain.sourceforge.net/
> Please post a revised log message and diff once you have addressed the
> above.
Okay, There also seem to be some problems with hlc.gc.par, so I'll address
those before I re-post it.
I've fixed all the other errors you've pointed out.
Thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 489 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20100607/55cdbcb3/attachment.sig>
More information about the reviews
mailing list