Blame malloc/tst-mallocstate.c

Packit Service 82fcde
/* Emulate Emacs heap dumping to test malloc_set_state.
Packit Service 82fcde
   Copyright (C) 2001-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Wolfram Gloger <wg@malloc.de>, 2001.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <stdbool.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <libc-symbols.h>
Packit Service 82fcde
#include <shlib-compat.h>
Packit Service 82fcde
#include <support/check.h>
Packit Service 82fcde
#include <support/support.h>
Packit Service 82fcde
#include <support/test-driver.h>
Packit Service 82fcde
Packit Service 82fcde
#include "malloc.h"
Packit Service 82fcde
Packit Service 82fcde
#if TEST_COMPAT (libc, GLIBC_2_0, GLIBC_2_25)
Packit Service 82fcde
Packit Service 82fcde
/* Make the compatibility symbols availabile to this test case.  */
Packit Service 82fcde
void *malloc_get_state (void);
Packit Service 82fcde
compat_symbol_reference (libc, malloc_get_state, malloc_get_state, GLIBC_2_0);
Packit Service 82fcde
int malloc_set_state (void *);
Packit Service 82fcde
compat_symbol_reference (libc, malloc_set_state, malloc_set_state, GLIBC_2_0);
Packit Service 82fcde
Packit Service 82fcde
/* Maximum object size in the fake heap.  */
Packit Service 82fcde
enum { max_size = 64 };
Packit Service 82fcde
Packit Service 82fcde
/* Allocation actions.  These are randomized actions executed on the
Packit Service 82fcde
   dumped heap (see allocation_tasks below).  They are interspersed
Packit Service 82fcde
   with operations on the new heap (see heap_activity).  */
Packit Service 82fcde
enum allocation_action
Packit Service 82fcde
  {
Packit Service 82fcde
    action_free,                /* Dumped and freed.  */
Packit Service 82fcde
    action_realloc,             /* Dumped and realloc'ed.  */
Packit Service 82fcde
    action_realloc_same,        /* Dumped and realloc'ed, same size.  */
Packit Service 82fcde
    action_realloc_smaller,     /* Dumped and realloc'ed, shrinked.  */
Packit Service 82fcde
    action_count
Packit Service 82fcde
  };
Packit Service 82fcde
Packit Service 82fcde
/* Dumped heap.  Initialize it, so that the object is placed into the
Packit Service 82fcde
   .data section, for increased realism.  The size is an upper bound;
Packit Service 82fcde
   we use about half of the space.  */
Packit Service 82fcde
static size_t dumped_heap[action_count * max_size * max_size
Packit Service 82fcde
                          / sizeof (size_t)] = {1};
Packit Service 82fcde
Packit Service 82fcde
/* Next free space in the dumped heap.  Also top of the heap at the
Packit Service 82fcde
   end of the initialization procedure.  */
Packit Service 82fcde
static size_t *next_heap_chunk;
Packit Service 82fcde
Packit Service 82fcde
/* Copied from malloc.c and hooks.c.  The version is deliberately
Packit Service 82fcde
   lower than the final version of malloc_set_state.  */
Packit Service 82fcde
# define NBINS 128
Packit Service 82fcde
# define MALLOC_STATE_MAGIC   0x444c4541l
Packit Service 82fcde
# define MALLOC_STATE_VERSION (0 * 0x100l + 4l)
Packit Service 82fcde
static struct
Packit Service 82fcde
{
Packit Service 82fcde
  long magic;
Packit Service 82fcde
  long version;
Packit Service 82fcde
  void *av[NBINS * 2 + 2];
Packit Service 82fcde
  char *sbrk_base;
Packit Service 82fcde
  int sbrked_mem_bytes;
Packit Service 82fcde
  unsigned long trim_threshold;
Packit Service 82fcde
  unsigned long top_pad;
Packit Service 82fcde
  unsigned int n_mmaps_max;
Packit Service 82fcde
  unsigned long mmap_threshold;
Packit Service 82fcde
  int check_action;
Packit Service 82fcde
  unsigned long max_sbrked_mem;
Packit Service 82fcde
  unsigned long max_total_mem;
Packit Service 82fcde
  unsigned int n_mmaps;
Packit Service 82fcde
  unsigned int max_n_mmaps;
Packit Service 82fcde
  unsigned long mmapped_mem;
Packit Service 82fcde
  unsigned long max_mmapped_mem;
Packit Service 82fcde
  int using_malloc_checking;
Packit Service 82fcde
  unsigned long max_fast;
Packit Service 82fcde
  unsigned long arena_test;
Packit Service 82fcde
  unsigned long arena_max;
Packit Service 82fcde
  unsigned long narenas;
Packit Service 82fcde
} save_state =
Packit Service 82fcde
  {
Packit Service 82fcde
    .magic = MALLOC_STATE_MAGIC,
Packit Service 82fcde
    .version = MALLOC_STATE_VERSION,
Packit Service 82fcde
  };
