Changed the way the pty reader and output parser thread communicate. The
parser was acquiring a semaphore for each character. Now it only acquires a semaphore when the buffer is empty. This speeds up output bound programs. In my setup "seq" is now 3 times faster. Which is still rather slow. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25886 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -56,8 +56,9 @@ TermParse::TermParse(int fd)
|
|||||||
fReaderThread(-1),
|
fReaderThread(-1),
|
||||||
fReaderSem(-1),
|
fReaderSem(-1),
|
||||||
fReaderLocker(-1),
|
fReaderLocker(-1),
|
||||||
fBufferPosition(0),
|
fBufferPosition(0),
|
||||||
fLockFlag(0),
|
fReadBufferSize(0),
|
||||||
|
fParserWaiting(false),
|
||||||
fBuffer(NULL),
|
fBuffer(NULL),
|
||||||
fQuitting(true)
|
fQuitting(true)
|
||||||
{
|
{
|
||||||
@@ -117,45 +118,37 @@ TermParse::StopThreads()
|
|||||||
status_t
|
status_t
|
||||||
TermParse::GetReaderBuf(uchar &c)
|
TermParse::GetReaderBuf(uchar &c)
|
||||||
{
|
{
|
||||||
status_t status;
|
// wait for new input from pty
|
||||||
#if 0
|
if (fReadBufferSize == 0) {
|
||||||
do {
|
fBuffer->Unlock();
|
||||||
status = acquire_sem_etc(fReaderSem, 1, B_TIMEOUT, 10000);
|
|
||||||
} while (status == B_INTERRUPTED);
|
|
||||||
|
|
||||||
if (status == B_TIMED_OUT) {
|
fParserWaiting = true;
|
||||||
fBuffer->ScrollAtCursor();
|
|
||||||
fBuffer->UpdateLine();
|
|
||||||
|
|
||||||
// Reset cursor blinking time and turn on cursor blinking.
|
status_t status = B_OK;
|
||||||
fBuffer->SetCurDraw(true);
|
while (fReadBufferSize == 0 && status == B_OK) {
|
||||||
#endif
|
do {
|
||||||
|
status = acquire_sem(fReaderSem);
|
||||||
|
} while (status == B_INTERRUPTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
fParserWaiting = false;
|
||||||
|
|
||||||
|
fBuffer->Lock();
|
||||||
|
|
||||||
// wait new input from pty.
|
|
||||||
fBuffer->Unlock();
|
|
||||||
do {
|
|
||||||
status = acquire_sem(fReaderSem);
|
|
||||||
} while (status == B_INTERRUPTED);
|
|
||||||
fBuffer->Lock();
|
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
#if 0
|
|
||||||
} else if (status == B_OK) {
|
|
||||||
// Do nothing
|
|
||||||
} else
|
|
||||||
return status;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
c = fReadBuffer[fBufferPosition % READ_BUF_SIZE];
|
|
||||||
fBufferPosition++;
|
|
||||||
// If PtyReader thread locked, decrement counter and unlock thread.
|
|
||||||
if (fLockFlag != 0) {
|
|
||||||
if (--fLockFlag == 0)
|
|
||||||
release_sem(fReaderLocker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fBuffer->SetCurDraw(false);
|
c = fReadBuffer[fBufferPosition];
|
||||||
|
fBufferPosition = (fBufferPosition + 1) % READ_BUF_SIZE;
|
||||||
|
|
||||||
|
int32 bufferSize = atomic_add(&fReadBufferSize, -1) - 1;
|
||||||
|
|
||||||
|
// If the pty reader thread waits and we have made enough space in the
|
||||||
|
// buffer now, let it run again.
|
||||||
|
if (READ_BUF_SIZE - bufferSize == MIN_PTY_BUFFER_SPACE)
|
||||||
|
release_sem(fReaderLocker);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,22 +241,24 @@ TermParse::StopPtyReader()
|
|||||||
int32
|
int32
|
||||||
TermParse::PtyReader()
|
TermParse::PtyReader()
|
||||||
{
|
{
|
||||||
uint read_p = 0;
|
int32 bufferSize = 0;
|
||||||
|
int32 readPos = 0;
|
||||||
while (!fQuitting) {
|
while (!fQuitting) {
|
||||||
// If Pty Buffer nearly full, snooze this thread, and continue.
|
// If Pty Buffer nearly full, snooze this thread, and continue.
|
||||||
if ((read_p - fBufferPosition) > READ_BUF_SIZE - 16) {
|
while (READ_BUF_SIZE - bufferSize < MIN_PTY_BUFFER_SPACE) {
|
||||||
fLockFlag = READ_BUF_SIZE / 2;
|
|
||||||
status_t status;
|
status_t status;
|
||||||
do {
|
do {
|
||||||
status = acquire_sem(fReaderLocker);
|
status = acquire_sem(fReaderLocker);
|
||||||
} while (status == B_INTERRUPTED);
|
} while (status == B_INTERRUPTED);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
bufferSize = fReadBufferSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read PTY
|
// Read PTY
|
||||||
uchar buf[READ_BUF_SIZE];
|
uchar buf[READ_BUF_SIZE];
|
||||||
int nread = read(fFd, buf, READ_BUF_SIZE - (read_p - fBufferPosition));
|
ssize_t nread = read(fFd, buf, READ_BUF_SIZE - bufferSize);
|
||||||
if (nread <= 0) {
|
if (nread <= 0) {
|
||||||
fBuffer->NotifyQuit(errno);
|
fBuffer->NotifyQuit(errno);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -271,19 +266,20 @@ TermParse::PtyReader()
|
|||||||
|
|
||||||
// Copy read string to PtyBuffer.
|
// Copy read string to PtyBuffer.
|
||||||
|
|
||||||
int left = READ_BUF_SIZE - (read_p % READ_BUF_SIZE);
|
int32 left = READ_BUF_SIZE - readPos;
|
||||||
int mod = read_p % READ_BUF_SIZE;
|
|
||||||
|
|
||||||
if (nread >= left) {
|
if (nread >= left) {
|
||||||
memcpy(fReadBuffer + mod, buf, left);
|
memcpy(fReadBuffer + readPos, buf, left);
|
||||||
memcpy(fReadBuffer, buf + left, nread - left);
|
memcpy(fReadBuffer, buf + left, nread - left);
|
||||||
} else
|
} else
|
||||||
memcpy(fReadBuffer + mod, buf, nread);
|
memcpy(fReadBuffer + readPos, buf, nread);
|
||||||
|
|
||||||
read_p += nread;
|
bufferSize = atomic_add(&fReadBufferSize, nread);
|
||||||
|
if (bufferSize == 0 && fParserWaiting)
|
||||||
|
release_sem(fReaderSem);
|
||||||
|
|
||||||
// Release semaphore. Number of semaphore counter is nread.
|
bufferSize += nread;
|
||||||
release_sem_etc(fReaderSem, nread, 0);
|
readPos = (readPos + nread) % READ_BUF_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -37,8 +37,11 @@
|
|||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
|
|
||||||
//PtyReader buffer size.
|
|
||||||
#define READ_BUF_SIZE 2048
|
#define READ_BUF_SIZE 2048
|
||||||
|
// pty read buffer size
|
||||||
|
#define MIN_PTY_BUFFER_SPACE 16
|
||||||
|
// minimal space left before the reader tries to read more
|
||||||
|
|
||||||
|
|
||||||
class TerminalBuffer;
|
class TerminalBuffer;
|
||||||
|
|
||||||
@@ -80,6 +83,8 @@ private:
|
|||||||
|
|
||||||
uint fBufferPosition;
|
uint fBufferPosition;
|
||||||
uchar fReadBuffer[READ_BUF_SIZE];
|
uchar fReadBuffer[READ_BUF_SIZE];
|
||||||
|
vint32 fReadBufferSize;
|
||||||
|
volatile bool fParserWaiting;
|
||||||
|
|
||||||
int fLockFlag;
|
int fLockFlag;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user