- /*
- * If there are entries in the splay tree,
- * then we have work to do:
- * 1) transfer entries to the table
- * 2) update is_tree_small
- */
- assert(!is_fast_space(space) || space->is_tree_total == 0);
- if (space->is_tree_total > 0) {
- mach_port_index_t index;
- boolean_t delete;
- struct ipc_splay_tree ignore;
- struct ipc_splay_tree move;
- struct ipc_splay_tree small;
- ipc_entry_num_t nosmall;
- ipc_tree_entry_t tentry;
-
- /*
- * The splay tree divides into four regions,
- * based on the index of the entries:
- * 1) 0 <= index < osize
- * 2) osize <= index < size
- * 3) size <= index < nsize
- * 4) nsize <= index
- *
- * Entries in the first part are ignored.
- * Entries in the second part, that don't
- * collide, are moved into the table.
- * Entries in the third part, that don't
- * collide, are counted for is_tree_small.
- * Entries in the fourth part are ignored.
- */
-
- ipc_splay_tree_split(&space->is_tree,
- MACH_PORT_MAKE(nsize, 0),
- &small);
- ipc_splay_tree_split(&small,
- MACH_PORT_MAKE(size, 0),
- &move);
- ipc_splay_tree_split(&move,
- MACH_PORT_MAKE(osize, 0),
- &ignore);
-
- /* move entries into the table */
-
- for (tentry = ipc_splay_traverse_start(&move);
- tentry != ITE_NULL;
- tentry = ipc_splay_traverse_next(&move, delete)) {
-
- mach_port_name_t name;
- mach_port_gen_t gen;
- mach_port_type_t type;
- ipc_entry_bits_t bits;
- ipc_object_t obj;
- ipc_entry_t entry;
-
- name = tentry->ite_name;
- gen = MACH_PORT_GEN(name);
- index = MACH_PORT_INDEX(name);
-
- assert(tentry->ite_space == space);
- assert((osize <= index) && (index < size));
-
- entry = &table[index];
- bits = entry->ie_bits;
- if (IE_BITS_TYPE(bits)) {
- assert(IE_BITS_GEN(bits) != gen);
- entry->ie_bits |= IE_BITS_COLLISION;
- delete = FALSE;
- continue;
- }
-
- bits = tentry->ite_bits;
- type = IE_BITS_TYPE(bits);
- assert(type != MACH_PORT_TYPE_NONE);
-
- entry->ie_bits = bits | gen;
- entry->ie_request = tentry->ite_request;
- entry->ie_object = obj = tentry->ite_object;
-
- if (type == MACH_PORT_TYPE_SEND) {
- ipc_hash_global_delete(space, obj,
- name, tentry);
- ipc_hash_local_insert(space, obj,
- index, entry);
- }
- space->is_tree_total--;
- delete = TRUE;
+ low_mod = 0;
+ hi_mod = osize - 1;
+rescan:
+ /*
+ * Within the range of the table that changed, determine what we
+ * have to take action on. For each entry, take a snapshot of the
+ * corresponding entry in the old table (so it won't change
+ * during this iteration). The snapshot may not be self-consistent
+ * (if we caught it in the middle of being changed), so be very
+ * cautious with the values.
+ */
+ for (i = low_mod; i <= hi_mod; i++) {
+ ipc_entry_t entry = &table[i];
+ struct ipc_entry osnap = otable[i];
+
+ if (entry->ie_object != osnap.ie_object ||
+ IE_BITS_TYPE(entry->ie_bits) != IE_BITS_TYPE(osnap.ie_bits)) {
+ if (entry->ie_object != IO_NULL &&
+ IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_SEND) {
+ ipc_hash_table_delete(table, size, entry->ie_object, i, entry);