Packit Service 82fcde
Packit Service 82fcde
/* Allocate a blob in the fake heap.  */
Packit Service 82fcde
static void *
Packit Service 82fcde
dumped_heap_alloc (size_t length)
Packit Service 82fcde
{
Packit Service 82fcde
  /* malloc needs three state bits in the size field, so the minimum
Packit Service 82fcde
     alignment is 8 even on 32-bit architectures.  malloc_set_state
Packit Service 82fcde
     should be compatible with such heaps even if it currently
Packit Service 82fcde
     provides more alignment to applications.  */
Packit Service 82fcde
  enum
Packit Service 82fcde
  {
Packit Service 82fcde
    heap_alignment = 8,
Packit Service 82fcde
    heap_alignment_mask = heap_alignment - 1
Packit Service 82fcde
  };
Packit Service 82fcde
  _Static_assert (sizeof (size_t) <= heap_alignment,
Packit Service 82fcde
                  "size_t compatible with heap alignment");
Packit Service 82fcde
Packit Service 82fcde
  /* Need at least this many bytes for metadata and application
Packit Service 82fcde
     data. */
Packit Service 82fcde
  size_t chunk_size = sizeof (size_t) + length;
Packit Service 82fcde
  /* Round up the allocation size to the heap alignment.  */
Packit Service 82fcde
  chunk_size += heap_alignment_mask;
Packit Service 82fcde
  chunk_size &= ~heap_alignment_mask;
Packit Service 82fcde
  TEST_VERIFY_EXIT ((chunk_size & 3) == 0);
Packit Service 82fcde
  if (next_heap_chunk == NULL)
Packit Service 82fcde
    /* Initialize the top of the heap.  Add one word of zero padding,
Packit Service 82fcde
       to match existing practice.  */
Packit Service 82fcde
    {
Packit Service 82fcde
      dumped_heap[0] = 0;
Packit Service 82fcde
      next_heap_chunk = dumped_heap + 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    /* The previous chunk is allocated. */
Packit Service 82fcde
    chunk_size |= 1;
Packit Service 82fcde
  *next_heap_chunk = chunk_size;
Packit Service 82fcde
Packit Service 82fcde
  /* User data starts after the chunk header.  */
Packit Service 82fcde
  void *result = next_heap_chunk + 1;
Packit Service 82fcde
  next_heap_chunk += chunk_size / sizeof (size_t);
Packit Service 82fcde
Packit Service 82fcde
  /* Mark the previous chunk as used.   */
Packit Service 82fcde
  *next_heap_chunk = 1;
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Global seed variable for the random number generator.  */
Packit Service 82fcde
static unsigned long long global_seed;
Packit Service 82fcde
Packit Service 82fcde
/* Simple random number generator.  The numbers are in the range from
Packit Service 82fcde
   0 to UINT_MAX (inclusive).  */
Packit Service 82fcde
static unsigned int
Packit Service 82fcde
rand_next (unsigned long long *seed)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Linear congruential generated as used for MMIX.  */
Packit Service 82fcde
  *seed = *seed * 6364136223846793005ULL + 1442695040888963407ULL;
Packit Service 82fcde
  return *seed >> 32;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Fill LENGTH bytes at BUFFER with random contents, as determined by
Packit Service 82fcde
   SEED.  */
Packit Service 82fcde
static void
Packit Service 82fcde
randomize_buffer (unsigned char *buffer, size_t length,
Packit Service 82fcde
                  unsigned long long seed)
Packit Service 82fcde
{
Packit Service 82fcde
  for (size_t i = 0; i < length; ++i)
Packit Service 82fcde
    buffer[i] = rand_next (&seed);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Dumps the buffer to standard output,  in hexadecimal.  */
Packit Service 82fcde
static void
Packit Service 82fcde
dump_hex (unsigned char *buffer, size_t length)
Packit Service 82fcde
{
Packit Service 82fcde
  for (int i = 0; i < length; ++i)
Packit Service 82fcde
    printf (" %02X", buffer[i]);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Set to true if an error is encountered.  */
Packit Service 82fcde
static bool errors = false;
Packit Service 82fcde
Packit Service 82fcde
/* Keep track of object allocations.  */
Packit Service 82fcde
struct allocation
Packit Service 82fcde
{
Packit Service 82fcde
  unsigned char *data;
Packit Service 82fcde
  unsigned int size;
Packit Service 82fcde
  unsigned int seed;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Check that the allocation task allocation has the expected
Packit Service 82fcde
   contents.  */
Packit Service 82fcde
static void
Packit Service 82fcde
check_allocation (const struct allocation *alloc, int index)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t size = alloc->size;
Packit Service 82fcde
  if (alloc->data == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("error: NULL pointer for allocation of size %zu at %d, seed %u\n",
Packit Service 82fcde
              size, index, alloc->seed);
Packit Service 82fcde
      errors = true;
Packit Service 82fcde
      return;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  unsigned char expected[4096];
Packit Service 82fcde
  if (size > sizeof (expected))
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("error: invalid allocation size %zu at %d, seed %u\n",
Packit Service 82fcde
              size, index, alloc->seed);
Packit Service 82fcde
      errors = true;
Packit Service 82fcde
      return;
Packit Service 82fcde
    }
Packit Service 82fcde
  randomize_buffer (expected, size, alloc->seed);
Packit Service 82fcde
  if (memcmp (alloc->data, expected, size) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("error: allocation %d data mismatch, size %zu, seed %u\n",
Packit Service 82fcde
              index, size, alloc->seed);
Packit Service 82fcde
      printf ("  expected:");
Packit Service 82fcde
      dump_hex (expected, size);
Packit Service 82fcde
      putc ('\n', stdout);
Packit Service 82fcde
      printf ("    actual:");
Packit Service 82fcde
      dump_hex (alloc->data, size);
Packit Service 82fcde
      putc ('\n', stdout);
Packit Service 82fcde
      errors = true;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* A heap allocation combined with pending actions on it.  */
Packit Service 82fcde
struct allocation_task
Packit Service 82fcde
{
Packit Service 82fcde
  struct allocation allocation;
Packit Service 82fcde
  enum allocation_action action;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Allocation tasks.  Initialized by init_allocation_tasks and used by
Packit Service 82fcde
   perform_allocations.  */
Packit Service 82fcde
enum { allocation_task_count = action_count * max_size };
Packit Service 82fcde
static struct allocation_task allocation_tasks[allocation_task_count];
Packit Service 82fcde
Packit Service 82fcde
/* Fisher-Yates shuffle of allocation_tasks.  */
Packit Service 82fcde
static void
Packit Service 82fcde
shuffle_allocation_tasks (void)
Packit Service 82fcde
{
Packit Service 82fcde
  for (int i = 0; i < allocation_task_count - 1; ++i)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Pick pair in the tail of the array.  */
Packit Service 82fcde
      int j = i + (rand_next (&global_seed)
Packit Service 82fcde
                   % ((unsigned) (allocation_task_count - i)));
Packit Service 82fcde
      TEST_VERIFY_EXIT (j >= 0 && j < allocation_task_count);
Packit Service 82fcde
      /* Exchange. */
Packit Service 82fcde
      struct allocation_task tmp = allocation_tasks[i];
Packit Service 82fcde
      allocation_tasks[i] = allocation_tasks[j];
Packit Service 82fcde
      allocation_tasks[j] = tmp;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Set up the allocation tasks and the dumped heap.  */
Packit Service 82fcde
static void
Packit Service 82fcde
initial_allocations (void)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Initialize in a position-dependent way.  */
Packit Service 82fcde
  for (int i = 0; i < allocation_task_count; ++i)
Packit Service 82fcde
    allocation_tasks[i] = (struct allocation_task)
Packit Service 82fcde
      {
Packit Service 82fcde
        .allocation =
Packit Service 82fcde
          {
Packit Service 82fcde
            .size = 1 + (i / action_count),
Packit Service 82fcde
            .seed = i,
Packit Service 82fcde
          },
Packit Service 82fcde
        .action = i % action_count
Packit Service 82fcde
      };
Packit Service 82fcde
Packit Service 82fcde
  /* Execute the tasks in a random order.  */
Packit Service 82fcde
  shuffle_allocation_tasks ();
Packit Service 82fcde
Packit Service 82fcde
  /* Initialize the contents of the dumped heap.   */
Packit Service 82fcde
  for (int i = 0; i < allocation_task_count; ++i)
Packit Service 82fcde
    {
Packit Service 82fcde
      struct allocation_task *task = allocation_tasks + i;
Packit Service 82fcde
      task->allocation.data = dumped_heap_alloc (task->allocation.size);
Packit Service 82fcde
      randomize_buffer (task->allocation.data, task->allocation.size,
Packit Service 82fcde
                        task->allocation.seed);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  for (int i = 0; i < allocation_task_count; ++i)
Packit Service 82fcde
    check_allocation (&allocation_tasks[i].allocation, i);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Indicates whether init_heap has run.  This variable needs to be
Packit Service 82fcde
   volatile because malloc is declared __THROW, which implies it is a
Packit Service 82fcde
   leaf function, but we expect it to run our hooks.  */
Packit Service 82fcde
static volatile bool heap_initialized;
Packit Service 82fcde
Packit Service 82fcde
/* Executed by glibc malloc, through __malloc_initialize_hook
Packit Service 82fcde
   below.  */
Packit Service 82fcde
static void
Packit Service 82fcde
init_heap (void)
Packit Service 82fcde
{
Packit Service 82fcde
  if (test_verbose)
Packit Service 82fcde
    printf ("info: performing heap initialization\n");
Packit Service 82fcde
  heap_initialized = true;
Packit Service 82fcde
Packit Service 82fcde
  /* Populate the dumped heap.  */
Packit Service 82fcde
  initial_allocations ();
Packit Service 82fcde
Packit Service 82fcde
  /* Complete initialization of the saved heap data structure.  */
Packit Service 82fcde
  save_state.sbrk_base = (void *) dumped_heap;
Packit Service 82fcde
  save_state.sbrked_mem_bytes = sizeof (dumped_heap);
Packit Service 82fcde
  /* Top pointer.  Adjust so that it points to the start of struct
Packit Service 82fcde
     malloc_chunk.  */
Packit Service 82fcde
  save_state.av[2] = (void *) (next_heap_chunk - 1);
Packit Service 82fcde
Packit Service 82fcde
  /* Integrate the dumped heap into the process heap.  */
Packit Service 82fcde
  TEST_VERIFY_EXIT (malloc_set_state (&save_state) == 0);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Interpose the initialization callback.  */
Packit Service 82fcde
void (*volatile __malloc_initialize_hook) (void) = init_heap;
Packit Service 82fcde
Packit Service 82fcde
/* Simulate occasional unrelated heap activity in the non-dumped
Packit Service 82fcde
   heap.  */
Packit Service 82fcde
enum { heap_activity_allocations_count = 32 };
Packit Service 82fcde
static struct allocation heap_activity_allocations
Packit Service 82fcde
  [heap_activity_allocations_count] = {};
Packit Service 82fcde
static int heap_activity_seed_counter = 1000 * 1000;
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
heap_activity (void)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Only do this from time to time.  */
Packit Service 82fcde
  if ((rand_next (&global_seed) % 4) == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      int slot = rand_next (&global_seed) % heap_activity_allocations_count;
Packit Service 82fcde
      struct allocation *alloc = heap_activity_allocations + slot;
Packit Service 82fcde
      if (alloc->data == NULL)
Packit Service 82fcde
        {
Packit Service 82fcde
          alloc->size = rand_next (&global_seed) % (4096U + 1);
Packit Service 82fcde
          alloc->data = xmalloc (alloc->size);
Packit Service 82fcde
          alloc->seed = heap_activity_seed_counter++;
Packit Service 82fcde
          randomize_buffer (alloc->data, alloc->size, alloc->seed);
Packit Service 82fcde
          check_allocation (alloc, 1000 + slot);
Packit Service 82fcde
        }
Packit Service 82fcde
      else
Packit Service 82fcde
        {
Packit Service 82fcde
          check_allocation (alloc, 1000 + slot);
Packit Service 82fcde
          free (alloc->data);
Packit Service 82fcde
          alloc->data = NULL;
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
heap_activity_deallocate (void)
Packit Service 82fcde
{
Packit Service 82fcde
  for (int i = 0; i < heap_activity_allocations_count; ++i)
Packit Service 82fcde
    free (heap_activity_allocations[i].data);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Perform a full heap check across the dumped heap allocation tasks,
Packit Service 82fcde
   and the simulated heap activity directly above.  */
Packit Service 82fcde
static void
Packit Service 82fcde
full_heap_check (void)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Dumped heap.  */
Packit Service 82fcde
  for (int i = 0; i < allocation_task_count; ++i)
Packit Service 82fcde
    if (allocation_tasks[i].allocation.data != NULL)
Packit Service 82fcde
      check_allocation (&allocation_tasks[i].allocation, i);
Packit Service 82fcde
Packit Service 82fcde
  /* Heap activity allocations.  */
Packit Service 82fcde
  for (int i = 0; i < heap_activity_allocations_count; ++i)
Packit Service 82fcde
    if (heap_activity_allocations[i].data != NULL)
Packit Service 82fcde
      check_allocation (heap_activity_allocations + i, i);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Used as an optimization barrier to force a heap allocation.  */
Packit Service 82fcde
__attribute__ ((noinline, noclone))
Packit Service 82fcde
static void
Packit Service 82fcde
my_free (void *ptr)
Packit Service 82fcde
{
Packit Service 82fcde
  free (ptr);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
do_test (void)
Packit Service 82fcde
{
Packit Service 82fcde
  my_free (malloc (1));
Packit Service 82fcde
  TEST_VERIFY_EXIT (heap_initialized);
Packit Service 82fcde
Packit Service 82fcde
  /* The first pass performs the randomly generated allocation
Packit Service 82fcde
     tasks.  */
Packit Service 82fcde
  if (test_verbose)
Packit Service 82fcde
    printf ("info: first pass through allocation tasks\n");
Packit Service 82fcde
  full_heap_check ();
Packit Service 82fcde
Packit Service 82fcde
  /* Execute the post-undump tasks in a random order.  */
Packit Service 82fcde
  shuffle_allocation_tasks ();
Packit Service 82fcde
Packit Service 82fcde
  for (int i = 0; i < allocation_task_count; ++i)
Packit Service 82fcde
    {
Packit Service 82fcde
      heap_activity ();
Packit Service 82fcde
      struct allocation_task *task = allocation_tasks + i;
Packit Service 82fcde
      switch (task->action)
Packit Service 82fcde
        {
Packit Service 82fcde
        case action_free:
Packit Service 82fcde
          check_allocation (&task->allocation, i);
Packit Service 82fcde
          free (task->allocation.data);
Packit Service 82fcde
          task->allocation.data = NULL;
Packit Service 82fcde
          break;
Packit Service 82fcde
Packit Service 82fcde
        case action_realloc:
Packit Service 82fcde
          check_allocation (&task->allocation, i);
Packit Service 82fcde
          task->allocation.data = xrealloc
Packit Service 82fcde
            (task->allocation.data, task->allocation.size + max_size);
Packit Service 82fcde
          check_allocation (&task->allocation, i);
Packit Service 82fcde
          break;
Packit Service 82fcde
Packit Service 82fcde
        case action_realloc_same:
Packit Service 82fcde
          check_allocation (&task->allocation, i);
Packit Service 82fcde
          task->allocation.data = xrealloc
Packit Service 82fcde
            (task->allocation.data, task->allocation.size);
Packit Service 82fcde
          check_allocation (&task->allocation, i);
Packit Service 82fcde
          break;
Packit Service 82fcde
Packit Service 82fcde
        case action_realloc_smaller:
Packit Service 82fcde
          check_allocation (&task->allocation, i);
Packit Service 82fcde
          size_t new_size = task->allocation.size - 1;
Packit Service 82fcde
          task->allocation.data = xrealloc (task->allocation.data, new_size);
Packit Service 82fcde
          if (new_size == 0)
Packit Service 82fcde
            {
Packit Service 82fcde
              if (task->allocation.data != NULL)
Packit Service 82fcde
                {
Packit Service 82fcde
                  printf ("error: realloc with size zero did not deallocate\n");
Packit Service 82fcde
                  errors = true;
Packit Service 82fcde
                }
Packit Service 82fcde
              /* No further action on this task.  */
Packit Service 82fcde
              task->action = action_free;
Packit Service 82fcde
            }
Packit Service 82fcde
          else
Packit Service 82fcde
            {
Packit Service 82fcde
              task->allocation.size = new_size;
Packit Service 82fcde
              check_allocation (&task->allocation, i);
Packit Service 82fcde
            }
Packit Service 82fcde
          break;
Packit Service 82fcde
Packit Service 82fcde
        case action_count:
Packit Service 82fcde
          FAIL_EXIT1 ("task->action should never be action_count");
Packit Service 82fcde
        }
Packit Service 82fcde
      full_heap_check ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* The second pass frees the objects which were allocated during the
Packit Service 82fcde
     first pass.  */
Packit Service 82fcde
  if (test_verbose)
Packit Service 82fcde
    printf ("info: second pass through allocation tasks\n");
Packit Service 82fcde
Packit Service 82fcde
  shuffle_allocation_tasks ();
Packit Service 82fcde
  for (int i = 0; i < allocation_task_count; ++i)
Packit Service 82fcde
    {
Packit Service 82fcde
      heap_activity ();
Packit Service 82fcde
      struct allocation_task *task = allocation_tasks + i;
Packit Service 82fcde
      switch (task->action)
Packit Service 82fcde
        {
Packit Service 82fcde
        case action_free:
Packit Service 82fcde
          /* Already freed, nothing to do.  */
Packit Service 82fcde
          break;
Packit Service 82fcde
Packit Service 82fcde
        case action_realloc:
Packit Service 82fcde
        case action_realloc_same:
Packit Service 82fcde
        case action_realloc_smaller:
Packit Service 82fcde
          check_allocation (&task->allocation, i);
Packit Service 82fcde
          free (task->allocation.data);
Packit Service 82fcde
          task->allocation.data = NULL;
Packit Service 82fcde
          break;
Packit Service 82fcde
Packit Service 82fcde
        case action_count:
Packit Service 82fcde
          FAIL_EXIT1 ("task->action should never be action_count");
Packit Service 82fcde
        }
Packit Service 82fcde
      full_heap_check ();
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  heap_activity_deallocate ();
Packit Service 82fcde
Packit Service 82fcde
  /* Check that the malloc_get_state stub behaves in the intended
Packit Service 82fcde
     way.  */
Packit Service 82fcde
  errno = 0;
Packit Service 82fcde
  if (malloc_get_state () != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("error: malloc_get_state succeeded\n");
Packit Service 82fcde
      errors = true;
Packit Service 82fcde
    }
Packit Service 82fcde
  if (errno != ENOSYS)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("error: malloc_get_state: %m\n");
Packit Service 82fcde
      errors = true;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return errors;
Packit Service 82fcde
}
Packit Service 82fcde
#else
Packit Service 82fcde
static int
Packit Service 82fcde
do_test (void)
Packit Service 82fcde
{
Packit Service 82fcde
  return 77;
Packit Service 82fcde
}
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#include <support/test-driver.c>