Re: [Gc] allocation with lowest overhead

Bruce Hoult <[email protected]> Thu, 29 May 2014 18:23:59 +1200
Newsgroups gmane.comp.programming.garbage-collection.boehmgc
Message-ID <CAMU+EkzTkCh+wONYx6+ba5nKpFdVsmtPq1jenn8bXFRTBD+-MA@mail.gmail.com>
This patch prevents the crash:

https://github.com/ivmai/bdwgc/pull/45/commits

--- a/mallocx.c

+++ b/mallocx.c

@@ -314,8 +314,8 @@ GC_API void GC_CALL GC_generic_malloc_many(size_t lb,
int k, void **result)

       }

     /* First see if we can reclaim a page of objects waiting to be */

     /* reclaimed.                                                  */

-    {

-        struct hblk ** rlh = ok -> ok_reclaim_list;

+    struct hblk ** rlh = ok -> ok_reclaim_list;

+    if (rlh){

         struct hblk * hbp;

         hdr * hhdr;



On Wed, May 28, 2014 at 6:56 PM, Kenjiro Taura <tau-6gqOUJIvMG0T5sms4jGy2S+Ac/[email protected]
> wrote:

>
> Thanks.
>
> (i) I will work around the bug by calling
> GC_MALLOC once.  Thank you very much for this
> info.
>
> (ii) For your question about the intention of the
> code, it is simply where I arrived at after
> digging into the problem.  The original code
> indeed allocates many objects of a similar size
> (using GC_MALLOC_WORDS, for that matter).  Looking
> into the problem, I simply arrived the simplest
> code that reproduces what I experienced.
>
>
> > Hi,
> >
> > First of all, it seems we have a bug in the GC. Attention Ivan :)
> >
> > Code similar to yours (but fixed, see below) also crashes on OS X. If I
> > allocate even one object using the normal interface e.g. GC_malloc()
> first
> > then all is well, but using GC_malloc_many() immediately after GC_INIT()
> > crashes.
> >
> > However, I'm not sure what you're expecting GC_malloc_many() to do there.
> > That's a completely different way of lowering the overhead of allocating
> > objects. It's useful if you want to allocate many objects all of the same
> > size e.g.
> >
> > typedef struct {
> >   int stuff_here;
> >   int more_stuff[10];
> > } my_common_thing;
> >
> > my_common_thing *new_common_thing(){
> >   static my_common_thing *free_list = 0;
> >   if (!free_list){
> >     printf("Refilling free list\n");
> >     free_list = GC_malloc_many(sizeof(my_common_thing));
> >   }
> >   my_common_thing *res = free_list;
> >   free_list = GC_NEXT(free_list);
> >   return res;
> > }
> >
> > int main() {
> >   GC_INIT();
> >   GC_malloc(1); // avoid bug
> >
> >   my_common_thing *p;
> >   while ((p = new_common_thing())){
> >     printf("%p\n", p);
> >   }
> >   return 0;
> > }
> >
> >
> > However if you want to allocate things of a number of different sizes and
> > types then the tiny_fl mechanism is appropriate.
> >
> > Your original code works for me deleting the GC_malloc_many() and adding
> > GC_malloc(1);
> >
> > Just remember the argument to GC_MALLOC_WORDS() is words not bytes...
> >
> > Note: if you are using these interfaces to the GC instead of the normal
> > ones, really you are extending the GC itself. I'd advise putting code
> doing
> > this into its own source file and export useful functions. Don't pollute
> > the rest of your code with gc internal headers including unqualified
> things
> > such as NORMAL!
> >
> >
> > On Wed, May 28, 2014 at 4:00 PM, Kenjiro Taura <
> [email protected]
> >> wrote:
> >
> >> Hi Bruce,
> >>
> >> Thank you very much for your reply.
> >>
> >>
> >> > GC_MALLOC_WORDS will work. You don't get tiny_fl from somewhere, you
> >> > allocate it yourself as your own private fast-access cache of objects.
> >>
> >> So, you mean something like the following should work?
> >>
> >> #include <stdio.h>
> >> #include <gc/gc.h>
> >> #include <gc/gc_inline.h>
> >>
> >> int main() {
> >>   GC_INIT();
> >>   void * fl[GC_TINY_FREELISTS];
> >>   int i;
> >>   for (i = 0; i < GC_TINY_FREELISTS; i++) fl[i] = 0;
> >>   void * p;
> >>   p = GC_malloc_many(16);
> >>   GC_MALLOC_WORDS(p, 1, fl);
> >>   printf("%p\n", p);
> >>   return 0;
> >> }
> >>
> >> ----------------------------
> >>
> >> Here is what happend when I tried it with 7.4.0
> >> source (built on Ubuntu 14.04 64 bit platform).  I
> >> feel I must be missing something basic, but any
> >> further help is appreciated.
> >>
> >> (i) First, the compiler complains about undefined symbol NORMAL.
> >>
> >> export
> >>
> gc_dir=/home/tau/public_html/lecture/programming_languages/gen/progs/gc/inst
> >> gcc -o a_gc -DUSE_GC=1 -O0 -g -I${gc_dir}/include a.c -L${gc_dir}/lib
> >> -Wl,-R${gc_dir}/lib -lgc
> >>
> >>
> /home/tau/public_html/lecture/programming_languages/gen/progs/gc/inst/include/gc/gc_inline.h:124:26:
> >> error: ‘NORMAL’ undeclared (first use in this function)
> >>                           NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \
> >>
> >> (ii) NORMAL seems defined in private/gc_priv.h.
> >> Feeling I am already on a wrong track, I included
> >> it anyways.  It got compiled, but it results in
> >> segfault in the very first call to
> >> GC_generic_malloc_many.
> >>
> >> nanamomo:gc% ./a_gc
> >> Segmentation fault (core dumped)
> >>
> >> gdb says the segfault happened at the following line
> >> marked -----> and the value of rlh was 0x8.
> >>
> >> Reading symbols from a_gc...done.
> >> [New LWP 10538]
> >> [New LWP 10541]
> >> [New LWP 10539]
> >> [New LWP 10540]
> >> [Thread debugging using libthread_db enabled]
> >> Using host libthread_db library
> "/lib/x86_64-linux-gnu/libthread_db.so.1".
> >> Core was generated by `./a_gc'.
> >> Program terminated with signal SIGSEGV, Segmentation fault.
> >>
> >>
> >>         struct hblk ** rlh = ok -> ok_reclaim_list;
> >>         struct hblk * hbp;
> >>         hdr * hhdr;
> >>
> >>         rlh += lg;
> >> --->        while ((hbp = *rlh) != 0) {
> >>             hhdr = HDR(hbp);
> >>             *rlh = hhdr -> hb_next;
> >>             GC_ASSERT(hhdr -> hb_sz == lb);
> >>
> >>
> >> (iii) In fact, the same fault occurs when I
> >> directly call GC_malloc_many, not GC_MALLOC_WORDS.
> >> So it seems to have nothing to do with my wild
> >> modification of including what is supposed to be
> >> private.  i.e., the following program results in
> >> almost the same phenomenon.
> >>
> >> #include <stdio.h>
> >> #include <gc/gc.h>
> >>
> >> int main() {
> >>   void * p;
> >>   p = GC_malloc_many(16);
> >>   printf("%p\n", p);
> >>   return 0;
> >> }
> >>
> >>
> >> The same error occurs with the package (i.e., with
> >> the one I did not built from the source).
> >>
> >> >
> >> > As it says in the include file:
> >> >
> >> > "Tiny_fl should be an array of GC_TINY_FREELISTS void * pointers."
> >> >
> >> > If you're using GC_MALLOC_WORDS() then you can just initialise your
> >> tiny_fl
> >> > array to zeros before the first use.
> >> >
> >> >
> >> >
> >> > On Mon, May 26, 2014 at 3:57 PM, Kenjiro Taura <
> >> [email protected]
> >> >> wrote:
> >> >
> >> >> Hi,
> >> >>
> >> >> What is the fastest, yet portable way to allocate
> >> >> a small object in recent versions (e.g., 7.4.0)?
> >> >> The current interface seems more complex than what
> >> >> it used to be many years ago.
> >> >>
> >> >> Below, I am seeing 7.4.0 sources.
> >> >>
> >> >> I initially thought:
> >> >>
> >> >> # define GC_MALLOC_WORDS(result,n,tiny_fl)
> >> >>
> >> >> in gc_inline.h is the one I should use, but it
> >> >> requires tiny_fl argument I must obtain somehow.
> >> >>
> >> >> Digging into GC_malloc in thread_local_alloc.c,
> >> >> I found that the following line eventually gets it.
> >> >>
> >> >>     tiny_fl = ((GC_tlfs)tsd) -> normal_freelists;
> >> >>
> >> >> The next question then is how to get tsd, for
> >> >> which a fairly complex conditional compilation
> >> >> is going on.  Ignoring portability for a moment,
> >> >> I figured out that
> >> >>
> >> >>       tsd = GC_getspecific(GC_thread_key);
> >> >>
> >> >> is it.
> >> >>
> >> >> I tried copied and pasted it into my source and
> >> >> got compilation errors.  All in all, I feel I am
> >> >> not on the right track; they seem intentionally
> >> >> kept private inside a collector implementation.
> >> >>
> >> >> I started feeling I am missing some functions that
> >> >> portably return what needs to be passed to
> >> >> GC_MALLOC_WORDS, but could not find any so far.
> >> >>
> >> >> I appreciate if anybody sheds light on it.
> >> >> _______________________________________________
> >> >> bdwgc mailing list
> >> >> [email protected]
> >> >> https://lists.opendylan.org/mailman/listinfo/bdwgc
> >> >>
> >> >> --
> >> >> This message has been scanned for viruses and
> >> >> dangerous content by MailScanner, and is
> >> >> believed to be clean.
> >> >>
> >> >>
> >>
> >> --
> >> This message has been scanned for viruses and
> >> dangerous content by MailScanner, and is
> >> believed to be clean.
> >>
> >>
>
> --
> This message has been scanned for viruses and
> dangerous content by MailScanner, and is
> believed to be clean.
>
>

_______________________________________________
bdwgc mailing list
[email protected]
https://lists.opendylan.org/mailman/listinfo/bdwgc