Back to index

tor  0.2.3.19-rc
Classes | Defines | Functions | Variables
OpenBSD_malloc_Linux.c File Reference
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <err.h>
#include "torint.h"
#include <pthread.h>

Go to the source code of this file.

Classes

struct  pginfo
struct  pgfree
struct  pdinfo

Defines

#define SOME_JUNK   0xd0 /* as in "Duh" :-) */
#define PGSHIFT   12
#define MADV_FREE   MADV_DONTNEED
#define _MALLOC_LOCK_INIT()   {;}
#define _MALLOC_LOCK()   {pthread_mutex_lock(&gen_mutex);}
#define _MALLOC_UNLOCK()   {pthread_mutex_unlock(&gen_mutex);}
#define malloc_pageshift   (PGSHIFT)
#define MALLOC_BITS   (int)((NBBY * sizeof(u_long)))
#define MALLOC_NOT_MINE   ((struct pginfo*) 0)
#define MALLOC_FREE   ((struct pginfo*) 1)
#define MALLOC_FIRST   ((struct pginfo*) 2)
#define MALLOC_FOLLOW   ((struct pginfo*) 3)
#define MALLOC_MAGIC   ((struct pginfo*) 4)
#define malloc_minsize   16UL
#define malloc_pagesize   (1UL<<malloc_pageshift)
#define malloc_maxsize   ((malloc_pagesize)>>1)
#define malloc_pagemask   ((malloc_pagesize)-1)
#define pageround(foo)   (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
#define ptr2index(foo)   (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
#define index2ptr(idx)   ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift))
#define PD_IDX(num)   ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
#define PD_OFF(num)   ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
#define PI_IDX(index)   ((index) / pdi_mod)
#define PI_OFF(index)   ((index) % pdi_mod)
#define UTRACE(a, b, c)
#define MMAP(size)
#define PTR_GAP   (malloc_pagesize - sizeof(void *))
#define PTR_SIZE   (sizeof(void *))
#define PTR_ALIGNED(p)   (((unsigned long)p & malloc_pagemask) == PTR_GAP)
#define SIZE_MAX   SIZE_T_MAX

Functions

static int issetugid (void)
static void * imalloc (size_t size)
static void ifree (void *ptr)
static void * irealloc (void *ptr, size_t size)
static void * malloc_bytes (size_t size)
void * memalign (size_t boundary, size_t size)
size_t malloc_good_size (size_t size)
static int pdir_lookup (u_long index, struct pdinfo **pdi)
static void wrterror (const char *p)
static void wrtwarning (const char *p)
static void * MMAP_A (size_t pages, size_t alignment)
static void * map_pages (size_t pages)
static void malloc_init (void)
static void * malloc_pages (size_t size)
static __inline__ int malloc_make_chunks (int bits)
static __inline__ void free_pages (void *ptr, u_long index, struct pginfo *info)
static __inline__ void free_bytes (void *ptr, u_long index, struct pginfo *info)
static void malloc_recurse (void)
void * malloc (size_t size)
void free (void *ptr)
void * realloc (void *ptr, size_t size)
void * calloc (size_t num, size_t size)
static int ispowerof2 (size_t a)
int posix_memalign (void **memptr, size_t alignment, size_t size)
void * valloc (size_t size)

Variables

static int align = 0
static size_t g_alignment = 0
int __libc_enable_secure
static pthread_mutex_t gen_mutex = PTHREAD_MUTEX_INITIALIZER
static unsigned int malloc_started
static unsigned int malloc_cache = 16
static struct pdinfolast_dir
static struct pdinfoprev_dir
static size_t pdi_off
static u_long pdi_mod
static u_long last_index
static struct pginfo ** page_dir
static struct pgfree
static int malloc_abort = 2
static int suicide
static int malloc_silent
static int malloc_realloc
static int malloc_freeprot
static size_t malloc_guard = 0
static size_t malloc_guarded
static int malloc_ptrguard
static int malloc_hint = 1
static int malloc_xmalloc
static int malloc_zero
static int malloc_junk
static int malloc_active
static size_t malloc_used
static caddr_t malloc_brk
static struct pgfreepx
char * malloc_options
static const char * malloc_func
char * __progname

Class Documentation

struct pginfo

Definition at line 115 of file OpenBSD_malloc_Linux.c.

Collaboration diagram for pginfo:
Class Members
u_long bits
u_short free
struct pginfo * next
void * page
u_short shift
u_short size
u_short total
struct pgfree

Definition at line 131 of file OpenBSD_malloc_Linux.c.

Collaboration diagram for pgfree:
Class Members
struct pgfree * next
void * page
void * pdir
struct pgfree * prev
size_t size
struct pdinfo

Definition at line 178 of file OpenBSD_malloc_Linux.c.

Collaboration diagram for pdinfo:
Class Members
struct pginfo ** base
u_long dirnum
struct pdinfo * next
struct pdinfo * prev

Define Documentation

#define _MALLOC_LOCK ( )    {pthread_mutex_lock(&gen_mutex);}

Definition at line 96 of file OpenBSD_malloc_Linux.c.

#define _MALLOC_LOCK_INIT ( )    {;}

Definition at line 95 of file OpenBSD_malloc_Linux.c.

#define _MALLOC_UNLOCK ( )    {pthread_mutex_unlock(&gen_mutex);}

Definition at line 97 of file OpenBSD_malloc_Linux.c.

#define index2ptr (   idx)    ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift))

Definition at line 169 of file OpenBSD_malloc_Linux.c.

#define MADV_FREE   MADV_DONTNEED

Definition at line 91 of file OpenBSD_malloc_Linux.c.

#define MALLOC_BITS   (int)((NBBY * sizeof(u_long)))

Definition at line 126 of file OpenBSD_malloc_Linux.c.

#define MALLOC_FIRST   ((struct pginfo*) 2)

Definition at line 144 of file OpenBSD_malloc_Linux.c.

#define MALLOC_FOLLOW   ((struct pginfo*) 3)

Definition at line 145 of file OpenBSD_malloc_Linux.c.

#define MALLOC_FREE   ((struct pginfo*) 1)

Definition at line 143 of file OpenBSD_malloc_Linux.c.

#define MALLOC_MAGIC   ((struct pginfo*) 4)

Definition at line 146 of file OpenBSD_malloc_Linux.c.

#define malloc_maxsize   ((malloc_pagesize)>>1)

Definition at line 161 of file OpenBSD_malloc_Linux.c.

#define malloc_minsize   16UL

Definition at line 149 of file OpenBSD_malloc_Linux.c.

#define MALLOC_NOT_MINE   ((struct pginfo*) 0)

Definition at line 142 of file OpenBSD_malloc_Linux.c.

#define malloc_pagemask   ((malloc_pagesize)-1)

Definition at line 165 of file OpenBSD_malloc_Linux.c.

#define malloc_pageshift   (PGSHIFT)

Definition at line 107 of file OpenBSD_malloc_Linux.c.

#define malloc_pagesize   (1UL<<malloc_pageshift)

Definition at line 153 of file OpenBSD_malloc_Linux.c.

#define MMAP (   size)
Value:
mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
           -1, (off_t)0)

Definition at line 277 of file OpenBSD_malloc_Linux.c.

#define pageround (   foo)    (((foo) + (malloc_pagemask)) & ~malloc_pagemask)

