FIFO: Handle user reads/writes more correctly
* Determine whether called from userland or kernel. * Check the buffer address via IS_USER_ADDRESS(), if from userland. * Simplify things by merging UserRead() with Read() and UserWrite() with Write().
This commit is contained in:
@@ -62,12 +62,11 @@ public:
|
|||||||
status_t CreateBuffer();
|
status_t CreateBuffer();
|
||||||
void DeleteBuffer();
|
void DeleteBuffer();
|
||||||
|
|
||||||
ssize_t Write(const void* buffer, size_t length);
|
ssize_t Write(const void* buffer, size_t length,
|
||||||
ssize_t Read(void* buffer, size_t length);
|
bool isUser);
|
||||||
|
ssize_t Read(void* buffer, size_t length, bool isUser);
|
||||||
ssize_t Peek(size_t offset, void* buffer,
|
ssize_t Peek(size_t offset, void* buffer,
|
||||||
size_t length) const;
|
size_t length) const;
|
||||||
ssize_t UserWrite(const void* buffer, ssize_t length);
|
|
||||||
ssize_t UserRead(void* buffer, ssize_t length);
|
|
||||||
|
|
||||||
size_t Readable() const;
|
size_t Readable() const;
|
||||||
size_t Writable() const;
|
size_t Writable() const;
|
||||||
@@ -172,9 +171,11 @@ public:
|
|||||||
mutex* RequestLock() { return &fRequestLock; }
|
mutex* RequestLock() { return &fRequestLock; }
|
||||||
|
|
||||||
status_t WriteDataToBuffer(const void* data,
|
status_t WriteDataToBuffer(const void* data,
|
||||||
size_t* _length, bool nonBlocking);
|
size_t* _length, bool nonBlocking,
|
||||||
|
bool isUser);
|
||||||
status_t ReadDataFromBuffer(void* data, size_t* _length,
|
status_t ReadDataFromBuffer(void* data, size_t* _length,
|
||||||
bool nonBlocking, ReadRequest& request);
|
bool nonBlocking, bool isUser,
|
||||||
|
ReadRequest& request);
|
||||||
size_t BytesAvailable() const
|
size_t BytesAvailable() const
|
||||||
{ return fBuffer.Readable(); }
|
{ return fBuffer.Readable(); }
|
||||||
size_t BytesWritable() const
|
size_t BytesWritable() const
|
||||||
@@ -292,22 +293,30 @@ RingBuffer::DeleteBuffer()
|
|||||||
|
|
||||||
|
|
||||||
inline ssize_t
|
inline ssize_t
|
||||||
RingBuffer::Write(const void* buffer, size_t length)
|
RingBuffer::Write(const void* buffer, size_t length, bool isUser)
|
||||||
{
|
{
|
||||||
if (fBuffer == NULL)
|
if (fBuffer == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
if (isUser && !IS_USER_ADDRESS(buffer))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return ring_buffer_write(fBuffer, (const uint8*)buffer, length);
|
return isUser
|
||||||
|
? ring_buffer_user_write(fBuffer, (const uint8*)buffer, length)
|
||||||
|
: ring_buffer_write(fBuffer, (const uint8*)buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline ssize_t
|
inline ssize_t
|
||||||
RingBuffer::Read(void* buffer, size_t length)
|
RingBuffer::Read(void* buffer, size_t length, bool isUser)
|
||||||
{
|
{
|
||||||
if (fBuffer == NULL)
|
if (fBuffer == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
if (isUser && !IS_USER_ADDRESS(buffer))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return ring_buffer_read(fBuffer, (uint8*)buffer, length);
|
return isUser
|
||||||
|
? ring_buffer_user_read(fBuffer, (uint8*)buffer, length)
|
||||||
|
: ring_buffer_read(fBuffer, (uint8*)buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -321,26 +330,6 @@ RingBuffer::Peek(size_t offset, void* buffer, size_t length) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline ssize_t
|
|
||||||
RingBuffer::UserWrite(const void* buffer, ssize_t length)
|
|
||||||
{
|
|
||||||
if (fBuffer == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
return ring_buffer_user_write(fBuffer, (const uint8*)buffer, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline ssize_t
|
|
||||||
RingBuffer::UserRead(void* buffer, ssize_t length)
|
|
||||||
{
|
|
||||||
if (fBuffer == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
return ring_buffer_user_read(fBuffer, (uint8*)buffer, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline size_t
|
inline size_t
|
||||||
RingBuffer::Readable() const
|
RingBuffer::Readable() const
|
||||||
{
|
{
|
||||||
@@ -400,7 +389,8 @@ Inode::InitCheck()
|
|||||||
the returned length is > 0, the returned error code can be ignored.
|
the returned length is > 0, the returned error code can be ignored.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
Inode::WriteDataToBuffer(const void* _data, size_t* _length, bool nonBlocking)
|
Inode::WriteDataToBuffer(const void* _data, size_t* _length, bool nonBlocking,
|
||||||
|
bool isUser)
|
||||||
{
|
{
|
||||||
const uint8* data = (const uint8*)_data;
|
const uint8* data = (const uint8*)_data;
|
||||||
size_t dataSize = *_length;
|
size_t dataSize = *_length;
|
||||||
@@ -452,8 +442,11 @@ Inode::WriteDataToBuffer(const void* _data, size_t* _length, bool nonBlocking)
|
|||||||
if (toWrite > dataSize)
|
if (toWrite > dataSize)
|
||||||
toWrite = dataSize;
|
toWrite = dataSize;
|
||||||
|
|
||||||
if (toWrite > 0 && fBuffer.UserWrite(data, toWrite) < 0)
|
if (toWrite > 0) {
|
||||||
return B_BAD_ADDRESS;
|
ssize_t bytesWritten = fBuffer.Write(data, toWrite, isUser);
|
||||||
|
if (bytesWritten < 0)
|
||||||
|
return bytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
data += toWrite;
|
data += toWrite;
|
||||||
dataSize -= toWrite;
|
dataSize -= toWrite;
|
||||||
@@ -468,7 +461,7 @@ Inode::WriteDataToBuffer(const void* _data, size_t* _length, bool nonBlocking)
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
Inode::ReadDataFromBuffer(void* data, size_t* _length, bool nonBlocking,
|
Inode::ReadDataFromBuffer(void* data, size_t* _length, bool nonBlocking,
|
||||||
ReadRequest& request)
|
bool isUser, ReadRequest& request)
|
||||||
{
|
{
|
||||||
size_t dataSize = *_length;
|
size_t dataSize = *_length;
|
||||||
*_length = 0;
|
*_length = 0;
|
||||||
@@ -508,8 +501,9 @@ Inode::ReadDataFromBuffer(void* data, size_t* _length, bool nonBlocking,
|
|||||||
if (toRead > dataSize)
|
if (toRead > dataSize)
|
||||||
toRead = dataSize;
|
toRead = dataSize;
|
||||||
|
|
||||||
if (fBuffer.UserRead(data, toRead) < 0)
|
ssize_t bytesRead = fBuffer.Read(data, toRead, isUser);
|
||||||
return B_BAD_ADDRESS;
|
if (bytesRead < 0)
|
||||||
|
return bytesRead;
|
||||||
|
|
||||||
NotifyBytesRead(toRead);
|
NotifyBytesRead(toRead);
|
||||||
|
|
||||||
@@ -970,7 +964,8 @@ fifo_read(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
|||||||
|
|
||||||
size_t length = *_length;
|
size_t length = *_length;
|
||||||
status_t status = inode->ReadDataFromBuffer(buffer, &length,
|
status_t status = inode->ReadDataFromBuffer(buffer, &length,
|
||||||
(cookie->open_mode & O_NONBLOCK) != 0, request);
|
(cookie->open_mode & O_NONBLOCK) != 0, is_called_via_syscall(),
|
||||||
|
request);
|
||||||
|
|
||||||
inode->RemoveReadRequest(request);
|
inode->RemoveReadRequest(request);
|
||||||
inode->NotifyReadDone();
|
inode->NotifyReadDone();
|
||||||
@@ -1006,7 +1001,7 @@ fifo_write(fs_volume* _volume, fs_vnode* _node, void* _cookie,
|
|||||||
|
|
||||||
// copy data into ring buffer
|
// copy data into ring buffer
|
||||||
status_t status = inode->WriteDataToBuffer(buffer, &length,
|
status_t status = inode->WriteDataToBuffer(buffer, &length,
|
||||||
(cookie->open_mode & O_NONBLOCK) != 0);
|
(cookie->open_mode & O_NONBLOCK) != 0, is_called_via_syscall());
|
||||||
|
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
status = B_OK;
|
status = B_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user