WriterLocker mixed up source and target and always locked the wrong one.

tty_write_to_tty() now takes the extra character into account that may be
inserted with OPOST and ONLCR and don't write more characters as there is
space.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9151 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2004-10-01 17:27:57 +00:00
parent 549360d822
commit 87df3fdab8

View File

@ -80,12 +80,11 @@ WriterLocker::WriterLocker(struct tty *source, struct tty *target, bool echo, bo
fTarget(target),
fEcho(echo)
{
if (echo) {
if (!sourceIsMaster) {
// just switch the two, we have to lock both of them anyway
fSource = target;
fTarget = source;
}
if (echo && sourceIsMaster) {
// just switch the two, we have to lock both of
// them anyway - master is always locked first
fSource = target;
fTarget = source;
}
Lock();
@ -98,22 +97,22 @@ WriterLocker::~WriterLocker()
}
void
void
WriterLocker::Lock()
{
mutex_lock(&fSource->lock);
mutex_lock(&fTarget->lock);
if (fEcho)
mutex_lock(&fTarget->lock);
mutex_lock(&fSource->lock);
}
void
void
WriterLocker::Unlock()
{
if (fEcho)
mutex_unlock(&fTarget->lock);
mutex_unlock(&fSource->lock);
mutex_unlock(&fSource->lock);
mutex_unlock(&fTarget->lock);
}
@ -125,14 +124,14 @@ WriterLocker::AcquireWriter(bool dontBlock)
if (!dontBlock)
Unlock();
status_t status = acquire_sem_etc(fSource->write_sem, 1, (dontBlock ? B_TIMEOUT : 0) | B_CAN_INTERRUPT, 0);
status_t status = acquire_sem_etc(fTarget->write_sem, 1, (dontBlock ? B_TIMEOUT : 0) | B_CAN_INTERRUPT, 0);
if (status == B_OK && fEcho) {
// We need to hold two write semaphores in order to echo the output to
// the local TTY as well. We need to make sure that these semaphores
// are always acquired in the same order to prevent deadlocks
status = acquire_sem_etc(fTarget->write_sem, 1, (dontBlock ? B_TIMEOUT : 0) | B_CAN_INTERRUPT, 0);
status = acquire_sem_etc(fSource->write_sem, 1, (dontBlock ? B_TIMEOUT : 0) | B_CAN_INTERRUPT, 0);
if (status != B_OK)
release_sem(fSource->write_sem);
release_sem(fTarget->write_sem);
}
// reacquire TTY lock
@ -140,9 +139,9 @@ WriterLocker::AcquireWriter(bool dontBlock)
Lock();
if (status == B_OK) {
fSourceBytes = line_buffer_writable(fSource->input_buffer);
fTargetBytes = line_buffer_writable(fTarget->input_buffer);
if (fEcho)
fTargetBytes = line_buffer_writable(fTarget->input_buffer);
fSourceBytes = line_buffer_writable(fSource->input_buffer);
}
return status;
}
@ -151,11 +150,11 @@ WriterLocker::AcquireWriter(bool dontBlock)
void
WriterLocker::ReportWritten(size_t written)
{
if (written < fSourceBytes)
release_sem_etc(fSource->write_sem, 1, fTarget ? B_DO_NOT_RESCHEDULE : 0);
if (written < fTargetBytes)
release_sem_etc(fTarget->write_sem, 1, fEcho ? B_DO_NOT_RESCHEDULE : 0);
if (fEcho && written < fTargetBytes)
release_sem(fTarget->write_sem);
if (fEcho && written < fSourceBytes)
release_sem(fSource->write_sem);
// there is now probably something to read, too
@ -521,7 +520,7 @@ tty_input_read(struct tty *tty, void *buffer, size_t *_length, uint32 mode)
// ToDo: add support for ICANON mode
ssize_t bytesRead = line_buffer_user_read(tty->input_buffer, (char *)buffer, length);
bytesRead = line_buffer_user_read(tty->input_buffer, (char *)buffer, length);
if (bytesRead < B_OK) {
*_length = 0;
locker.ReportRead(0);
@ -562,10 +561,8 @@ tty_write_to_tty(struct tty *source, struct tty *target, const void *buffer, siz
}
size_t writable = line_buffer_writable(target->input_buffer);
if (writable > length)
writable = length;
if (echo) {
// we can only write as much as is available on both ends
size_t locallyWritable = line_buffer_writable(source->input_buffer);
if (locallyWritable < writable)
writable = locallyWritable;
@ -576,7 +573,7 @@ tty_write_to_tty(struct tty *source, struct tty *target, const void *buffer, siz
continue;
}
while (writable > bytesWritten) {
while (writable > bytesWritten && bytesWritten < length) {
char c = data[0];
if (c == '\n' && (source->termios.c_oflag & (OPOST | ONLCR)) == OPOST | ONLCR) {
@ -584,6 +581,9 @@ tty_write_to_tty(struct tty *source, struct tty *target, const void *buffer, siz
tty_input_putc_locked(target, '\r');
if (echo)
tty_input_putc_locked(source, '\r');
if (--writable == 0)
continue;
}
tty_input_putc_locked(target, c);