Definition at line 167 of file OpenBSD_malloc_Linux.c.

#define PD_IDX (   num)    ((num) / (malloc_pagesize/sizeof(struct pginfo *)))

Definition at line 189 of file OpenBSD_malloc_Linux.c.

#define PD_OFF (   num)    ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))

Definition at line 190 of file OpenBSD_malloc_Linux.c.

#define PGSHIFT   12

Definition at line 90 of file OpenBSD_malloc_Linux.c.

#define PI_IDX (   index)    ((index) / pdi_mod)

Definition at line 191 of file OpenBSD_malloc_Linux.c.

#define PI_OFF (   index)    ((index) % pdi_mod)

Definition at line 192 of file OpenBSD_malloc_Linux.c.

#define ptr2index (   foo)    (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)

Definition at line 168 of file OpenBSD_malloc_Linux.c.

#define PTR_ALIGNED (   p)    (((unsigned long)p & malloc_pagemask) == PTR_GAP)

Definition at line 1216 of file OpenBSD_malloc_Linux.c.

#define PTR_GAP   (malloc_pagesize - sizeof(void *))

Definition at line 1214 of file OpenBSD_malloc_Linux.c.

#define PTR_SIZE   (sizeof(void *))

Definition at line 1215 of file OpenBSD_malloc_Linux.c.

#define SIZE_MAX   SIZE_T_MAX

Definition at line 1954 of file OpenBSD_malloc_Linux.c.

#define SOME_JUNK   0xd0 /* as in "Duh" :-) */

Definition at line 41 of file OpenBSD_malloc_Linux.c.

#define UTRACE (   a,
  b,
 
)

Definition at line 256 of file OpenBSD_malloc_Linux.c.


Function Documentation

void* calloc ( size_t  num,
size_t  size 
)

Definition at line 1958 of file OpenBSD_malloc_Linux.c.

