Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/cygheap.cc')
-rw-r--r--winsup/cygwin/cygheap.cc126
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;
}
}