pc_serial: wait for writes to complete on a sem
This avoids close being called too early and discarding output.
This commit is contained in:
@@ -62,6 +62,8 @@ SerialDevice::~SerialDevice()
|
|||||||
{
|
{
|
||||||
Removed();
|
Removed();
|
||||||
|
|
||||||
|
if (fDoneWrite >= B_OK)
|
||||||
|
delete_sem(fDoneWrite);
|
||||||
if (fReadBufferSem >= B_OK)
|
if (fReadBufferSem >= B_OK)
|
||||||
delete_sem(fReadBufferSem);
|
delete_sem(fReadBufferSem);
|
||||||
if (fWriteBufferSem >= B_OK)
|
if (fWriteBufferSem >= B_OK)
|
||||||
@@ -87,6 +89,7 @@ SerialDevice::Probe()
|
|||||||
status_t
|
status_t
|
||||||
SerialDevice::Init()
|
SerialDevice::Init()
|
||||||
{
|
{
|
||||||
|
fDoneWrite = create_sem(0, "pc_serial:done_write");
|
||||||
fReadBufferSem = create_sem(0, "pc_serial:done_read");
|
fReadBufferSem = create_sem(0, "pc_serial:done_read");
|
||||||
fWriteBufferSem = create_sem(0, "pc_serial:done_write");
|
fWriteBufferSem = create_sem(0, "pc_serial:done_write");
|
||||||
|
|
||||||
@@ -429,6 +432,11 @@ SerialDevice::InterruptHandler()
|
|||||||
sizeof(readable));
|
sizeof(readable));
|
||||||
TRACE("%s: FIONREAD: %d\n", __FUNCTION__, readable);
|
TRACE("%s: FIONREAD: %d\n", __FUNCTION__, readable);
|
||||||
|
|
||||||
|
if (readable == 0) {
|
||||||
|
release_sem_etc(fDoneWrite, 1, B_DO_NOT_RESCHEDULE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
bytesLeft = MIN(fifoavail, sizeof(buffer));
|
bytesLeft = MIN(fifoavail, sizeof(buffer));
|
||||||
bytesLeft = MIN(bytesLeft, readable);
|
bytesLeft = MIN(bytesLeft, readable);
|
||||||
TRACE("%s: left %d\n", __FUNCTION__, bytesLeft);
|
TRACE("%s: left %d\n", __FUNCTION__, bytesLeft);
|
||||||
@@ -619,6 +627,7 @@ SerialDevice::Write(const char *buffer, size_t *numBytes)
|
|||||||
return B_DEV_NOT_READY;
|
return B_DEV_NOT_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t status;
|
||||||
size_t bytesLeft = *numBytes;
|
size_t bytesLeft = *numBytes;
|
||||||
*numBytes = 0;
|
*numBytes = 0;
|
||||||
|
|
||||||
@@ -629,11 +638,11 @@ SerialDevice::Write(const char *buffer, size_t *numBytes)
|
|||||||
// that isn't a problem, we shouldn't just hardcode the value here.
|
// that isn't a problem, we shouldn't just hardcode the value here.
|
||||||
|
|
||||||
TRACE("%s: tty_write(,&%d)\n", __FUNCTION__, length);
|
TRACE("%s: tty_write(,&%d)\n", __FUNCTION__, length);
|
||||||
status_t result = gTTYModule->tty_write(fSystemTTYCookie, buffer,
|
status = gTTYModule->tty_write(fSystemTTYCookie, buffer,
|
||||||
&length);
|
&length);
|
||||||
if (result != B_OK) {
|
if (status != B_OK) {
|
||||||
TRACE_ALWAYS("failed to write to tty: %s\n", strerror(result));
|
TRACE_ALWAYS("failed to write to tty: %s\n", strerror(status));
|
||||||
return result;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer += length;
|
buffer += length;
|
||||||
@@ -645,6 +654,14 @@ SerialDevice::Write(const char *buffer, size_t *numBytes)
|
|||||||
Service(fMasterTTY, TTYOSTART, NULL, 0);
|
Service(fMasterTTY, TTYOSTART, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = acquire_sem_etc(fDoneWrite, 1, B_CAN_INTERRUPT, 0);
|
||||||
|
if (status != B_OK) {
|
||||||
|
TRACE_ALWAYS("write: failed to get write done sem "
|
||||||
|
"0x%08x\n", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (*numBytes > 0)
|
if (*numBytes > 0)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user