]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/lib/amm/amm_select.c
update
[l4.git] / kernel / fiasco / src / lib / amm / amm_select.c
1 /*
2  * Copyright (c) 1996-1998 University of Utah and the Flux Group.
3  * All rights reserved.
4  * 
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.
10  * 
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.
16  */
17
18 /*
19  * Select (isolate) a range of address space
20  */
21 #include <errno.h>
22 #include "amm.h"
23
24 /*
25  * Select (isolate) the specified range by splitting off everything before
26  * and after as necessary.  Result is one or more entries exactly covering
27  * the range.  Returns a pointer to the first entry for the start of the
28  * range or zero if the range could not be isolated.  Successive entries
29  * can be located using amm_find_addr.
30  */
31 amm_entry_t *
32 amm_select(struct amm *amm, vm_offset_t addr, vm_size_t size)
33 {
34         struct amm_entry **pentry, *entry, *hentry, *tentry;
35         vm_offset_t eaddr;
36         int rc;
37
38         eaddr = addr + size;
39         if (eaddr < addr)
40                 return 0;
41
42         entry = amm_find_addr(amm, addr);
43         pentry = amm->hint;
44
45         /*
46          * Split off anything before the region of interest.
47          * Leave hint pointing at the beginning of the region.
48          */
49         if (entry->start < addr) {
50                 rc = amm_split(amm, pentry, entry, addr, &hentry, &tentry);
51                 if (rc)
52                         return 0;
53                 pentry = &hentry->next;
54                 entry = tentry;
55                 amm->hint = pentry;
56         }
57         assert(entry->start == addr);
58
59         /*
60          * Skip over entries that are completely covered by the range.
61          */
62         while (entry->end < eaddr) {
63                 pentry = &entry->next;
64                 entry = *pentry;
65         }
66
67         /*
68          * Split off anything after the region of interest
69          */
70         if (entry->end > eaddr) {
71                 rc = amm_split(amm, pentry, entry, eaddr, &hentry, &tentry);
72                 if (rc)
73                         return 0;
74                 entry = hentry;
75         }
76         assert(entry->end == eaddr);
77
78         /*
79          * Return the first entry.
80          */
81         return *amm->hint;
82 }
83