diff options
Diffstat (limited to 'winsup/cygwin/cygheap.cc')
-rw-r--r-- | winsup/cygwin/cygheap.cc | 126 |
1 files changed, 71 insertions, 55 deletions
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 90873215b..bb926118f 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -27,6 +27,7 @@ #include "ntdll.h" #include <unistd.h> #include <wchar.h> +#include <sys/param.h> static mini_cygheap NO_COPY cygheap_dummy = { @@ -60,13 +61,11 @@ public: }; muto NO_COPY tls_sentry::lock; -static NO_COPY size_t nthreads; +static NO_COPY uint32_t nthreads; #define THREADLIST_CHUNK 256 -#define NBUCKETS (sizeof (cygheap->buckets) / sizeof (cygheap->buckets[0])) -#define N0 ((_cmalloc_entry *) NULL) -#define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - (unsigned) (N0->data))) +#define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - offsetof (_cmalloc_entry, data))) #define CFMAP_OPTIONS (SEC_RESERVE | PAGE_READWRITE) #define MVMAP_OPTIONS (FILE_MAP_WRITE) @@ -116,47 +115,6 @@ init_cygheap::close_ctty () cygheap->ctty = NULL; } -#define nextpage(x) ((char *) (((DWORD) ((char *) x + granmask)) & ~granmask)) -#define allocsize(x) ((DWORD) nextpage (x)) -#ifdef DEBUGGING -#define somekinda_printf debug_printf -#else -#define somekinda_printf malloc_printf -#endif - -static void *__stdcall -_csbrk (int sbs) -{ - void *prebrk = cygheap_max; - size_t granmask = wincap.allocation_granularity () - 1; - char *newbase = nextpage (prebrk); - cygheap_max = (char *) cygheap_max + sbs; - if (!sbs || (newbase >= cygheap_max) || (cygheap_max <= _cygheap_end)) - /* nothing to do */; - else - { - if (prebrk <= _cygheap_end) - newbase = _cygheap_end; - - DWORD adjsbs = allocsize ((char *) cygheap_max - newbase); - if (adjsbs && !VirtualAlloc (newbase, adjsbs, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)) - { - MEMORY_BASIC_INFORMATION m; - if (!VirtualQuery (newbase, &m, sizeof m)) - system_printf ("couldn't get memory info, %E"); - somekinda_printf ("Couldn't reserve/commit %d bytes of space for cygwin's heap, %E", - adjsbs); - somekinda_printf ("AllocationBase %p, BaseAddress %p, RegionSize %p, State %p\n", - m.AllocationBase, m.BaseAddress, m.RegionSize, m.State); - __seterrno (); - cygheap_max = (char *) cygheap_max - sbs; - return NULL; - } - } - - return prebrk; -} - /* Use absolute path of cygwin1.dll to derive the Win32 dir which is our installation_root. Note that we can't handle Cygwin installation root dirs of more than 4K path length. I assume that's ok... @@ -261,6 +219,21 @@ cygheap_init () sizeof (*cygheap)); cygheap_max = cygheap; _csbrk (sizeof (*cygheap)); + /* Initialize bucket_val. The value is the max size of a block + fitting into the bucket. The values are powers of two and their + medians: 12, 16, 24, 32, 48, 64, ... On 64 bit, start with 24 to + accommodate bigger size of struct cygheap_entry. + With NBUCKETS == 40, the maximum block size is 6291456/12582912. + The idea is to have better matching bucket sizes (not wasting + space) without trading in performance compared to the old powers + of 2 method. */ +#ifdef __x86_64__ + unsigned sz[2] = { 16, 24 }; /* sizeof cygheap_entry == 16 */ +#else + unsigned sz[2] = { 8, 12 }; /* sizeof cygheap_entry == 8 */ +#endif + for (unsigned b = 1; b < NBUCKETS; b++, sz[b & 1] <<= 1) + cygheap->bucket_val[b] = sz[b & 1]; /* Default locale settings. */ cygheap->locale.mbtowc = __utf8_mbtowc; cygheap->locale.wctomb = __utf8_wctomb; @@ -276,6 +249,47 @@ cygheap_init () cygheap->init_tls_list (); } +#define nextpage(x) ((char *) roundup2 ((uintptr_t) (x), \ + wincap.allocation_granularity ())) +#define allocsize(x) ((SIZE_T) nextpage (x)) +#ifdef DEBUGGING +#define somekinda_printf debug_printf +#else +#define somekinda_printf malloc_printf +#endif + +static void *__stdcall +_csbrk (int sbs) +{ + void *prebrk = cygheap_max; + char *newbase = nextpage (prebrk); + cygheap_max = (char *) cygheap_max + sbs; + if (!sbs || (newbase >= cygheap_max) || (cygheap_max <= _cygheap_end)) + /* nothing to do */; + else + { + if (prebrk <= _cygheap_end) + newbase = _cygheap_end; + + SIZE_T adjsbs = allocsize ((char *) cygheap_max - newbase); + if (adjsbs && !VirtualAlloc (newbase, adjsbs, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)) + { + MEMORY_BASIC_INFORMATION m; + if (!VirtualQuery (newbase, &m, sizeof m)) + system_printf ("couldn't get memory info, %E"); + somekinda_printf ("Couldn't reserve/commit %ld bytes of space for cygwin's heap, %E", + adjsbs); + somekinda_printf ("AllocationBase %p, BaseAddress %p, RegionSize %lx, State %x\n", + m.AllocationBase, m.BaseAddress, m.RegionSize, m.State); + __seterrno (); + cygheap_max = (char *) cygheap_max - sbs; + return NULL; + } + } + + return prebrk; +} + /* Copyright (C) 1997, 2000 DJ Delorie */ static void *__reg1 _cmalloc (unsigned size); @@ -285,11 +299,13 @@ static void *__reg1 _cmalloc (unsigned size) { _cmalloc_entry *rvc; - unsigned b, sz; + unsigned b; - /* Calculate "bit bucket" and size as a power of two. */ - for (b = 3, sz = 8; sz && sz < size; b++, sz <<= 1) + /* Calculate "bit bucket". */ + for (b = 1; b < NBUCKETS && cygheap->bucket_val[b] < size; b++) continue; + if (b >= NBUCKETS) + return NULL; cygheap_protect.acquire (); if (cygheap->buckets[b]) @@ -300,7 +316,8 @@ _cmalloc (unsigned size) } else { - rvc = (_cmalloc_entry *) _csbrk (sz + sizeof (_cmalloc_entry)); + rvc = (_cmalloc_entry *) _csbrk (cygheap->bucket_val[b] + + sizeof (_cmalloc_entry)); if (!rvc) { cygheap_protect.release (); @@ -320,7 +337,7 @@ _cfree (void *ptr) { cygheap_protect.acquire (); _cmalloc_entry *rvc = to_cmalloc (ptr); - DWORD b = rvc->b; + unsigned b = rvc->b; rvc->ptr = cygheap->buckets[b]; cygheap->buckets[b] = (char *) rvc; cygheap_protect.release (); @@ -334,7 +351,7 @@ _crealloc (void *ptr, unsigned size) newptr = _cmalloc (size); else { - unsigned oldsize = 1 << to_cmalloc (ptr)->b; + unsigned oldsize = cygheap->bucket_val[to_cmalloc (ptr)->b]; if (size <= oldsize) return ptr; newptr = _cmalloc (size); @@ -351,8 +368,7 @@ _crealloc (void *ptr, unsigned size) #define sizeof_cygheap(n) ((n) + sizeof (cygheap_entry)) -#define N ((cygheap_entry *) NULL) -#define tocygheap(s) ((cygheap_entry *) (((char *) (s)) - (int) (N->data))) +#define tocygheap(s) ((cygheap_entry *) (((char *) (s)) - offsetof (cygheap_entry, data))) inline static void * creturn (cygheap_types x, cygheap_entry * c, unsigned len, const char *fn = NULL) @@ -600,12 +616,12 @@ init_cygheap::remove_tls (_cygtls *t, DWORD wait) tls_sentry here (wait); if (here.acquired ()) { - for (size_t i = 0; i < nthreads; i++) + for (uint32_t i = 0; i < nthreads; i++) if (t == threadlist[i]) { if (i < --nthreads) threadlist[i] = threadlist[nthreads]; - debug_only_printf ("removed %p element %d", this, i); + debug_only_printf ("removed %p element %u", this, i); break; } } |