(root)/
glibc-2.38/
malloc/
tst-memalign-2.c
       1  /* Test for memalign chunk reuse.
       2     Copyright (C) 2022 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <malloc.h>
      21  #include <stdio.h>
      22  #include <string.h>
      23  #include <unistd.h>
      24  #include <array_length.h>
      25  #include <libc-pointer-arith.h>
      26  #include <support/check.h>
      27  
      28  typedef struct TestCase {
      29    size_t size;
      30    size_t alignment;
      31    void *ptr1;
      32    void *ptr2;
      33  } TestCase;
      34  
      35  static TestCase tcache_allocs[] = {
      36    { 24, 32, NULL, NULL },
      37    { 24, 64, NULL, NULL },
      38    { 128, 128, NULL, NULL },
      39    { 500, 128, NULL, NULL }
      40  };
      41  #define TN array_length (tcache_allocs)
      42  
      43  static TestCase large_allocs[] = {
      44    { 23450, 64, NULL, NULL },
      45    { 23450, 64, NULL, NULL },
      46    { 23550, 64, NULL, NULL },
      47    { 23550, 64, NULL, NULL },
      48    { 23650, 64, NULL, NULL },
      49    { 23650, 64, NULL, NULL },
      50    { 33650, 64, NULL, NULL },
      51    { 33650, 64, NULL, NULL }
      52  };
      53  #define LN array_length (large_allocs)
      54  
      55  void *p;
      56  
      57  /* Sanity checks, ancillary to the actual test.  */
      58  #define CHECK(p,a) \
      59    if (p == NULL || !PTR_IS_ALIGNED (p, a)) \
      60      FAIL_EXIT1 ("NULL or misaligned memory detected.\n");
      61  
      62  static int
      63  do_test (void)
      64  {
      65    int i, j;
      66    int count;
      67    void *ptr[10];
      68    void *p;
      69  
      70    /* TCache test.  */
      71  
      72    for (i = 0; i < TN; ++ i)
      73      {
      74        size_t sz2;
      75  
      76        tcache_allocs[i].ptr1 = memalign (tcache_allocs[i].alignment, tcache_allocs[i].size);
      77        CHECK (tcache_allocs[i].ptr1, tcache_allocs[i].alignment);
      78        sz2 = malloc_usable_size (tcache_allocs[i].ptr1);
      79        free (tcache_allocs[i].ptr1);
      80  
      81        /* This should return the same chunk as was just free'd.  */
      82        tcache_allocs[i].ptr2 = memalign (tcache_allocs[i].alignment, sz2);
      83        CHECK (tcache_allocs[i].ptr2, tcache_allocs[i].alignment);
      84        free (tcache_allocs[i].ptr2);
      85  
      86        TEST_VERIFY (tcache_allocs[i].ptr1 == tcache_allocs[i].ptr2);
      87      }
      88  
      89    /* Test for non-head tcache hits.  */
      90    for (i = 0; i < array_length (ptr); ++ i)
      91      {
      92        if (i == 4)
      93  	{
      94  	  ptr[i] = memalign (64, 256);
      95  	  CHECK (ptr[i], 64);
      96  	}
      97        else
      98  	{
      99  	  ptr[i] = malloc (256);
     100  	  CHECK (ptr[i], 4);
     101  	}
     102      }
     103    for (i = 0; i < array_length (ptr); ++ i)
     104      free (ptr[i]);
     105  
     106    p = memalign (64, 256);
     107    CHECK (p, 64);
     108  
     109    count = 0;
     110    for (i = 0; i < 10; ++ i)
     111      if (ptr[i] == p)
     112        ++ count;
     113    free (p);
     114    TEST_VERIFY (count > 0);
     115  
     116    /* Large bins test.  */
     117  
     118    for (i = 0; i < LN; ++ i)
     119      {
     120        large_allocs[i].ptr1 = memalign (large_allocs[i].alignment, large_allocs[i].size);
     121        CHECK (large_allocs[i].ptr1, large_allocs[i].alignment);
     122        /* Keep chunks from combining by fragmenting the heap.  */
     123        p = malloc (512);
     124        CHECK (p, 4);
     125      }
     126  
     127    for (i = 0; i < LN; ++ i)
     128      free (large_allocs[i].ptr1);
     129  
     130    /* Force the unsorted bins to be scanned and moved to small/large
     131       bins.  */
     132    p = malloc (60000);
     133  
     134    for (i = 0; i < LN; ++ i)
     135      {
     136        large_allocs[i].ptr2 = memalign (large_allocs[i].alignment, large_allocs[i].size);
     137        CHECK (large_allocs[i].ptr2, large_allocs[i].alignment);
     138      }
     139  
     140    count = 0;
     141    for (i = 0; i < LN; ++ i)
     142      {
     143        int ok = 0;
     144        for (j = 0; j < LN; ++ j)
     145  	if (large_allocs[i].ptr1 == large_allocs[j].ptr2)
     146  	  ok = 1;
     147        if (ok == 1)
     148  	count ++;
     149      }
     150  
     151    /* The allocation algorithm is complicated outside of the memalign
     152       logic, so just make sure it's working for most of the
     153       allocations.  This avoids possible boundary conditions with
     154       empty/full heaps.  */
     155    TEST_VERIFY (count > LN / 2);
     156  
     157    return 0;
     158  }
     159  
     160  #include <support/test-driver.c>