* Renamed GetReaderBuf() to _NextParseChar().
* Introduced a small (64 byte) buffer for the parser thread. Instead of directly reading single characters out of the reader buffer, we read a full parser buffer and process the characters from the parser buffer. Thus _NextParseChar() could be inlined, since it merely consists of a conditional method call and an access to the parser buffer, now. * Improved the locking of the terminal buffer. Instead of unlocking and relocking after every multi-byte char or escape sequence, we only unlock while refilling the parser buffer. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25911 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
ced75fc6b0
commit
540e66d6a6
@ -49,6 +49,23 @@ extern int gMbcsTable[]; /* ESC $ */
|
||||
#define NPARAM 10 // Max parameters
|
||||
|
||||
|
||||
//! Get char from pty reader buffer.
|
||||
inline status_t
|
||||
TermParse::_NextParseChar(uchar &c)
|
||||
{
|
||||
if (fParserBufferOffset >= fParserBufferSize) {
|
||||
// parser buffer empty
|
||||
status_t error = _ReadParserBuffer();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
c = fParserBuffer[fParserBufferOffset++];
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
TermParse::TermParse(int fd)
|
||||
:
|
||||
fFd(fd),
|
||||
@ -58,6 +75,8 @@ TermParse::TermParse(int fd)
|
||||
fReaderLocker(-1),
|
||||
fBufferPosition(0),
|
||||
fReadBufferSize(0),
|
||||
fParserBufferSize(0),
|
||||
fParserBufferOffset(0),
|
||||
fParserWaiting(false),
|
||||
fBuffer(NULL),
|
||||
fQuitting(true)
|
||||
@ -114,45 +133,6 @@ TermParse::StopThreads()
|
||||
}
|
||||
|
||||
|
||||
//! Get char from pty reader buffer.
|
||||
status_t
|
||||
TermParse::GetReaderBuf(uchar &c)
|
||||
{
|
||||
// wait for new input from pty
|
||||
if (fReadBufferSize == 0) {
|
||||
fBuffer->Unlock();
|
||||
|
||||
fParserWaiting = true;
|
||||
|
||||
status_t status = B_OK;
|
||||
while (fReadBufferSize == 0 && status == B_OK) {
|
||||
do {
|
||||
status = acquire_sem(fReaderSem);
|
||||
} while (status == B_INTERRUPTED);
|
||||
}
|
||||
|
||||
fParserWaiting = false;
|
||||
|
||||
fBuffer->Lock();
|
||||
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//! Initialize and spawn EscParse thread.
|
||||
status_t
|
||||
TermParse::InitTermParse()
|
||||
@ -346,12 +326,11 @@ TermParse::EscParse()
|
||||
int *groundtable = gUTF8GroundTable;
|
||||
int *parsestate = groundtable;
|
||||
|
||||
while (!fQuitting) {
|
||||
// TODO: Fix the locking!
|
||||
BAutolock locker(fBuffer);
|
||||
|
||||
while (!fQuitting) {
|
||||
uchar c;
|
||||
if (GetReaderBuf(c) < B_OK)
|
||||
if (_NextParseChar(c) < B_OK)
|
||||
break;
|
||||
|
||||
//DumpState(groundtable, parsestate, c);
|
||||
@ -412,7 +391,7 @@ TermParse::EscParse()
|
||||
case CASE_SS3: /* JIS X 0212 */
|
||||
*ptr++ = curess;
|
||||
*ptr++ = c;
|
||||
GetReaderBuf(c);
|
||||
_NextParseChar(c);
|
||||
*ptr++ = c;
|
||||
*ptr = 0;
|
||||
curess = 0;
|
||||
@ -420,7 +399,7 @@ TermParse::EscParse()
|
||||
|
||||
default: /* JIS X 0208 */
|
||||
*ptr++ = c;
|
||||
GetReaderBuf(c);
|
||||
_NextParseChar(c);
|
||||
*ptr++ = c;
|
||||
*ptr = 0;
|
||||
break;
|
||||
@ -443,7 +422,7 @@ TermParse::EscParse()
|
||||
|
||||
case CASE_PRINT_CS96:
|
||||
cbuf[0] = c | 0x80;
|
||||
GetReaderBuf(c);
|
||||
_NextParseChar(c);
|
||||
cbuf[1] = c | 0x80;
|
||||
cbuf[2] = 0;
|
||||
CodeConv::ConvertToInternal(cbuf, 2, dstbuf, B_EUC_CONVERSION);
|
||||
@ -467,7 +446,7 @@ TermParse::EscParse()
|
||||
|
||||
case CASE_SJIS_INSTRING:
|
||||
cbuf[0] = c;
|
||||
GetReaderBuf(c);
|
||||
_NextParseChar(c);
|
||||
cbuf[1] = c;
|
||||
cbuf[2] = '\0';
|
||||
CodeConv::ConvertToInternal(cbuf, 2, dstbuf, now_coding);
|
||||
@ -476,7 +455,7 @@ TermParse::EscParse()
|
||||
|
||||
case CASE_UTF8_2BYTE:
|
||||
cbuf[0] = c;
|
||||
GetReaderBuf(c);
|
||||
_NextParseChar(c);
|
||||
if (groundtable[c] != CASE_UTF8_INSTRING)
|
||||
break;
|
||||
cbuf[1] = c;
|
||||
@ -487,12 +466,12 @@ TermParse::EscParse()
|
||||
|
||||
case CASE_UTF8_3BYTE:
|
||||
cbuf[0] = c;
|
||||
GetReaderBuf(c);
|
||||
_NextParseChar(c);
|
||||
if (groundtable[c] != CASE_UTF8_INSTRING)
|
||||
break;
|
||||
cbuf[1] = c;
|
||||
|
||||
GetReaderBuf(c);
|
||||
_NextParseChar(c);
|
||||
if (groundtable[c] != CASE_UTF8_INSTRING)
|
||||
break;
|
||||
cbuf[2] = c;
|
||||
@ -515,7 +494,7 @@ TermParse::EscParse()
|
||||
{
|
||||
cs96 = 0;
|
||||
uchar dummy;
|
||||
GetReaderBuf(dummy);
|
||||
_NextParseChar(dummy);
|
||||
parsestate = groundtable;
|
||||
break;
|
||||
}
|
||||
@ -881,7 +860,7 @@ TermParse::EscParse()
|
||||
char string[512];
|
||||
uint32 len = 0;
|
||||
uchar mode_char;
|
||||
GetReaderBuf(mode_char);
|
||||
_NextParseChar(mode_char);
|
||||
if (mode_char != '0'
|
||||
&& mode_char != '1'
|
||||
&& mode_char != '2') {
|
||||
@ -889,8 +868,8 @@ TermParse::EscParse()
|
||||
break;
|
||||
}
|
||||
uchar current_char;
|
||||
GetReaderBuf(current_char);
|
||||
while (GetReaderBuf(current_char) == B_OK
|
||||
_NextParseChar(current_char);
|
||||
while (_NextParseChar(current_char) == B_OK
|
||||
&& current_char != 0x7) {
|
||||
if (!isprint(current_char & 0x7f)
|
||||
|| len+2 >= sizeof(string))
|
||||
@ -988,6 +967,59 @@ TermParse::_escparse_thread(void *data)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TermParse::_ReadParserBuffer()
|
||||
{
|
||||
// We have to unlock the terminal buffer while waiting for data from the
|
||||
// PTY. We don't have to unlock when we don't need to wait, but we do it
|
||||
// anyway, so that TermView won't be starved when trying to synchronize.
|
||||
fBuffer->Unlock();
|
||||
|
||||
// wait for new input from pty
|
||||
if (fReadBufferSize == 0) {
|
||||
fParserWaiting = true;
|
||||
|
||||
status_t status = B_OK;
|
||||
while (fReadBufferSize == 0 && status == B_OK) {
|
||||
do {
|
||||
status = acquire_sem(fReaderSem);
|
||||
} while (status == B_INTERRUPTED);
|
||||
}
|
||||
|
||||
fParserWaiting = false;
|
||||
|
||||
if (status < B_OK) {
|
||||
fBuffer->Lock();
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
int32 toRead = fReadBufferSize;
|
||||
if (toRead > ESC_PARSER_BUFFER_SIZE)
|
||||
toRead = ESC_PARSER_BUFFER_SIZE;
|
||||
|
||||
for (int32 i = 0; i < toRead; i++) {
|
||||
fParserBuffer[i] = fReadBuffer[fBufferPosition];
|
||||
fBufferPosition = (fBufferPosition + 1) % READ_BUF_SIZE;
|
||||
}
|
||||
|
||||
int32 bufferSize = atomic_add(&fReadBufferSize, -toRead);
|
||||
|
||||
// If the pty reader thread waits and we have made enough space in the
|
||||
// buffer now, let it run again.
|
||||
if (bufferSize > READ_BUF_SIZE - MIN_PTY_BUFFER_SPACE
|
||||
&& bufferSize - toRead <= READ_BUF_SIZE - MIN_PTY_BUFFER_SPACE) {
|
||||
release_sem(fReaderLocker);
|
||||
}
|
||||
|
||||
fParserBufferSize = toRead;
|
||||
fParserBufferOffset = 0;
|
||||
|
||||
fBuffer->Lock();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TermParse::_DeviceStatusReport(int n)
|
||||
{
|
||||
|
@ -41,6 +41,8 @@
|
||||
// pty read buffer size
|
||||
#define MIN_PTY_BUFFER_SPACE 16
|
||||
// minimal space left before the reader tries to read more
|
||||
#define ESC_PARSER_BUFFER_SIZE 64
|
||||
// size of the parser buffer
|
||||
|
||||
|
||||
class TerminalBuffer;
|
||||
@ -54,6 +56,8 @@ public:
|
||||
status_t StopThreads();
|
||||
|
||||
private:
|
||||
inline status_t _NextParseChar(uchar &c);
|
||||
|
||||
// Initialize TermParse and PtyReader thread.
|
||||
status_t InitTermParse();
|
||||
status_t InitPtyReader();
|
||||
@ -69,8 +73,7 @@ private:
|
||||
static int32 _ptyreader_thread(void *);
|
||||
static int32 _escparse_thread(void *);
|
||||
|
||||
// Reading ReadBuf at one Char.
|
||||
status_t GetReaderBuf(uchar &c);
|
||||
status_t _ReadParserBuffer();
|
||||
|
||||
void _DeviceStatusReport(int n);
|
||||
|
||||
@ -84,6 +87,10 @@ private:
|
||||
uint fBufferPosition;
|
||||
uchar fReadBuffer[READ_BUF_SIZE];
|
||||
vint32 fReadBufferSize;
|
||||
|
||||
uchar fParserBuffer[ESC_PARSER_BUFFER_SIZE];
|
||||
int32 fParserBufferSize;
|
||||
int32 fParserBufferOffset;
|
||||
volatile bool fParserWaiting;
|
||||
|
||||
int fLockFlag;
|
||||
|
Loading…
Reference in New Issue
Block a user