OpenSolaris_b135/stand/lib/sa/memlist.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/machparam.h>
#include <sys/promif.h>
#include <sys/bootconf.h>
#include <sys/salib.h>

extern caddr_t memlistpage;

/* Always pts to the next free link in the headtable */
/* i.e. it is always memlistpage+tableoffset */
caddr_t tablep = NULL;
static int table_freespace;

/*
 *	Function prototypes
 */
extern void 		reset_alloc(void);

void
print_memlist(struct memlist *av)
{
	struct memlist *p = av;

	while (p != NULL) {
		printf("addr = 0x%x:0x%x, size = 0x%x:0x%x\n",
		    (uint_t)(p->ml_address >> 32), (uint_t)p->ml_address,
		    (uint_t)(p->ml_size >> 32), (uint_t)p->ml_size);
		p = p->ml_next;
	}

}

/* allocate room for n bytes, return 8-byte aligned address */
void *
getlink(uint_t n)
{
	void *p;
	extern int pagesize;

	if (memlistpage == NULL)
		reset_alloc();

	if (tablep == NULL) {
		/*
		 * Took the following 2 lines out of above test for
		 * memlistpage == null so we can initialize table_freespace
		 */
		table_freespace = pagesize - sizeof (struct bsys_mem);
		tablep = memlistpage + sizeof (struct bsys_mem);
		tablep = (caddr_t)roundup((uintptr_t)tablep, 8);
	}

	if (n == 0)
		return (NULL);

	n = roundup(n, 8);
	p = tablep;

	table_freespace -= n;
	tablep += n;
	if (table_freespace <= 0) {
		char buf[80];

		(void) sprintf(buf,
		    "Boot getlink(): no memlist space (need %d)\n", n);
		prom_panic(buf);
	}

	return (p);
}


/*
 * This is the number of memlist structures allocated in one shot. kept
 * to small number to reduce wastage of memory, it should not be too small
 * to slow down boot.
 */
#define		ALLOC_SZ	5
static struct memlist *free_memlist_ptr = NULL;

/*
 * Free memory lists are maintained as simple single linked lists.
 * get_memlist_struct returns a memlist structure without initializing
 * any of the fields.  It is caller's responsibility to do that.
 */

struct memlist *
get_memlist_struct(void)
{
	struct memlist *ptr;
	int i;

	if (free_memlist_ptr == NULL) {
		ptr = free_memlist_ptr = getlink(ALLOC_SZ *
		    sizeof (struct memlist));
		bzero(free_memlist_ptr, (ALLOC_SZ * sizeof (struct memlist)));
		for (i = 0; i < ALLOC_SZ; i++)
			ptr[i].ml_next = &ptr[i+1];
		ptr[i-1].ml_next = NULL;
	}
	ptr = free_memlist_ptr;
	free_memlist_ptr = ptr->ml_next;
	return (ptr);
}

/*
 * Return memlist structure to free list.
 */
void
add_to_freelist(struct memlist *ptr)
{
	struct memlist *tmp;

	if (free_memlist_ptr == NULL) {
		free_memlist_ptr = ptr;
	} else {
		for (tmp = free_memlist_ptr; tmp->ml_next; tmp = tmp->ml_next)
			;
		tmp->ml_next = ptr;
	}
}