summaryrefslogtreecommitdiff
path: root/ipc/ipc_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/ipc_table.c')
-rw-r--r--ipc/ipc_table.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/ipc/ipc_table.c b/ipc/ipc_table.c
new file mode 100644
index 0000000..e572358
--- /dev/null
+++ b/ipc/ipc_table.c
@@ -0,0 +1,205 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ */
+/*
+ * File: ipc/ipc_table.c
+ * Author: Rich Draves
+ * Date: 1989
+ *
+ * Functions to manipulate tables of IPC capabilities.
+ */
+
+#include <mach/kern_return.h>
+#include <mach/vm_param.h>
+#include <ipc/ipc_table.h>
+#include <ipc/ipc_port.h>
+#include <ipc/ipc_entry.h>
+#include <kern/kalloc.h>
+#include <vm/vm_kern.h>
+
+/*
+ * Forward declarations
+ */
+void ipc_table_fill(
+ ipc_table_size_t its,
+ unsigned int num,
+ unsigned int min,
+ vm_size_t elemsize);
+
+/*
+ * We borrow the kalloc map, rather than creating
+ * yet another submap of the kernel map.
+ */
+
+extern vm_map_t kalloc_map;
+
+ipc_table_size_t ipc_table_entries;
+unsigned int ipc_table_entries_size = 512;
+
+ipc_table_size_t ipc_table_dnrequests;
+unsigned int ipc_table_dnrequests_size = 64;
+
+void
+ipc_table_fill(
+ ipc_table_size_t its, /* array to fill */
+ unsigned int num, /* size of array */
+ unsigned int min, /* at least this many elements */
+ vm_size_t elemsize) /* size of elements */
+{
+ unsigned int index;
+ vm_size_t minsize = min * elemsize;
+ vm_size_t size;
+ vm_size_t incrsize;
+
+ /* first use powers of two, up to the page size */
+
+ for (index = 0, size = 1;
+ (index < num) && (size < PAGE_SIZE);
+ size <<= 1) {
+ if (size >= minsize) {
+ its[index].its_size = size / elemsize;
+ index++;
+ }
+ }
+
+ /* then increments of a page, then two pages, etc. */
+
+ for (incrsize = PAGE_SIZE; index < num;) {
+ unsigned int period;
+
+ for (period = 0;
+ (period < 15) && (index < num);
+ period++, size += incrsize) {
+ if (size >= minsize) {
+ its[index].its_size = size / elemsize;
+ index++;
+ }
+ }
+ if (incrsize < (PAGE_SIZE << 3))
+ incrsize <<= 1;
+ }
+}
+
+void
+ipc_table_init(void)
+{
+ ipc_table_entries = (ipc_table_size_t)
+ kalloc(sizeof(struct ipc_table_size) *
+ ipc_table_entries_size);
+ assert(ipc_table_entries != ITS_NULL);
+
+ ipc_table_fill(ipc_table_entries, ipc_table_entries_size - 1,
+ 4, sizeof(struct ipc_entry));
+
+ /* the last two elements should have the same size */
+
+ ipc_table_entries[ipc_table_entries_size - 1].its_size =
+ ipc_table_entries[ipc_table_entries_size - 2].its_size;
+
+
+ ipc_table_dnrequests = (ipc_table_size_t)
+ kalloc(sizeof(struct ipc_table_size) *
+ ipc_table_dnrequests_size);
+ assert(ipc_table_dnrequests != ITS_NULL);
+
+ ipc_table_fill(ipc_table_dnrequests, ipc_table_dnrequests_size - 1,
+ 2, sizeof(struct ipc_port_request));
+
+ /* the last element should have zero size */
+
+ ipc_table_dnrequests[ipc_table_dnrequests_size - 1].its_size = 0;
+}
+
+/*
+ * Routine: ipc_table_alloc
+ * Purpose:
+ * Allocate a table.
+ * Conditions:
+ * May block.
+ */
+
+vm_offset_t
+ipc_table_alloc(
+ vm_size_t size)
+{
+ vm_offset_t table;
+
+ if (size < PAGE_SIZE)
+ table = kalloc(size);
+ else
+ if (kmem_alloc(kalloc_map, &table, size) != KERN_SUCCESS)
+ table = 0;
+
+ return table;
+}
+
+/*
+ * Routine: ipc_table_realloc
+ * Purpose:
+ * Reallocate a big table.
+ *
+ * The new table remaps the old table,
+ * so copying is not necessary.
+ * Conditions:
+ * Only works for page-size or bigger tables.
+ * May block.
+ */
+
+vm_offset_t
+ipc_table_realloc(
+ vm_size_t old_size,
+ vm_offset_t old_table,
+ vm_size_t new_size)
+{
+ vm_offset_t new_table;
+
+ if (kmem_realloc(kalloc_map, old_table, old_size,
+ &new_table, new_size) != KERN_SUCCESS)
+ new_table = 0;
+
+ return new_table;
+}
+
+/*
+ * Routine: ipc_table_free
+ * Purpose:
+ * Free a table allocated with ipc_table_alloc or
+ * ipc_table_realloc.
+ * Conditions:
+ * May block.
+ */
+
+void
+ipc_table_free(
+ vm_size_t size,
+ vm_offset_t table)
+{
+ if (size < PAGE_SIZE)
+ kfree(table, size);
+ else
+ kmem_free(kalloc_map, table, size);
+}