典型的なmalloc
(x86-64 プラットフォームおよび Linux OS の場合) は、最初に単純にミューテックスをロックし、完了したら解放しますか、それとも、同時呼び出しのロック競合が軽減されるように、より巧妙な方法でより細かいレベルでミューテックスをロックしますか? 実際に 2 番目の方法で行う場合、どのように行うのですか?
ベストアンサー1
glibc 2.15
複数の割り当てを操作するアリーナ各アリーナには独自のロックがあります。スレッドがメモリを割り当てる必要がある場合、malloc()
アリーナを選択し、それをロックして、そこからメモリを割り当てます。
アリーナを選択するためのメカニズムはやや複雑で、ロックの競合を減らすことを目的としています。
/* arena_get() acquires an arena and locks the corresponding mutex.
First, try the one last locked successfully by this thread. (This
is the common case and handled with a macro for speed.) Then, loop
once over the circularly linked list of arenas. If no arena is
readily available, create a new one. In this latter case, `size'
is just a hint as to how much memory will be required immediately
in the new arena. */
これを念頭に置くと、malloc()
基本的には次のようになります (簡潔にするために編集されています)。
mstate ar_ptr;
void *victim;
arena_lookup(ar_ptr);
arena_lock(ar_ptr, bytes);
if(!ar_ptr)
return 0;
victim = _int_malloc(ar_ptr, bytes);
if(!victim) {
/* Maybe the failure is due to running out of mmapped areas. */
if(ar_ptr != &main_arena) {
(void)mutex_unlock(&ar_ptr->mutex);
ar_ptr = &main_arena;
(void)mutex_lock(&ar_ptr->mutex);
victim = _int_malloc(ar_ptr, bytes);
(void)mutex_unlock(&ar_ptr->mutex);
} else {
/* ... or sbrk() has failed and there is still a chance to mmap() */
ar_ptr = arena_get2(ar_ptr->next ? ar_ptr : 0, bytes);
(void)mutex_unlock(&main_arena.mutex);
if(ar_ptr) {
victim = _int_malloc(ar_ptr, bytes);
(void)mutex_unlock(&ar_ptr->mutex);
}
}
} else
(void)mutex_unlock(&ar_ptr->mutex);
return victim;
このアロケータはptmalloc
に基づいています以前の作品Doug Lea によって作成され、Wolfram Gloger によって保守されています。