create_port() incremented the used ports counter twice, thanks to Stefano
Ceccherini for the hint. The first port ID is now 1 and not 0 anymore. Added a first free slot hint to speed up port creation. Added more debug output when tracing is enabled. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10260 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+69
-41
@@ -1,12 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2004, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright 2001, Mark-Jan Bastian. All rights reserved.
|
||||||
|
* Distributed under the terms of the NewOS License.
|
||||||
|
*/
|
||||||
|
|
||||||
/* ports for IPC */
|
/* ports for IPC */
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright 2002-2004, The OpenBeOS Team. All rights reserved.
|
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
|
||||||
**
|
|
||||||
** Copyright 2001, Mark-Jan Bastian. All rights reserved.
|
|
||||||
** Distributed under the terms of the NewOS License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
@@ -64,7 +65,8 @@ static int32 sUsedPorts = 0;
|
|||||||
static struct port_entry *sPorts = NULL;
|
static struct port_entry *sPorts = NULL;
|
||||||
static area_id sPortArea = 0;
|
static area_id sPortArea = 0;
|
||||||
static bool sPortsActive = false;
|
static bool sPortsActive = false;
|
||||||
static port_id sNextPort = 0;
|
static port_id sNextPort = 1;
|
||||||
|
static int32 sFirstFreeSlot = 1;
|
||||||
|
|
||||||
static spinlock sPortSpinlock = 0;
|
static spinlock sPortSpinlock = 0;
|
||||||
|
|
||||||
@@ -293,6 +295,8 @@ delete_owned_ports(team_id owner)
|
|||||||
int i;
|
int i;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
TRACE(("delete_owned_ports(owner = %ld)\n", owner));
|
||||||
|
|
||||||
if (!sPortsActive)
|
if (!sPortsActive)
|
||||||
return B_BAD_PORT_ID;
|
return B_BAD_PORT_ID;
|
||||||
|
|
||||||
@@ -378,9 +382,11 @@ create_port(int32 queueLength, const char *name)
|
|||||||
cpu_status state;
|
cpu_status state;
|
||||||
char nameBuffer[B_OS_NAME_LENGTH];
|
char nameBuffer[B_OS_NAME_LENGTH];
|
||||||
sem_id readSem, writeSem;
|
sem_id readSem, writeSem;
|
||||||
port_id returnValue;
|
status_t status;
|
||||||
team_id owner;
|
team_id owner;
|
||||||
int i;
|
int32 slot;
|
||||||
|
|
||||||
|
TRACE(("create_port(queueLength = %ld, name = \"%s\")\n", queueLength, name));
|
||||||
|
|
||||||
if (!sPortsActive)
|
if (!sPortsActive)
|
||||||
return B_BAD_PORT_ID;
|
return B_BAD_PORT_ID;
|
||||||
@@ -392,8 +398,8 @@ create_port(int32 queueLength, const char *name)
|
|||||||
|
|
||||||
// check early on if there are any free port slots to use
|
// check early on if there are any free port slots to use
|
||||||
if (atomic_add(&sUsedPorts, 1) >= sMaxPorts) {
|
if (atomic_add(&sUsedPorts, 1) >= sMaxPorts) {
|
||||||
atomic_add(&sUsedPorts, -1);
|
status = B_NO_MORE_PORTS;
|
||||||
return B_NO_MORE_PORTS;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check & dup name
|
// check & dup name
|
||||||
@@ -404,28 +410,23 @@ create_port(int32 queueLength, const char *name)
|
|||||||
strlcpy(nameBuffer, name, B_OS_NAME_LENGTH);
|
strlcpy(nameBuffer, name, B_OS_NAME_LENGTH);
|
||||||
name = strdup(nameBuffer);
|
name = strdup(nameBuffer);
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
atomic_add(&sUsedPorts, -1);
|
status = B_NO_MEMORY;
|
||||||
return B_NO_MEMORY;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create read sem with owner set to -1
|
// create read sem with owner set to -1
|
||||||
// ToDo: should be B_SYSTEM_TEAM
|
// ToDo: should be B_SYSTEM_TEAM
|
||||||
readSem = create_sem_etc(0, name, -1);
|
readSem = create_sem_etc(0, name, -1);
|
||||||
if (readSem < B_OK) {
|
if (readSem < B_OK) {
|
||||||
// cleanup
|
status = readSem;
|
||||||
free((char *)name);
|
goto err2;
|
||||||
atomic_add(&sUsedPorts, -1);
|
|
||||||
return readSem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create write sem
|
// create write sem
|
||||||
writeSem = create_sem_etc(queueLength, name, -1);
|
writeSem = create_sem_etc(queueLength, name, -1);
|
||||||
if (writeSem < 0) {
|
if (writeSem < B_OK) {
|
||||||
// cleanup
|
status = writeSem;
|
||||||
delete_sem(readSem);
|
goto err3;
|
||||||
free((char *)name);
|
|
||||||
atomic_add(&sUsedPorts, -1);
|
|
||||||
return writeSem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
owner = team_get_current_team_id();
|
owner = team_get_current_team_id();
|
||||||
@@ -434,17 +435,21 @@ create_port(int32 queueLength, const char *name)
|
|||||||
GRAB_PORT_LIST_LOCK();
|
GRAB_PORT_LIST_LOCK();
|
||||||
|
|
||||||
// find the first empty spot
|
// find the first empty spot
|
||||||
for (i = 0; i < sMaxPorts; i++) {
|
for (slot = 0; slot < sMaxPorts; slot++) {
|
||||||
|
int32 i = (slot + sFirstFreeSlot) % sMaxPorts;
|
||||||
|
|
||||||
if (sPorts[i].id == -1) {
|
if (sPorts[i].id == -1) {
|
||||||
|
port_id id;
|
||||||
|
|
||||||
// make the port_id be a multiple of the slot it's in
|
// make the port_id be a multiple of the slot it's in
|
||||||
if (i >= sNextPort % sMaxPorts)
|
if (i >= sNextPort % sMaxPorts)
|
||||||
sNextPort += i - sNextPort % sMaxPorts;
|
sNextPort += i - sNextPort % sMaxPorts;
|
||||||
else
|
else
|
||||||
sNextPort += sMaxPorts - (sNextPort % sMaxPorts - i);
|
sNextPort += sMaxPorts - (sNextPort % sMaxPorts - i);
|
||||||
|
sFirstFreeSlot = slot + 1;
|
||||||
|
|
||||||
GRAB_PORT_LOCK(sPorts[i]);
|
GRAB_PORT_LOCK(sPorts[i]);
|
||||||
sPorts[i].id = sNextPort++;
|
sPorts[i].id = sNextPort++;
|
||||||
atomic_add(&sUsedPorts, 1);
|
|
||||||
RELEASE_PORT_LIST_LOCK();
|
RELEASE_PORT_LIST_LOCK();
|
||||||
|
|
||||||
sPorts[i].capacity = queueLength;
|
sPorts[i].capacity = queueLength;
|
||||||
@@ -456,33 +461,36 @@ create_port(int32 queueLength, const char *name)
|
|||||||
|
|
||||||
list_init(&sPorts[i].msg_queue);
|
list_init(&sPorts[i].msg_queue);
|
||||||
sPorts[i].total_count = 0;
|
sPorts[i].total_count = 0;
|
||||||
returnValue = sPorts[i].id;
|
id = sPorts[i].id;
|
||||||
|
|
||||||
RELEASE_PORT_LOCK(sPorts[i]);
|
RELEASE_PORT_LOCK(sPorts[i]);
|
||||||
goto out;
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// not enough ports...
|
||||||
|
|
||||||
// ToDo: due to sUsedPorts, this cannot happen anymore - as
|
// ToDo: due to sUsedPorts, this cannot happen anymore - as
|
||||||
// long as sMaxPorts stays constant over the kernel run
|
// long as sMaxPorts stays constant over the kernel run
|
||||||
// time (which it should be). IOW we could simply panic()
|
// time (which it should be). IOW we could simply panic()
|
||||||
// here.
|
// here.
|
||||||
|
|
||||||
// not enough ports...
|
|
||||||
RELEASE_PORT_LIST_LOCK();
|
RELEASE_PORT_LIST_LOCK();
|
||||||
returnValue = B_NO_MORE_PORTS;
|
|
||||||
dprintf("create_port(): B_NO_MORE_PORTS\n");
|
|
||||||
|
|
||||||
// cleanup
|
|
||||||
delete_sem(writeSem);
|
|
||||||
delete_sem(readSem);
|
|
||||||
free((char *)name);
|
|
||||||
atomic_add(&sUsedPorts, -1);
|
|
||||||
|
|
||||||
out:
|
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
return returnValue;
|
status = B_NO_MORE_PORTS;
|
||||||
|
|
||||||
|
delete_sem(writeSem);
|
||||||
|
err3:
|
||||||
|
delete_sem(readSem);
|
||||||
|
err2:
|
||||||
|
free((char *)name);
|
||||||
|
err1:
|
||||||
|
atomic_add(&sUsedPorts, -1);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -492,6 +500,8 @@ close_port(port_id id)
|
|||||||
cpu_status state;
|
cpu_status state;
|
||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
|
TRACE(("close_port(id = %ld)\n", id));
|
||||||
|
|
||||||
if (!sPortsActive || id < 0)
|
if (!sPortsActive || id < 0)
|
||||||
return B_BAD_PORT_ID;
|
return B_BAD_PORT_ID;
|
||||||
|
|
||||||
@@ -528,6 +538,8 @@ delete_port(port_id id)
|
|||||||
port_msg *msg;
|
port_msg *msg;
|
||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
|
TRACE(("delete_port(id = %ld)\n", id));
|
||||||
|
|
||||||
if (!sPortsActive || id < 0)
|
if (!sPortsActive || id < 0)
|
||||||
return B_BAD_PORT_ID;
|
return B_BAD_PORT_ID;
|
||||||
|
|
||||||
@@ -539,7 +551,8 @@ delete_port(port_id id)
|
|||||||
if (sPorts[slot].id != id) {
|
if (sPorts[slot].id != id) {
|
||||||
RELEASE_PORT_LOCK(sPorts[slot]);
|
RELEASE_PORT_LOCK(sPorts[slot]);
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
dprintf("delete_port: invalid port_id %ld\n", id);
|
|
||||||
|
TRACE(("delete_port: invalid port_id %ld\n", id));
|
||||||
return B_BAD_PORT_ID;
|
return B_BAD_PORT_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,6 +565,13 @@ delete_port(port_id id)
|
|||||||
list_move_to_list(&sPorts[slot].msg_queue, &list);
|
list_move_to_list(&sPorts[slot].msg_queue, &list);
|
||||||
|
|
||||||
RELEASE_PORT_LOCK(sPorts[slot]);
|
RELEASE_PORT_LOCK(sPorts[slot]);
|
||||||
|
|
||||||
|
// update the first free slot hint in the array
|
||||||
|
GRAB_PORT_LIST_LOCK();
|
||||||
|
if (slot < sFirstFreeSlot)
|
||||||
|
sFirstFreeSlot = slot;
|
||||||
|
RELEASE_PORT_LIST_LOCK();
|
||||||
|
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
atomic_add(&sUsedPorts, -1);
|
atomic_add(&sUsedPorts, -1);
|
||||||
@@ -579,6 +599,8 @@ find_port(const char *name)
|
|||||||
cpu_status state;
|
cpu_status state;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
TRACE(("find_port(name = \"%s\")\n", name));
|
||||||
|
|
||||||
if (!sPortsActive)
|
if (!sPortsActive)
|
||||||
return B_NAME_NOT_FOUND;
|
return B_NAME_NOT_FOUND;
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
@@ -636,6 +658,8 @@ _get_port_info(port_id id, port_info *info, size_t size)
|
|||||||
cpu_status state;
|
cpu_status state;
|
||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
|
TRACE(("get_port_info(id = %ld)\n", id));
|
||||||
|
|
||||||
if (info == NULL || size != sizeof(port_info))
|
if (info == NULL || size != sizeof(port_info))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (!sPortsActive || id < 0)
|
if (!sPortsActive || id < 0)
|
||||||
@@ -669,6 +693,8 @@ _get_next_port_info(team_id team, int32 *_cookie, struct port_info *info, size_t
|
|||||||
cpu_status state;
|
cpu_status state;
|
||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
|
TRACE(("get_next_port_info(team = %ld)\n", team));
|
||||||
|
|
||||||
if (info == NULL || size != sizeof(port_info) || _cookie == NULL || team < B_OK)
|
if (info == NULL || size != sizeof(port_info) || _cookie == NULL || team < B_OK)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
if (!sPortsActive)
|
if (!sPortsActive)
|
||||||
@@ -1053,6 +1079,8 @@ set_port_owner(port_id id, team_id team)
|
|||||||
cpu_status state;
|
cpu_status state;
|
||||||
int slot;
|
int slot;
|
||||||
|
|
||||||
|
TRACE(("set_port_owner(id = %ld, team = %ld)\n", id, team));
|
||||||
|
|
||||||
if (!sPortsActive || id < 0)
|
if (!sPortsActive || id < 0)
|
||||||
return B_BAD_PORT_ID;
|
return B_BAD_PORT_ID;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user