|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
4: * Copyright (c) 1993,1994 The University of Utah and
5: * the Computer Systems Laboratory (CSL).
6: * All rights reserved.
7: *
8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
13: *
14: * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
15: * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
16: * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
17: * THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or [email protected]
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie Mellon
27: * the rights to redistribute these changes.
28: */
29: /*
30: */
31: /*
32: * File: ipc/ipc_space.h
33: * Author: Rich Draves
34: * Date: 1989
35: *
36: * Definitions for IPC spaces of capabilities.
37: */
38:
39: #ifndef _IPC_IPC_SPACE_H_
40: #define _IPC_IPC_SPACE_H_
41:
42: #include <mach/boolean.h>
43: #include <mach/kern_return.h>
1.1.1.3 root 44: #include <mach/mach_types.h>
1.1.1.4 ! root 45: #include <machine/vm_param.h>
! 46: #include <kern/macros.h>
1.1 root 47: #include <kern/lock.h>
1.1.1.4 ! root 48: #include <kern/rdxtree.h>
1.1.1.3 root 49: #include <kern/slab.h>
1.1.1.4 ! root 50: #include <ipc/ipc_entry.h>
1.1.1.3 root 51: #include <ipc/ipc_types.h>
1.1 root 52:
53: /*
54: * Every task has a space of IPC capabilities.
55: * IPC operations like send and receive use this space.
56: * IPC kernel calls manipulate the space of the target task.
57: */
58:
59: typedef unsigned int ipc_space_refs_t;
60:
61: struct ipc_space {
62: decl_simple_lock_data(,is_ref_lock_data)
63: ipc_space_refs_t is_references;
64:
1.1.1.4 ! root 65: struct lock is_lock_data;
1.1 root 66: boolean_t is_active; /* is the space alive? */
1.1.1.4 ! root 67: struct rdxtree is_map; /* a map of entries */
! 68: size_t is_size; /* number of entries */
! 69: struct rdxtree is_reverse_map; /* maps objects to entries */
! 70: ipc_entry_t is_free_list; /* a linked list of free entries */
! 71: size_t is_free_list_size; /* number of free entries */
! 72: #define IS_FREE_LIST_SIZE_LIMIT 64 /* maximum number of entries
! 73: in the free list */
1.1 root 74: };
75:
1.1.1.4 ! root 76:
1.1 root 77: #define IS_NULL ((ipc_space_t) 0)
78:
1.1.1.3 root 79: extern struct kmem_cache ipc_space_cache;
1.1 root 80:
1.1.1.3 root 81: #define is_alloc() ((ipc_space_t) kmem_cache_alloc(&ipc_space_cache))
82: #define is_free(is) kmem_cache_free(&ipc_space_cache, (vm_offset_t) (is))
1.1 root 83:
84: extern struct ipc_space *ipc_space_kernel;
85: extern struct ipc_space *ipc_space_reply;
86:
87: #define is_ref_lock_init(is) simple_lock_init(&(is)->is_ref_lock_data)
88:
89: #define ipc_space_reference_macro(is) \
90: MACRO_BEGIN \
91: simple_lock(&(is)->is_ref_lock_data); \
92: assert((is)->is_references > 0); \
93: (is)->is_references++; \
94: simple_unlock(&(is)->is_ref_lock_data); \
95: MACRO_END
96:
97: #define ipc_space_release_macro(is) \
98: MACRO_BEGIN \
99: ipc_space_refs_t _refs; \
100: \
101: simple_lock(&(is)->is_ref_lock_data); \
102: assert((is)->is_references > 0); \
103: _refs = --(is)->is_references; \
104: simple_unlock(&(is)->is_ref_lock_data); \
105: \
106: if (_refs == 0) \
107: is_free(is); \
108: MACRO_END
109:
1.1.1.4 ! root 110: #define is_lock_init(is) lock_init(&(is)->is_lock_data, TRUE)
1.1 root 111:
1.1.1.4 ! root 112: #define is_read_lock(is) lock_read(&(is)->is_lock_data)
! 113: #define is_read_unlock(is) lock_done(&(is)->is_lock_data)
1.1 root 114:
1.1.1.4 ! root 115: #define is_write_lock(is) lock_write(&(is)->is_lock_data)
! 116: #define is_write_lock_try(is) lock_try_write(&(is)->is_lock_data)
! 117: #define is_write_unlock(is) lock_done(&(is)->is_lock_data)
1.1 root 118:
1.1.1.4 ! root 119: #define is_write_to_read_lock(is) lock_write_to_read(&(is)->is_lock_data)
1.1 root 120:
121: extern void ipc_space_reference(struct ipc_space *space);
122: extern void ipc_space_release(struct ipc_space *space);
123:
1.1.1.4 ! root 124: #define is_reference(is) ipc_space_reference_macro(is)
! 125: #define is_release(is) ipc_space_release_macro(is)
1.1 root 126:
1.1.1.4 ! root 127: kern_return_t ipc_space_create(ipc_space_t *);
1.1 root 128: kern_return_t ipc_space_create_special(struct ipc_space **);
129: void ipc_space_destroy(struct ipc_space *);
130:
1.1.1.4 ! root 131: /* IPC entry lookups. */
! 132:
! 133: /*
! 134: * Routine: ipc_entry_lookup
! 135: * Purpose:
! 136: * Searches for an entry, given its name.
! 137: * Conditions:
! 138: * The space must be read or write locked throughout.
! 139: * The space must be active.
! 140: */
! 141:
! 142: static inline ipc_entry_t
! 143: ipc_entry_lookup(
! 144: ipc_space_t space,
! 145: mach_port_t name)
! 146: {
! 147: ipc_entry_t entry;
! 148:
! 149: assert(space->is_active);
! 150: entry = rdxtree_lookup(&space->is_map, (rdxtree_key_t) name);
! 151: if (entry != IE_NULL
! 152: && IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
! 153: entry = NULL;
! 154: assert((entry == IE_NULL) || IE_BITS_TYPE(entry->ie_bits));
! 155: return entry;
! 156: }
! 157:
! 158: /*
! 159: * Routine: ipc_entry_get
! 160: * Purpose:
! 161: * Tries to allocate an entry out of the space.
! 162: * Conditions:
! 163: * The space is write-locked and active throughout.
! 164: * An object may be locked. Will not allocate memory.
! 165: * Returns:
! 166: * KERN_SUCCESS A free entry was found.
! 167: * KERN_NO_SPACE No entry allocated.
! 168: */
! 169:
! 170: static inline kern_return_t
! 171: ipc_entry_get(
! 172: ipc_space_t space,
! 173: mach_port_t *namep,
! 174: ipc_entry_t *entryp)
! 175: {
! 176: mach_port_t new_name;
! 177: ipc_entry_t free_entry;
! 178:
! 179: assert(space->is_active);
! 180:
! 181: /* Get entry from the free list. */
! 182: free_entry = space->is_free_list;
! 183: if (free_entry == IE_NULL)
! 184: return KERN_NO_SPACE;
! 185:
! 186: space->is_free_list = free_entry->ie_next_free;
! 187: space->is_free_list_size -= 1;
! 188:
! 189: /*
! 190: * Initialize the new entry. We need only
! 191: * increment the generation number and clear ie_request.
! 192: */
! 193:
! 194: {
! 195: mach_port_gen_t gen;
! 196:
! 197: assert((free_entry->ie_bits &~ IE_BITS_GEN_MASK) == 0);
! 198: gen = free_entry->ie_bits + IE_BITS_GEN_ONE;
! 199: free_entry->ie_bits = gen;
! 200: free_entry->ie_request = 0;
! 201: new_name = MACH_PORT_MAKE(free_entry->ie_name, gen);
! 202: }
! 203:
! 204: /*
! 205: * The new name can't be MACH_PORT_NULL because index
! 206: * is non-zero. It can't be MACH_PORT_DEAD because
! 207: * the table isn't allowed to grow big enough.
! 208: * (See comment in ipc/ipc_table.h.)
! 209: */
! 210:
! 211: assert(MACH_PORT_VALID(new_name));
! 212: assert(free_entry->ie_object == IO_NULL);
! 213:
! 214: space->is_size += 1;
! 215: *namep = new_name;
! 216: *entryp = free_entry;
! 217: return KERN_SUCCESS;
! 218: }
! 219:
! 220: /*
! 221: * Routine: ipc_entry_dealloc
! 222: * Purpose:
! 223: * Deallocates an entry from a space.
! 224: * Conditions:
! 225: * The space must be write-locked throughout.
! 226: * The space must be active.
! 227: */
! 228:
! 229: static inline void
! 230: ipc_entry_dealloc(
! 231: ipc_space_t space,
! 232: mach_port_t name,
! 233: ipc_entry_t entry)
! 234: {
! 235: assert(space->is_active);
! 236: assert(entry->ie_object == IO_NULL);
! 237: assert(entry->ie_request == 0);
! 238:
! 239: if (space->is_free_list_size < IS_FREE_LIST_SIZE_LIMIT) {
! 240: space->is_free_list_size += 1;
! 241: entry->ie_bits &= IE_BITS_GEN_MASK;
! 242: entry->ie_next_free = space->is_free_list;
! 243: space->is_free_list = entry;
! 244: } else {
! 245: rdxtree_remove(&space->is_map, (rdxtree_key_t) name);
! 246: ie_free(entry);
! 247: }
! 248: space->is_size -= 1;
! 249: }
! 250:
! 251: /* Reverse lookups. */
! 252:
! 253: /* Cast a pointer to a suitable key. */
! 254: #define KEY(X) \
! 255: ({ \
! 256: assert((((unsigned long) (X)) & 0x07) == 0); \
! 257: ((unsigned long long) \
! 258: (((unsigned long) (X) - VM_MIN_KERNEL_ADDRESS) >> 3)); \
! 259: })
! 260:
! 261: /* Insert (OBJ, ENTRY) pair into the reverse mapping. SPACE must
! 262: be write-locked. */
! 263: static inline kern_return_t
! 264: ipc_reverse_insert(ipc_space_t space,
! 265: ipc_object_t obj,
! 266: ipc_entry_t entry)
! 267: {
! 268: assert(space != IS_NULL);
! 269: assert(obj != IO_NULL);
! 270: return (kern_return_t) rdxtree_insert(&space->is_reverse_map,
! 271: KEY(obj), entry);
! 272: }
! 273:
! 274: /* Remove OBJ from the reverse mapping. SPACE must be
! 275: write-locked. */
! 276: static inline ipc_entry_t
! 277: ipc_reverse_remove(ipc_space_t space,
! 278: ipc_object_t obj)
! 279: {
! 280: assert(space != IS_NULL);
! 281: assert(obj != IO_NULL);
! 282: return rdxtree_remove(&space->is_reverse_map, KEY(obj));
! 283: }
! 284:
! 285: /* Remove all entries from the reverse mapping. SPACE must be
! 286: write-locked. */
! 287: static inline void
! 288: ipc_reverse_remove_all(ipc_space_t space)
! 289: {
! 290: assert(space != IS_NULL);
! 291: rdxtree_remove_all(&space->is_reverse_map);
! 292: assert(space->is_reverse_map.height == 0);
! 293: assert(space->is_reverse_map.root == NULL);
! 294: }
! 295:
! 296: /* Return ENTRY related to OBJ, or NULL if no such entry is found in
! 297: the reverse mapping. SPACE must be read-locked or
! 298: write-locked. */
! 299: static inline ipc_entry_t
! 300: ipc_reverse_lookup(ipc_space_t space,
! 301: ipc_object_t obj)
! 302: {
! 303: assert(space != IS_NULL);
! 304: assert(obj != IO_NULL);
! 305: return rdxtree_lookup(&space->is_reverse_map, KEY(obj));
! 306: }
! 307:
! 308: #undef KEY
! 309:
1.1.1.2 root 310: #endif /* _IPC_IPC_SPACE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.