Author: axeld Date: 2009-10-26 14:34:43 +0100 (Mon, 26 Oct 2009) New Revision: 33771 Changeset: http://dev.haiku-os.org/changeset/33771/haiku Modified: haiku/trunk/headers/private/kernel/port.h haiku/trunk/headers/private/kernel/thread_types.h haiku/trunk/src/system/kernel/port.cpp haiku/trunk/src/system/kernel/team.cpp Log: * delete_owned_ports() no longer scans the whole port array for ports belonging to the owning team. * Instead, the team now maintains a list containing the ports it owns. Modified: haiku/trunk/headers/private/kernel/port.h =================================================================== --- haiku/trunk/headers/private/kernel/port.h 2009-10-26 13:29:29 UTC (rev 33770) +++ haiku/trunk/headers/private/kernel/port.h 2009-10-26 13:34:43 UTC (rev 33771) @@ -32,7 +32,7 @@ #endif status_t port_init(struct kernel_args *args); -int delete_owned_ports(team_id owner); +void delete_owned_ports(struct team* team); int32 port_max_ports(void); int32 port_used_ports(void); @@ -41,12 +41,9 @@ // currently private API status_t writev_port_etc(port_id id, int32 msgCode, const iovec *msgVecs, - size_t vecCount, size_t bufferSize, uint32 flags, - bigtime_t timeout); + size_t vecCount, size_t bufferSize, uint32 flags, + bigtime_t timeout); -// temp: test -void port_test(void); - // user syscalls port_id _user_create_port(int32 queueLength, const char *name); status_t _user_close_port(port_id id); Modified: haiku/trunk/headers/private/kernel/thread_types.h =================================================================== --- haiku/trunk/headers/private/kernel/thread_types.h 2009-10-26 13:29:29 UTC (rev 33770) +++ haiku/trunk/headers/private/kernel/thread_types.h 2009-10-26 13:34:43 UTC (rev 33771) @@ -194,6 +194,7 @@ struct list image_list; struct list watcher_list; struct list sem_list; + struct list port_list; struct arch_team arch_info; addr_t user_data; Modified: haiku/trunk/src/system/kernel/port.cpp =================================================================== --- haiku/trunk/src/system/kernel/port.cpp 2009-10-26 13:29:29 UTC (rev 33770) +++ haiku/trunk/src/system/kernel/port.cpp 2009-10-26 13:34:43 UTC (rev 33771) @@ -52,6 +52,7 @@ typedef DoublyLinkedList<port_message> MessageList; struct port_entry { + struct list_link team_link; port_id id; team_id owner; int32 capacity; @@ -563,38 +564,52 @@ } -// #pragma mark - private kernel API +static void +uninit_port_locked(struct port_entry& port) +{ + int32 id = port.id; + // mark port as invalid + port.id = -1; + free((char*)port.lock.name); + port.lock.name = NULL; -/*! This function cycles through the ports table, deleting all - the ports that are owned by the passed team_id -*/ -int -delete_owned_ports(team_id owner) -{ - // TODO: investigate maintaining a list of ports in the team - // to make this simpler and more efficient. + while (port_message* message = port.messages.RemoveHead()) { + put_port_message(message); + } - TRACE(("delete_owned_ports(owner = %ld)\n", owner)); + notify_port_select_events(id % sMaxPorts, B_EVENT_INVALID); + port.select_infos = NULL; - MutexLocker locker(sPortsLock); + // Release the threads that were blocking on this port. + // read_port() will see the B_BAD_PORT_ID return value, and act accordingly + port.read_condition.NotifyAll(B_BAD_PORT_ID); + port.write_condition.NotifyAll(B_BAD_PORT_ID); + sNotificationService.Notify(PORT_REMOVED, id); +} - int32 count = 0; - for (int32 i = 0; i < sMaxPorts; i++) { - if (sPorts[i].id != -1 && sPorts[i].owner == owner) { - port_id id = sPorts[i].id; +// #pragma mark - private kernel API - locker.Unlock(); - delete_port(id); - count++; +/*! This function delets all the ports that are owned by the passed team. +*/ +void +delete_owned_ports(struct team* team) +{ + TRACE(("delete_owned_ports(owner = %ld)\n", team->id)); - locker.Lock(); - } + struct list queue; + + { + InterruptsSpinLocker locker(gTeamSpinlock); + list_move_to_list(&team->port_list, &queue); } - return count; + while (port_entry* port = (port_entry*)list_remove_head_item(&queue)) { + MutexLocker locker(port->lock); + uninit_port_locked(*port); + } } @@ -693,6 +708,10 @@ if (queueLength < 1 || queueLength > MAX_QUEUE_LENGTH) return B_BAD_VALUE; + struct team* team = thread_get_current_thread()->team; + if (team == NULL) + return B_BAD_TEAM_ID; + MutexLocker locker(sPortsLock); // check early on if there are any free port slots to use @@ -730,6 +749,11 @@ sPorts[i].total_count = 0; sPorts[i].select_infos = NULL; + { + InterruptsSpinLocker teamLocker(gTeamSpinlock); + list_add_item(&team->port_list, &sPorts[i].team_link); + } + port_id id = sPorts[i].id; T(Create(sPorts[i])); @@ -800,24 +824,13 @@ T(Delete(sPorts[slot])); - // mark port as invalid - sPorts[slot].id = -1; - free((char*)sPorts[slot].lock.name); - sPorts[slot].lock.name = NULL; - - while (port_message* message = sPorts[slot].messages.RemoveHead()) { - put_port_message(message); + { + InterruptsSpinLocker teamLocker(gTeamSpinlock); + list_remove_link(&sPorts[slot].team_link); } - notify_port_select_events(slot, B_EVENT_INVALID); - sPorts[slot].select_infos = NULL; + uninit_port_locked(sPorts[slot]); - // Release the threads that were blocking on this port. - // read_port() will see the B_BAD_PORT_ID return value, and act accordingly - sPorts[slot].read_condition.NotifyAll(B_BAD_PORT_ID); - sPorts[slot].write_condition.NotifyAll(B_BAD_PORT_ID); - sNotificationService.Notify(PORT_REMOVED, id); - locker.Unlock(); MutexLocker _(sPortsLock); Modified: haiku/trunk/src/system/kernel/team.cpp =================================================================== --- haiku/trunk/src/system/kernel/team.cpp 2009-10-26 13:29:29 UTC (rev 33770) +++ haiku/trunk/src/system/kernel/team.cpp 2009-10-26 13:34:43 UTC (rev 33771) @@ -7,8 +7,10 @@ * Distributed under the terms of the NewOS License. */ + /*! Team functions */ + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -798,6 +800,7 @@ team->job_control_entry->team = team; list_init(&team->sem_list); + list_init(&team->port_list); list_init(&team->image_list); list_init(&team->watcher_list); @@ -1392,7 +1395,7 @@ delete_team_user_data(team); vm_delete_areas(team->address_space); xsi_sem_undo(team); - delete_owned_ports(team->id); + delete_owned_ports(team); sem_delete_owned_sems(team); remove_images(team); vfs_exec_io_context(team->io_context); @@ -2463,7 +2466,7 @@ vfs_put_io_context(team->io_context); delete_realtime_sem_context(team->realtime_sem_context); xsi_sem_undo(team); - delete_owned_ports(teamID); + delete_owned_ports(team); sem_delete_owned_sems(team); remove_images(team); vm_delete_address_space(team->address_space);