{
       void *p;
       
       if (num && SIZE_MAX / num < size) {
              fprintf(stderr,"OOOOPS");
              errno = ENOMEM;
              return NULL;
       }
       size *= num;
       p = malloc(size);
       if (p)
              memset(p, 0, size);
       return(p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void free ( void *  ptr)

Definition at line 1901 of file OpenBSD_malloc_Linux.c.

{
       /* This is legal. XXX quick path */
       if (ptr == NULL)
              return;

       _MALLOC_LOCK();
       malloc_func = " in free():";
       if (malloc_active++) {
              malloc_recurse();
              return;
       }
       ifree(ptr);
       UTRACE(ptr, 0, 0);
       malloc_active--;
       _MALLOC_UNLOCK();
       return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static __inline__ void free_bytes ( void *  ptr,
u_long  index,
struct pginfo info 
) [static]

Definition at line 1706 of file OpenBSD_malloc_Linux.c.

{
       struct pginfo **mp, **pd;
       struct pdinfo *pi;
#ifdef MALLOC_EXTRA_SANITY
       u_long        pidx;
#endif /* MALLOC_EXTRA_SANITY */
       void          *vp;
       long          i;
       (void) index;

       /* Find the chunk number on the page */
       i = ((u_long) ptr & malloc_pagemask) >> info->shift;

       if ((u_long) ptr & ((1UL << (info->shift)) - 1)) {
              wrtwarning("modified (chunk-) pointer");
              return;
       }
       if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
              wrtwarning("chunk is already free");
              return;
       }
       if (malloc_junk && info->size != 0)
              memset(ptr, SOME_JUNK, (size_t)info->size);

       info->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
       info->free++;

       if (info->size != 0)
              mp = page_dir + info->shift;
       else
              mp = page_dir;

       if (info->free == 1) {
              /* Page became non-full */

              /* Insert in address order */
              while (*mp != NULL && (*mp)->next != NULL &&
                  (*mp)->next->page < info->page)
                     mp = &(*mp)->next;
              info->next = *mp;
              *mp = info;
              return;
       }
       if (info->free != info->total)
              return;

       /* Find & remove this page in the queue */
       while (*mp != info) {
              mp = &((*mp)->next);
#ifdef MALLOC_EXTRA_SANITY
              if (!*mp) {
                     wrterror("(ES): Not on queue");
                     errno = EFAULT;
                     return;
              }
#endif /* MALLOC_EXTRA_SANITY */
       }
       *mp = info->next;

       /* Free the page & the info structure if need be */
       pdir_lookup(ptr2index(info->page), &pi);
#ifdef MALLOC_EXTRA_SANITY
       pidx = PI_IDX(ptr2index(info->page));
       if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
              wrterror("(ES): mapped pages not found in directory");
              errno = EFAULT;
              return;
       }
#endif /* MALLOC_EXTRA_SANITY */
       if (pi != last_dir) {
              prev_dir = last_dir;
              last_dir = pi;
       }
       pd = pi->base;
       pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;

       /* If the page was mprotected, unprotect it before releasing it */
       if (info->size == 0)
              mprotect(info->page, malloc_pagesize, PROT_READ | PROT_WRITE);

       vp = info->page;     /* Order is important ! */
       if (vp != (void *) info)
              ifree(info);
       ifree(vp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static __inline__ void free_pages ( void *  ptr,
u_long  index,
struct pginfo info 
) [static]

Definition at line 1401 of file OpenBSD_malloc_Linux.c.

{
       u_long        i, pidx, lidx;
       size_t        l, cachesize = 0;
       struct pginfo **pd;
       struct pdinfo *pi, *spi;
       struct pgfree *pf, *pt = NULL;
       caddr_t              tail;

       if (info == MALLOC_FREE) {
              wrtwarning("page is already free");
              return;
       }
       if (info != MALLOC_FIRST) {
              wrtwarning("free_pages: pointer to wrong page");
              return;
       }
       if ((u_long) ptr & malloc_pagemask) {
              wrtwarning("modified (page-) pointer");
              return;
       }
       /* Count how many pages and mark them free at the same time */
       pidx = PI_IDX(index);
       pdir_lookup(index, &pi);
#ifdef MALLOC_EXTRA_SANITY
       if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
              wrterror("(ES): mapped pages not found in directory");
              errno = EFAULT;
              return;
       }
#endif /* MALLOC_EXTRA_SANITY */

       spi = pi;            /* Save page index for start of region. */

       pd = pi->base;
       pd[PI_OFF(index)] = MALLOC_FREE;
       i = 1;
       if (!PI_OFF(index + i)) {
              pi = pi->next;
              if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i))
                     pi = NULL;
              else
                     pd = pi->base;
       }
       while (pi != NULL && pd[PI_OFF(index + i)] == MALLOC_FOLLOW) {
              pd[PI_OFF(index + i)] = MALLOC_FREE;
              i++;
              if (!PI_OFF(index + i)) {
                     if ((pi = pi->next) == NULL ||
                         PD_IDX(pi->dirnum) != PI_IDX(index + i))
                            pi = NULL;
                     else
                            pd = pi->base;
              }
       }

       l = i << malloc_pageshift;

       if (malloc_junk)
              memset(ptr, SOME_JUNK, l);

       malloc_used -= l;
       malloc_guarded -= malloc_guard;
       if (malloc_guard) {
#ifdef MALLOC_EXTRA_SANITY
              if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) {
                     wrterror("(ES): hole in mapped pages directory");
                     errno = EFAULT;
                     return;
              }
#endif /* MALLOC_EXTRA_SANITY */
              pd[PI_OFF(index + i)] = MALLOC_FREE;
              l += malloc_guard;
       }
       tail = (caddr_t)ptr + l;

       if (malloc_hint)
              madvise(ptr, l, MADV_FREE);

       if (malloc_freeprot)
              mprotect(ptr, l, PROT_NONE);

       /* Add to free-list. */
       if (px == NULL && (px = malloc_bytes(sizeof *px)) == NULL)
                     goto not_return;
       px->page = ptr;
       px->pdir = spi;
       px->size = l;

       if (free_list.next == NULL) {
              /* Nothing on free list, put this at head. */
              px->next = NULL;
              px->prev = &free_list;
              free_list.next = px;
              pf = px;
              px = NULL;
       } else {
              /*
               * Find the right spot, leave pf pointing to the modified
               * entry.
               */

              /* Race ahead here, while calculating cache size. */
              for (pf = free_list.next;
                  (caddr_t)ptr > ((caddr_t)pf->page + pf->size)
                  && pf->next != NULL;
                  pf = pf->next)
                     cachesize += pf->size;

              /* Finish cache size calculation. */
              pt = pf;
              while (pt) {
                     cachesize += pt->size;
                     pt = pt->next;
              }

              if ((caddr_t)pf->page > tail) {
                     /* Insert before entry */
                     px->next = pf;
                     px->prev = pf->prev;
                     pf->prev = px;
                     px->prev->next = px;
                     pf = px;
                     px = NULL;
              } else if (((caddr_t)pf->page + pf->size) == ptr) {
                     /* Append to the previous entry. */
                     cachesize -= pf->size;
                     pf->size += l;
                     if (pf->next != NULL &&
                         pf->next->page == ((caddr_t)pf->page + pf->size)) {
                            /* And collapse the next too. */
                            pt = pf->next;
                            pf->size += pt->size;
                            pf->next = pt->next;
                            if (pf->next != NULL)
                                   pf->next->prev = pf;
                     }
              } else if (pf->page == tail) {
                     /* Prepend to entry. */
                     cachesize -= pf->size;
                     pf->size += l;
                     pf->page = ptr;
                     pf->pdir = spi;
              } else if (pf->next == NULL) {
                     /* Append at tail of chain. */
                     px->next = NULL;
                     px->prev = pf;
                     pf->next = px;
                     pf = px;
                     px = NULL;
              } else {
                     wrterror("freelist is destroyed");
                     errno = EFAULT;
                     return;
              }
       }

       if (pf->pdir != last_dir) {
              prev_dir = last_dir;
              last_dir = pf->pdir;
       }

       /* Return something to OS ? */
       if (pf->size > (malloc_cache - cachesize)) {

              /*
               * Keep the cache intact.  Notice that the '>' above guarantees that
               * the pf will always have at least one page afterwards.
               */
              if (munmap((char *) pf->page + (malloc_cache - cachesize),
                  pf->size - (malloc_cache - cachesize)) != 0)
                     goto not_return;
              tail = (caddr_t)pf->page + pf->size;
              lidx = ptr2index(tail) - 1;
              pf->size = malloc_cache - cachesize;

              index = ptr2index((caddr_t)pf->page + pf->size);

              pidx = PI_IDX(index);
              if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx)
                     prev_dir = NULL;     /* Will be wiped out below ! */

              for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
                  pi = pi->next)
                     ;

              spi = pi;
              if (pi != NULL && PD_IDX(pi->dirnum) == pidx) {
                     pd = pi->base;

                     for (i = index; i <= lidx;) {
                            if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
                                   pd[PI_OFF(i)] = MALLOC_NOT_MINE;
#ifdef MALLOC_EXTRA_SANITY
                                   if (!PD_OFF(pi->dirnum)) {
                                          wrterror("(ES): pages directory underflow");
                                          errno = EFAULT;
                                          return;
                                   }
#endif /* MALLOC_EXTRA_SANITY */
                                   pi->dirnum--;
                            }
#ifdef MALLOC_EXTRA_SANITY
                            else
                                   wrtwarning("(ES): page already unmapped");
#endif /* MALLOC_EXTRA_SANITY */
                            i++;
                            if (!PI_OFF(i)) {
                                   /*
                                    * If no page in that dir, free
                                    * directory page.
                                    */
                                   if (!PD_OFF(pi->dirnum)) {
                                          /* Remove from list. */
                                          if (spi == pi)
                                                 spi = pi->prev;
                                          if (pi->prev != NULL)
                                                 pi->prev->next = pi->next;
                                          if (pi->next != NULL)
                                                 pi->next->prev = pi->prev;
                                          pi = pi->next;
                                          munmap(pd, malloc_pagesize);
                                   } else
                                          pi = pi->next;
                                   if (pi == NULL ||
                                       PD_IDX(pi->dirnum) != PI_IDX(i))
                                          break;
                                   pd = pi->base;
                            }
                     }
                     if (pi && !PD_OFF(pi->dirnum)) {
                            /* Resulting page dir is now empty. */
                            /* Remove from list. */
                            if (spi == pi)       /* Update spi only if first. */
                                   spi = pi->prev;
                            if (pi->prev != NULL)
                                   pi->prev->next = pi->next;
                            if (pi->next != NULL)
                                   pi->next->prev = pi->prev;
                            pi = pi->next;
                            munmap(pd, malloc_pagesize);
                     }
              }
              if (pi == NULL && malloc_brk == tail) {
                     /* Resize down the malloc upper boundary. */
                     last_index = index - 1;
                     malloc_brk = index2ptr(index);
              }

              /* XXX: We could realloc/shrink the pagedir here I guess. */
              if (pf->size == 0) { /* Remove from free-list as well. */
                     if (px)
                            ifree(px);
                     if ((px = pf->prev) != &free_list) {
                            if (pi == NULL && last_index == (index - 1)) {
                                   if (spi == NULL) {
                                          malloc_brk = NULL;
                                          i = 11;
                                   } else {
                                          pd = spi->base;
                                          if (PD_IDX(spi->dirnum) < pidx)
                                                 index =
                                                     ((PD_IDX(spi->dirnum) + 1) *
                                                     pdi_mod) - 1;
                                          for (pi = spi, i = index;
                                              pd[PI_OFF(i)] == MALLOC_NOT_MINE;
                                              i--)
#ifdef MALLOC_EXTRA_SANITY
                                                 if (!PI_OFF(i)) {
                                                        pi = pi->prev;
                                                        if (pi == NULL || i == 0)
                                                               break;
                                                        pd = pi->base;
                                                        i = (PD_IDX(pi->dirnum) + 1) * pdi_mod;
                                                 }
#else /* !MALLOC_EXTRA_SANITY */
                                          {
                                          }
#endif /* MALLOC_EXTRA_SANITY */
                                          malloc_brk = index2ptr(i + 1);
                                   }
                                   last_index = i;
                            }
                            if ((px->next = pf->next) != NULL)
                                   px->next->prev = px;
                     } else {
                            if ((free_list.next = pf->next) != NULL)
                                   free_list.next->prev = &free_list;
                     }
                     px = pf;
                     last_dir = prev_dir;
                     prev_dir = NULL;
              }
       }
not_return:
       if (pt != NULL)
              ifree(pt);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ifree ( void *  ptr) [static]

