pthread_key_create.c raw

   1  #include "pthread_impl.h"
   2  
   3  volatile size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX;
   4  void *__pthread_tsd_main[PTHREAD_KEYS_MAX] = { 0 };
   5  
   6  static void (*keys[PTHREAD_KEYS_MAX])(void *);
   7  
   8  static pthread_rwlock_t key_lock = PTHREAD_RWLOCK_INITIALIZER;
   9  
  10  static pthread_key_t next_key;
  11  
  12  static void nodtor(void *dummy)
  13  {
  14  }
  15  
  16  static void dummy_0(void)
  17  {
  18  }
  19  
  20  weak_alias(dummy_0, __tl_lock);
  21  weak_alias(dummy_0, __tl_unlock);
  22  
  23  int __pthread_key_create(pthread_key_t *k, void (*dtor)(void *))
  24  {
  25  	pthread_t self = __pthread_self();
  26  
  27  	/* This can only happen in the main thread before
  28  	 * pthread_create has been called. */
  29  	if (!self->tsd) self->tsd = __pthread_tsd_main;
  30  
  31  	/* Purely a sentinel value since null means slot is free. */
  32  	if (!dtor) dtor = nodtor;
  33  
  34  	__pthread_rwlock_wrlock(&key_lock);
  35  	pthread_key_t j = next_key;
  36  	do {
  37  		if (!keys[j]) {
  38  			keys[next_key = *k = j] = dtor;
  39  			__pthread_rwlock_unlock(&key_lock);
  40  			return 0;
  41  		}
  42  	} while ((j=(j+1)%PTHREAD_KEYS_MAX) != next_key);
  43  
  44  	__pthread_rwlock_unlock(&key_lock);
  45  	return EAGAIN;
  46  }
  47  
  48  int __pthread_key_delete(pthread_key_t k)
  49  {
  50  	sigset_t set;
  51  	pthread_t self = __pthread_self(), td=self;
  52  
  53  	__block_app_sigs(&set);
  54  	__pthread_rwlock_wrlock(&key_lock);
  55  
  56  	__tl_lock();
  57  	do td->tsd[k] = 0;
  58  	while ((td=td->next)!=self);
  59  	__tl_unlock();
  60  
  61  	keys[k] = 0;
  62  
  63  	__pthread_rwlock_unlock(&key_lock);
  64  	__restore_sigs(&set);
  65  
  66  	return 0;
  67  }
  68  
  69  void __pthread_tsd_run_dtors()
  70  {
  71  	pthread_t self = __pthread_self();
  72  	int i, j;
  73  	for (j=0; self->tsd_used && j<PTHREAD_DESTRUCTOR_ITERATIONS; j++) {
  74  		__pthread_rwlock_rdlock(&key_lock);
  75  		self->tsd_used = 0;
  76  		for (i=0; i<PTHREAD_KEYS_MAX; i++) {
  77  			void *val = self->tsd[i];
  78  			void (*dtor)(void *) = keys[i];
  79  			self->tsd[i] = 0;
  80  			if (val && dtor && dtor != nodtor) {
  81  				__pthread_rwlock_unlock(&key_lock);
  82  				dtor(val);
  83  				__pthread_rwlock_rdlock(&key_lock);
  84  			}
  85  		}
  86  		__pthread_rwlock_unlock(&key_lock);
  87  	}
  88  }
  89  
  90  weak_alias(__pthread_key_create, pthread_key_create);
  91  weak_alias(__pthread_key_delete, pthread_key_delete);
  92