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:
Ingo Weinhold
2008-06-09 19:35:33 +00:00
parent bdc33077f9
commit 066dcdc34b
2 changed files with 47 additions and 46 deletions
+41 -45
View File
@@ -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;
+6 -1
View File
@@ -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;