- 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; const Info* GetInfo() const;
void* GetBuffer() const; void* GetBuffer() const { return fBuffer; }
int32 GetCapacity() const; 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, status_t Receive(void** _message, size_t* _size,
bigtime_t timeout = -1); bigtime_t timeout = -1);
@ -46,6 +50,7 @@ private:
Info fInfo; Info fInfo;
uint8* fBuffer; uint8* fBuffer;
int32 fCapacity; int32 fCapacity;
int32 fReservedSize;
status_t fInitStatus; status_t fInitStatus;
bool fOwner; bool fOwner;
}; };

View File

@ -61,6 +61,8 @@ private:
Port* fPort; Port* fPort;
Request* fRequest; Request* fRequest;
int32 fRequestSize; int32 fRequestSize;
int32 fPortReservedOffset;
int32 fRequestOffset;
area_id fAllocatedAreas[MAX_REQUEST_ADDRESS_COUNT]; area_id fAllocatedAreas[MAX_REQUEST_ADDRESS_COUNT];
int32 fAllocatedAreaCount; int32 fAllocatedAreaCount;
DeferredInitInfo fDeferredInitInfos[MAX_REQUEST_ADDRESS_COUNT]; DeferredInitInfo fDeferredInitInfos[MAX_REQUEST_ADDRESS_COUNT];

View File

