]> rtime.felk.cvut.cz Git - l4.git/blobdiff - kernel/fiasco/src/lib/amm/amm_select.c
Inital import
[l4.git] / kernel / fiasco / src / lib / amm / amm_select.c
diff --git a/kernel/fiasco/src/lib/amm/amm_select.c b/kernel/fiasco/src/lib/amm/amm_select.c
new file mode 100644 (file)
index 0000000..03ffc62
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1996-1998 University of Utah and the Flux Group.
+ * All rights reserved.
+ * 
+ * This file is part of the Flux OSKit.  The OSKit is free software, also known
+ * as "open source;" you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License (GPL), version 2, as published by the Free
+ * Software Foundation (FSF).  To explore alternate licensing terms, contact
+ * the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
+ * 
+ * The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GPL for more details.  You should have
+ * received a copy of the GPL along with the OSKit; see the file COPYING.  If
+ * not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Select (isolate) a range of address space
+ */
+#include <errno.h>
+#include "amm.h"
+
+/*
+ * Select (isolate) the specified range by splitting off everything before
+ * and after as necessary.  Result is one or more entries exactly covering
+ * the range.  Returns a pointer to the first entry for the start of the
+ * range or zero if the range could not be isolated.  Successive entries
+ * can be located using amm_find_addr.
+ */
+amm_entry_t *
+amm_select(struct amm *amm, vm_offset_t addr, vm_size_t size)
+{
+       struct amm_entry **pentry, *entry, *hentry, *tentry;
+       vm_offset_t eaddr;
+       int rc;
+
+       eaddr = addr + size;
+       if (eaddr < addr)
+               return 0;
+
+       entry = amm_find_addr(amm, addr);
+       pentry = amm->hint;
+
+       /*
+        * Split off anything before the region of interest.
+        * Leave hint pointing at the beginning of the region.
+        */
+       if (entry->start < addr) {
+               rc = amm_split(amm, pentry, entry, addr, &hentry, &tentry);
+               if (rc)
+                       return 0;
+               pentry = &hentry->next;
+               entry = tentry;
+               amm->hint = pentry;
+       }
+       assert(entry->start == addr);
+
+       /*
+        * Skip over entries that are completely covered by the range.
+        */
+       while (entry->end < eaddr) {
+               pentry = &entry->next;
+               entry = *pentry;
+       }
+
+       /*
+        * Split off anything after the region of interest
+        */
+       if (entry->end > eaddr) {
+               rc = amm_split(amm, pentry, entry, eaddr, &hentry, &tentry);
+               if (rc)
+                       return 0;
+               entry = hentry;
+       }
+       assert(entry->end == eaddr);
+
+       /*
+        * Return the first entry.
+        */
+       return *amm->hint;
+}
+