On Tue, Mar 10, 2020 at 03:04:00AM +0530, Neeraj Pal wrote:

> Hi there,
> 
> I am reading and learning the internals of malloc(3).
> So, after compiling the debug version of libc and using it for one
> basic sample code for malloc(3).
> 
> Not able to understand some parts of the following code snippet:
> 
> void
> _malloc_init(int from_rthreads)
> {
>     u_int i, nmutexes;
>     struct dir_info *d;
> 
>     _MALLOC_LOCK(1);
>     if (!from_rthreads && mopts.malloc_pool[1]) {
>         _MALLOC_UNLOCK(1);
>         return;
>     }
>     if (!mopts.malloc_canary)
>         omalloc_init();
> 
>     nmutexes = from_rthreads ? mopts.malloc_mutexes : 2;
>     if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0)
>         mprotect(&malloc_readonly, sizeof(malloc_readonly),
>             PROT_READ | PROT_WRITE);
>     for (i = 0; i < nmutexes; i++) {
>         if (mopts.malloc_pool[i])
>             continue;
>         if (i == 0) {
>             omalloc_poolinit(&d, MAP_CONCEAL);
>             d->malloc_junk = 2;
>             d->malloc_cache = 0;
>         } else {
>             omalloc_poolinit(&d, 0);
>             d->malloc_junk = mopts.def_malloc_junk;
>             d->malloc_cache = mopts.def_malloc_cache;
>         }
>         d->mutex = i;
>         mopts.malloc_pool[i] = d;
>     }
> 
>     if (from_rthreads)
>         mopts.malloc_mt = 1;
>     else
>         mopts.internal_funcs = 1;
> 
>     /*
>      * Options have been set and will never be reset.
>      * Prevent further tampering with them.
>      */
>     if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0)
>         mprotect(&malloc_readonly, sizeof(malloc_readonly), PROT_READ);
>     _MALLOC_UNLOCK(1);
> }
> 
> In the above code snippet, could some please through some light on the
> following queries
> 1. Use of nmutexes?
> 2. And, why it is looping till nmutexes and calls function
> omalloc_poolinit(&d, MAP_CONCEAL) /* when i == 0*/
> and other calls to omalloc_poolinit(&d, 0) /* when i != 0 */
> So, suppose in the case of nmutexes = 2, I am not sure where are the
> uses of these 3 initialized pools, that is, malloc_pool[0],
> malloc_pool[1] and malloc_pool[2]?

There's an off by one in your question :-)

Fo single threaded programs, two malloc_dir pools are maintained. 
One for MAP_CONCEALED memory (#0) and one for regular (#1). 
For multi-threaded porgram more pools are created. This is to avoid contention,
accesses to diffrent pools can run concurently.

> 
> 
> static void
> omalloc_poolinit(struct dir_info **dp, int mmap_flag)
> {
>     char *p;
>     size_t d_avail, regioninfo_size;
>     struct dir_info *d;
>     int i, j;
> 
>     /*
>      * Allocate dir_info with a guard page on either side. Also
>      * randomise offset inside the page at which the dir_info
>      * lies (subject to alignment by 1 << MALLOC_MINSHIFT)
>      */
>     if ((p = MMAPNONE(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2), mmap_flag)) ==
>         MAP_FAILED)
>         wrterror(NULL, "malloc init mmap failed");
>     mprotect(p + MALLOC_PAGESIZE, DIR_INFO_RSZ, PROT_READ | PROT_WRITE);
>     d_avail = (DIR_INFO_RSZ - sizeof(*d)) >> MALLOC_MINSHIFT;
>     d = (struct dir_info *)(p + MALLOC_PAGESIZE +
>         (arc4random_uniform(d_avail) << MALLOC_MINSHIFT));
> 
>     rbytes_init(d);
>     d->regions_free = d->regions_total = MALLOC_INITIAL_REGIONS;
>     regioninfo_size = d->regions_total * sizeof(struct region_info);
>     d->r = MMAP(regioninfo_size, mmap_flag);
>     if (d->r == MAP_FAILED) {
>         d->regions_total = 0;
>         wrterror(NULL, "malloc init mmap failed");
>     }
>     for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
>         LIST_INIT(&d->chunk_info_list[i]);
>         for (j = 0; j < MALLOC_CHUNK_LISTS; j++)
>             LIST_INIT(&d->chunk_dir[i][j]);
> ...
> ...
> ...
> In the above code, inside function omalloc_poolinit(), first, it will
> allocate dir_info structure with a guard page on *both sides* like
> [guard page] <dir_info> [guard page]?

yes. That way both underflow and oveflow has a chance to be caught.

> 
> And, why it is initializing the list  chunk_info_list to 32 times and
> chunk_dir to 64 times, that is chunk_info_list[0...31] and
> chunk_dir[0...31][0...31]?

The second index of chunk_dir has size MALLOC_CHUNK_LISTS which is 4,
not 32.

More than one list of free chunk pages per chunk size is maintained to
allow for more randomization.

        -Otto


> 
> Could someone please provide some hints on the above queries?
> 
> Regards,
> Neeraj
> 

Reply via email to