@ -21,10 +21,12 @@ static const int32 kMaxPortSize = 64 * 1024; // 64 kB
// constructor // constructor
Port::Port(int32 size) Port::Port(int32 size)
: fBuffer(NULL), :
fCapacity(0), fBuffer(NULL),
fInitStatus(B_NO_INIT), fCapacity(0),
fOwner(true) fReservedSize(0),
fInitStatus(B_NO_INIT),
fOwner(true)
{ {
// adjust size to be within the sane bounds // adjust size to be within the sane bounds
if (size < kMinPortSize) if (size < kMinPortSize)
@ -57,10 +59,12 @@ Port::Port(int32 size)
// constructor // constructor
Port::Port(const Info* info) Port::Port(const Info* info)
: fBuffer(NULL), :
fCapacity(0), fBuffer(NULL),
fInitStatus(B_NO_INIT), fCapacity(0),
fOwner(false) fReservedSize(0),
fInitStatus(B_NO_INIT),
fOwner(false)
{ {
// check parameters // check parameters
if (!info || info->owner_port < 0 || info->client_port < 0 if (!info || info->owner_port < 0 || info->client_port < 0
@ -126,35 +130,39 @@ Port::GetInfo() const
} }
// GetBuffer // Reserve
void* void
Port::GetBuffer() const Port::Reserve(int32 endOffset)
{ {
return fBuffer; if (endOffset > fReservedSize)
fReservedSize = endOffset;
} }
// GetCapacity // Unreserve
int32 void
Port::GetCapacity() const Port::Unreserve(int32 endOffset)
{ {
return fCapacity; if (endOffset < fReservedSize)
fReservedSize = endOffset;
} }
// Send // Send
status_t status_t
Port::Send(int32 size) Port::Send(const void* message, int32 size)
{ {
if (fInitStatus != B_OK) if (fInitStatus != B_OK)
return fInitStatus; return fInitStatus;
if (size <= 0 || size > fCapacity) if (size <= 0)
return B_BAD_VALUE; return B_BAD_VALUE;
port_id port = (fOwner ? fInfo.client_port : fInfo.owner_port); port_id port = (fOwner ? fInfo.client_port : fInfo.owner_port);
status_t error; status_t error;
do { do {
error = write_port(port, 0, fBuffer, size); error = write_port(port, 0, message, size);
} while (error == B_INTERRUPTED); } while (error == B_INTERRUPTED);
return (fInitStatus = error); return (fInitStatus = error);
} }

View File

@ -14,13 +14,15 @@
// constructor // constructor
RequestAllocator::RequestAllocator(Port* port) RequestAllocator::RequestAllocator(Port* port)
: fError(B_NO_INIT), :
fPort(NULL), fError(B_NO_INIT),
fRequest(NULL), fPort(NULL),
fRequestSize(0), fRequest(NULL),
fAllocatedAreaCount(0), fRequestSize(0),
fDeferredInitInfoCount(0), fPortReservedOffset(0),
fRequestInPortBuffer(false) fAllocatedAreaCount(0),
fDeferredInitInfoCount(0),
fRequestInPortBuffer(false)
{ {
Init(port); Init(port);
} }
@ -39,6 +41,7 @@ RequestAllocator::Init(Port* port)
if (port) { if (port) {
fPort = port; fPort = port;
fError = fPort->InitCheck(); fError = fPort->InitCheck();
fPortReservedOffset = fPort->ReservedSize();
} }
return fError; return fError;
} }
@ -47,20 +50,26 @@ RequestAllocator::Init(Port* port)
void void
RequestAllocator::Uninit() RequestAllocator::Uninit()
{ {
if (!fRequestInPortBuffer) if (fRequestInPortBuffer)
fPort->Unreserve(fPortReservedOffset);
else
free(fRequest); free(fRequest);
for (int32 i = 0; i < fAllocatedAreaCount; i++) for (int32 i = 0; i < fAllocatedAreaCount; i++)
delete_area(fAllocatedAreas[i]); delete_area(fAllocatedAreas[i]);
fAllocatedAreaCount = 0; fAllocatedAreaCount = 0;
for (int32 i = 0; i < fDeferredInitInfoCount; i++) { for (int32 i = 0; i < fDeferredInitInfoCount; i++) {
if (fDeferredInitInfos[i].inPortBuffer) if (fDeferredInitInfos[i].inPortBuffer)
free(fDeferredInitInfos[i].data); free(fDeferredInitInfos[i].data);
} }
fDeferredInitInfoCount = 0; fDeferredInitInfoCount = 0;
fError = B_NO_INIT; fError = B_NO_INIT;
fPort = NULL; fPort = NULL;
fRequest = NULL; fRequest = NULL;
fRequestSize = 0; fRequestSize = 0;
fPortReservedOffset = 0;
} }
// Error // Error
@ -96,11 +105,18 @@ RequestAllocator::AllocateRequest(int32 size)
{ {
if (fError != B_OK) if (fError != B_OK)
RETURN_ERROR(fError); 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); RETURN_ERROR(fError = B_BAD_VALUE);
fRequest = (Request*)fPort->GetBuffer(); }
fRequest = (Request*)((uint8*)fPort->GetBuffer() + fRequestOffset);
fRequestSize = size; fRequestSize = size;
fRequestInPortBuffer = true; fRequestInPortBuffer = true;
fPort->Reserve(fRequestOffset + fRequestSize);
return B_OK; return B_OK;
} }
@ -129,6 +145,7 @@ RequestAllocator::ReadRequest(bigtime_t timeout)
// init the request // init the request
fRequest = (Request*)message; fRequest = (Request*)message;
fRequestOffset = 0;
fRequestSize = messageSize; fRequestSize = messageSize;
fRequestInPortBuffer = false; fRequestInPortBuffer = false;
@ -185,9 +202,10 @@ RequestAllocator::AllocateAddress(Address& address, int32 size, int32 align,
// get the next free aligned offset in the port buffer // get the next free aligned offset in the port buffer
int32 offset = (fRequestSize + align - 1) / align * align; int32 offset = (fRequestSize + align - 1) / align * align;
// allocate the data // allocate the data
if (offset + size <= fPort->GetCapacity()) { if (fRequestOffset + offset + size <= fPort->GetCapacity()) {
// there's enough free space in the port buffer // there's enough free space in the port buffer
fRequestSize = offset + size; fRequestSize = offset + size;
fPort->Reserve(fRequestOffset + fRequestSize);
if (deferredInit) { if (deferredInit) {
DeferredInitInfo& info DeferredInitInfo& info
= fDeferredInitInfos[fDeferredInitInfoCount]; = fDeferredInitInfos[fDeferredInitInfoCount];

View File

@ -77,9 +77,8 @@ RequestPort::SendRequest(RequestAllocator* allocator)
// check initialization and parameters // check initialization and parameters
if (InitCheck() != B_OK) if (InitCheck() != B_OK)
RETURN_ERROR(InitCheck()); RETURN_ERROR(InitCheck());
if (!allocator || allocator->GetRequest() != fPort.GetBuffer() if (!allocator || allocator->GetRequest() == NULL
|| allocator->GetRequestSize() < (int32)sizeof(Request) || allocator->GetRequestSize() < (int32)sizeof(Request)) {
|| allocator->GetRequestSize() > fPort.GetCapacity()) {
RETURN_ERROR(B_BAD_VALUE); RETURN_ERROR(B_BAD_VALUE);
} }
allocator->FinishDeferredInit(); allocator->FinishDeferredInit();
@ -97,7 +96,8 @@ RequestPort::SendRequest(RequestAllocator* allocator)
debugger("Request is not a kernel request."); debugger("Request is not a kernel request.");
} }
#endif #endif
RETURN_ERROR(fPort.Send(allocator->GetRequestSize())); RETURN_ERROR(fPort.Send(allocator->GetRequest(),
allocator->GetRequestSize()));
} }
// SendRequest // SendRequest