diff -cr gc-7.4.2/include/private/gc_priv.h gc-7.4.2-new/include/private/gc_priv.h
*** gc-7.4.2/include/private/gc_priv.h	2014-06-03 07:08:02.000000000 +0100
--- gc-7.4.2-new/include/private/gc_priv.h	2016-01-15 12:25:16.000000000 +0000
***************
*** 725,730 ****
--- 725,738 ----
  #   define CPP_LOG_HBLKSIZE 13
  # elif HBLKSIZE == 16384
  #   define CPP_LOG_HBLKSIZE 14
+ # elif HBLKSIZE == 32768
+ #   define CPP_LOG_HBLKSIZE 15
+ # elif HBLKSIZE == 65536
+ #   define CPP_LOG_HBLKSIZE 16
+ # elif HBLKSIZE == 131072
+ #   define CPP_LOG_HBLKSIZE 17
+ # elif HBLKSIZE == 262144
+ #   define CPP_LOG_HBLKSIZE 18
  # else
      --> fix HBLKSIZE
  # endif
diff -cr gc-7.4.2/include/private/gcconfig.h gc-7.4.2-new/include/private/gcconfig.h
*** gc-7.4.2/include/private/gcconfig.h	2014-06-03 07:08:02.000000000 +0100
--- gc-7.4.2-new/include/private/gcconfig.h	2016-01-15 12:25:16.000000000 +0000
***************
*** 25,30 ****
--- 25,37 ----
  #ifndef GCCONFIG_H
  #define GCCONFIG_H
  
+ /* Override system-specific block size so that thread-local allocations
+  * are more efficient.
+  */
+ #ifndef HBLKSIZE
+ #define HBLKSIZE 8192
+ #endif
+ 
  # ifndef GC_PRIVATE_H
      /* Fake ptr_t declaration, just to avoid compilation errors.        */
      /* This avoids many instances if "ifndef GC_PRIVATE_H" below.       */
diff -cr gc-7.4.2/mark.c gc-7.4.2-new/mark.c
*** gc-7.4.2/mark.c	2014-06-03 07:08:02.000000000 +0100
--- gc-7.4.2-new/mark.c	2016-01-15 12:25:16.000000000 +0000
***************
*** 16,21 ****
--- 16,25 ----
  
  #include "private/gc_pmark.h"
  
+ #ifndef MAX_MARKERS
+ # define MAX_MARKERS 16
+ #endif
+ 
  #include <stdio.h>
  
  #if defined(MSWIN32) && defined(__GNUC__)
***************
*** 1112,1124 ****
      }
  }
  
  /* Perform Parallel mark.                       */
  /* We hold the GC lock, not the mark lock.      */
  /* Currently runs until the mark stack is       */
  /* empty.                                       */
  STATIC void GC_do_parallel_mark(void)
  {
!     mse local_mark_stack[LOCAL_MARK_STACK_SIZE];
                  /* Note: local_mark_stack is quite big (up to 128 KiB). */
  
      GC_acquire_mark_lock();
--- 1116,1130 ----
      }
  }
  
+ GC_INNER mse GC_local_mark_stacks[MAX_MARKERS+1][LOCAL_MARK_STACK_SIZE];
+ 
  /* Perform Parallel mark.                       */
  /* We hold the GC lock, not the mark lock.      */
  /* Currently runs until the mark stack is       */
  /* empty.                                       */
  STATIC void GC_do_parallel_mark(void)
  {
!     mse *local_mark_stack = &(GC_local_mark_stacks[0][0]);
                  /* Note: local_mark_stack is quite big (up to 128 KiB). */
  
      GC_acquire_mark_lock();
***************
*** 1151,1163 ****
      GC_notify_all_marker();
  }
  
- 
  /* Try to help out the marker, if it's running.         */
  /* We do not hold the GC lock, but the requestor does.  */
  GC_INNER void GC_help_marker(word my_mark_no)
  {
      unsigned my_id;
!     mse local_mark_stack[LOCAL_MARK_STACK_SIZE];
                  /* Note: local_mark_stack is quite big (up to 128 KiB). */
  
      if (!GC_parallel) return;
--- 1157,1168 ----
      GC_notify_all_marker();
  }
  
  /* Try to help out the marker, if it's running.         */
  /* We do not hold the GC lock, but the requestor does.  */
  GC_INNER void GC_help_marker(word my_mark_no)
  {
      unsigned my_id;
!     mse *local_mark_stack;
                  /* Note: local_mark_stack is quite big (up to 128 KiB). */
  
      if (!GC_parallel) return;
***************
*** 1168,1173 ****
--- 1173,1179 ----
        GC_wait_marker();
      }
      my_id = GC_helper_count;
+     local_mark_stack = &(GC_local_mark_stacks[my_id][0]);
      if (GC_mark_no != my_mark_no || my_id > (unsigned)GC_markers_m1) {
        /* Second test is useful only if original threads can also        */
        /* act as helpers.  Under Linux they can't.                       */
***************
*** 1238,1243 ****
--- 1244,1253 ----
  GC_INNER void GC_mark_init(void)
  {
      alloc_mark_stack(INITIAL_MARK_STACK_SIZE);
+ #   ifdef PARALLEL_MARK
+         GC_exclude_static_roots_inner(GC_local_mark_stacks,
+ 	    (char *)GC_local_mark_stacks + sizeof(GC_local_mark_stacks));
+ #   endif
  }
  
  /*
diff -cr gc-7.4.2/os_dep.c gc-7.4.2-new/os_dep.c
*** gc-7.4.2/os_dep.c	2014-06-03 07:08:02.000000000 +0100
--- gc-7.4.2-new/os_dep.c	2016-01-15 12:25:16.000000000 +0000
***************
*** 752,757 ****
--- 752,759 ----
          }
        }
  #   endif
+     if (HBLKSIZE > GC_page_size)
+       GC_page_size = HBLKSIZE;
    }
  
  # ifndef CYGWIN32
***************
*** 815,820 ****
--- 817,824 ----
  #   if defined(MPROTECT_VDB) || defined(PROC_VDB) || defined(USE_MMAP)
        GC_page_size = GETPAGESIZE();
        if (!GC_page_size) ABORT("getpagesize failed");
+       if (HBLKSIZE > GC_page_size)
+         GC_page_size = HBLKSIZE;
  #   else
        /* It's acceptable to fake it.    */
        GC_page_size = HBLKSIZE;
***************
*** 2062,2073 ****
--- 2066,2089 ----
  #   endif
  
      if (bytes & (GC_page_size - 1)) ABORT("Bad GET_MEM arg");
+     bytes += GC_page_size;
      result = mmap(last_addr, bytes, (PROT_READ | PROT_WRITE)
                                      | (GC_pages_executable ? PROT_EXEC : 0),
                    GC_MMAP_FLAGS | OPT_MAP_ANON, zero_fd, 0/* offset */);
  #   undef IGNORE_PAGES_EXECUTABLE
  
      if (result == MAP_FAILED) return(0);
+ 
+     if ((word) result & (GC_page_size - 1)) {
+         word delta = (word) result & (GC_page_size - 1);
+ 	if (delta) delta = GC_page_size - delta;
+         munmap(result, delta);
+         result = (char *) result + delta;
+         munmap((char *) result + bytes, GC_page_size - delta);
+     } else {
+         munmap((char *) result + bytes, GC_page_size);
+     }
+ 
      last_addr = (ptr_t)result + bytes + GC_page_size - 1;
      last_addr = (ptr_t)((word)last_addr & ~(GC_page_size - 1));
  #   if !defined(LINUX)
