- Send() now also gets the message to send as parameter.
  - Added methods to reserve and unreserve space in the buffer.
* RequestAllocator: Uses the port buffer reservation methods now. This allows
  to let more than one RequestAllocator use a Port in a stack-like manner.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29565 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-03-17 01:24:31 +00:00
parent c1f05b2803
commit b19ee1e164
5 changed files with 70 additions and 37 deletions

View File

@ -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;
};

View File

@ -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];

View File

@ -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);
}

View File

@ -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];

View File

@ -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