Files
haiku-beta6/src/system/kernel/device_manager/io_requests.h
T
Ingo Weinhold c1cec366af * Removed B_USER_IO_REQUEST flag. It was superfluous, since whether the
buffer lives in userland can easily be checked via IS_USER_ADDRESS.
* Added B_VIP_IO_REQUEST flag which will be used by the page writer and
  should cause allocations to be made in a way that they cannot fail.
  Not implemented yet, though.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26632 a95241bf-73f2-0310-859d-f6bbb57e9c96
2008-07-25 14:01:56 +00:00

263 lines
7.1 KiB
C++

/*
* Copyright 2008, Ingo Weinhold, [email protected].
* Copyright 2008, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef IO_REQUESTS_H
#define IO_REQUESTS_H
#include <sys/uio.h>
#include <SupportDefs.h>
#include <condition_variable.h>
#include <lock.h>
#include <util/DoublyLinkedList.h>
#include "dma_resources.h"
#define B_PHYSICAL_IO_REQUEST 0x01 /* buffer points to physical memory */
#define B_VIP_IO_REQUEST 0x02 /* used by the page writer -- make sure
allocations won't fail */
struct DMABuffer;
struct IOOperation;
typedef struct IOOperation io_operation;
class IOBuffer : public DoublyLinkedListLinkImpl<IOBuffer> {
public:
static IOBuffer* Create(size_t count);
bool IsVirtual() const { return !fPhysical; }
bool IsPhysical() const { return fPhysical; }
bool IsUser() const { return fUser; }
void SetVecs(const iovec* vecs, uint32 count,
size_t length, uint32 flags);
void SetPhysical(bool physical)
{ fPhysical = physical; }
void SetUser(bool user) { fUser = user; }
void SetLength(size_t length) { fLength = length; }
void SetVecCount(uint32 count) { fVecCount = count; }
size_t Length() const { return fLength; }
iovec* Vecs() { return fVecs; }
iovec& VecAt(size_t index) { return fVecs[index]; }
size_t VecCount() const { return fVecCount; }
size_t Capacity() const { return fCapacity; }
status_t LockMemory(team_id team, bool isWrite);
void UnlockMemory(team_id team, bool isWrite);
private:
~IOBuffer();
// not implemented
void _UnlockMemory(team_id team, size_t count,
bool isWrite);
bool fUser;
bool fPhysical;
size_t fLength;
size_t fVecCount;
size_t fCapacity;
iovec fVecs[1];
};
class IORequest;
class IORequestChunk {
public:
IORequestChunk();
virtual ~IORequestChunk();
IORequest* Parent() const { return fParent; }
void SetParent(IORequest* parent)
{ fParent = parent; }
status_t Status() const { return fStatus; }
void SetStatus(status_t status)
{ fStatus = status; }
void ResetStatus()
{ fStatus = 1; }
DoublyLinkedListLink<IORequestChunk>*
ListLink() { return &fListLink; }
protected:
IORequest* fParent;
status_t fStatus;
public:
DoublyLinkedListLink<IORequestChunk> fListLink;
};
typedef DoublyLinkedList<IORequestChunk,
DoublyLinkedListMemberGetLink<IORequestChunk, &IORequestChunk::fListLink> >
IORequestChunkList;
struct IOOperation : IORequestChunk, DoublyLinkedListLinkImpl<IOOperation> {
public:
bool Finish();
// returns true, if it can be recycled
status_t Prepare(IORequest* request);
void SetOriginalRange(off_t offset, size_t length);
// also sets range
void SetRange(off_t offset, size_t length);
off_t Offset() const;
size_t Length() const;
off_t OriginalOffset() const
{ return fOriginalOffset; }
size_t OriginalLength() const
{ return fOriginalLength; }
iovec* Vecs() const;
uint32 VecCount() const;
void SetPartial(bool partialBegin, bool partialEnd);
bool HasPartialBegin() const
{ return fPartialBegin; }
bool HasPartialEnd() const
{ return fPartialEnd; }
bool IsWrite() const;
bool IsRead() const;
void SetBlockSize(size_t blockSize)
{ fBlockSize = blockSize; }
bool UsesBounceBuffer() const
{ return fUsesBounceBuffer; }
void SetUsesBounceBuffer(bool uses)
{ fUsesBounceBuffer = uses; }
DMABuffer* Buffer() const { return fDMABuffer; }
void SetBuffer(DMABuffer* buffer)
{ fDMABuffer = buffer; }
protected:
void _PrepareVecs();
status_t _CopyPartialBegin(bool isWrite,
bool& partialBlockOnly);
status_t _CopyPartialEnd(bool isWrite);
DMABuffer* fDMABuffer;
off_t fOffset;
off_t fOriginalOffset;
size_t fLength;
size_t fOriginalLength;
size_t fBlockSize;
uint16 fSavedVecIndex;
uint16 fSavedVecLength;
uint8 fPhase;
bool fPartialBegin;
bool fPartialEnd;
bool fUsesBounceBuffer;
};
typedef IOOperation io_operation;
typedef DoublyLinkedList<IOOperation> IOOperationList;
typedef struct IORequest io_request;
typedef status_t (*io_request_callback)(void* data, io_request* request);
struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
IORequest();
virtual ~IORequest();
status_t Init(off_t offset, void* buffer, size_t length,
bool write, uint32 flags);
status_t Init(off_t offset, iovec* vecs, size_t count,
size_t length, bool write, uint32 flags);
void SetFinishedCallback(
io_request_callback callback,
void* cookie);
void SetIterationCallback(
io_request_callback callback,
void* cookie);
status_t Wait(uint32 flags = 0, bigtime_t timeout = 0);
bool IsFinished() const
{ return fStatus != 1
&& fPendingChildren == 0; }
void NotifyFinished();
bool HasCallbacks() const;
void OperationFinished(IOOperation* operation,
status_t status);
void SubrequestFinished(IORequest* request,
status_t status);
size_t RemainingBytes() const
{ return fRemainingBytes; }
bool IsWrite() const { return fIsWrite; }
bool IsRead() const { return !fIsWrite; }
team_id Team() const { return fTeam; }
IOBuffer* Buffer() const { return fBuffer; }
off_t Offset() const { return fOffset; }
size_t Length() const { return fLength; }
uint32 VecIndex() const { return fVecIndex; }
size_t VecOffset() const { return fVecOffset; }
void Advance(size_t bySize);
void AddOperation(IOOperation* operation);
void RemoveOperation(IOOperation* operation);
status_t CopyData(off_t offset, void* buffer,
size_t size);
status_t CopyData(const void* buffer, off_t offset,
size_t size);
private:
status_t _CopyData(void* buffer, off_t offset,
size_t size, bool copyIn);
static status_t _CopySimple(void* bounceBuffer, void* external,
size_t size, team_id team, bool copyIn);
static status_t _CopyPhysical(void* bounceBuffer,
void* external, size_t size, team_id team,
bool copyIn);
static status_t _CopyUser(void* bounceBuffer, void* external,
size_t size, team_id team, bool copyIn);
mutex fLock;
IOBuffer* fBuffer;
off_t fOffset;
size_t fLength;
IORequestChunkList fChildren;
int32 fPendingChildren;
uint32 fFlags;
team_id fTeam;
bool fIsWrite;
io_request_callback fFinishedCallback;
void* fFinishedCookie;
io_request_callback fIterationCallback;
void* fIterationCookie;
ConditionVariable fFinishedCondition;
// these are for iteration
uint32 fVecIndex;
size_t fVecOffset;
size_t fRemainingBytes;
};
typedef DoublyLinkedList<IORequest> IORequestList;
#endif // IO_REQUESTS_H