X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..7e41aa883dd258f888d0470250eead40a53ef1f5:/osfmk/ipc/ipc_entry.c diff --git a/osfmk/ipc/ipc_entry.c b/osfmk/ipc/ipc_entry.c index 80eb3d662..aabb15ada 100644 --- a/osfmk/ipc/ipc_entry.c +++ b/osfmk/ipc/ipc_entry.c @@ -99,7 +99,6 @@ ipc_entry_lookup( assert(is_active(space)); - index = MACH_PORT_INDEX(name); if (index < space->is_table_size) { entry = &space->is_table[index]; @@ -115,69 +114,127 @@ ipc_entry_lookup( return entry; } + /* - * Routine: ipc_entry_get + * Routine: ipc_entries_hold * Purpose: - * Tries to allocate an entry out of the space. + * Verifies that there are at least 'entries_needed' + * free list members * Conditions: * The space is write-locked and active throughout. * An object may be locked. Will not allocate memory. * Returns: - * KERN_SUCCESS A free entry was found. + * KERN_SUCCESS Free entries were found. * KERN_NO_SPACE No entry allocated. */ kern_return_t -ipc_entry_get( +ipc_entries_hold( + ipc_space_t space, + uint32_t entries_needed) +{ + + ipc_entry_t table; + mach_port_index_t next_free = 0; + uint32_t i; + + assert(is_active(space)); + + table = &space->is_table[0]; + + for (i = 0; i < entries_needed; i++) { + next_free = table[next_free].ie_next; + if (next_free == 0) { + return KERN_NO_SPACE; + } + assert(next_free < space->is_table_size); + assert(table[next_free].ie_object == IO_NULL); + } + return KERN_SUCCESS; +} + +/* + * Routine: ipc_entry_claim + * Purpose: + * Take formal ownership of a held entry. + * Conditions: + * The space is write-locked and active throughout. + * An object may be locked. Will not allocate memory. + * + * Note: The returned entry must be marked as modified before + * releasing the space lock + */ + +kern_return_t +ipc_entry_claim( ipc_space_t space, mach_port_name_t *namep, ipc_entry_t *entryp) { + ipc_entry_t entry; ipc_entry_t table; mach_port_index_t first_free; - ipc_entry_t free_entry; + mach_port_gen_t gen; + mach_port_name_t new_name; - assert(is_active(space)); + table = &space->is_table[0]; - { - table = space->is_table; - first_free = table->ie_next; + first_free = table->ie_next; + assert(first_free != 0); - if (first_free == 0) - return KERN_NO_SPACE; + entry = &table[first_free]; + table->ie_next = entry->ie_next; + space->is_table_free--; - assert(first_free < space->is_table_size); - free_entry = &table[first_free]; - table->ie_next = free_entry->ie_next; - } + assert(table->ie_next < space->is_table_size); /* * Initialize the new entry. We need only * increment the generation number and clear ie_request. */ - { - mach_port_name_t new_name; - mach_port_gen_t gen; + gen = IE_BITS_NEW_GEN(entry->ie_bits); + entry->ie_bits = gen; + entry->ie_request = IE_REQ_NONE; - gen = IE_BITS_NEW_GEN(free_entry->ie_bits); - free_entry->ie_bits = gen; - free_entry->ie_request = IE_REQ_NONE; + /* + * The new name can't be MACH_PORT_NULL because index + * is non-zero. It can't be MACH_PORT_DEAD because + * the table isn't allowed to grow big enough. + * (See comment in ipc/ipc_table.h.) + */ + new_name = MACH_PORT_MAKE(first_free, gen); + assert(MACH_PORT_VALID(new_name)); + *namep = new_name; + *entryp = entry; - /* - * The new name can't be MACH_PORT_NULL because index - * is non-zero. It can't be MACH_PORT_DEAD because - * the table isn't allowed to grow big enough. - * (See comment in ipc/ipc_table.h.) - */ - new_name = MACH_PORT_MAKE(first_free, gen); - assert(MACH_PORT_VALID(new_name)); - *namep = new_name; - } + return KERN_SUCCESS; +} - assert(free_entry->ie_object == IO_NULL); +/* + * Routine: ipc_entry_get + * Purpose: + * Tries to allocate an entry out of the space. + * Conditions: + * The space is write-locked and active throughout. + * An object may be locked. Will not allocate memory. + * Returns: + * KERN_SUCCESS A free entry was found. + * KERN_NO_SPACE No entry allocated. + */ - *entryp = free_entry; - return KERN_SUCCESS; +kern_return_t +ipc_entry_get( + ipc_space_t space, + mach_port_name_t *namep, + ipc_entry_t *entryp) +{ + kern_return_t kr; + + kr = ipc_entries_hold(space, 1); + if (KERN_SUCCESS != kr) + return kr; + + return ipc_entry_claim(space, namep, entryp); } /* @@ -306,7 +363,8 @@ ipc_entry_alloc_name( table[free_index].ie_next = table[next_index].ie_next; - + space->is_table_free--; + /* mark the previous entry modified - reconstructing the name */ ipc_entry_modified(space, MACH_PORT_MAKE(free_index, @@ -376,6 +434,7 @@ ipc_entry_dealloc( entry->ie_bits &= IE_BITS_GEN_MASK; entry->ie_next = table->ie_next; table->ie_next = index; + space->is_table_free++; } else { /* * Nothing to do. The entry does not match @@ -675,6 +734,7 @@ ipc_entry_grow_table( space->is_table = table; space->is_table_size = size; space->is_table_next = nits; + space->is_table_free += size - osize; is_done_growing(space); is_write_unlock(space);