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