首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 操作系统 >

Glibc内存储器管理-ptmalloc2源代码分析(二十二)

2012-08-08 
Glibc内存管理--ptmalloc2源代码分析(二十二)5.6.3 Arena_get2()static mstateinternal_function#if __STD

Glibc内存管理--ptmalloc2源代码分析(二十二)

5.6.3 Arena_get2()

static mstateinternal_function#if __STD_Carena_get2(mstate a_tsd, size_t size)#elsearena_get2(a_tsd, size) mstate a_tsd; size_t size;#endif{ mstate a;#ifdef PER_THREAD if ((a = get_free_list ()) == NULL && (a = reused_arena ()) == NULL) /* Nothing immediately available, so generate a new arena. */a = _int_new_arena(size);

#else if(!a_tsd) a = a_tsd = &main_arena; else { a = a_tsd->next; if(!a) { /* This can only happen while initializing the new arena. */ (void)mutex_lock(&main_arena.mutex); THREAD_STAT(++(main_arena.stat_lock_wait)); return &main_arena; } }

/* Check the global, circularly linked list for available arenas. */ bool retried = false; repeat: do { if(!mutex_trylock(&a->mutex)) { if (retried) (void)mutex_unlock(&list_lock); THREAD_STAT(++(a->stat_lock_loop)); tsd_setspecific(arena_key, (Void_t *)a); return a; } a = a->next; } while(a != a_tsd);

/* If not even the list_lock can be obtained, try again. This can happen during `atfork', or for example on systems where thread creation makes it temporarily impossible to obtain _any_ locks. */ if(!retried && mutex_trylock(&list_lock)) { /* We will block to not run in a busy loop. */ (void)mutex_lock(&list_lock); /* Since we blocked there might be an arena available now. */ retried = true; a = a_tsd; goto repeat; }

/* Nothing immediately available, so generate a new arena. */ a = _int_new_arena(size); (void)mutex_unlock(&list_lock);

#endif return a;}

?5.6.4 _int_new_arena()

static mstate_int_new_arena(size_t size){ mstate a; heap_info *h; char *ptr; unsigned long misalign; h = new_heap(size + (sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT), mp_.top_pad); if(!h) { /* Maybe size is too large to fit in a single heap. So, just try to create a minimally-sized arena and let _int_malloc() attempt to deal with the large request via mmap_chunk(). */ h = new_heap(sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT, mp_.top_pad); if(!h) return 0; }

a = h->ar_ptr = (mstate)(h+1); malloc_init_state(a); /*a->next = NULL;*/ a->system_mem = a->max_system_mem = h->size; arena_mem += h->size;

#ifdef NO_THREADS if((unsigned long)(mp_.mmapped_mem + arena_mem + main_arena.system_mem) > mp_.max_total_mem) mp_.max_total_mem = mp_.mmapped_mem + arena_mem + main_arena.system_mem;#endif /* Set up the top chunk, with proper alignment. */ ptr = (char *)(a + 1); misalign = (unsigned long)chunk2mem(ptr) & MALLOC_ALIGN_MASK; if (misalign > 0) ptr += MALLOC_ALIGNMENT - misalign; top(a) = (mchunkptr)ptr; set_head(top(a), (((char*)h + h->size) - ptr) | PREV_INUSE);

tsd_setspecific(arena_key, (Void_t *)a); mutex_init(&a->mutex); (void)mutex_lock(&a->mutex);

#ifdef PER_THREAD (void)mutex_lock(&list_lock);#endif /* Add the new arena to the global list. */ a->next = main_arena.next; atomic_write_barrier (); main_arena.next = a;#ifdef PER_THREAD ++narenas; (void)mutex_unlock(&list_lock);#endif

?将刚创建的非主分配区加入到分配区的全局链表中,如果开启了PER_THREAD优化,在arena_get2()函数中没有对全局锁list_lock加锁,这里修改全局分配区链表时需要获得全局锁list_lock。如果没有开启PER_THREAD优化,arene_get2()函数调用_int_new_arena()函数时已经获得了全局锁list_lock,所以对全局分配区链表的修改不用再加锁。

  THREAD_STAT(++(a->stat_lock_loop));  return a;}
?

?

热点排行