Definition at line 1794 of file OpenBSD_malloc_Linux.c.

{
       struct pginfo *info, **pd;
       u_long        index;
#ifdef MALLOC_EXTRA_SANITY
       u_long        pidx;
#endif /* MALLOC_EXTRA_SANITY */
       struct pdinfo *pi;

       if (!malloc_started) {
              wrtwarning("malloc() has never been called");
              return;
       }
       /* If we're already sinking, don't make matters any worse. */
       if (suicide)
              return;

       if (malloc_ptrguard && PTR_ALIGNED(ptr))
              ptr = (char *) ptr - PTR_GAP;

       index = ptr2index(ptr);

       if (index < malloc_pageshift) {
              warnx("(%p)", ptr);
              wrtwarning("ifree: junk pointer, too low to make sense");
              return;
       }
       if (index > last_index) {
              warnx("(%p)", ptr);
              wrtwarning("ifree: junk pointer, too high to make sense");
              return;
       }
       pdir_lookup(index, &pi);
#ifdef MALLOC_EXTRA_SANITY
       pidx = PI_IDX(index);
       if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
              wrterror("(ES): mapped pages not found in directory");
              errno = EFAULT;
              return;
       }
#endif /* MALLOC_EXTRA_SANITY */
       if (pi != last_dir) {
              prev_dir = last_dir;
              last_dir = pi;
       }
       pd = pi->base;
       info = pd[PI_OFF(index)];

       if (info < MALLOC_MAGIC)
              free_pages(ptr, index, info);
       else
              free_bytes(ptr, index, info);

       /* does not matter if malloc_bytes fails */
       if (px == NULL)
              px = malloc_bytes(sizeof *px);

       return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void * imalloc ( size_t  size) [static]

Definition at line 1222 of file OpenBSD_malloc_Linux.c.

