Branch: Tag:

2001-03-30

2001-03-30 09:09:09 by Fredrik Hübinette (Hubbe) <hubbe@hubbe.net>

stralloc.c may now RUN_UNLOCKED

Rev: src/stralloc.c:1.121

26:   #define HUGE HUGE_VAL   #endif /*!HUGE*/    - RCSID("$Id: stralloc.c,v 1.120 2001/03/29 20:23:32 grubba Exp $"); + RCSID("$Id: stralloc.c,v 1.121 2001/03/30 09:09:09 hubbe Exp $");    -  + #if PIKE_RUN_UNLOCKED + static PIKE_MUTEX_T *bucket_locks; +  + #define LOCK_BUCKET(HVAL) do { \ +  size_t hval__=(HVAL); \ +  PIKE_MUTEX_T *bucket_lock; \ +  while(1) \ +  { \ +  bucket_lock=bucket_locks + (hval__ % htable_size); \ +  mt_lock(bucket_lock); \ +  if(bucket_lock == bucket_locks + (hval__ % htable_size)) \ +  break; \ +  mt_unlock(bucket_lock); \ +  } \ + }while(0) +  + #define UNLOCK_BUCKET(HVAL) do { \ +  size_t hval__=(HVAL); \ +  mt_unlock(bucket_locks + ( hval__ % htable_size )); \ + }while(0) +  + #else + #define LOCK_BUCKET(HVAL) + #define UNLOCK_BUCKET(HVAL) + #endif +    #define BEGIN_HASH_SIZE 997   #define MAX_AVG_LINK_LENGTH 3   
252:       for(e=0;e<htable_size;e++)    { +  LOCK_BUCKET(e);    for(s=base_table[e];s;s=s->next)    {    if(isproblem(s))
263:    DM(add_marks_to_memhdr(no,s));    }    } +  UNLOCK_BUCKET(e);    }       DM(fprintf(stderr,"Plausible problem location(s):\n"));
300: Inside #if undefined(HASH_PREFIX)
  #ifndef HASH_PREFIX    unsigned int depth=0;   #endif -  size_t h=hval % htable_size; +  size_t h; +  LOCK_BUCKET(hval); +  h=hval % htable_size;    for(base = prev = base_table + h;( curr=*prev ); prev=&curr->next)    {   #ifdef PIKE_DEBUG
322:    *prev = curr->next;    curr->next = *base;    *base = curr; +  UNLOCK_BUCKET(hval);    return curr; /* pointer to string */    }   #ifndef HASH_PREFIX
339: Inside #if undefined(HASH_PREFIX)
   need_more_hash_prefix--;    }   #endif +  UNLOCK_BUCKET(hval);    return 0; /* not found */   }   
