(root)/
glibc-2.38/
nptl/
pthread_getspecific.c
       1  /* Copyright (C) 2002-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  #include <stdlib.h>
      19  #include "pthreadP.h"
      20  #include <shlib-compat.h>
      21  
      22  void *
      23  ___pthread_getspecific (pthread_key_t key)
      24  {
      25    struct pthread_key_data *data;
      26  
      27    /* Special case access to the first 2nd-level block.  This is the
      28       usual case.  */
      29    if (__glibc_likely (key < PTHREAD_KEY_2NDLEVEL_SIZE))
      30      data = &THREAD_SELF->specific_1stblock[key];
      31    else
      32      {
      33        /* Verify the key is sane.  */
      34        if (key >= PTHREAD_KEYS_MAX)
      35  	/* Not valid.  */
      36  	return NULL;
      37  
      38        unsigned int idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE;
      39        unsigned int idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE;
      40  
      41        /* If the sequence number doesn't match or the key cannot be defined
      42  	 for this thread since the second level array is not allocated
      43  	 return NULL, too.  */
      44        struct pthread_key_data *level2 = THREAD_GETMEM_NC (THREAD_SELF,
      45  							  specific, idx1st);
      46        if (level2 == NULL)
      47  	/* Not allocated, therefore no data.  */
      48  	return NULL;
      49  
      50        /* There is data.  */
      51        data = &level2[idx2nd];
      52      }
      53  
      54    void *result = data->data;
      55    if (result != NULL)
      56      {
      57        uintptr_t seq = data->seq;
      58  
      59        if (__glibc_unlikely (seq != __pthread_keys[key].seq))
      60  	result = data->data = NULL;
      61      }
      62  
      63    return result;
      64  }
      65  versioned_symbol (libc, ___pthread_getspecific, pthread_getspecific,
      66  		  GLIBC_2_34);
      67  libc_hidden_ver (___pthread_getspecific, __pthread_getspecific)
      68  #ifndef SHARED
      69  strong_alias (___pthread_getspecific, __pthread_getspecific)
      70  #endif
      71  
      72  #if OTHER_SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34)
      73  compat_symbol (libpthread, ___pthread_getspecific, __pthread_getspecific,
      74  	       GLIBC_2_0);
      75  compat_symbol (libpthread, ___pthread_getspecific, pthread_getspecific,
      76  	       GLIBC_2_0);
      77  #endif