xref: /onnv-gate/usr/src/uts/common/os/memlist_new.c (revision 11474:857f9db4ef05)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57240Srh87107  * Common Development and Distribution License (the "License").
67240Srh87107  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*11474SJonathan.Adams@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23567Sdmick  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/cmn_err.h>
280Sstevel@tonic-gate #include <sys/mutex.h>
290Sstevel@tonic-gate #include <sys/param.h>		/* for NULL */
300Sstevel@tonic-gate #include <sys/debug.h>
310Sstevel@tonic-gate #include <sys/memlist.h>
320Sstevel@tonic-gate #include <sys/memlist_impl.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate static struct memlist *memlist_freelist;
35567Sdmick static uint_t memlist_freelist_count;
360Sstevel@tonic-gate static kmutex_t memlist_freelist_mutex;
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate  * Caller must test for NULL return.
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate struct memlist *
memlist_get_one(void)420Sstevel@tonic-gate memlist_get_one(void)
430Sstevel@tonic-gate {
440Sstevel@tonic-gate 	struct memlist *mlp;
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 	mutex_enter(&memlist_freelist_mutex);
470Sstevel@tonic-gate 	mlp = memlist_freelist;
480Sstevel@tonic-gate 	if (mlp != NULL) {
49*11474SJonathan.Adams@Sun.COM 		memlist_freelist = mlp->ml_next;
500Sstevel@tonic-gate 		memlist_freelist_count--;
510Sstevel@tonic-gate 	}
520Sstevel@tonic-gate 	mutex_exit(&memlist_freelist_mutex);
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	return (mlp);
550Sstevel@tonic-gate }
560Sstevel@tonic-gate 
570Sstevel@tonic-gate void
memlist_free_one(struct memlist * mlp)580Sstevel@tonic-gate memlist_free_one(struct memlist *mlp)
590Sstevel@tonic-gate {
600Sstevel@tonic-gate 	ASSERT(mlp != NULL);
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	mutex_enter(&memlist_freelist_mutex);
63*11474SJonathan.Adams@Sun.COM 	mlp->ml_next = memlist_freelist;
640Sstevel@tonic-gate 	memlist_freelist = mlp;
650Sstevel@tonic-gate 	memlist_freelist_count++;
660Sstevel@tonic-gate 	mutex_exit(&memlist_freelist_mutex);
670Sstevel@tonic-gate }
680Sstevel@tonic-gate 
690Sstevel@tonic-gate void
memlist_free_list(struct memlist * mlp)700Sstevel@tonic-gate memlist_free_list(struct memlist *mlp)
710Sstevel@tonic-gate {
720Sstevel@tonic-gate 	struct memlist *mlendp;
73567Sdmick 	uint_t count;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	if (mlp == NULL) {
760Sstevel@tonic-gate 		return;
770Sstevel@tonic-gate 	}
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	count = 1;
80*11474SJonathan.Adams@Sun.COM 	for (mlendp = mlp; mlendp->ml_next != NULL; mlendp = mlendp->ml_next)
810Sstevel@tonic-gate 		count++;
820Sstevel@tonic-gate 	mutex_enter(&memlist_freelist_mutex);
83*11474SJonathan.Adams@Sun.COM 	mlendp->ml_next = memlist_freelist;
840Sstevel@tonic-gate 	memlist_freelist = mlp;
850Sstevel@tonic-gate 	memlist_freelist_count += count;
860Sstevel@tonic-gate 	mutex_exit(&memlist_freelist_mutex);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate 
890Sstevel@tonic-gate void
memlist_free_block(caddr_t base,size_t bytes)900Sstevel@tonic-gate memlist_free_block(caddr_t base, size_t bytes)
910Sstevel@tonic-gate {
920Sstevel@tonic-gate 	struct memlist *mlp, *mlendp;
93567Sdmick 	uint_t count;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	count = bytes / sizeof (struct memlist);
960Sstevel@tonic-gate 	if (count == 0)
970Sstevel@tonic-gate 		return;
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	mlp = (struct memlist *)base;
1000Sstevel@tonic-gate 	mlendp = &mlp[count - 1];
1010Sstevel@tonic-gate 	for (; mlp != mlendp; mlp++)
102*11474SJonathan.Adams@Sun.COM 		mlp->ml_next = mlp + 1;
103*11474SJonathan.Adams@Sun.COM 	mlendp->ml_next = NULL;
1040Sstevel@tonic-gate 	mlp = (struct memlist *)base;
1050Sstevel@tonic-gate 	mutex_enter(&memlist_freelist_mutex);
106*11474SJonathan.Adams@Sun.COM 	mlendp->ml_next = memlist_freelist;
1070Sstevel@tonic-gate 	memlist_freelist = mlp;
1080Sstevel@tonic-gate 	memlist_freelist_count += count;
1090Sstevel@tonic-gate 	mutex_exit(&memlist_freelist_mutex);
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate  * Insert into a sorted memory list.
1140Sstevel@tonic-gate  * new = new element to insert
1150Sstevel@tonic-gate  * curmemlistp = memory list to which to add segment.
1160Sstevel@tonic-gate  */
1170Sstevel@tonic-gate void
memlist_insert(struct memlist * new,struct memlist ** curmemlistp)1180Sstevel@tonic-gate memlist_insert(
1190Sstevel@tonic-gate 	struct memlist *new,
1200Sstevel@tonic-gate 	struct memlist **curmemlistp)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate 	struct memlist *cur, *last;
1230Sstevel@tonic-gate 	uint64_t start, end;
1240Sstevel@tonic-gate 
125*11474SJonathan.Adams@Sun.COM 	start = new->ml_address;
126*11474SJonathan.Adams@Sun.COM 	end = start + new->ml_size;
1270Sstevel@tonic-gate 	last = NULL;
128*11474SJonathan.Adams@Sun.COM 	for (cur = *curmemlistp; cur; cur = cur->ml_next) {
1290Sstevel@tonic-gate 		last = cur;
130*11474SJonathan.Adams@Sun.COM 		if (cur->ml_address >= end) {
131*11474SJonathan.Adams@Sun.COM 			new->ml_next = cur;
132*11474SJonathan.Adams@Sun.COM 			new->ml_prev = cur->ml_prev;
133*11474SJonathan.Adams@Sun.COM 			cur->ml_prev = new;
1340Sstevel@tonic-gate 			if (cur == *curmemlistp)
1350Sstevel@tonic-gate 				*curmemlistp = new;
1360Sstevel@tonic-gate 			else
137*11474SJonathan.Adams@Sun.COM 				new->ml_prev->ml_next = new;
1380Sstevel@tonic-gate 			return;
1390Sstevel@tonic-gate 		}
140*11474SJonathan.Adams@Sun.COM 		if (cur->ml_address + cur->ml_size > start)
1417240Srh87107 			panic("munged memory list = 0x%p\n",
1427240Srh87107 			    (void *)curmemlistp);
1430Sstevel@tonic-gate 	}
144*11474SJonathan.Adams@Sun.COM 	new->ml_next = NULL;
145*11474SJonathan.Adams@Sun.COM 	new->ml_prev = last;
1460Sstevel@tonic-gate 	if (last != NULL)
147*11474SJonathan.Adams@Sun.COM 		last->ml_next = new;
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate void
memlist_del(struct memlist * memlistp,struct memlist ** curmemlistp)1510Sstevel@tonic-gate memlist_del(struct memlist *memlistp,
1520Sstevel@tonic-gate 	struct memlist **curmemlistp)
1530Sstevel@tonic-gate {
1540Sstevel@tonic-gate #ifdef DEBUG
1550Sstevel@tonic-gate 	/*
1560Sstevel@tonic-gate 	 * Check that the memlist is on the list.
1570Sstevel@tonic-gate 	 */
1580Sstevel@tonic-gate 	struct memlist *mlp;
1590Sstevel@tonic-gate 
160*11474SJonathan.Adams@Sun.COM 	for (mlp = *curmemlistp; mlp != NULL; mlp = mlp->ml_next)
1610Sstevel@tonic-gate 		if (mlp == memlistp)
1620Sstevel@tonic-gate 			break;
1630Sstevel@tonic-gate 	ASSERT(mlp == memlistp);
1640Sstevel@tonic-gate #endif /* DEBUG */
1650Sstevel@tonic-gate 	if (*curmemlistp == memlistp) {
166*11474SJonathan.Adams@Sun.COM 		ASSERT(memlistp->ml_prev == NULL);
167*11474SJonathan.Adams@Sun.COM 		*curmemlistp = memlistp->ml_next;
1680Sstevel@tonic-gate 	}
169*11474SJonathan.Adams@Sun.COM 	if (memlistp->ml_prev != NULL) {
170*11474SJonathan.Adams@Sun.COM 		ASSERT(memlistp->ml_prev->ml_next == memlistp);
171*11474SJonathan.Adams@Sun.COM 		memlistp->ml_prev->ml_next = memlistp->ml_next;
1720Sstevel@tonic-gate 	}
173*11474SJonathan.Adams@Sun.COM 	if (memlistp->ml_next != NULL) {
174*11474SJonathan.Adams@Sun.COM 		ASSERT(memlistp->ml_next->ml_prev == memlistp);
175*11474SJonathan.Adams@Sun.COM 		memlistp->ml_next->ml_prev = memlistp->ml_prev;
1760Sstevel@tonic-gate 	}
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate struct memlist *
memlist_find(struct memlist * mlp,uint64_t address)1800Sstevel@tonic-gate memlist_find(struct memlist *mlp, uint64_t address)
1810Sstevel@tonic-gate {
182*11474SJonathan.Adams@Sun.COM 	for (; mlp != NULL; mlp = mlp->ml_next)
183*11474SJonathan.Adams@Sun.COM 		if (address >= mlp->ml_address &&
184*11474SJonathan.Adams@Sun.COM 		    address < (mlp->ml_address + mlp->ml_size))
1850Sstevel@tonic-gate 			break;
1860Sstevel@tonic-gate 	return (mlp);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate /*
1900Sstevel@tonic-gate  * Add a span to a memlist.
1910Sstevel@tonic-gate  * Return:
1920Sstevel@tonic-gate  * MEML_SPANOP_OK if OK.
1930Sstevel@tonic-gate  * MEML_SPANOP_ESPAN if part or all of span already exists
1940Sstevel@tonic-gate  * MEML_SPANOP_EALLOC for allocation failure
1950Sstevel@tonic-gate  */
1960Sstevel@tonic-gate int
memlist_add_span(uint64_t address,uint64_t bytes,struct memlist ** curmemlistp)1970Sstevel@tonic-gate memlist_add_span(
1980Sstevel@tonic-gate 	uint64_t address,
1990Sstevel@tonic-gate 	uint64_t bytes,
2000Sstevel@tonic-gate 	struct memlist **curmemlistp)
2010Sstevel@tonic-gate {
2020Sstevel@tonic-gate 	struct memlist *dst;
2030Sstevel@tonic-gate 	struct memlist *prev, *next;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	/*
2060Sstevel@tonic-gate 	 * allocate a new struct memlist
2070Sstevel@tonic-gate 	 */
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	dst = memlist_get_one();
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	if (dst == NULL) {
2120Sstevel@tonic-gate 		return (MEML_SPANOP_EALLOC);
2130Sstevel@tonic-gate 	}
2140Sstevel@tonic-gate 
215*11474SJonathan.Adams@Sun.COM 	dst->ml_address = address;
216*11474SJonathan.Adams@Sun.COM 	dst->ml_size = bytes;
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	/*
2190Sstevel@tonic-gate 	 * First insert.
2200Sstevel@tonic-gate 	 */
2210Sstevel@tonic-gate 	if (*curmemlistp == NULL) {
222*11474SJonathan.Adams@Sun.COM 		dst->ml_prev = NULL;
223*11474SJonathan.Adams@Sun.COM 		dst->ml_next = NULL;
2240Sstevel@tonic-gate 		*curmemlistp = dst;
2250Sstevel@tonic-gate 		return (MEML_SPANOP_OK);
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	/*
2290Sstevel@tonic-gate 	 * Insert into sorted list.
2300Sstevel@tonic-gate 	 */
2310Sstevel@tonic-gate 	for (prev = NULL, next = *curmemlistp; next != NULL;
232*11474SJonathan.Adams@Sun.COM 	    prev = next, next = next->ml_next) {
233*11474SJonathan.Adams@Sun.COM 		if (address > (next->ml_address + next->ml_size))
2340Sstevel@tonic-gate 			continue;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 		/*
2370Sstevel@tonic-gate 		 * Else insert here.
2380Sstevel@tonic-gate 		 */
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 		/*
2410Sstevel@tonic-gate 		 * Prepend to next.
2420Sstevel@tonic-gate 		 */
243*11474SJonathan.Adams@Sun.COM 		if ((address + bytes) == next->ml_address) {
2440Sstevel@tonic-gate 			memlist_free_one(dst);
2450Sstevel@tonic-gate 
246*11474SJonathan.Adams@Sun.COM 			next->ml_address = address;
247*11474SJonathan.Adams@Sun.COM 			next->ml_size += bytes;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 			return (MEML_SPANOP_OK);
2500Sstevel@tonic-gate 		}
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 		/*
2530Sstevel@tonic-gate 		 * Append to next.
2540Sstevel@tonic-gate 		 */
255*11474SJonathan.Adams@Sun.COM 		if (address == (next->ml_address + next->ml_size)) {
2560Sstevel@tonic-gate 			memlist_free_one(dst);
2570Sstevel@tonic-gate 
258*11474SJonathan.Adams@Sun.COM 			if (next->ml_next) {
2590Sstevel@tonic-gate 				/*
260*11474SJonathan.Adams@Sun.COM 				 * don't overlap with next->ml_next
2610Sstevel@tonic-gate 				 */
262*11474SJonathan.Adams@Sun.COM 				if ((address + bytes) >
263*11474SJonathan.Adams@Sun.COM 				    next->ml_next->ml_address) {
2640Sstevel@tonic-gate 					return (MEML_SPANOP_ESPAN);
2650Sstevel@tonic-gate 				}
2660Sstevel@tonic-gate 				/*
267*11474SJonathan.Adams@Sun.COM 				 * Concatenate next and next->ml_next
2680Sstevel@tonic-gate 				 */
269*11474SJonathan.Adams@Sun.COM 				if ((address + bytes) ==
270*11474SJonathan.Adams@Sun.COM 				    next->ml_next->ml_address) {
271*11474SJonathan.Adams@Sun.COM 					struct memlist *mlp = next->ml_next;
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 					if (next == *curmemlistp)
274*11474SJonathan.Adams@Sun.COM 						*curmemlistp = next->ml_next;
2750Sstevel@tonic-gate 
276*11474SJonathan.Adams@Sun.COM 					mlp->ml_address = next->ml_address;
277*11474SJonathan.Adams@Sun.COM 					mlp->ml_size += next->ml_size;
278*11474SJonathan.Adams@Sun.COM 					mlp->ml_size += bytes;
2790Sstevel@tonic-gate 
280*11474SJonathan.Adams@Sun.COM 					if (next->ml_prev)
281*11474SJonathan.Adams@Sun.COM 						next->ml_prev->ml_next = mlp;
282*11474SJonathan.Adams@Sun.COM 					mlp->ml_prev = next->ml_prev;
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 					memlist_free_one(next);
2850Sstevel@tonic-gate 					return (MEML_SPANOP_OK);
2860Sstevel@tonic-gate 				}
2870Sstevel@tonic-gate 			}
2880Sstevel@tonic-gate 
289*11474SJonathan.Adams@Sun.COM 			next->ml_size += bytes;
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 			return (MEML_SPANOP_OK);
2920Sstevel@tonic-gate 		}
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 		/* don't overlap with next */
295*11474SJonathan.Adams@Sun.COM 		if ((address + bytes) > next->ml_address) {
2960Sstevel@tonic-gate 			memlist_free_one(dst);
2970Sstevel@tonic-gate 			return (MEML_SPANOP_ESPAN);
2980Sstevel@tonic-gate 		}
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 		/*
3010Sstevel@tonic-gate 		 * Insert before next.
3020Sstevel@tonic-gate 		 */
303*11474SJonathan.Adams@Sun.COM 		dst->ml_prev = prev;
304*11474SJonathan.Adams@Sun.COM 		dst->ml_next = next;
305*11474SJonathan.Adams@Sun.COM 		next->ml_prev = dst;
3060Sstevel@tonic-gate 		if (prev == NULL) {
3070Sstevel@tonic-gate 			*curmemlistp = dst;
3080Sstevel@tonic-gate 		} else {
309*11474SJonathan.Adams@Sun.COM 			prev->ml_next = dst;
3100Sstevel@tonic-gate 		}
3110Sstevel@tonic-gate 		return (MEML_SPANOP_OK);
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	/*
3150Sstevel@tonic-gate 	 * End of list, prev is valid and next is NULL.
3160Sstevel@tonic-gate 	 */
317*11474SJonathan.Adams@Sun.COM 	prev->ml_next = dst;
318*11474SJonathan.Adams@Sun.COM 	dst->ml_prev = prev;
319*11474SJonathan.Adams@Sun.COM 	dst->ml_next = NULL;
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 	return (MEML_SPANOP_OK);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate  * Delete a span from a memlist.
3260Sstevel@tonic-gate  * Return:
3270Sstevel@tonic-gate  * MEML_SPANOP_OK if OK.
3280Sstevel@tonic-gate  * MEML_SPANOP_ESPAN if part or all of span does not exist
3290Sstevel@tonic-gate  * MEML_SPANOP_EALLOC for allocation failure
3300Sstevel@tonic-gate  */
3310Sstevel@tonic-gate int
memlist_delete_span(uint64_t address,uint64_t bytes,struct memlist ** curmemlistp)3320Sstevel@tonic-gate memlist_delete_span(
3330Sstevel@tonic-gate 	uint64_t address,
3340Sstevel@tonic-gate 	uint64_t bytes,
3350Sstevel@tonic-gate 	struct memlist **curmemlistp)
3360Sstevel@tonic-gate {
3370Sstevel@tonic-gate 	struct memlist *dst, *next;
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	/*
3400Sstevel@tonic-gate 	 * Find element containing address.
3410Sstevel@tonic-gate 	 */
342*11474SJonathan.Adams@Sun.COM 	for (next = *curmemlistp; next != NULL; next = next->ml_next) {
343*11474SJonathan.Adams@Sun.COM 		if ((address >= next->ml_address) &&
344*11474SJonathan.Adams@Sun.COM 		    (address < next->ml_address + next->ml_size))
3450Sstevel@tonic-gate 			break;
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	/*
3490Sstevel@tonic-gate 	 * If start address not in list.
3500Sstevel@tonic-gate 	 */
3510Sstevel@tonic-gate 	if (next == NULL) {
3520Sstevel@tonic-gate 		return (MEML_SPANOP_ESPAN);
3530Sstevel@tonic-gate 	}
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	/*
3560Sstevel@tonic-gate 	 * Error if size goes off end of this struct memlist.
3570Sstevel@tonic-gate 	 */
358*11474SJonathan.Adams@Sun.COM 	if (address + bytes > next->ml_address + next->ml_size) {
3590Sstevel@tonic-gate 		return (MEML_SPANOP_ESPAN);
3600Sstevel@tonic-gate 	}
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	/*
3630Sstevel@tonic-gate 	 * Span at beginning of struct memlist.
3640Sstevel@tonic-gate 	 */
365*11474SJonathan.Adams@Sun.COM 	if (address == next->ml_address) {
3660Sstevel@tonic-gate 		/*
3670Sstevel@tonic-gate 		 * If start & size match, delete from list.
3680Sstevel@tonic-gate 		 */
369*11474SJonathan.Adams@Sun.COM 		if (bytes == next->ml_size) {
3700Sstevel@tonic-gate 			if (next == *curmemlistp)
371*11474SJonathan.Adams@Sun.COM 				*curmemlistp = next->ml_next;
372*11474SJonathan.Adams@Sun.COM 			if (next->ml_prev != NULL)
373*11474SJonathan.Adams@Sun.COM 				next->ml_prev->ml_next = next->ml_next;
374*11474SJonathan.Adams@Sun.COM 			if (next->ml_next != NULL)
375*11474SJonathan.Adams@Sun.COM 				next->ml_next->ml_prev = next->ml_prev;
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 			memlist_free_one(next);
3780Sstevel@tonic-gate 		} else {
3790Sstevel@tonic-gate 			/*
3800Sstevel@tonic-gate 			 * Increment start address by bytes.
3810Sstevel@tonic-gate 			 */
382*11474SJonathan.Adams@Sun.COM 			next->ml_address += bytes;
383*11474SJonathan.Adams@Sun.COM 			next->ml_size -= bytes;
3840Sstevel@tonic-gate 		}
3850Sstevel@tonic-gate 		return (MEML_SPANOP_OK);
3860Sstevel@tonic-gate 	}
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	/*
3890Sstevel@tonic-gate 	 * Span at end of struct memlist.
3900Sstevel@tonic-gate 	 */
391*11474SJonathan.Adams@Sun.COM 	if (address + bytes == next->ml_address + next->ml_size) {
3920Sstevel@tonic-gate 		/*
3930Sstevel@tonic-gate 		 * decrement size by bytes
3940Sstevel@tonic-gate 		 */
395*11474SJonathan.Adams@Sun.COM 		next->ml_size -= bytes;
3960Sstevel@tonic-gate 		return (MEML_SPANOP_OK);
3970Sstevel@tonic-gate 	}
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	/*
4000Sstevel@tonic-gate 	 * Delete a span in the middle of the struct memlist.
4010Sstevel@tonic-gate 	 */
4020Sstevel@tonic-gate 	{
4030Sstevel@tonic-gate 		/*
4040Sstevel@tonic-gate 		 * create a new struct memlist
4050Sstevel@tonic-gate 		 */
4060Sstevel@tonic-gate 		dst = memlist_get_one();
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 		if (dst == NULL) {
4090Sstevel@tonic-gate 			return (MEML_SPANOP_EALLOC);
4100Sstevel@tonic-gate 		}
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 		/*
4130Sstevel@tonic-gate 		 * Existing struct memlist gets address
4140Sstevel@tonic-gate 		 * and size up to start of span.
4150Sstevel@tonic-gate 		 */
416*11474SJonathan.Adams@Sun.COM 		dst->ml_address = address + bytes;
417*11474SJonathan.Adams@Sun.COM 		dst->ml_size =
418*11474SJonathan.Adams@Sun.COM 		    (next->ml_address + next->ml_size) - dst->ml_address;
419*11474SJonathan.Adams@Sun.COM 		next->ml_size = address - next->ml_address;
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 		/*
4220Sstevel@tonic-gate 		 * New struct memlist gets address starting
4230Sstevel@tonic-gate 		 * after span, until end.
4240Sstevel@tonic-gate 		 */
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 		/*
4270Sstevel@tonic-gate 		 * link in new memlist after old
4280Sstevel@tonic-gate 		 */
429*11474SJonathan.Adams@Sun.COM 		dst->ml_next = next->ml_next;
430*11474SJonathan.Adams@Sun.COM 		dst->ml_prev = next;
4310Sstevel@tonic-gate 
432*11474SJonathan.Adams@Sun.COM 		if (next->ml_next != NULL)
433*11474SJonathan.Adams@Sun.COM 			next->ml_next->ml_prev = dst;
434*11474SJonathan.Adams@Sun.COM 		next->ml_next = dst;
4350Sstevel@tonic-gate 	}
4360Sstevel@tonic-gate 	return (MEML_SPANOP_OK);
4370Sstevel@tonic-gate }
438