{
       void          *result;
       int           ptralloc = 0;

       if (!malloc_started)
              malloc_init();

       if (suicide)
              abort();

       /* does not matter if malloc_bytes fails */
       if (px == NULL)
              px = malloc_bytes(sizeof *px);

       if (malloc_ptrguard && size == PTR_SIZE) {
              ptralloc = 1;
              size = malloc_pagesize;
       }
       if (size > SIZE_MAX - malloc_pagesize) { /* Check for overflow */
              result = NULL;
              errno = ENOMEM;
       } else if (size <= malloc_maxsize)
              result = malloc_bytes(size);
       else
              result = malloc_pages(size);

       if (malloc_abort == 1 && result == NULL)
              wrterror("allocation failed");

       if (malloc_zero && result != NULL)
              memset(result, 0, size);

       if (result && ptralloc)
              return ((char *) result + PTR_GAP);
       return (result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void * irealloc ( void *  ptr,
size_t  size 
) [static]

Definition at line 1264 of file OpenBSD_malloc_Linux.c.

{
       void          *p;
       size_t        osize;
       u_long        index, i;
       struct pginfo **mp;
       struct pginfo **pd;
       struct pdinfo *pi;
#ifdef MALLOC_EXTRA_SANITY
       u_long        pidx;
#endif /* MALLOC_EXTRA_SANITY */

       if (suicide)
              abort();

       if (!malloc_started) {
              wrtwarning("malloc() has never been called");
              return (NULL);
       }
       if (malloc_ptrguard && PTR_ALIGNED(ptr)) {
              if (size <= PTR_SIZE)
                     return (ptr);

              p = imalloc(size);
              if (p)
                     memcpy(p, ptr, PTR_SIZE);
              ifree(ptr);
              return (p);
       }
       index = ptr2index(ptr);

       if (index < malloc_pageshift) {
              wrtwarning("junk pointer, too low to make sense");
              return (NULL);
       }
       if (index > last_index) {
              wrtwarning("junk pointer, too high to make sense");
              return (NULL);
       }
       pdir_lookup(index, &pi);
#ifdef MALLOC_EXTRA_SANITY
       pidx = PI_IDX(index);
       if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
              wrterror("(ES): mapped pages not found in directory");
              errno = EFAULT;
              return (NULL);
       }
#endif /* MALLOC_EXTRA_SANITY */
       if (pi != last_dir) {
              prev_dir = last_dir;
              last_dir = pi;
       }
       pd = pi->base;
       mp = &pd[PI_OFF(index)];

       if (*mp == MALLOC_FIRST) {  /* Page allocation */

              /* Check the pointer */
              if ((u_long) ptr & malloc_pagemask) {
                     wrtwarning("modified (page-) pointer");
                     return (NULL);
              }
              /* Find the size in bytes */
              i = index;
              if (!PI_OFF(++i)) {
                     pi = pi->next;
                     if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
                            pi = NULL;
                     if (pi != NULL)
                            pd = pi->base;
              }
              for (osize = malloc_pagesize;
                  pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
                     osize += malloc_pagesize;
                     if (!PI_OFF(++i)) {
                            pi = pi->next;
                            if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
                                   pi = NULL;
                            if (pi != NULL)
                                   pd = pi->base;
                     }
              }

              if (!malloc_realloc && size <= osize &&
                  size > osize - malloc_pagesize) {
                     if (malloc_junk)
                            memset((char *)ptr + size, SOME_JUNK, osize - size);
                     return (ptr); /* ..don't do anything else. */
              }
       } else if (*mp >= MALLOC_MAGIC) {  /* Chunk allocation */

              /* Check the pointer for sane values */
              if ((u_long) ptr & ((1UL << ((*mp)->shift)) - 1)) {
                     wrtwarning("modified (chunk-) pointer");
                     return (NULL);
              }
              /* Find the chunk index in the page */
              i = ((u_long) ptr & malloc_pagemask) >> (*mp)->shift;

              /* Verify that it isn't a free chunk already */
              if ((*mp)->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
                     wrtwarning("chunk is already free");
                     return (NULL);
              }
              osize = (*mp)->size;

              if (!malloc_realloc && size <= osize &&
                  (size > osize / 2 || osize == malloc_minsize)) {
                     if (malloc_junk)
                            memset((char *) ptr + size, SOME_JUNK, osize - size);
                     return (ptr); /* ..don't do anything else. */
              }
       } else {
              wrtwarning("irealloc: pointer to wrong page");
              return (NULL);
       }

       p = imalloc(size);

       if (p != NULL) {
              /* copy the lesser of the two sizes, and free the old one */
              /* Don't move from/to 0 sized region !!! */
              if (osize != 0 && size != 0) {
                     if (osize < size)
                            memcpy(p, ptr, osize);
                     else
                            memcpy(p, ptr, size);
              }
              ifree(ptr);
       }
       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ispowerof2 ( size_t  a) [static]

Definition at line 1974 of file OpenBSD_malloc_Linux.c.

                                 {
       size_t b;
       for (b = 1ULL << (sizeof(size_t)*NBBY - 1); b > 1; b >>= 1)
         if (b == a)
              return 1;
       return 0;
}

Here is the caller graph for this function:

static int issetugid ( void  ) [static]

Definition at line 82 of file OpenBSD_malloc_Linux.c.

{
       if (__libc_enable_secure) return 1;
       if (getuid() != geteuid()) return 1;
       if (getgid() != getegid()) return 1;
       return 0;
}

Here is the caller graph for this function:

void* malloc ( size_t  size)

Definition at line 1877 of file OpenBSD_malloc_Linux.c.

{
       void          *r;

       if (!align)
       _MALLOC_LOCK();
       malloc_func = " in malloc():";
       if (malloc_active++) {
              malloc_recurse();
              return (NULL);
       }
       r = imalloc(size);
       UTRACE(0, size, r);
       malloc_active--;
       if (!align)
       _MALLOC_UNLOCK();
       if (malloc_xmalloc && r == NULL) {
              wrterror("out of memory");
              errno = ENOMEM;
       }
       return (r);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void * malloc_bytes ( size_t  size) [static]

Definition at line 1132 of file OpenBSD_malloc_Linux.c.

{
       int           i, j;
       size_t        k;
       u_long        u, *lp;
       struct pginfo *bp;

       /* Don't bother with anything less than this */
       /* unless we have a malloc(0) requests */
       if (size != 0 && size < malloc_minsize)
              size = malloc_minsize;

       /* Find the right bucket */
       if (size == 0)
              j = 0;
       else {
              j = 1;
              i = size - 1;
              while (i >>= 1)
                     j++;
       }

       /* If it's empty, make a page more of that size chunks */
       if (page_dir[j] == NULL && !malloc_make_chunks(j))
              return (NULL);

       bp = page_dir[j];

       /* Find first word of bitmap which isn't empty */
       for (lp = bp->bits; !*lp; lp++);

       /* Find that bit, and tweak it */
       u = 1;
       k = 0;
       while (!(*lp & u)) {
              u += u;
              k++;
       }

       if (malloc_guard) {
              /* Walk to a random position. */
//            i = arc4random() % bp->free;
              i = rand() % bp->free;
              while (i > 0) {
                     u += u;
                     k++;
                     if (k >= MALLOC_BITS) {
                            lp++;
                            u = 1;
                            k = 0;
                     }
#ifdef MALLOC_EXTRA_SANITY
                     if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
                            wrterror("chunk overflow");
                            errno = EFAULT;
                            return (NULL);
                     }
#endif /* MALLOC_EXTRA_SANITY */
                     if (*lp & u)
                            i--;
              }
       }
       *lp ^= u;

       /* If there are no more free, remove from free-list */
       if (!--bp->free) {
              page_dir[j] = bp->next;
              bp->next = NULL;
       }
       /* Adjust to the real offset of that chunk */
       k += (lp - bp->bits) * MALLOC_BITS;
       k <<= bp->shift;

       if (malloc_junk && bp->size != 0)
              memset((char *)bp->page + k, SOME_JUNK, (size_t)bp->size);

       return ((u_char *) bp->page + k);
}

Here is the call graph for this function:

Here is the caller graph for this function:

size_t malloc_good_size ( size_t  size)

Definition at line 2019 of file OpenBSD_malloc_Linux.c.

{
       if (size == 0) {
              return 1;
       } else if (size <= malloc_maxsize) {
              int i, j;
              /* round up to the nearest power of 2, with same approach
               * as malloc_bytes() uses. */
              j = 1;
              i = size - 1;
              while (i >>= 1)
                     j++;
              return ((size_t)1) << j;
       } else {
              return pageround(size);
       }
}

Here is the caller graph for this function:

static void malloc_init ( void  ) [static]

Definition at line 654 of file OpenBSD_malloc_Linux.c.

{
       char          *p, b[64];
       int           i, j, save_errno = errno;

       _MALLOC_LOCK_INIT();

#ifdef MALLOC_EXTRA_SANITY
       malloc_junk = 1;
#endif /* MALLOC_EXTRA_SANITY */

       for (i = 0; i < 3; i++) {
              switch (i) {
              case 0:
                     j = readlink("/etc/malloc.conf", b, sizeof b - 1);
                     if (j <= 0)
                            continue;
                     b[j] = '\0';
                     p = b;
                     break;
              case 1:
                     if (issetugid() == 0)
                            p = getenv("MALLOC_OPTIONS");
                     else
                            continue;
                     break;
              case 2:
                     p = malloc_options;
                     break;
              default:
                     p = NULL;
              }

              for (; p != NULL && *p != '\0'; p++) {
                     switch (*p) {
                     case '>':
                            malloc_cache <<= 1;
                            break;
                     case '<':
                            malloc_cache >>= 1;
                            break;
                     case 'a':
                            malloc_abort = 0;
                            break;
                     case 'A':
                            malloc_abort = 1;
                            break;
#ifdef MALLOC_STATS
                     case 'd':
                            malloc_stats = 0;
                            break;
                     case 'D':
                            malloc_stats = 1;
                            break;
#endif /* MALLOC_STATS */
                     case 'f':
                            malloc_freeprot = 0;
                            break;
                     case 'F':
                            malloc_freeprot = 1;
                            break;
                     case 'g':
                            malloc_guard = 0;
                            break;
                     case 'G':
                            malloc_guard = malloc_pagesize;
                            break;
                     case 'h':
                            malloc_hint = 0;
                            break;
                     case 'H':
                            malloc_hint = 1;
                            break;
                     case 'j':
                            malloc_junk = 0;
                            break;
                     case 'J':
                            malloc_junk = 1;
                            break;
                     case 'n':
                            malloc_silent = 0;
                            break;
                     case 'N':
                            malloc_silent = 1;
                            break;
                     case 'p':
                            malloc_ptrguard = 0;
                            break;
                     case 'P':
                            malloc_ptrguard = 1;
                            break;
                     case 'r':
                            malloc_realloc = 0;
                            break;
                     case 'R':
                            malloc_realloc = 1;
                            break;
#ifdef __FreeBSD__
                     case 'u':
                            malloc_utrace = 0;
                            break;
                     case 'U':
                            malloc_utrace = 1;
                            break;
#endif /* __FreeBSD__ */
                     case 'x':
                            malloc_xmalloc = 0;
                            break;
                     case 'X':
                            malloc_xmalloc = 1;
                            break;
                     case 'z':
                            malloc_zero = 0;
                            break;
                     case 'Z':
                            malloc_zero = 1;
                            break;
                     default:
                            j = malloc_abort;
                            malloc_abort = 0;
                            wrtwarning("unknown char in MALLOC_OPTIONS");
                            malloc_abort = j;
                            break;
                     }
              }
       }

       UTRACE(0, 0, 0);

       /*
        * We want junk in the entire allocation, and zero only in the part
        * the user asked for.
        */
       if (malloc_zero)
              malloc_junk = 1;

#ifdef MALLOC_STATS
       if (malloc_stats && (atexit(malloc_exit) == -1))
              wrtwarning("atexit(2) failed."
                  "  Will not be able to dump malloc stats on exit");
#endif /* MALLOC_STATS */

       if (malloc_pagesize != getpagesize()) {
              wrterror("malloc() replacement compiled with a different "
                      "page size from what we're running with.  Failing.");
              errno = ENOMEM;
              return;
       }

       /* Allocate one page for the page directory. */
       page_dir = (struct pginfo **)MMAP(malloc_pagesize);

       if (page_dir == MAP_FAILED) {
              wrterror("mmap(2) failed, check limits");
              errno = ENOMEM;
              return;
       }
       pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1);
       pdi_mod = pdi_off / sizeof(struct pginfo *);

       last_dir = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
       last_dir->base = page_dir;
       last_dir->prev = last_dir->next = NULL;
       last_dir->dirnum = malloc_pageshift;

       /* Been here, done that. */
       malloc_started++;

       /* Recalculate the cache size in bytes, and make sure it's nonzero. */
       if (!malloc_cache)
              malloc_cache++;
       malloc_cache <<= malloc_pageshift;
       errno = save_errno;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static __inline__ int malloc_make_chunks ( int  bits) [static]

Definition at line 1020 of file OpenBSD_malloc_Linux.c.

{
       struct pginfo *bp, **pd;
       struct pdinfo *pi;
#ifdef MALLOC_EXTRA_SANITY
       u_long        pidx;
#endif /* MALLOC_EXTRA_SANITY */
       void          *pp;
       long          i, k;
       size_t        l;

       /* Allocate a new bucket */
       pp = malloc_pages((size_t) malloc_pagesize);
       if (pp == NULL)
              return (0);

       /* Find length of admin structure */
       l = sizeof *bp - sizeof(u_long);
       l += sizeof(u_long) *
           (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS);

       /* Don't waste more than two chunks on this */

       /*
        * If we are to allocate a memory protected page for the malloc(0)
        * case (when bits=0), it must be from a different page than the
        * pginfo page.
        * --> Treat it like the big chunk alloc, get a second data page.
        */
       if (bits != 0 && (1UL << (bits)) <= l + l) {
              bp = (struct pginfo *) pp;
       } else {
              bp = (struct pginfo *) imalloc(l);
              if (bp == NULL) {
                     ifree(pp);
                     return (0);
              }
       }

       /* memory protect the page allocated in the malloc(0) case */
       if (bits == 0) {
              bp->size = 0;
              bp->shift = 1;
              i = malloc_minsize - 1;
              while (i >>= 1)
                     bp->shift++;
              bp->total = bp->free = malloc_pagesize >> bp->shift;
              bp->page = pp;

              k = mprotect(pp, malloc_pagesize, PROT_NONE);
              if (k < 0) {
                     ifree(pp);
                     ifree(bp);
                     return (0);
              }
       } else {
              bp->size = (1UL << bits);
              bp->shift = bits;
              bp->total = bp->free = malloc_pagesize >> bits;
              bp->page = pp;
       }

       /* set all valid bits in the bitmap */
       k = bp->total;
       i = 0;

       /* Do a bunch at a time */
       for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS)
              bp->bits[i / MALLOC_BITS] = ~0UL;

       for (; i < k; i++)
              bp->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);

       k = (long)l;
       if (bp == bp->page) {
              /* Mark the ones we stole for ourselves */
              for (i = 0; k > 0; i++) {
                     bp->bits[i / MALLOC_BITS] &= ~(1UL << (i % MALLOC_BITS));
                     bp->free--;
                     bp->total--;
                     k -= (1 << bits);
              }
       }
       /* MALLOC_LOCK */

       pdir_lookup(ptr2index(pp), &pi);
#ifdef MALLOC_EXTRA_SANITY
       pidx = PI_IDX(ptr2index(pp));
       if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
              wrterror("(ES): mapped pages not found in directory");
              errno = EFAULT;
              return (0);
       }
