⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 openbsd_malloc_linux.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#endif /* MALLOC_STATS */

/*
 * Allocate aligned mmaped chunk
 */

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

	return j;
}


/*
 * Allocate a number of pages from the OS
 */
static void *
map_pages(size_t pages)
{
	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);
}

/*
 * Initialize the world
 */
static void
malloc_init(void)
{
	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;
}

/*
 * Allocate a number of complete pages
 */
static void *
malloc_pages(size_t size)
{
	void		*p, *delay_free = NULL, *tp;
	int		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);
}

/*
 * Allocate a page of fragments
 */

static __inline__ int
malloc_make_chunks(int bits)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -