2 * Copyright (c) 1996, 1998 University of Utah and the Flux Group.
5 * This file is part of the Flux OSKit. The OSKit is free software, also known
6 * as "open source;" you can redistribute it and/or modify it under the terms
7 * of the GNU General Public License (GPL), version 2, as published by the Free
8 * Software Foundation (FSF). To explore alternate licensing terms, contact
9 * the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
11 * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have
14 * received a copy of the GPL along with the OSKit; see the file COPYING. If
15 * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
19 * Modify a range of address space
26 * Modifies an address range to be associated with a new entry and new flags.
27 * Any existing entries wholly within the range are deleted, any that partly
28 * overlap the range are split as necessary. After adding the new entry,
29 * the amm may attempt to join it with adjacent already-existing entries if
30 * it appears possible (i.e., if the flags words are the same). The standard
31 * amm_join function is called in this case.
33 * Function returns zero if successful, non-zero if a split failed (e.g.,
34 * due to lack of memory).
36 * Parameters addr and size define the range to be modified.
38 * nflags is the new flags for the range.
40 * Nentry is the new entry to use. nentry may be zero, in which case the amm
41 * allocates a new standard entry itself. If nentry is non-zero, the caller
42 * must have already allocated any extra attribate data in the entry. In
43 * either case, the amm will initialize the private part of the new amm_entry,
44 * including setting its address range type flags to the nflags parameter.
47 amm_modify(struct amm *amm, vm_offset_t addr, vm_size_t size,
48 int nflags, struct amm_entry *nentry)
50 struct amm_entry **pentry, *entry, *hentry, *tentry;
58 entry = amm_find_addr(amm, addr);
62 * If no explicit entry was specified and the indicated range
63 * already has the desired attributes, there is nothing to do.
65 if (nentry == 0 && addr >= entry->start && eaddr <= entry->end &&
66 nflags == entry->flags)
70 * Split off anything before the region of interest.
72 if (entry->start < addr) {
73 rc = amm_split(amm, pentry, entry, addr, &hentry, &tentry);
76 pentry = &hentry->next;
79 assert(entry->start == addr);
82 * Now traverse entries that are completely covered by the new
83 * one and delete them.
85 while (entry->end < eaddr) {
86 *pentry = entry->next;
87 amm_free_entry(amm, entry);
92 * Split off anything after the region of interest
94 if (entry->end > eaddr) {
95 rc = amm_split(amm, pentry, entry, eaddr, &hentry, &tentry);
100 assert(entry->end == eaddr);
103 * Final entry corresponding to end of range.
104 * If no explicit new entry was specified or the current entry
105 * was specified we just modify the existing entry.
107 if (nentry == entry) {
109 entry->flags = nflags;
113 nentry = amm_alloc_entry(amm, addr, eaddr-addr, nflags);
118 nentry->next = entry->next;
119 nentry->start = addr;
121 nentry->flags = nflags;
122 amm_free_entry(amm, entry);
126 * Finally, try to merge with previous entry...
128 if (pentry != &amm->nodes) {
129 hentry = (struct amm_entry *)pentry;
131 assert(hentry->next == tentry);
132 if (hentry->flags == tentry->flags) {
133 for (pentry = &amm->nodes; *pentry;
134 pentry = &(*pentry)->next)
135 if (*pentry == hentry)
138 rc = amm_join(amm, pentry, hentry, tentry, &nentry);
139 /* XXX return an error on rc != 0? */
141 pentry = &hentry->next;
149 tentry = nentry->next;
150 if (hentry->flags == tentry->flags) {
151 rc = amm_join(amm, pentry, hentry, tentry, &nentry);
152 /* XXX return an error on rc != 0? */