* 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.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33771 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-10-26 13:34:43 +00:00
parent 07e9fd1d84
commit 86a999adfb
4 changed files with 60 additions and 46 deletions
+3 -6
View File
@@ -32,7 +32,7 @@ extern "C" {
#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,11 +41,8 @@ status_t deselect_port(int32 object, struct select_info *info, bool kernel);
// 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);
// temp: test
void port_test(void);
size_t vecCount, size_t bufferSize, uint32 flags,
bigtime_t timeout);
// user syscalls
port_id _user_create_port(int32 queueLength, const char *name);
+1
View File
@@ -194,6 +194,7 @@ struct team {
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;
+51 -38
View File
@@ -52,6 +52,7 @@ struct port_message : DoublyLinkedListLinkImpl<port_message> {
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 @@ copy_port_message(port_message* message, int32* _code, void* buffer,
}
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;
while (port_message* message = port.messages.RemoveHead()) {
put_port_message(message);
}
notify_port_select_events(id % sMaxPorts, B_EVENT_INVALID);
port.select_infos = NULL;
// 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);
}
// #pragma mark - private kernel API
/*! This function cycles through the ports table, deleting all
the ports that are owned by the passed team_id
/*! This function delets all the ports that are owned by the passed team.
*/
int
delete_owned_ports(team_id owner)
void
delete_owned_ports(struct team* team)
{
// TODO: investigate maintaining a list of ports in the team
// to make this simpler and more efficient.
TRACE(("delete_owned_ports(owner = %ld)\n", team->id));
TRACE(("delete_owned_ports(owner = %ld)\n", owner));
struct list queue;
MutexLocker locker(sPortsLock);
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;
locker.Unlock();
delete_port(id);
count++;
locker.Lock();
}
{
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 @@ create_port(int32 queueLength, const char* name)
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 @@ create_port(int32 queueLength, const char* name)
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,23 +824,12 @@ delete_port(port_id id)
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;
// 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);
uninit_port_locked(sPorts[slot]);
locker.Unlock();
+5 -2
View File
@@ -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 @@ create_team_struct(const char *name, bool kernel)
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 @@ exec_team(const char *path, char**& _flatArgs, size_t flatArgsSize,
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 @@ team_delete_team(struct team *team)
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);