xref: /illumos-gate/usr/src/uts/common/os/memlist_new.c (revision e0cd43fe)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5903a11ebSrh  * Common Development and Distribution License (the "License").
6903a11ebSrh  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
2256f33205SJonathan Adams  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
239f1a1f17Sdmick  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
287c478bd9Sstevel@tonic-gate #include <sys/mutex.h>
297c478bd9Sstevel@tonic-gate #include <sys/param.h>		/* for NULL */
307c478bd9Sstevel@tonic-gate #include <sys/debug.h>
317c478bd9Sstevel@tonic-gate #include <sys/memlist.h>
327c478bd9Sstevel@tonic-gate #include <sys/memlist_impl.h>
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate static struct memlist *memlist_freelist;
359f1a1f17Sdmick static uint_t memlist_freelist_count;
367c478bd9Sstevel@tonic-gate static kmutex_t memlist_freelist_mutex;
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * Caller must test for NULL return.
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate struct memlist *
memlist_get_one(void)427c478bd9Sstevel@tonic-gate memlist_get_one(void)
437c478bd9Sstevel@tonic-gate {
447c478bd9Sstevel@tonic-gate 	struct memlist *mlp;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate 	mutex_enter(&memlist_freelist_mutex);
477c478bd9Sstevel@tonic-gate 	mlp = memlist_freelist;
487c478bd9Sstevel@tonic-gate 	if (mlp != NULL) {
4956f33205SJonathan Adams 		memlist_freelist = mlp->ml_next;
507c478bd9Sstevel@tonic-gate 		memlist_freelist_count--;
517c478bd9Sstevel@tonic-gate 	}
527c478bd9Sstevel@tonic-gate 	mutex_exit(&memlist_freelist_mutex);
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	return (mlp);
557c478bd9Sstevel@tonic-gate }
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate void
memlist_free_one(struct memlist * mlp)587c478bd9Sstevel@tonic-gate memlist_free_one(struct memlist *mlp)
597c478bd9Sstevel@tonic-gate {
607c478bd9Sstevel@tonic-gate 	ASSERT(mlp != NULL);
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 	mutex_enter(&memlist_freelist_mutex);
6356f33205SJonathan Adams 	mlp->ml_next = memlist_freelist;
647c478bd9Sstevel@tonic-gate 	memlist_freelist = mlp;
657c478bd9Sstevel@tonic-gate 	memlist_freelist_count++;
667c478bd9Sstevel@tonic-gate 	mutex_exit(&memlist_freelist_mutex);
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate void
memlist_free_list(struct memlist * mlp)707c478bd9Sstevel@tonic-gate memlist_free_list(struct memlist *mlp)
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate 	struct memlist *mlendp;
739f1a1f17Sdmick 	uint_t count;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	if (mlp == NULL) {
767c478bd9Sstevel@tonic-gate 		return;
777c478bd9Sstevel@tonic-gate 	}
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate 	count = 1;
8056f33205SJonathan Adams 	for (mlendp = mlp; mlendp->ml_next != NULL; mlendp = mlendp->ml_next)
817c478bd9Sstevel@tonic-gate 		count++;
827c478bd9Sstevel@tonic-gate 	mutex_enter(&memlist_freelist_mutex);
8356f33205SJonathan Adams 	mlendp->ml_next = memlist_freelist;
847c478bd9Sstevel@tonic-gate 	memlist_freelist = mlp;
857c478bd9Sstevel@tonic-gate 	memlist_freelist_count += count;
867c478bd9Sstevel@tonic-gate 	mutex_exit(&memlist_freelist_mutex);
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate void
memlist_free_block(caddr_t base,size_t bytes)907c478bd9Sstevel@tonic-gate memlist_free_block(caddr_t base, size_t bytes)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	struct memlist *mlp, *mlendp;
939f1a1f17Sdmick 	uint_t count;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	count = bytes / sizeof (struct memlist);
967c478bd9Sstevel@tonic-gate 	if (count == 0)
977c478bd9Sstevel@tonic-gate 		return;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	mlp = (struct memlist *)base;
1007c478bd9Sstevel@tonic-gate 	mlendp = &mlp[count - 1];
1017c478bd9Sstevel@tonic-gate 	for (; mlp != mlendp; mlp++)
10256f33205SJonathan Adams 		mlp->ml_next = mlp + 1;
10356f33205SJonathan Adams 	mlendp->ml_next = NULL;
1047c478bd9Sstevel@tonic-gate 	mlp = (struct memlist *)base;
1057c478bd9Sstevel@tonic-gate 	mutex_enter(&memlist_freelist_mutex);
10656f33205SJonathan Adams 	mlendp->ml_next = memlist_freelist;
1077c478bd9Sstevel@tonic-gate 	memlist_freelist = mlp;
1087c478bd9Sstevel@tonic-gate 	memlist_freelist_count += count;
1097c478bd9Sstevel@tonic-gate 	mutex_exit(&memlist_freelist_mutex);
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  * Insert into a sorted memory list.
1147c478bd9Sstevel@tonic-gate  * new = new element to insert
1157c478bd9Sstevel@tonic-gate  * curmemlistp = memory list to which to add segment.
1167c478bd9Sstevel@tonic-gate  */
1177c478bd9Sstevel@tonic-gate void
memlist_insert(struct memlist * new,struct memlist ** curmemlistp)1187c478bd9Sstevel@tonic-gate memlist_insert(
1197c478bd9Sstevel@tonic-gate 	struct memlist *new,
1207c478bd9Sstevel@tonic-gate 	struct memlist **curmemlistp)
1217c478bd9Sstevel@tonic-gate {
1227c478bd9Sstevel@tonic-gate 	struct memlist *cur, *last;
1237c478bd9Sstevel@tonic-gate 	uint64_t start, end;
1247c478bd9Sstevel@tonic-gate 
12556f33205SJonathan Adams 	start = new->ml_address;
12656f33205SJonathan Adams 	end = start + new->ml_size;
1277c478bd9Sstevel@tonic-gate 	last = NULL;
12856f33205SJonathan Adams 	for (cur = *curmemlistp; cur; cur = cur->ml_next) {
1297c478bd9Sstevel@tonic-gate 		last = cur;
13056f33205SJonathan Adams 		if (cur->ml_address >= end) {
13156f33205SJonathan Adams 			new->ml_next = cur;
13256f33205SJonathan Adams 			new->ml_prev = cur->ml_prev;
13356f33205SJonathan Adams 			cur->ml_prev = new;
1347c478bd9Sstevel@tonic-gate 			if (cur == *curmemlistp)
1357c478bd9Sstevel@tonic-gate 				*curmemlistp = new;
1367c478bd9Sstevel@tonic-gate 			else
13756f33205SJonathan Adams 				new->ml_prev->ml_next = new;
1387c478bd9Sstevel@tonic-gate 			return;
1397c478bd9Sstevel@tonic-gate 		}
14056f33205SJonathan Adams 		if (cur->ml_address + cur->ml_size > start)
141903a11ebSrh 			panic("munged memory list = 0x%p\n",
142903a11ebSrh 			    (void *)curmemlistp);
1437c478bd9Sstevel@tonic-gate 	}
14456f33205SJonathan Adams 	new->ml_next = NULL;
14556f33205SJonathan Adams 	new->ml_prev = last;
146*e0cd43feSRobert Mustacchi 	if (last != NULL) {
14756f33205SJonathan Adams 		last->ml_next = new;
148*e0cd43feSRobert Mustacchi 	} else {
149*e0cd43feSRobert Mustacchi 		ASSERT3P(*curmemlistp, ==, NULL);
150*e0cd43feSRobert Mustacchi 		*curmemlistp = new;
151*e0cd43feSRobert Mustacchi 	}
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate void
memlist_del(struct memlist * memlistp,struct memlist ** curmemlistp)1557c478bd9Sstevel@tonic-gate memlist_del(struct memlist *memlistp,
156*e0cd43feSRobert Mustacchi     struct memlist **curmemlistp)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate #ifdef DEBUG
1597c478bd9Sstevel@tonic-gate 	/*
1607c478bd9Sstevel@tonic-gate 	 * Check that the memlist is on the list.
1617c478bd9Sstevel@tonic-gate 	 */
1627c478bd9Sstevel@tonic-gate 	struct memlist *mlp;
1637c478bd9Sstevel@tonic-gate 
16456f33205SJonathan Adams 	for (mlp = *curmemlistp; mlp != NULL; mlp = mlp->ml_next)
1657c478bd9Sstevel@tonic-gate 		if (mlp == memlistp)
1667c478bd9Sstevel@tonic-gate 			break;
1677c478bd9Sstevel@tonic-gate 	ASSERT(mlp == memlistp);
1687c478bd9Sstevel@tonic-gate #endif /* DEBUG */
1697c478bd9Sstevel@tonic-gate 	if (*curmemlistp == memlistp) {
17056f33205SJonathan Adams 		ASSERT(memlistp->ml_prev == NULL);
17156f33205SJonathan Adams 		*curmemlistp = memlistp->ml_next;
1727c478bd9Sstevel@tonic-gate 	}
17356f33205SJonathan Adams 	if (memlistp->ml_prev != NULL) {
17456f33205SJonathan Adams 		ASSERT(memlistp->ml_prev->ml_next == memlistp);
17556f33205SJonathan Adams 		memlistp->ml_prev->ml_next = memlistp->ml_next;
1767c478bd9Sstevel@tonic-gate 	}
17756f33205SJonathan Adams 	if (memlistp->ml_next != NULL) {
17856f33205SJonathan Adams 		ASSERT(memlistp->ml_next->ml_prev == memlistp);
17956f33205SJonathan Adams 		memlistp->ml_next->ml_prev = memlistp->ml_prev;
1807c478bd9Sstevel@tonic-gate 	}
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate struct memlist *
memlist_find(struct memlist * mlp,uint64_t address)1847c478bd9Sstevel@tonic-gate memlist_find(struct memlist *mlp, uint64_t address)
1857c478bd9Sstevel@tonic-gate {
18656f33205SJonathan Adams 	for (; mlp != NULL; mlp = mlp->ml_next)
18756f33205SJonathan Adams 		if (address >= mlp->ml_address &&
18856f33205SJonathan Adams 		    address < (mlp->ml_address + mlp->ml_size))
1897c478bd9Sstevel@tonic-gate 			break;
1907c478bd9Sstevel@tonic-gate 	return (mlp);
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate /*
1947c478bd9Sstevel@tonic-gate  * Add a span to a memlist.
1957c478bd9Sstevel@tonic-gate  * Return:
1967c478bd9Sstevel@tonic-gate  * MEML_SPANOP_OK if OK.
1977c478bd9Sstevel@tonic-gate  * MEML_SPANOP_ESPAN if part or all of span already exists
1987c478bd9Sstevel@tonic-gate  * MEML_SPANOP_EALLOC for allocation failure
1997c478bd9Sstevel@tonic-gate  */
2007c478bd9Sstevel@tonic-gate int
memlist_add_span(uint64_t address,uint64_t bytes,struct memlist ** curmemlistp)2017c478bd9Sstevel@tonic-gate memlist_add_span(
2027c478bd9Sstevel@tonic-gate 	uint64_t address,
2037c478bd9Sstevel@tonic-gate 	uint64_t bytes,
2047c478bd9Sstevel@tonic-gate 	struct memlist **curmemlistp)
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate 	struct memlist *dst;
2077c478bd9Sstevel@tonic-gate 	struct memlist *prev, *next;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	/*
2107c478bd9Sstevel@tonic-gate 	 * allocate a new struct memlist
2117c478bd9Sstevel@tonic-gate 	 */
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	dst = memlist_get_one();
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	if (dst == NULL) {
2167c478bd9Sstevel@tonic-gate 		return (MEML_SPANOP_EALLOC);
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 
21956f33205SJonathan Adams 	dst->ml_address = address;
22056f33205SJonathan Adams 	dst->ml_size = bytes;
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	/*
2237c478bd9Sstevel@tonic-gate 	 * First insert.
2247c478bd9Sstevel@tonic-gate 	 */
2257c478bd9Sstevel@tonic-gate 	if (*curmemlistp == NULL) {
22656f33205SJonathan Adams 		dst->ml_prev = NULL;
22756f33205SJonathan Adams 		dst->ml_next = NULL;
2287c478bd9Sstevel@tonic-gate 		*curmemlistp = dst;
2297c478bd9Sstevel@tonic-gate 		return (MEML_SPANOP_OK);
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	/*
2337c478bd9Sstevel@tonic-gate 	 * Insert into sorted list.
2347c478bd9Sstevel@tonic-gate 	 */
2357c478bd9Sstevel@tonic-gate 	for (prev = NULL, next = *curmemlistp; next != NULL;
23656f33205SJonathan Adams 	    prev = next, next = next->ml_next) {
23756f33205SJonathan Adams 		if (address > (next->ml_address + next->ml_size))
2387c478bd9Sstevel@tonic-gate 			continue;
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 		/*
2417c478bd9Sstevel@tonic-gate 		 * Else insert here.
2427c478bd9Sstevel@tonic-gate 		 */
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 		/*
2457c478bd9Sstevel@tonic-gate 		 * Prepend to next.
2467c478bd9Sstevel@tonic-gate 		 */
24756f33205SJonathan Adams 		if ((address + bytes) == next->ml_address) {
2487c478bd9Sstevel@tonic-gate 			memlist_free_one(dst);
2497c478bd9Sstevel@tonic-gate 
25056f33205SJonathan Adams 			next->ml_address = address;
25156f33205SJonathan Adams 			next->ml_size += bytes;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 			return (MEML_SPANOP_OK);
2547c478bd9Sstevel@tonic-gate 		}
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 		/*
2577c478bd9Sstevel@tonic-gate 		 * Append to next.
2587c478bd9Sstevel@tonic-gate 		 */
25956f33205SJonathan Adams 		if (address == (next->ml_address + next->ml_size)) {
2607c478bd9Sstevel@tonic-gate 			memlist_free_one(dst);
2617c478bd9Sstevel@tonic-gate 
26256f33205SJonathan Adams 			if (next->ml_next) {
2637c478bd9Sstevel@tonic-gate 				/*
26456f33205SJonathan Adams 				 * don't overlap with next->ml_next
2657c478bd9Sstevel@tonic-gate 				 */
26656f33205SJonathan Adams 				if ((address + bytes) >
26756f33205SJonathan Adams 				    next->ml_next->ml_address) {
2687c478bd9Sstevel@tonic-gate 					return (MEML_SPANOP_ESPAN);
2697c478bd9Sstevel@tonic-gate 				}
2707c478bd9Sstevel@tonic-gate 				/*
27156f33205SJonathan Adams 				 * Concatenate next and next->ml_next
2727c478bd9Sstevel@tonic-gate 				 */
27356f33205SJonathan Adams 				if ((address + bytes) ==
27456f33205SJonathan Adams 				    next->ml_next->ml_address) {
27556f33205SJonathan Adams 					struct memlist *mlp = next->ml_next;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 					if (next == *curmemlistp)
27856f33205SJonathan Adams 						*curmemlistp = next->ml_next;
2797c478bd9Sstevel@tonic-gate 
28056f33205SJonathan Adams 					mlp->ml_address = next->ml_address;
28156f33205SJonathan Adams 					mlp->ml_size += next->ml_size;
28256f33205SJonathan Adams 					mlp->ml_size += bytes;
2837c478bd9Sstevel@tonic-gate 
28456f33205SJonathan Adams 					if (next->ml_prev)
28556f33205SJonathan Adams 						next->ml_prev->ml_next = mlp;
28656f33205SJonathan Adams 					mlp->ml_prev = next->ml_prev;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 					memlist_free_one(next);
2897c478bd9Sstevel@tonic-gate 					return (MEML_SPANOP_OK);
2907c478bd9Sstevel@tonic-gate 				}
2917c478bd9Sstevel@tonic-gate 			}
2927c478bd9Sstevel@tonic-gate 
29356f33205SJonathan Adams 			next->ml_size += bytes;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 			return (MEML_SPANOP_OK);
2967c478bd9Sstevel@tonic-gate 		}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 		/* don't overlap with next */
29956f33205SJonathan Adams 		if ((address + bytes) > next->ml_address) {
3007c478bd9Sstevel@tonic-gate 			memlist_free_one(dst);
3017c478bd9Sstevel@tonic-gate 			return (MEML_SPANOP_ESPAN);
3027c478bd9Sstevel@tonic-gate 		}
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 		/*
3057c478bd9Sstevel@tonic-gate 		 * Insert before next.
3067c478bd9Sstevel@tonic-gate 		 */
30756f33205SJonathan Adams 		dst->ml_prev = prev;
30856f33205SJonathan Adams 		dst->ml_next = next;
30956f33205SJonathan Adams 		next->ml_prev = dst;
3107c478bd9Sstevel@tonic-gate 		if (prev == NULL) {
3117c478bd9Sstevel@tonic-gate 			*curmemlistp = dst;
3127c478bd9Sstevel@tonic-gate 		} else {
31356f33205SJonathan Adams 			prev->ml_next = dst;
3147c478bd9Sstevel@tonic-gate 		}
3157c478bd9Sstevel@tonic-gate 		return (MEML_SPANOP_OK);
3167c478bd9Sstevel@tonic-gate 	}
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	/*
3197c478bd9Sstevel@tonic-gate 	 * End of list, prev is valid and next is NULL.
3207c478bd9Sstevel@tonic-gate 	 */
32156f33205SJonathan Adams 	prev->ml_next = dst;
32256f33205SJonathan Adams 	dst->ml_prev = prev;
32356f33205SJonathan Adams 	dst->ml_next = NULL;
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate 	return (MEML_SPANOP_OK);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate /*
3297c478bd9Sstevel@tonic-gate  * Delete a span from a memlist.
3307c478bd9Sstevel@tonic-gate  * Return:
3317c478bd9Sstevel@tonic-gate  * MEML_SPANOP_OK if OK.
3327c478bd9Sstevel@tonic-gate  * MEML_SPANOP_ESPAN if part or all of span does not exist
3337c478bd9Sstevel@tonic-gate  * MEML_SPANOP_EALLOC for allocation failure
3347c478bd9Sstevel@tonic-gate  */
3357c478bd9Sstevel@tonic-gate int
memlist_delete_span(uint64_t address,uint64_t bytes,struct memlist ** curmemlistp)3367c478bd9Sstevel@tonic-gate memlist_delete_span(
3377c478bd9Sstevel@tonic-gate 	uint64_t address,
3387c478bd9Sstevel@tonic-gate 	uint64_t bytes,
3397c478bd9Sstevel@tonic-gate 	struct memlist **curmemlistp)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	struct memlist *dst, *next;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	/*
3447c478bd9Sstevel@tonic-gate 	 * Find element containing address.
3457c478bd9Sstevel@tonic-gate 	 */
34656f33205SJonathan Adams 	for (next = *curmemlistp; next != NULL; next = next->ml_next) {
34756f33205SJonathan Adams 		if ((address >= next->ml_address) &&
34856f33205SJonathan Adams 		    (address < next->ml_address + next->ml_size))
3497c478bd9Sstevel@tonic-gate 			break;
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	/*
3537c478bd9Sstevel@tonic-gate 	 * If start address not in list.
3547c478bd9Sstevel@tonic-gate 	 */
3557c478bd9Sstevel@tonic-gate 	if (next == NULL) {
3567c478bd9Sstevel@tonic-gate 		return (MEML_SPANOP_ESPAN);
3577c478bd9Sstevel@tonic-gate 	}
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	/*
3607c478bd9Sstevel@tonic-gate 	 * Error if size goes off end of this struct memlist.
3617c478bd9Sstevel@tonic-gate 	 */
36256f33205SJonathan Adams 	if (address + bytes > next->ml_address + next->ml_size) {
3637c478bd9Sstevel@tonic-gate 		return (MEML_SPANOP_ESPAN);
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	/*
3677c478bd9Sstevel@tonic-gate 	 * Span at beginning of struct memlist.
3687c478bd9Sstevel@tonic-gate 	 */
36956f33205SJonathan Adams 	if (address == next->ml_address) {
3707c478bd9Sstevel@tonic-gate 		/*
3717c478bd9Sstevel@tonic-gate 		 * If start & size match, delete from list.
3727c478bd9Sstevel@tonic-gate 		 */
37356f33205SJonathan Adams 		if (bytes == next->ml_size) {
3747c478bd9Sstevel@tonic-gate 			if (next == *curmemlistp)
37556f33205SJonathan Adams 				*curmemlistp = next->ml_next;
37656f33205SJonathan Adams 			if (next->ml_prev != NULL)
37756f33205SJonathan Adams 				next->ml_prev->ml_next = next->ml_next;
37856f33205SJonathan Adams 			if (next->ml_next != NULL)
37956f33205SJonathan Adams 				next->ml_next->ml_prev = next->ml_prev;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 			memlist_free_one(next);
3827c478bd9Sstevel@tonic-gate 		} else {
3837c478bd9Sstevel@tonic-gate 			/*
3847c478bd9Sstevel@tonic-gate 			 * Increment start address by bytes.
3857c478bd9Sstevel@tonic-gate 			 */
38656f33205SJonathan Adams 			next->ml_address += bytes;
38756f33205SJonathan Adams 			next->ml_size -= bytes;
3887c478bd9Sstevel@tonic-gate 		}
3897c478bd9Sstevel@tonic-gate 		return (MEML_SPANOP_OK);
3907c478bd9Sstevel@tonic-gate 	}
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	/*
3937c478bd9Sstevel@tonic-gate 	 * Span at end of struct memlist.
3947c478bd9Sstevel@tonic-gate 	 */
39556f33205SJonathan Adams 	if (address + bytes == next->ml_address + next->ml_size) {
3967c478bd9Sstevel@tonic-gate 		/*
3977c478bd9Sstevel@tonic-gate 		 * decrement size by bytes
3987c478bd9Sstevel@tonic-gate 		 */
39956f33205SJonathan Adams 		next->ml_size -= bytes;
4007c478bd9Sstevel@tonic-gate 		return (MEML_SPANOP_OK);
4017c478bd9Sstevel@tonic-gate 	}
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	/*
4047c478bd9Sstevel@tonic-gate 	 * Delete a span in the middle of the struct memlist.
4057c478bd9Sstevel@tonic-gate 	 */
4067c478bd9Sstevel@tonic-gate 	{
4077c478bd9Sstevel@tonic-gate 		/*
4087c478bd9Sstevel@tonic-gate 		 * create a new struct memlist
4097c478bd9Sstevel@tonic-gate 		 */
4107c478bd9Sstevel@tonic-gate 		dst = memlist_get_one();
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 		if (dst == NULL) {
4137c478bd9Sstevel@tonic-gate 			return (MEML_SPANOP_EALLOC);
4147c478bd9Sstevel@tonic-gate 		}
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 		/*
4177c478bd9Sstevel@tonic-gate 		 * Existing struct memlist gets address
4187c478bd9Sstevel@tonic-gate 		 * and size up to start of span.
4197c478bd9Sstevel@tonic-gate 		 */
42056f33205SJonathan Adams 		dst->ml_address = address + bytes;
42156f33205SJonathan Adams 		dst->ml_size =
42256f33205SJonathan Adams 		    (next->ml_address + next->ml_size) - dst->ml_address;
42356f33205SJonathan Adams 		next->ml_size = address - next->ml_address;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 		/*
4267c478bd9Sstevel@tonic-gate 		 * New struct memlist gets address starting
4277c478bd9Sstevel@tonic-gate 		 * after span, until end.
4287c478bd9Sstevel@tonic-gate 		 */
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 		/*
4317c478bd9Sstevel@tonic-gate 		 * link in new memlist after old
4327c478bd9Sstevel@tonic-gate 		 */
43356f33205SJonathan Adams 		dst->ml_next = next->ml_next;
43456f33205SJonathan Adams 		dst->ml_prev = next;
4357c478bd9Sstevel@tonic-gate 
43656f33205SJonathan Adams 		if (next->ml_next != NULL)
43756f33205SJonathan Adams 			next->ml_next->ml_prev = dst;
43856f33205SJonathan Adams 		next->ml_next = dst;
4397c478bd9Sstevel@tonic-gate 	}
4407c478bd9Sstevel@tonic-gate 	return (MEML_SPANOP_OK);
4417c478bd9Sstevel@tonic-gate }
442