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