394:    base_table[h]=s;   }    - static void rehash(void) + static void stralloc_rehash(void)   {    int h,old;    struct pike_string **old_base;    -  + #ifdef PIKE_RUN_UNLOCKED +  int new_htable_size; +  PIKE_MUTEX_T *old_locks; +  PIKE_MUTEX_T *new_locks; +     old=htable_size;    old_base=base_table;    -  +  LOCK_BUCKET(0); +  if(old != htable_size) +  { +  /* Someone got here before us */ +  UNLOCK_BUCKET(0); +  return; +  } +  +  new_htable_size=hashprimes[++hashprimes_entry]; +  +  /* Now that we have bucket zero, the hash table +  * cannot change, go ahead and lock ALL buckets. +  * NOTE: bucket zero is already locked +  */ +  for(h=1;h<old;h++) LOCK_BUCKET(h); +  new_locks=(PIKE_MUTEX_T *)xalloc(sizeof(PIKE_MUTEX_T)*new_htable_size); +  for(h=0;h<new_htable_size;h++) +  { +  mt_init(new_locks + h); +  mt_lock(new_locks + h); +  } +  old_locks=bucket_locks; +  bucket_locks=new_locks; +  htable_size=new_htable_size; + #else +  old=htable_size; +  old_base=base_table; +     htable_size=hashprimes[++hashprimes_entry]; -  + #endif +     base_table=(struct pike_string **)xalloc(sizeof(struct pike_string *)*htable_size);    MEMSET((char *)base_table,0,sizeof(struct pike_string *)*htable_size);   
411:       if(old_base)    free((char *)old_base); +  + #ifdef PIKE_RUN_UNLOCKED +  for(h=0;h<old;h++) mt_unlock(old_locks + h); +  for(h=0;h<htable_size;h++) mt_unlock(new_locks + h); +  +  +  /* This loop tries to make sure that nobody is still waiting +  * for the old locks. I'm not sure if it actually works 100% of +  * the time though... /Hubbe +  */ +  for(h=0;h<old;h++) +  { +  mt_lock(old_locks + h); +  mt_unlock(old_locks + h); +  mt_destroy(old_locks+h);    } -  +  free((char *)old_locks); + #endif + }      /* Allocation of strings */   
494:   static void link_pike_string(struct pike_string *s, size_t hval)   {    size_t h; +  LOCK_BUCKET(hval);    h=hval % htable_size;    s->refs = 0;    s->next = base_table[h];    base_table[h] = s;    s->hval=hval;    num_strings++; -  +  UNLOCK_BUCKET(hval); +     if(num_strings > MAX_AVG_LINK_LENGTH * htable_size) -  rehash(); +  stralloc_rehash();      #ifndef HASH_PREFIX    /* These heuruistics might require tuning! /Hubbe */
801:      PMOD_EXPORT void unlink_pike_string(struct pike_string *s)   { -  size_t h = s->hval % htable_size; +  size_t h; +  LOCK_BUCKET(s->hval); +  h= s->hval % htable_size;    propagate_shared_string(s,h);    base_table[h]=s->next;   #ifdef PIKE_DEBUG    s->next=(struct pike_string *)(ptrdiff_t)-1;   #endif    num_strings--; -  +  UNLOCK_BUCKET(s->hval);   }      PMOD_EXPORT void do_free_string(struct pike_string *s)
882:    struct pike_string *p;    for(e=0;e<htable_size;e++)    { +  LOCK_BUCKET(e);    for(p=base_table[e];p;p=p->next)    {    num_distinct_strings++;
889:    allocd_strings+=p->refs;    allocd_bytes+=p->refs*DO_ALIGN(p->len+3,sizeof(void *));    } -  +  UNLOCK_BUCKET(e);    }    overhead_bytes=(sizeof(struct pike_string)-1)*num_distinct_strings;    my_strcat("\nShared string hash table:\n");
945: Inside #if defined(PIKE_DEBUG)
   for(e=0;e<htable_size;e++)    {    h=0; +  LOCK_BUCKET(e);    for(s=base_table[e];s;s=s->next)    {    num++;
982: Inside #if defined(PIKE_DEBUG)
   h=0;    }    } +  UNLOCK_BUCKET(e);    }    if(num != num_strings)    fatal("Num strings is wrong %d!=%d\n",num,num_strings);
994: Inside #if defined(PIKE_DEBUG)
   for(e=0;e<htable_size;e++)    {    struct pike_string *p; +  LOCK_BUCKET(e);    for(p=base_table[e];p;p=p->next) -  if(p==foo) return 1; +  { +  if(p==foo) +  { +  UNLOCK_BUCKET(e); +  return 1;    } -  +  } +  UNLOCK_BUCKET(e); +  }    return 0;   }   
1016: Inside #if defined(PIKE_DEBUG) and #if 0
   (long)foo->len,    foo->str);    +  LOCK_BUCKET(foo->hval);    fprintf(stderr,"------ %p %ld\n",    base_table[foo->hval %htable_size],    foo->hval);
1027: Inside #if defined(PIKE_DEBUG) and #if 0
   fprintf(stderr,"%p->",tmp2);    }    fprintf(stderr,"0\n"); +  UNLOCK_BUCKET(foo->hval);       for(e=0;e<htable_size;e++)    { -  +  LOCK_BUCKET(e);    for(tmp2=base_table[e];tmp2;tmp2=tmp2->next)    {    if(tmp2 == tmp)
1037: Inside #if defined(PIKE_DEBUG) and #if 0
   (long)e,    (long)(foo->hval % htable_size));    } +  UNLOCK_BUCKET(e);    }    }   #endif
1086: Inside #if defined(PIKE_DEBUG)
   unsigned INT32 e;    struct pike_string *p;    for(e=0;e<htable_size;e++) +  { +  LOCK_BUCKET(e);    for(p=base_table[e];p;p=p->next)    debug_dump_pike_string(p, 70); -  +  UNLOCK_BUCKET(e);    } -  + }      #endif   
1650:   /*** init/exit memory ***/   void init_shared_string_table(void)   { - #ifdef PIKE_RUN_UNLOCKED -  mt_init(&stralloc_mutex); - #endif +     init_short_pike_string0_blocks();    init_short_pike_string1_blocks();    init_short_pike_string2_blocks();
1660:    htable_size=hashprimes[hashprimes_entry];    base_table=(struct pike_string **)xalloc(sizeof(struct pike_string *)*htable_size);    MEMSET((char *)base_table,0,sizeof(struct pike_string *)*htable_size); + #ifdef PIKE_RUN_UNLOCKED +  { +  int h; +  bucket_locks=(PIKE_MUTEX_T *)xalloc(sizeof(PIKE_MUTEX_T)*htable_size); +  for(h=0;h<htable_size;h++) mt_init(bucket_locks + h);    } -  + #endif + }      #ifdef DEBUG_MALLOC   struct shared_string_location *all_shared_string_locations;
1695:       for(e=0;e<htable_size;e++)    { +  LOCK_BUCKET(e);    for(s=base_table[e];s;s=next)    {    next=s->next;
1705:   #endif    }    base_table[e]=0; +  UNLOCK_BUCKET(e);    }    free((char *)base_table);    base_table=0;
1729:    for(e=0;e<htable_size;e++)    {    struct pike_string *p; +  LOCK_BUCKET(e);    for(p=base_table[e];p;p=p->next)    {    num_++;    size_+=sizeof(struct pike_string)+(p->len<<p->size_shift);    } -  +  UNLOCK_BUCKET(e);    }   #ifdef PIKE_DEBUG    if(num_strings != num_)