#endif /* MALLOC_EXTRA_SANITY */
       if (pi != last_dir) {
              prev_dir = last_dir;
              last_dir = pi;
       }
       pd = pi->base;
       pd[PI_OFF(ptr2index(pp))] = bp;

       bp->next = page_dir[bits];
       page_dir[bits] = bp;

       /* MALLOC_UNLOCK */
       return (1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* malloc_pages ( size_t  size) [static]

Definition at line 833 of file OpenBSD_malloc_Linux.c.

{
       void          *p, *delay_free = NULL, *tp;
       size_t        i;
       struct pginfo **pd;
       struct pdinfo *pi;
       u_long        pidx, index;
       struct pgfree *pf;

       size = pageround(size) + malloc_guard;

       p = NULL;
       /* Look for free pages before asking for more */
       if (!align)
       for (pf = free_list.next; pf; pf = pf->next) {

#ifdef MALLOC_EXTRA_SANITY
              if (pf->size & malloc_pagemask) {
                     wrterror("(ES): junk length entry on free_list");
                     errno = EFAULT;
                     return (NULL);
              }
              if (!pf->size) {
                     wrterror("(ES): zero length entry on free_list");
                     errno = EFAULT;
                     return (NULL);
              }
              if (pf->page > (pf->page + pf->size)) {
                     wrterror("(ES): sick entry on free_list");
                     errno = EFAULT;
                     return (NULL);
              }
              if ((pi = pf->pdir) == NULL) {
                     wrterror("(ES): invalid page directory on free-list");
                     errno = EFAULT;
                     return (NULL);
              }
              if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
                     wrterror("(ES): directory index mismatch on free-list");
                     errno = EFAULT;
                     return (NULL);
              }
              pd = pi->base;
              if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
                     wrterror("(ES): non-free first page on free-list");
                     errno = EFAULT;
                     return (NULL);
              }
              pidx = PI_IDX(ptr2index((pf->page) + (pf->size)) - 1);
              for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
                  pi = pi->next)
                     ;
              if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
                     wrterror("(ES): last page not referenced in page directory");
                     errno = EFAULT;
                     return (NULL);
              }
              pd = pi->base;
              if (pd[PI_OFF(ptr2index((pf->page) + (pf->size)) - 1)] != MALLOC_FREE) {
                     wrterror("(ES): non-free last page on free-list");
                     errno = EFAULT;
                     return (NULL);
              }
#endif /* MALLOC_EXTRA_SANITY */

              if (pf->size < size)
                     continue;

              if (pf->size == size) {
                     p = pf->page;
                     pi = pf->pdir;
                     if (pf->next != NULL)
                            pf->next->prev = pf->prev;
                     pf->prev->next = pf->next;
                     delay_free = pf;
                     break;
              }
              p = pf->page;
              pf->page = (char *) pf->page + size;
              pf->size -= size;
              pidx = PI_IDX(ptr2index(pf->page));
              for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
                  pi = pi->next)
                     ;
              if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
                     wrterror("(ES): hole in directories");
                     errno = EFAULT;
                     return (NULL);
              }
              tp = pf->pdir;
              pf->pdir = pi;
              pi = tp;
              break;
       }

       size -= malloc_guard;

#ifdef MALLOC_EXTRA_SANITY
       if (p != NULL && pi != NULL) {
              pidx = PD_IDX(pi->dirnum);
              pd = pi->base;
       }
       if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
              wrterror("(ES): allocated non-free page on free-list");
              errno = EFAULT;
              return (NULL);
       }
#endif /* MALLOC_EXTRA_SANITY */

       if (p != NULL && (malloc_guard || malloc_freeprot))
              mprotect(p, size, PROT_READ | PROT_WRITE);

       size >>= malloc_pageshift;

       /* Map new pages */
       if (p == NULL)
              p = map_pages(size);

       if (p != NULL) {
              index = ptr2index(p);
              pidx = PI_IDX(index);
              pdir_lookup(index, &pi);
#ifdef MALLOC_EXTRA_SANITY
              if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
                     wrterror("(ES): mapped pages not found in directory");
                     errno = EFAULT;
                     return (NULL);
              }
