> Am 29.05.2025 um 08:28 schrieb Jakub Jelinek <ja...@redhat.com>:
> 
> On Tue, Apr 22, 2025 at 01:27:34PM +0200, Richard Biener wrote:
>> This is OK for trunk after we've released GCC 15.1.
> 
> This change broke build on non-USING_MMAP hosts.
> I don't have access to one, so I've just added #undef USING_MMAP
> before first use of that macro after the definitions.
> 
> There were 2 problems.  One was one missed G.free_pages
> to free_list->free_pages replacement in #ifdef USING_MALLOC_PAGE_GROUPS
> guarded code which resulted in obvious compile error.
> 
> Once fixed, there was an ICE during self-test and without self-test pretty
> much on any garbage collection.
> The problem is that the patch moved all of release_pages into new
> do_release_pages and runs it for each freelist from the new release_pages
> wrapper.  The #ifdef USING_MALLOC_PAGE_GROUPS code had two loops, one
> which walked the entries in the freelist and freed the ones which had
> unused group there and another which walked all the groups (regardless of
> which freelist they belong to) and freed the unused ones.
> With the change the first call to do_release_pages would free freelist
> entries from the first freelist with unused groups, then free all unused
> groups and then second and following would access already freed groups,
> crashing there, and then walk again all groups looking for unused ones (but
> there are guaranteed to be none).
> 
> So, this patch fixes it by moving the unused group freeing to the caller,
> release_pages after all freelists are freed, and while at it, moves there
> the statistics printout as well, we don't need to print separate info
> for each of the freelist, previously we were emitting just one.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux plus additionally
> tested with non-bootstrap build with #undef USING_MMAP + make check-gcc,
> ok for trunk?

Ok.

Thanks,
Richard 

