>From 2d386f229aba9ecda85736b931e2964d7922d90e Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 19 Oct 2020 04:04:18 +0200 Subject: [PATCH 2/2] ssfmalloc: Add tests. * tests/test-ssfmalloc.c: New file. * modules/ssfmalloc-tests: New file. --- ChangeLog | 4 + modules/ssfmalloc-tests | 11 ++ tests/test-ssfmalloc.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 335 insertions(+) create mode 100644 modules/ssfmalloc-tests create mode 100644 tests/test-ssfmalloc.c diff --git a/ChangeLog b/ChangeLog index 4925dfe..4903d51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2020-10-18 Bruno Haible + ssfmalloc: Add tests. + * tests/test-ssfmalloc.c: New file. + * modules/ssfmalloc-tests: New file. + ssfmalloc: New module. * lib/ssfmalloc.h: New file. * lib/ssfmalloc-bitmap.h: New file. diff --git a/modules/ssfmalloc-tests b/modules/ssfmalloc-tests new file mode 100644 index 0000000..ea1ed2c --- /dev/null +++ b/modules/ssfmalloc-tests @@ -0,0 +1,11 @@ +Files: +tests/test-ssfmalloc.c +tests/macros.h + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-ssfmalloc +check_PROGRAMS += test-ssfmalloc diff --git a/tests/test-ssfmalloc.c b/tests/test-ssfmalloc.c new file mode 100644 index 0000000..e1dfcec --- /dev/null +++ b/tests/test-ssfmalloc.c @@ -0,0 +1,320 @@ +/* Test of simple and straight-forward malloc implementation. + Copyright (C) 2020 Free Software Foundation, Inc. + + This program 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. + + This program 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 this program. If not, see . */ + +/* Written by Bruno Haible , 2020. */ + +#include + +#include +#include + +#if defined _WIN32 && !defined __CYGWIN__ + +/* Declare VirtualAlloc(), GetSystemInfo. */ +# define WIN32_LEAN_AND_MEAN +# define WIN32_EXTRA_LEAN +# include + +#else + +/* Declare getpagesize(). */ +# include +/* On HP-UX, getpagesize exists, but it is not declared in even if + the compiler options -D_HPUX_SOURCE -D_XOPEN_SOURCE=600 are used. */ +# ifdef __hpux +extern +# ifdef __cplusplus + "C" +# endif + int getpagesize (void); +# endif + +/* Declare mmap(). */ +# include +# include + +/* Some old mmap() implementations require the flag MAP_VARIABLE whenever you + pass an addr == NULL. */ +# ifndef MAP_VARIABLE +# define MAP_VARIABLE 0 +# endif + +#endif + +/* ================= Back end of the malloc implementation ================= */ + +/* The memory page size. + Once it is initialized, a power of 2. Typically 4096 or 8192. */ +static uintptr_t pagesize; + +/* Initializes pagesize. */ +static void +init_pagesize (void) +{ +#if defined _WIN32 && !defined __CYGWIN__ + /* GetSystemInfo + + */ + SYSTEM_INFO info; + GetSystemInfo (&info); + pagesize = info.dwPageSize; +#else + pagesize = getpagesize (); +#endif +} + +/* Allocates a contiguous set of pages of memory. + size > 0, must be a multiple of pagesize. + Returns a multiple of PAGESIZE, or 0 upon failure. */ +static uintptr_t +alloc_pages (size_t size) +{ +#if defined _WIN32 && !defined __CYGWIN__ + /* VirtualAlloc + + */ + void *mem = VirtualAlloc (NULL, size, MEM_COMMIT, PAGE_READWRITE); + if (mem == NULL) + return 0; + return (uintptr_t) mem; +#else + /* Use mmap with the MAP_ANONYMOUS or MAP_ANON flag. */ + void *mem = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_VARIABLE, -1, 0); + if (mem == (void *)(-1)) + return 0; + return (uintptr_t) mem; +#endif +} + +/* Frees a contiguous set of pages of memory, returned by alloc_pages. + size > 0, must be a multiple of pagesize. */ +static void +free_pages (uintptr_t pages, size_t size) +{ +#if defined _WIN32 && !defined __CYGWIN__ + /* VirtualFree + */ + if (!VirtualFree ((void *) pages, 0, MEM_RELEASE)) + abort (); +#else + if ((pages & (pagesize - 1)) != 0) + abort (); + if (munmap ((void *) pages, size) < 0) + abort (); +#endif +} + +/* ======================= Instantiate the front end ======================= */ + +#define PAGESIZE pagesize +#define ALLOC_PAGES alloc_pages +#define FREE_PAGES free_pages +#define ALIGNMENT (sizeof (void *)) /* or 8 or 16 or 32 */ +#define PAGE_RESERVED_HEADER_SIZE (3 * UINTPTR_WIDTH / 8) /* = 3 * sizeof (void *) */ +#include "ssfmalloc.h" + +/* ================================= Tests ================================= */ + +#include "macros.h" + +static void +fill_block (uintptr_t block, size_t size) +{ + unsigned char code = (size % (UCHAR_MAX - 1)) + 1; + memset ((char *) block, code, size); +} + +static void +verify_block (uintptr_t block, size_t size) +{ + unsigned char code = (size % (UCHAR_MAX - 1)) + 1; + char *p = (char *) block; + for (; size > 0; p++, size--) + if ((unsigned char) *p != code) + abort (); +} + +static size_t block_sizes[] = + { + /* Small blocks. */ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 12, + 15, + 16, + 17, + 24, + 31, + 32, + 37, + 42, + 49, + 57, + 63, + 64, + 65, + 71, + 83, + 99, + 110, + 127, + 128, + 169, + 249, + 255, + 256, + /* Medium blocks. */ + 257, + 281, + 284, + 294, + 301, + 308, + 341, + 447, + 525, + 659, + 771, + 842, + 729, + 999, + 1000, + 1020, + 1023, + 1024, + 1025, + 1280, + 1414, + 2047, + 2048, + 2049, + 2096, + 2401, + 2613, + 2843, + 3010, + 3213, + 3512, + 3678, + 3801, + 3900, + /* Large blocks. */ + 4000, + 4060, + 4080, + 4090, + 4095, + 4096, + 4097, + 4121, + 5381, + 7814, + 8191, + 8192, + 8193, + 11238, + 16383, + 16384, + 16385, + 20184, + 51202, + 135010 + }; + +#define RANDOM(n) (rand () % (n)) +#define RANDOM_BLOCK_SIZE() block_sizes[RANDOM (SIZEOF (block_sizes))] + +int +main (int argc, char *argv[]) +{ + /* Allow the user to provide a non-default random seed on the command line. */ + if (argc > 1) + srand (atoi (argv[1])); + + init_pagesize (); + + { + unsigned int repeat; + char *blocks[SIZEOF (block_sizes)]; + + { + size_t i; + + for (i = 0; i < SIZEOF (block_sizes); i++) + blocks[i] = NULL; + } + + for (repeat = 0; repeat < 100000; repeat++) + { + unsigned int operation = RANDOM (2); + + switch (operation) + { + case 0: + { /* Allocate a block. */ + size_t i = RANDOM (SIZEOF (block_sizes)); + size_t size = block_sizes[i]; + if (blocks[i] == NULL) + { + uintptr_t block = allocate_block (size); + if (block == 0) + abort (); + fill_block (block, size); + blocks[i] = (char *) block; + } + } + break; + case 1: + { /* Free a block. */ + size_t i = RANDOM (SIZEOF (block_sizes)); + size_t size = block_sizes[i]; + if (blocks[i] != NULL) + { + uintptr_t block = (uintptr_t) blocks[i]; + verify_block (block, size); + free_block (block); + blocks[i] = NULL; + } + } + break; + } + } + + /* Free the remaining blocks. */ + { + size_t i; + + for (i = 0; i < SIZEOF (block_sizes); i++) + if (blocks[i] != NULL) + { + uintptr_t block = (uintptr_t) blocks[i]; + size_t size = block_sizes[i]; + verify_block (block, size); + free_block (block); + } + } + } + + return 0; +} -- 2.7.4