diff --git a/headers/private/userlandfs/private/Port.h b/headers/private/userlandfs/private/Port.h index e4498564b4..0ba6a8edf0 100644 --- a/headers/private/userlandfs/private/Port.h +++ b/headers/private/userlandfs/private/Port.h @@ -33,10 +33,14 @@ public: const Info* GetInfo() const; - void* GetBuffer() const; - int32 GetCapacity() const; + void* GetBuffer() const { return fBuffer; } + int32 GetCapacity() const { return fCapacity; } - status_t Send(int32 size); + void Reserve(int32 endOffset); + void Unreserve(int32 endOffset); + int32 ReservedSize() const { return fReservedSize; } + + status_t Send(const void* message, int32 size); status_t Receive(void** _message, size_t* _size, bigtime_t timeout = -1); @@ -46,6 +50,7 @@ private: Info fInfo; uint8* fBuffer; int32 fCapacity; + int32 fReservedSize; status_t fInitStatus; bool fOwner; }; diff --git a/headers/private/userlandfs/private/RequestAllocator.h b/headers/private/userlandfs/private/RequestAllocator.h index 6084c95fa0..1c7b961fe5 100644 --- a/headers/private/userlandfs/private/RequestAllocator.h +++ b/headers/private/userlandfs/private/RequestAllocator.h @@ -61,6 +61,8 @@ private: Port* fPort; Request* fRequest; int32 fRequestSize; + int32 fPortReservedOffset; + int32 fRequestOffset; area_id fAllocatedAreas[MAX_REQUEST_ADDRESS_COUNT]; int32 fAllocatedAreaCount; DeferredInitInfo fDeferredInitInfos[MAX_REQUEST_ADDRESS_COUNT]; diff --git a/src/add-ons/kernel/file_systems/userlandfs/private/Port.cpp b/src/add-ons/kernel/file_systems/userlandfs/private/Port.cpp index 49cd005c0c..366356abff 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/private/Port.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/private/Port.cpp @@ -21,10 +21,12 @@ static const int32 kMaxPortSize = 64 * 1024; // 64 kB // constructor Port::Port(int32 size) - : fBuffer(NULL), - fCapacity(0), - fInitStatus(B_NO_INIT), - fOwner(true) + : + fBuffer(NULL), + fCapacity(0), + fReservedSize(0), + fInitStatus(B_NO_INIT), + fOwner(true) { // adjust size to be within the sane bounds if (size < kMinPortSize) @@ -57,10 +59,12 @@ Port::Port(int32 size) // constructor Port::Port(const Info* info) - : fBuffer(NULL), - fCapacity(0), - fInitStatus(B_NO_INIT), - fOwner(false) + : + fBuffer(NULL), + fCapacity(0), + fReservedSize(0), + fInitStatus(B_NO_INIT), + fOwner(false) { // check parameters if (!info || info->owner_port < 0 || info->client_port < 0 @@ -126,35 +130,39 @@ Port::GetInfo() const } -// GetBuffer -void* -Port::GetBuffer() const +// Reserve +void +Port::Reserve(int32 endOffset) { - return fBuffer; + if (endOffset > fReservedSize) + fReservedSize = endOffset; } -// GetCapacity -int32 -Port::GetCapacity() const +// Unreserve +void +Port::Unreserve(int32 endOffset) { - return fCapacity; + if (endOffset < fReservedSize) + fReservedSize = endOffset; } // Send status_t -Port::Send(int32 size) +Port::Send(const void* message, int32 size) { if (fInitStatus != B_OK) return fInitStatus; - if (size <= 0 || size > fCapacity) + if (size <= 0) return B_BAD_VALUE; + port_id port = (fOwner ? fInfo.client_port : fInfo.owner_port); status_t error; do { - error = write_port(port, 0, fBuffer, size); + error = write_port(port, 0, message, size); } while (error == B_INTERRUPTED); + return (fInitStatus = error); } diff --git a/src/add-ons/kernel/file_systems/userlandfs/private/RequestAllocator.cpp b/src/add-ons/kernel/file_systems/userlandfs/private/RequestAllocator.cpp index ce164afb6e..0316b56bd9 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/private/RequestAllocator.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/private/RequestAllocator.cpp @@ -14,13 +14,15 @@ // constructor RequestAllocator::RequestAllocator(Port* port) - : fError(B_NO_INIT), - fPort(NULL), - fRequest(NULL), - fRequestSize(0), - fAllocatedAreaCount(0), - fDeferredInitInfoCount(0), - fRequestInPortBuffer(false) + : + fError(B_NO_INIT), + fPort(NULL), + fRequest(NULL), + fRequestSize(0), + fPortReservedOffset(0), + fAllocatedAreaCount(0), + fDeferredInitInfoCount(0), + fRequestInPortBuffer(false) { Init(port); } @@ -39,6 +41,7 @@ RequestAllocator::Init(Port* port) if (port) { fPort = port; fError = fPort->InitCheck(); + fPortReservedOffset = fPort->ReservedSize(); } return fError; } @@ -47,20 +50,26 @@ RequestAllocator::Init(Port* port) void RequestAllocator::Uninit() { - if (!fRequestInPortBuffer) + if (fRequestInPortBuffer) + fPort->Unreserve(fPortReservedOffset); + else free(fRequest); + for (int32 i = 0; i < fAllocatedAreaCount; i++) delete_area(fAllocatedAreas[i]); fAllocatedAreaCount = 0; + for (int32 i = 0; i < fDeferredInitInfoCount; i++) { if (fDeferredInitInfos[i].inPortBuffer) free(fDeferredInitInfos[i].data); } + fDeferredInitInfoCount = 0; fError = B_NO_INIT; fPort = NULL; fRequest = NULL; fRequestSize = 0; + fPortReservedOffset = 0; } // Error @@ -96,11 +105,18 @@ RequestAllocator::AllocateRequest(int32 size) { if (fError != B_OK) RETURN_ERROR(fError); - if (size < (int32)sizeof(Request) || size > fPort->GetCapacity()) + + fRequestOffset = (fPortReservedOffset + 7) / 8 * 8; + + if (size < (int32)sizeof(Request) + || fRequestOffset + size > fPort->GetCapacity()) { RETURN_ERROR(fError = B_BAD_VALUE); - fRequest = (Request*)fPort->GetBuffer(); + } + + fRequest = (Request*)((uint8*)fPort->GetBuffer() + fRequestOffset); fRequestSize = size; fRequestInPortBuffer = true; + fPort->Reserve(fRequestOffset + fRequestSize); return B_OK; } @@ -129,6 +145,7 @@ RequestAllocator::ReadRequest(bigtime_t timeout) // init the request fRequest = (Request*)message; + fRequestOffset = 0; fRequestSize = messageSize; fRequestInPortBuffer = false; @@ -185,9 +202,10 @@ RequestAllocator::AllocateAddress(Address& address, int32 size, int32 align, // get the next free aligned offset in the port buffer int32 offset = (fRequestSize + align - 1) / align * align; // allocate the data - if (offset + size <= fPort->GetCapacity()) { + if (fRequestOffset + offset + size <= fPort->GetCapacity()) { // there's enough free space in the port buffer fRequestSize = offset + size; + fPort->Reserve(fRequestOffset + fRequestSize); if (deferredInit) { DeferredInitInfo& info = fDeferredInitInfos[fDeferredInitInfoCount]; diff --git a/src/add-ons/kernel/file_systems/userlandfs/private/RequestPort.cpp b/src/add-ons/kernel/file_systems/userlandfs/private/RequestPort.cpp index 38af9dfcc5..14b9f1a78b 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/private/RequestPort.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/private/RequestPort.cpp @@ -77,9 +77,8 @@ RequestPort::SendRequest(RequestAllocator* allocator) // check initialization and parameters if (InitCheck() != B_OK) RETURN_ERROR(InitCheck()); - if (!allocator || allocator->GetRequest() != fPort.GetBuffer() - || allocator->GetRequestSize() < (int32)sizeof(Request) - || allocator->GetRequestSize() > fPort.GetCapacity()) { + if (!allocator || allocator->GetRequest() == NULL + || allocator->GetRequestSize() < (int32)sizeof(Request)) { RETURN_ERROR(B_BAD_VALUE); } allocator->FinishDeferredInit(); @@ -97,7 +96,8 @@ RequestPort::SendRequest(RequestAllocator* allocator) debugger("Request is not a kernel request."); } #endif - RETURN_ERROR(fPort.Send(allocator->GetRequestSize())); + RETURN_ERROR(fPort.Send(allocator->GetRequest(), + allocator->GetRequestSize())); } // SendRequest