kernel: Cleanups to the XSI message queue & semaphore implementations.

* Remove unused/unneeded parameters to Dequeue.
 * Make use of StackOrHeapArray.
 * Reorder syscall-entry checks for efficiency.
 * Inline the unlock-block method and unset variables in the process.
 * Reorder code for clarity and to reduce indentation.
This commit is contained in:
Augustin Cavalier
2023-09-21 22:20:31 -04:00
parent f759ab2733
commit 959d9cd069
2 changed files with 66 additions and 75 deletions
@@ -123,7 +123,7 @@ public:
fMessageQueue.msg_ctime = (time_t)real_time_clock();
}
void Dequeue(ConditionVariableEntry *queueEntry, bool waitForMessage)
void Dequeue(ConditionVariableEntry *queueEntry)
{
queueEntry->Wait(B_RELATIVE_TIMEOUT, 0);
}
@@ -733,7 +733,7 @@ _user_xsi_msgrcv(int messageQueueID, void *messagePointer,
TRACE(("xsi_msgrcv: thread %d got interrupted while "
"waiting on message queue %d\n", (int)thread_get_current_thread_id(),
messageQueueID));
messageQueue->Dequeue(&queueEntry, /* waitForMessage */ true);
messageQueue->Dequeue(&queueEntry);
return EINTR;
} else {
messageQueueLocker.Lock();
@@ -841,7 +841,7 @@ _user_xsi_msgsnd(int messageQueueID, const void *messagePointer,
TRACE(("xsi_msgsnd: thread %d got interrupted while "
"waiting on message queue %d\n", (int)thread_get_current_thread_id(),
messageQueueID));
messageQueue->Dequeue(&queueEntry, /* waitForMessage */ false);
messageQueue->Dequeue(&queueEntry);
delete message;
notSent = false;
result = EINTR;
+63 -72
View File
@@ -23,6 +23,7 @@
#include <util/DoublyLinkedList.h>
#include <util/OpenHashTable.h>
#include <AutoDeleter.h>
#include <StackOrHeapArray.h>
//#define TRACE_XSI_SEM
@@ -125,14 +126,7 @@ public:
}
}
status_t BlockAndUnlock(ConditionVariableEntry *queueEntry, MutexLocker *setLocker)
{
// Unlock the set before blocking
setLocker->Unlock();
return queueEntry->Wait(B_CAN_INTERRUPT);
}
void Dequeue(ConditionVariableEntry *queueEntry, bool waitForZero)
static void Dequeue(ConditionVariableEntry *queueEntry)
{
queueEntry->Wait(B_RELATIVE_TIMEOUT, 0);
}
@@ -696,20 +690,7 @@ _user_xsi_semget(key_t key, int numberOfSemaphores, int flags)
// Check if key already exist, if it does it already has a semaphore
// set associated with it
ipcKey = sIpcHashTable.Lookup(key);
if (ipcKey == NULL) {
// The ipc key does not exist. Create it and add it to the system
if (!(flags & IPC_CREAT)) {
TRACE(("xsi_semget: key %d does not exist, but the "
"caller did not ask for creation\n",(int)key));
return ENOENT;
}
ipcKey = new(std::nothrow) Ipc(key);
if (ipcKey == NULL) {
TRACE_ERROR(("xsi_semget: failed to create new Ipc object "
"for key %d\n", (int)key));
return ENOMEM;
}
} else {
if (ipcKey != NULL) {
// The IPC key exist and it already has a semaphore
if ((flags & IPC_CREAT) && (flags & IPC_EXCL)) {
TRACE(("xsi_semget: key %d already exist\n", (int)key));
@@ -740,9 +721,22 @@ _user_xsi_semget(key_t key, int numberOfSemaphores, int flags)
return semaphoreSet->ID();
}
// The ipc key does not exist. Create it and add it to the system
if (!(flags & IPC_CREAT)) {
TRACE(("xsi_semget: key %d does not exist, but the "
"caller did not ask for creation\n",(int)key));
return ENOENT;
}
ipcKey = new(std::nothrow) Ipc(key);
if (ipcKey == NULL) {
TRACE_ERROR(("xsi_semget: failed to create new Ipc object "
"for key %d\n", (int)key));
return ENOMEM;
}
}
// Create a new sempahore set for this key
// Create a new semaphore set for this key
if (numberOfSemaphores <= 0
|| numberOfSemaphores >= MAX_XSI_SEMS_PER_TEAM) {
TRACE_ERROR(("xsi_semget: numberOfSemaphores out of range\n"));
@@ -820,16 +814,10 @@ _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
// the command it's not IPC_RMID, this prevents undesidered
// situation from happening while (hopefully) improving the
// concurrency.
MutexLocker setLocker;
MutexLocker setLocker(semaphoreSet->Lock());
if (command != IPC_RMID) {
setLocker.SetTo(&semaphoreSet->Lock(), false);
setHashLocker.Unlock();
ipcHashLocker.Unlock();
} else {
// We are about to delete the set along with its mutex, so
// we can't use the MutexLocker class, as the mutex itself
// won't exist on function exit
mutex_lock(&semaphoreSet->Lock());
}
int result = 0;
@@ -1015,6 +1003,7 @@ _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
delete entry;
}
setLocker.Detach();
delete semaphoreSet;
return 0;
}
@@ -1033,6 +1022,16 @@ _user_xsi_semop(int semaphoreID, struct sembuf *ops, size_t numOps)
{
TRACE(("xsi_semop: semaphoreID = %d, ops = %p, numOps = %ld\n",
semaphoreID, ops, numOps));
if (!IS_USER_ADDRESS(ops)) {
TRACE(("xsi_semop: sembuf address is not valid\n"));
return B_BAD_ADDRESS;
}
if (numOps < 0 || numOps >= MAX_XSI_SEMS_PER_TEAM) {
TRACE(("xsi_semop: numOps out of range\n"));
return EINVAL;
}
MutexLocker setHashLocker(sXsiSemaphoreSetLock);
XsiSemaphoreSet *semaphoreSet = sSemaphoreHashTable.Lookup(semaphoreID);
if (semaphoreSet == NULL) {
@@ -1043,23 +1042,11 @@ _user_xsi_semop(int semaphoreID, struct sembuf *ops, size_t numOps)
MutexLocker setLocker(semaphoreSet->Lock());
setHashLocker.Unlock();
if (!IS_USER_ADDRESS(ops)) {
TRACE(("xsi_semop: sembuf address is not valid\n"));
return B_BAD_ADDRESS;
}
if (numOps < 0 || numOps >= MAX_XSI_SEMS_PER_TEAM) {
TRACE(("xsi_semop: numOps out of range\n"));
return EINVAL;
}
struct sembuf *operations
= (struct sembuf *)malloc(sizeof(struct sembuf) * numOps);
if (operations == NULL) {
BStackOrHeapArray<struct sembuf, 16> operations(numOps);
if (!operations.IsValid()) {
TRACE_ERROR(("xsi_semop: failed to allocate sembuf struct\n"));
return B_NO_MEMORY;
}
MemoryDeleter operationsDeleter(operations);
if (user_memcpy(operations, ops,
(sizeof(struct sembuf) * numOps)) != B_OK) {
@@ -1077,7 +1064,7 @@ _user_xsi_semop(int semaphoreID, struct sembuf *ops, size_t numOps)
status_t result = 0;
while (notDone) {
XsiSemaphore *semaphore = NULL;
short numberOfSemaphores = semaphoreSet->NumberOfSemaphores();
const short numberOfSemaphores = semaphoreSet->NumberOfSemaphores();
bool goToSleep = false;
uint32 i = 0;
@@ -1142,10 +1129,13 @@ _user_xsi_semop(int semaphoreID, struct sembuf *ops, size_t numOps)
ConditionVariableEntry queueEntry;
semaphore->Enqueue(&queueEntry, waitOnZero);
uint32 sequenceNumber = semaphoreSet->SequenceNumber();
const uint32 sequenceNumber = semaphoreSet->SequenceNumber();
TRACE(("xsi_semop: thread %d going to sleep\n", (int)thread->id));
result = semaphore->BlockAndUnlock(&queueEntry, &setLocker);
setLocker.Unlock();
semaphoreSet = NULL;
semaphore = NULL;
result = queueEntry.Wait(B_CAN_INTERRUPT);
TRACE(("xsi_semop: thread %d back to life\n", (int)thread->id));
// We are back to life. Find out why!
@@ -1163,7 +1153,7 @@ _user_xsi_semop(int semaphoreID, struct sembuf *ops, size_t numOps)
TRACE(("xsi_semop: thread %d got interrupted while "
"waiting on semaphore set id %d\n", (int)thread_get_current_thread_id(),
semaphoreID));
semaphore->Dequeue(&queueEntry, waitOnZero);
XsiSemaphore::Dequeue(&queueEntry);
result = EINTR;
notDone = false;
} else {
@@ -1176,33 +1166,34 @@ _user_xsi_semop(int semaphoreID, struct sembuf *ops, size_t numOps)
TRACE(("xsi_semop: semaphore acquired succesfully\n"));
// We acquired the semaphore, now records the sem_undo
// requests
XsiSemaphore *semaphore = NULL;
uint32 i = 0;
for (; i < numOps; i++) {
for (uint32 i = 0; i < numOps; i++) {
if ((operations[i].sem_flg & SEM_UNDO) == 0)
continue;
short semaphoreNumber = operations[i].sem_num;
semaphore = semaphoreSet->Semaphore(semaphoreNumber);
XsiSemaphore *semaphore = semaphoreSet->Semaphore(semaphoreNumber);
short operation = operations[i].sem_op;
if (operations[i].sem_flg & SEM_UNDO)
if (semaphoreSet->RecordUndo(semaphoreNumber, operation)
!= B_OK) {
// Unlikely scenario, but we might get here.
// Undo everything!
// Start with semaphore operations
for (uint32 j = 0; j < numOps; j++) {
short semaphoreNumber = operations[j].sem_num;
semaphore = semaphoreSet->Semaphore(semaphoreNumber);
short operation = operations[j].sem_op;
if (operation != 0)
semaphore->Revert(operation);
}
// Remove all previously registered sem_undo request
for (uint32 j = 0; j < i; j++) {
if (operations[j].sem_flg & SEM_UNDO)
semaphoreSet->RevertUndo(operations[j].sem_num,
operations[j].sem_op);
}
result = ENOSPC;
if (semaphoreSet->RecordUndo(semaphoreNumber, operation) != B_OK) {
// Unlikely scenario, but we might get here.
// Undo everything!
// Start with semaphore operations
for (uint32 j = 0; j < numOps; j++) {
short semaphoreNumber = operations[j].sem_num;
semaphore = semaphoreSet->Semaphore(semaphoreNumber);
short operation = operations[j].sem_op;
if (operation != 0)
semaphore->Revert(operation);
}
// Remove all previously registered sem_undo request
for (uint32 j = 0; j < i; j++) {
if (operations[j].sem_flg & SEM_UNDO) {
semaphoreSet->RevertUndo(operations[j].sem_num,
operations[j].sem_op);
}
}
result = ENOSPC;
}
}
}
}