> 
> 2025-05-29  Jakub Jelinek  <ja...@redhat.com>
> 
>    PR bootstrap/120464
>    * ggc-page.cc (struct ggc_globals): Fix up comment formatting.
>    (find_free_list): Likewise.
>    (alloc_page): For defined(USING_MALLOC_PAGE_GROUPS) use
>    free_list->free_pages instead of G.free_pages.
>    (do_release_pages): Add n1 and n2 arguments, make them used.
>    Move defined(USING_MALLOC_PAGE_GROUPS) page group freeing to
>    release_pages and dumping of statistics as well.  Formatting fixes.
>    (release_pages): Adjust do_release_pages caller, move here
>    defined(USING_MALLOC_PAGE_GROUPS) page group freeing and dumping
>    of statistics.
>    (ggc_handle_finalizers): Fix up comment formatting and typo.
> 
> --- gcc/ggc-page.cc.jj    2025-05-27 23:08:37.969726172 +0200
> +++ gcc/ggc-page.cc    2025-05-29 08:11:01.231698412 +0200
> @@ -426,7 +426,7 @@ static struct ggc_globals
>   int dev_zero_fd;
> #endif
> 
> -  /* A cache of free system pages. Entry 0 is fallback.  */
> +  /* A cache of free system pages.  Entry 0 is fallback.  */
>   struct free_list free_lists[num_free_list];
> 
> #ifdef USING_MALLOC_PAGE_GROUPS
> @@ -787,7 +787,7 @@ find_free_list (size_t entry_size)
>      return &G.free_lists[i];
>    }
>     }
> -  /* Fallback. Does this happen?  */
> +  /* Fallback.  Does this happen?  */
>   if (GATHER_STATISTICS)
>     G.stats.fallback++;
>   return &G.free_lists[0];
> @@ -955,7 +955,7 @@ alloc_page (unsigned order)
>       /* If we allocated multiple pages, put the rest on the free list.  */
>       if (multiple_pages)
>    {
> -      struct page_entry *e, *f = G.free_pages;
> +      struct page_entry *e, *f = free_list->free_pages;
>      for (a = enda - G.pagesize; a != page; a -= G.pagesize)
>        {
>          e = XCNEWVAR (struct page_entry, page_entry_size);
> @@ -1073,10 +1073,10 @@ free_page (page_entry *entry)
> /* Release the free page cache for FREE_LIST to the system.  */
> 
> static void
> -do_release_pages (struct free_list *free_list)
> +do_release_pages (struct free_list *free_list, size_t &n1, size_t &n2)
> {
> -  size_t n1 = 0;
> -  size_t n2 = 0;
> +  (void) n1;
> +  (void) n2;
> #ifdef USING_MADVISE
>   page_entry *p, *start_p;
>   char *start;
> @@ -1089,7 +1089,7 @@ do_release_pages (struct free_list *free
>      This allows other allocators to grab these areas if needed.
>      This is only done on larger chunks to avoid fragmentation.
>      This does not always work because the free_pages list is only
> -     approximately sorted. */
> +     approximately sorted.  */
> 
>   p = free_list->free_pages;
>   prev = NULL;
> @@ -1104,7 +1104,7 @@ do_release_pages (struct free_list *free
>         {
>           len += p->bytes;
>      if (!p->discarded)
> -          mapped_len += p->bytes;
> +        mapped_len += p->bytes;
>      newprev = p;
>           p = p->next;
>         }
> @@ -1129,7 +1129,7 @@ do_release_pages (struct free_list *free
>    }
> 
>   /* Now give back the fragmented pages to the OS, but keep the address
> -     space to reuse it next time. */
> +     space to reuse it next time.  */
> 
>   for (p = free_list->free_pages; p; )
>     {
> @@ -1149,10 +1149,10 @@ do_release_pages (struct free_list *free
>         }
>       /* Give the page back to the kernel, but don't free the mapping.
>          This avoids fragmentation in the virtual memory map of the
> -     process. Next time we can reuse it by just touching it. */
> +     process.  Next time we can reuse it by just touching it.  */
>       madvise (start, len, MADV_DONTNEED);
>       /* Don't count those pages as mapped to not touch the garbage collector
> -         unnecessarily. */
> +     unnecessarily.  */
>       G.bytes_mapped -= len;
>       n2 += len;
>       while (start_p != p)
> @@ -1195,7 +1195,6 @@ do_release_pages (struct free_list *free
> #endif
> #ifdef USING_MALLOC_PAGE_GROUPS
>   page_entry **pp, *p;
> -  page_group **gp, *g;
> 
>   /* Remove all pages from free page groups from the list.  */
>   pp = &free_list->free_pages;
> @@ -1207,6 +1206,20 @@ do_release_pages (struct free_list *free
>       }
>     else
>       pp = &p->next;
> +#endif
> +}
> +
> +/* Release the free page cache to the system.  */
> +
> +static void
> +release_pages ()
> +{
> +  size_t n1 = 0;
> +  size_t n2 = 0;
> +  for (int i = 0; i < num_free_list; i++)
> +    do_release_pages (&G.free_lists[i], n1, n2);
> +#ifdef USING_MALLOC_PAGE_GROUPS
> +  page_group **gp, *g;
> 
>   /* Remove all free page groups, and release the storage.  */
>   gp = &G.page_groups;
> @@ -1232,15 +1245,6 @@ do_release_pages (struct free_list *free
>     }
> }
> 
> -/* Release the free page cache to the system.  */
> -
> -static void
> -release_pages ()
> -{
> -  for (int i = 0; i < num_free_list; i++)
> -    do_release_pages (&G.free_lists[i]);
> -}
> -
> /* This table provides a fast way to determine ceil(log_2(size)) for
>    allocation requests.  The minimum allocation size is eight bytes.  */
> #define NUM_SIZE_LOOKUP 512
> @@ -2008,9 +2012,9 @@ clear_marks (void)
>     }
> }
> 
> -/* Check if any blocks with a registered finalizer have become unmarked. If 
> so
> +/* Check if any blocks with a registered finalizer have become unmarked.  If 
> so
>    run the finalizer and unregister it because the block is about to be freed.
> -   Note that no garantee is made about what order finalizers will run in so
> +   Note that no guarantee is made about what order finalizers will run in so
>    touching other objects in gc memory is extremely unwise.  */
> 
> static void
> 
> 
>    Jakub
> 

Reply via email to