(root)/
glibc-2.38/
nptl/
tst-tls5.c
       1  /* Copyright (C) 2003-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  /* Check alignment, overlapping and layout of TLS variables.  */
      19  #include <stdint.h>
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <pthread.h>
      23  #include <pthreadP.h>
      24  #include <sys/param.h>
      25  
      26  #include "tst-tls5.h"
      27  
      28  #ifdef TLS_REGISTER
      29  
      30  struct tls_obj tls_registry[64];
      31  
      32  static int
      33  tls_addr_cmp (const void *a, const void *b)
      34  {
      35    if (((struct tls_obj *)a)->addr < ((struct tls_obj *)b)->addr)
      36      return -1;
      37    if (((struct tls_obj *)a)->addr > ((struct tls_obj *)b)->addr)
      38      return 1;
      39    return 0;
      40  }
      41  
      42  static int
      43  do_test (void)
      44  {
      45    size_t cnt, i;
      46    int res = 0;
      47    uintptr_t min_addr = ~(uintptr_t) 0, max_addr = 0;
      48  
      49    for (cnt = 0; tls_registry[cnt].name; ++cnt);
      50    tls_registry[cnt].name = NULL;
      51    tls_registry[cnt].addr = (uintptr_t) pthread_self ();
      52    tls_registry[cnt].size = sizeof (struct pthread);
      53    tls_registry[cnt++].align = __alignof__ (struct pthread);
      54  
      55    qsort (tls_registry, cnt, sizeof (struct tls_obj), tls_addr_cmp);
      56  
      57    for (i = 0; i < cnt; ++i)
      58      {
      59        printf ("%s%s = %p, size %zd, align %zd",
      60  	      tls_registry[i].name ? "&" : "",
      61  	      tls_registry[i].name ?: "pthread_self ()",
      62  	      (void *) tls_registry[i].addr,
      63  	      tls_registry[i].size, tls_registry[i].align);
      64        if (tls_registry[i].addr & (tls_registry[i].align - 1))
      65  	{
      66  	  fputs (", WRONG ALIGNMENT", stdout);
      67  	  res = 1;
      68  	}
      69        if (i > 0
      70  	  && (tls_registry[i - 1].addr + tls_registry[i - 1].size
      71  	      > tls_registry[i].addr))
      72  	{
      73  	  fputs (", ADDRESS OVERLAP", stdout);
      74  	  res = 1;
      75  	}
      76        puts ("");
      77        if (tls_registry[i].name)
      78  	{
      79  	  min_addr = MIN (tls_registry[i].addr, min_addr);
      80  	  max_addr = MAX (tls_registry[i].addr + tls_registry[i].size,
      81  			  max_addr);
      82  	}
      83      }
      84  
      85    if (cnt > 1)
      86      {
      87  #if TLS_TCB_AT_TP
      88        if (tls_registry[cnt - 1].name)
      89  	{
      90  	  puts ("pthread_self () not larger than all TLS addresses");
      91  	  res = 1;
      92  	}
      93        else
      94  	max_addr = MAX (tls_registry[cnt - 1].addr, max_addr);
      95  #elif TLS_DTV_AT_TP
      96        if (tls_registry[0].name)
      97  	{
      98  	  puts ("pthread_self () not smaller than all TLS addresses");
      99  	  res = 1;
     100  	}
     101  #else
     102        abort ();
     103  #endif
     104        printf ("Initial TLS used block size %zd\n",
     105  	      (size_t) (max_addr - min_addr));
     106      }
     107    return res;
     108  }
     109  
     110  #define TEST_FUNCTION do_test ()
     111  
     112  #else
     113  
     114  #define TEST_FUNCTION 0
     115  
     116  #endif
     117  
     118  #include "../test-skeleton.c"