Example #1
0
int PREFIXED(setspecific) (tsd * key, void * value) {
    pthread_t self = pthread_self();
    int hash_val = HASH(self);
    volatile tse * entry = (volatile tse *)MALLOC_CLEAR(sizeof (tse));
    
    GC_ASSERT(self != INVALID_THREADID);
    if (0 == entry) return ENOMEM;
    pthread_mutex_lock(&(key -> lock));
    /* Could easily check for an existing entry here.	*/
    entry -> next = key -> hash[hash_val];
    entry -> thread = self;
    entry -> value = value;
    GC_ASSERT(entry -> qtid == INVALID_QTID);
    /* There can only be one writer at a time, but this needs to be	*/
    /* atomic with respect to concurrent readers.			*/ 
    *(volatile tse **)(key -> hash + hash_val) = entry;
    pthread_mutex_unlock(&(key -> lock));
    return 0;
}
Example #2
0
int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *)) {
    int i;
    tsd * result = (tsd *)MALLOC_CLEAR(sizeof (tsd));

    /* A quick alignment check, since we need atomic stores */
      GC_ASSERT((unsigned long)(&invalid_tse.next) % sizeof(tse *) == 0);
    if (0 == result) return ENOMEM;
    pthread_mutex_init(&(result -> lock), NULL);
    for (i = 0; i < TS_CACHE_SIZE; ++i) {
	result -> cache[i] = &invalid_tse;
    }
#   ifdef GC_ASSERTIONS
      for (i = 0; i < TS_HASH_SIZE; ++i) {
	GC_ASSERT(result -> hash[i] == 0);
      }
#   endif
    *key_ptr = result;
    return 0;
}
Example #3
0
GC_INNER int GC_key_create_inner(tsd ** key_ptr)
{
    int i;
    tsd * result = (tsd *)MALLOC_CLEAR(sizeof(tsd));

    /* A quick alignment check, since we need atomic stores */
    GC_ASSERT((word)(&invalid_tse.next) % sizeof(tse *) == 0);
    if (0 == result) return ENOMEM;
    pthread_mutex_init(&(result -> lock), NULL);
    for (i = 0; i < TS_CACHE_SIZE; ++i) {
      result -> cache[i] = (/* no const */ tse *)&invalid_tse;
    }
#   ifdef GC_ASSERTIONS
      for (i = 0; i < TS_HASH_SIZE; ++i) {
        GC_ASSERT(result -> hash[i].p == 0);
      }
#   endif
    *key_ptr = result;
    return 0;
}
Example #4
0
/* Called with the lock held.   */
GC_INNER int GC_setspecific(tsd * key, void * value)
{
    pthread_t self = pthread_self();
    int hash_val = HASH(self);
    volatile tse * entry;

    GC_ASSERT(self != INVALID_THREADID);
    GC_dont_gc++; /* disable GC */
    entry = (volatile tse *)MALLOC_CLEAR(sizeof(tse));
    GC_dont_gc--;
    if (0 == entry) return ENOMEM;

    pthread_mutex_lock(&(key -> lock));
    /* Could easily check for an existing entry here.   */
    entry -> next = key->hash[hash_val].p;
    entry -> thread = self;
    entry -> value = value;
    GC_ASSERT(entry -> qtid == INVALID_QTID);
    /* There can only be one writer at a time, but this needs to be     */
    /* atomic with respect to concurrent readers.                       */
    AO_store_release(&key->hash[hash_val].ao, (AO_t)entry);
    pthread_mutex_unlock(&(key -> lock));
    return 0;
}