From 29cd838eab01ed7110f3ccb2e8c6a35c8a31dbcc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:21:29 +0200 Subject: Adding upstream version 1:0.1.9998svn3589+dfsg. Signed-off-by: Daniel Baumann --- src/kmk/electric.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 src/kmk/electric.c (limited to 'src/kmk/electric.c') diff --git a/src/kmk/electric.c b/src/kmk/electric.c new file mode 100644 index 0000000..b033073 --- /dev/null +++ b/src/kmk/electric.c @@ -0,0 +1,220 @@ +/* $Id: electric.c 2798 2015-09-19 20:35:03Z bird $ */ +/** @file + * A simple electric heap implementation. + */ + +/* + * Copyright (c) 2007-2010 knut st. osmundsen + * + * This file is part of kBuild. + * + * kBuild is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * kBuild is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with kBuild. If not, see + * + */ + +#ifdef ELECTRIC_HEAP + +# ifdef WINDOWS32 +# include +# else +# include +# include +# include +# endif +# include +# include +# include + + +# define FREED_ENTRIES 512 +static struct +{ + void *ptr; + unsigned aligned; +} freed[FREED_ENTRIES]; +static unsigned freed_head = 0; +static unsigned freed_tail = 0; + + +static void fatal_error (const char *msg) +{ +#ifdef _MSC_VER + fprintf (stderr, "electric heap error: %s\n", msg); + __debugbreak (); +#else + fprintf (stderr, "electric heap error: %s (errno=%d)\n", msg, errno); + __asm__ ("int3"); /* not portable... */ +#endif + abort (); + exit (1); +} + +static void free_it (void *ptr, unsigned aligned) +{ +# ifdef WINDOWS32 + if (!VirtualFree (ptr, 0, MEM_RELEASE)) + fatal_error ("VirtualFree failed"); +# else + if (munmap(ptr, aligned)) + fatal_error ("munmap failed"); +# endif +} + +/* Return 1 if something was freed, 0 otherwise. */ +static int free_up_some (void) +{ + if (freed_tail == freed_head) + return 0; + free_it (freed[freed_tail].ptr, freed[freed_tail].aligned); + freed[freed_tail].ptr = NULL; + freed[freed_tail].aligned = 0; + freed_tail = (freed_tail + 1) % FREED_ENTRIES; + return 1; +} + +static unsigned *get_hdr (void *ptr) +{ + if (((uintptr_t)ptr & 0xfff) < sizeof(unsigned)) + return (unsigned *)(((uintptr_t)ptr - 0x1000) & ~0xfff); + return (unsigned *)((uintptr_t)ptr & ~0xfff); +} + +void xfree (void *ptr) +{ + unsigned int size, aligned; + unsigned *hdr; +# ifdef WINDOWS32 + DWORD fFlags = PAGE_NOACCESS; +# endif + + if (!ptr) + return; + + hdr = get_hdr (ptr); + size = *hdr; + aligned = (size + 0x1fff + sizeof(unsigned)) & ~0xfff; +# ifdef WINDOWS32 + if (!VirtualProtect (hdr, aligned - 0x1000, fFlags, &fFlags)) + fatal_error ("failed to protect freed memory"); +# else + if (mprotect(hdr, aligned - 0x1000, PROT_NONE)) + fatal_error ("failed to protect freed memory"); +# endif + + freed[freed_head].ptr = hdr; + freed[freed_head].aligned = aligned; + if (((freed_head + 1) % FREED_ENTRIES) == freed_tail) + free_up_some(); + freed_head = (freed_head + 1) % FREED_ENTRIES; +} + +void * +xmalloc (unsigned int size) +{ + /* Make sure we don't allocate 0, for pre-ANSI libraries. */ + unsigned int aligned = (size + 0x1fff + sizeof(unsigned)) & ~0xfff; + unsigned *hdr; + unsigned i; + for (i = 0; i < FREED_ENTRIES; i++) + { +# ifdef WINDOWS32 + DWORD fFlags = PAGE_NOACCESS; + hdr = VirtualAlloc(NULL, aligned, MEM_COMMIT, PAGE_READWRITE); + if (hdr + && !VirtualProtect((char *)hdr + aligned - 0x1000, 0x1000, fFlags, &fFlags)) + fatal_error ("failed to set guard page protection"); +# else + hdr = mmap(NULL, aligned, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (hdr == MAP_FAILED) + hdr = 0; + if (hdr + && mprotect((char *)hdr + aligned - 0x1000, 0x1000, PROT_NONE)) + fatal_error ("failed to set guard page protection"); +# endif + if (hdr) + break; + if (!free_up_some ()) + break; + } + if (hdr == 0) + fatal_error ("virtual memory exhausted"); + + *hdr = size; +# if 0 + return hdr + 1; +# else + return (char *)hdr + aligned - 0x1000 - size; +# endif +} + + +void * +xcalloc (unsigned size) +{ + void *result; + result = xmalloc (size); + return memset (result, 0, size); +} + +void * +xrealloc (void *ptr, unsigned int size) +{ + void *result; + result = xmalloc (size); + if (ptr) + { + unsigned *hdr = get_hdr (ptr); + unsigned int oldsize = *hdr; + memcpy (result, ptr, oldsize >= size ? size : oldsize); + xfree (ptr); + } + return result; +} + +char * +xstrdup (const char *ptr) +{ + if (ptr) + { + size_t size = strlen (ptr) + 1; + char *result = xmalloc (size); + return memcpy (result, ptr, size); + } + return NULL; +} + +# ifdef __GNUC__ +void * +xmalloc_size_t (size_t size) +{ + return xmalloc(size); +} + +void * +xcalloc_size_t (size_t size, size_t items) +{ + return xcalloc(size * items); +} + +void * +xrealloc_size_t (void *ptr, size_t size) +{ + return xrealloc(ptr, size); +} +# endif /* __GNUC__ */ + +#else /* !ELECTRIC_HEAP */ +extern void electric_heap_keep_ansi_c_quiet (void); +#endif /* !ELECTRIC_HEAP */ + -- cgit v1.2.3