#endif /* MALLOC_EXTRA_SANITY */
              if (pi != last_dir) {
                     prev_dir = last_dir;
                     last_dir = pi;
              }
              pd = pi->base;
              pd[PI_OFF(index)] = MALLOC_FIRST;

              for (i = 1; i < size; i++) {
                     if (!PI_OFF(index + i)) {
                            pidx++;
                            pi = pi->next;
#ifdef MALLOC_EXTRA_SANITY
                            if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
                                   wrterror("(ES): hole in mapped pages directory");
                                   errno = EFAULT;
                                   return (NULL);
                            }
#endif /* MALLOC_EXTRA_SANITY */
                            pd = pi->base;
                     }
                     pd[PI_OFF(index + i)] = MALLOC_FOLLOW;
              }
              if (malloc_guard) {
                     if (!PI_OFF(index + i)) {
                            pidx++;
                            pi = pi->next;
#ifdef MALLOC_EXTRA_SANITY
                            if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
                                   wrterror("(ES): hole in mapped pages directory");
                                   errno = EFAULT;
                                   return (NULL);
                            }
#endif /* MALLOC_EXTRA_SANITY */
                            pd = pi->base;
                     }
                     pd[PI_OFF(index + i)] = MALLOC_FIRST;
              }

              malloc_used += size << malloc_pageshift;
              malloc_guarded += malloc_guard;

              if (malloc_junk)
                     memset(p, SOME_JUNK, size << malloc_pageshift);
       }
       if (delay_free) {
              if (px == NULL)
                     px = delay_free;
              else
                     ifree(delay_free);
       }
       return (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void malloc_recurse ( void  ) [static]

Definition at line 1860 of file OpenBSD_malloc_Linux.c.

{
       static int    noprint;

       if (noprint == 0) {
              noprint = 1;
              wrtwarning("recursive call");
       }
       malloc_active--;
       _MALLOC_UNLOCK();
       errno = EDEADLK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void* map_pages ( size_t  pages) [static]

Definition at line 540 of file OpenBSD_malloc_Linux.c.

{
       struct pdinfo *pi, *spi;
       struct pginfo **pd;
       u_long        idx, pidx, lidx;
       caddr_t              result, tail;
       u_long        index, lindex;
       void          *pdregion = NULL;
       size_t        dirs, cnt;

       pages <<= malloc_pageshift;
       if (!align)
              result = MMAP(pages + malloc_guard);
       else {
              result = MMAP_A(pages + malloc_guard, g_alignment);
       }
       if (result == MAP_FAILED) {
#ifdef MALLOC_EXTRA_SANITY
              wrtwarning("(ES): map_pages fails");
#endif /* MALLOC_EXTRA_SANITY */
              errno = ENOMEM;
              return (NULL);
       }
       index = ptr2index(result);
       tail = result + pages + malloc_guard;
       lindex = ptr2index(tail) - 1;
       if (malloc_guard)
              mprotect(result + pages, malloc_guard, PROT_NONE);

       pidx = PI_IDX(index);
       lidx = PI_IDX(lindex);

       if (tail > malloc_brk) {
              malloc_brk = tail;
              last_index = lindex;
       }

       dirs = lidx - pidx;

       /* Insert directory pages, if needed. */
       if (pdir_lookup(index, &pi) != 0)
              dirs++;

       if (dirs > 0) {
              pdregion = MMAP(malloc_pagesize * dirs);
              if (pdregion == MAP_FAILED) {
                     munmap(result, tail - result);
#ifdef MALLOC_EXTRA_SANITY
              wrtwarning("(ES): map_pages fails");
#endif
                     errno = ENOMEM;
                     return (NULL);
              }
       }

       cnt = 0;
       for (idx = pidx, spi = pi; idx <= lidx; idx++) {
              if (pi == NULL || PD_IDX(pi->dirnum) != idx) {
                     pd = (struct pginfo **)((char *)pdregion +
                         cnt * malloc_pagesize);
                     cnt++;
                     memset(pd, 0, malloc_pagesize);
                     pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);
                     pi->base = pd;
                     pi->prev = spi;
                     pi->next = spi->next;
                     pi->dirnum = idx * (malloc_pagesize /
                         sizeof(struct pginfo *));

                     if (spi->next != NULL)
                            spi->next->prev = pi;
                     spi->next = pi;
              }
              if (idx > pidx && idx < lidx) {
                     pi->dirnum += pdi_mod;
              } else if (idx == pidx) {
                     if (pidx == lidx) {
                            pi->dirnum += (u_long)(tail - result) >>
                                malloc_pageshift;
                     } else {
                            pi->dirnum += pdi_mod - PI_OFF(index);
                     }
              } else {
                     pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
              }
#ifdef MALLOC_EXTRA_SANITY
              if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) {
                     wrterror("(ES): pages directory overflow");
                     errno = EFAULT;
                     return (NULL);
              }
#endif /* MALLOC_EXTRA_SANITY */
              if (idx == pidx && pi != last_dir) {
                     prev_dir = last_dir;
                     last_dir = pi;
              }
              spi = pi;
              pi = spi->next;
       }
#ifdef MALLOC_EXTRA_SANITY
       if (cnt > dirs)
              wrtwarning("(ES): cnt > dirs");
#endif /* MALLOC_EXTRA_SANITY */
       if (cnt < dirs)
              munmap((char *)pdregion + cnt * malloc_pagesize,
                  (dirs - cnt) * malloc_pagesize);

       return (result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void * memalign ( size_t  boundary,
size_t  size 
)

Definition at line 2005 of file OpenBSD_malloc_Linux.c.

{
       void *r;
       posix_memalign(&r, boundary, size);
       return r;
}

Here is the call graph for this function:

static void* MMAP_A ( size_t  pages,
size_t  alignment 
) [static]

Definition at line 517 of file OpenBSD_malloc_Linux.c.

{
       void *j, *p;
       size_t first_size, rest, begin, end;
       if (pages%malloc_pagesize != 0)
              pages = pages - pages%malloc_pagesize + malloc_pagesize;
       first_size = pages + alignment - malloc_pagesize;
       p = MMAP(first_size);
       rest = ((size_t)p) % alignment;
       j = (rest == 0) ? p : (void*) ((size_t)p + alignment - rest);
       begin = (size_t)j - (size_t)p;
       if (begin != 0) munmap(p, begin);
       end = (size_t)p + first_size - ((size_t)j + pages);
       if(end != 0) munmap( (void*) ((size_t)j + pages), end);

       return j;
}

Here is the caller graph for this function:

static int pdir_lookup ( u_long  index,
struct pdinfo **  pdi 
) [static]

Definition at line 295 of file OpenBSD_malloc_Linux.c.

{
       struct pdinfo *spi;
       u_long        pidx = PI_IDX(index);

       if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
              *pdi = last_dir;
       else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
              *pdi = prev_dir;
       else if (last_dir != NULL && prev_dir != NULL) {
              if ((PD_IDX(last_dir->dirnum) > pidx) ?
                  (PD_IDX(last_dir->dirnum) - pidx) :
                  (pidx - PD_IDX(last_dir->dirnum))
                  < (PD_IDX(prev_dir->dirnum) > pidx) ?
                  (PD_IDX(prev_dir->dirnum) - pidx) :
                  (pidx - PD_IDX(prev_dir->dirnum)))
                     *pdi = last_dir;
              else
                     *pdi = prev_dir;

              if (PD_IDX((*pdi)->dirnum) > pidx) {
                     for (spi = (*pdi)->prev;
                         spi != NULL && PD_IDX(spi->dirnum) > pidx;
                         spi = spi->prev)
                            *pdi = spi;
                     if (spi != NULL)
                            *pdi = spi;
              } else
                     for (spi = (*pdi)->next;
                         spi != NULL && PD_IDX(spi->dirnum) <= pidx;
                         spi = spi->next)
                            *pdi = spi;
       } else {
              *pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
              for (spi = *pdi;
                  spi != NULL && PD_IDX(spi->dirnum) <= pidx;
                  spi = spi->next)
                     *pdi = spi;
       }

       return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 :
           (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1);
}

Here is the caller graph for this function:

int posix_memalign ( void **  memptr,
size_t  alignment,
size_t  size 
)

Definition at line 1982 of file OpenBSD_malloc_Linux.c.

{
       void *r;
       size_t max;
       if ((alignment < PTR_SIZE) || (alignment%PTR_SIZE != 0)) return EINVAL;
       if (!ispowerof2(alignment)) return EINVAL;
       if (alignment < malloc_minsize) alignment = malloc_minsize;
       max = alignment > size ? alignment : size;
       if (alignment <= malloc_pagesize)
              r = malloc(max);
       else {
              _MALLOC_LOCK();
              align = 1;
              g_alignment = alignment;
              r = malloc(size);
              align=0;
              _MALLOC_UNLOCK();
       }
       *memptr = r;
       if (!r) return ENOMEM;
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* realloc ( void *  ptr,
size_t  size 
)

Definition at line 1921 of file OpenBSD_malloc_Linux.c.

{
       void          *r;

       _MALLOC_LOCK();
       malloc_func = " in realloc():";
       if (malloc_active++) {
              malloc_recurse();
              return (NULL);
       }

       if (ptr == NULL)
              r = imalloc(size);
       else
              r = irealloc(ptr, size);

       UTRACE(ptr, size, r);
       malloc_active--;
       _MALLOC_UNLOCK();
       if (malloc_xmalloc && r == NULL) {
              wrterror("out of memory");
              errno = ENOMEM;
       }
       return (r);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* valloc ( size_t  size)

Definition at line 2012 of file OpenBSD_malloc_Linux.c.

{
       void *r;
       posix_memalign(&r, malloc_pagesize, size);
       return r;
}

Here is the call graph for this function:

static void wrterror ( const char *  p) [static]

Definition at line 444 of file OpenBSD_malloc_Linux.c.

{
       const char           *q = " error: ";
       struct iovec  iov[5];

       iov[0].iov_base = __progname;
       iov[0].iov_len = strlen(__progname);
       iov[1].iov_base = (char*)malloc_func;
       iov[1].iov_len = strlen(malloc_func);
       iov[2].iov_base = (char*)q;
       iov[2].iov_len = strlen(q);
       iov[3].iov_base = (char*)p;
       iov[3].iov_len = strlen(p);
       iov[4].iov_base = (char*)"\n";
       iov[4].iov_len = 1;
       writev(STDERR_FILENO, iov, 5);

       suicide = 1;
#ifdef MALLOC_STATS
       if (malloc_stats)
              malloc_dump(STDERR_FILENO);
#endif /* MALLOC_STATS */
       malloc_active--;
       if (malloc_abort)
              abort();
}

Here is the caller graph for this function:

static void wrtwarning ( const char *  p) [static]

Definition at line 472 of file OpenBSD_malloc_Linux.c.

{
       const char           *q = " warning: ";
       struct iovec  iov[5];

       if (malloc_abort)
              wrterror(p);
       else if (malloc_silent)
              return;

       iov[0].iov_base = __progname;
       iov[0].iov_len = strlen(__progname);
       iov[1].iov_base = (char*)malloc_func;
       iov[1].iov_len = strlen(malloc_func);
       iov[2].iov_base = (char*)q;
       iov[2].iov_len = strlen(q);
       iov[3].iov_base = (char*)p;
       iov[3].iov_len = strlen(p);
       iov[4].iov_base = (char*)"\n";
       iov[4].iov_len = 1;
       
       writev(STDERR_FILENO, iov, 5);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char* __progname
int align = 0 [static]

Definition at line 77 of file OpenBSD_malloc_Linux.c.

size_t g_alignment = 0 [static]

Definition at line 78 of file OpenBSD_malloc_Linux.c.

pthread_mutex_t gen_mutex = PTHREAD_MUTEX_INITIALIZER [static]

Definition at line 93 of file OpenBSD_malloc_Linux.c.

struct pdinfo* last_dir [static]

Definition at line 184 of file OpenBSD_malloc_Linux.c.

u_long last_index [static]

Definition at line 195 of file OpenBSD_malloc_Linux.c.

int malloc_abort = 2 [static]

Definition at line 204 of file OpenBSD_malloc_Linux.c.

int malloc_active [static]

Definition at line 260 of file OpenBSD_malloc_Linux.c.

caddr_t malloc_brk [static]

Definition at line 266 of file OpenBSD_malloc_Linux.c.

unsigned int malloc_cache = 16 [static]

Definition at line 175 of file OpenBSD_malloc_Linux.c.

int malloc_freeprot [static]

Definition at line 221 of file OpenBSD_malloc_Linux.c.

const char* malloc_func [static]

Definition at line 275 of file OpenBSD_malloc_Linux.c.

size_t malloc_guard = 0 [static]

Definition at line 224 of file OpenBSD_malloc_Linux.c.

size_t malloc_guarded [static]

Definition at line 225 of file OpenBSD_malloc_Linux.c.

int malloc_hint = 1 [static]

Definition at line 229 of file OpenBSD_malloc_Linux.c.

int malloc_junk [static]

Definition at line 238 of file OpenBSD_malloc_Linux.c.

Definition at line 272 of file OpenBSD_malloc_Linux.c.

int malloc_ptrguard [static]

Definition at line 227 of file OpenBSD_malloc_Linux.c.

int malloc_realloc [static]

Definition at line 218 of file OpenBSD_malloc_Linux.c.

int malloc_silent [static]

Definition at line 215 of file OpenBSD_malloc_Linux.c.

unsigned int malloc_started [static]

Definition at line 172 of file OpenBSD_malloc_Linux.c.

size_t malloc_used [static]

Definition at line 263 of file OpenBSD_malloc_Linux.c.

int malloc_xmalloc [static]

Definition at line 232 of file OpenBSD_malloc_Linux.c.

int malloc_zero [static]

Definition at line 235 of file OpenBSD_malloc_Linux.c.

struct pginfo** page_dir [static]

Definition at line 198 of file OpenBSD_malloc_Linux.c.

u_long pdi_mod [static]

Definition at line 188 of file OpenBSD_malloc_Linux.c.

size_t pdi_off [static]

Definition at line 187 of file OpenBSD_malloc_Linux.c.

struct pgfree [static]

Definition at line 201 of file OpenBSD_malloc_Linux.c.

struct pdinfo* prev_dir [static]

Definition at line 185 of file OpenBSD_malloc_Linux.c.

struct pgfree* px [static]

Definition at line 269 of file OpenBSD_malloc_Linux.c.

int suicide [static]

Definition at line 207 of file OpenBSD_malloc_Linux.c.