* 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:
@@ -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);
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user