Import Tcl-code 8.6.8
This commit is contained in:
@@ -93,17 +93,12 @@ typedef struct SerialInfo {
|
||||
* threads. */
|
||||
OVERLAPPED osRead; /* OVERLAPPED structure for read operations. */
|
||||
OVERLAPPED osWrite; /* OVERLAPPED structure for write operations */
|
||||
TclPipeThreadInfo *writeTI; /* Thread info structure of writer worker. */
|
||||
HANDLE writeThread; /* Handle to writer thread. */
|
||||
CRITICAL_SECTION csWrite; /* Writer thread synchronisation. */
|
||||
HANDLE evWritable; /* Manual-reset event to signal when the
|
||||
* writer thread has finished waiting for the
|
||||
* current buffer to be written. */
|
||||
HANDLE evStartWriter; /* Auto-reset event used by the main thread to
|
||||
* signal when the writer thread should
|
||||
* attempt to write to the serial. */
|
||||
HANDLE evStopWriter; /* Auto-reset event used by the main thread to
|
||||
* signal when the writer thread should close.
|
||||
*/
|
||||
DWORD writeError; /* An error caused by the last background
|
||||
* write. Set to 0 if no error has been
|
||||
* detected. This word is shared with the
|
||||
@@ -599,7 +594,6 @@ SerialCloseProc(
|
||||
int errorCode, result = 0;
|
||||
SerialInfo *infoPtr, **nextPtrPtr;
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
DWORD exitCode;
|
||||
|
||||
errorCode = 0;
|
||||
|
||||
@@ -609,56 +603,13 @@ SerialCloseProc(
|
||||
}
|
||||
serialPtr->validMask &= ~TCL_READABLE;
|
||||
|
||||
if (serialPtr->validMask & TCL_WRITABLE) {
|
||||
/*
|
||||
* Generally we cannot wait for a pending write operation because it
|
||||
* may hang due to handshake
|
||||
* WaitForSingleObject(serialPtr->evWritable, INFINITE);
|
||||
*/
|
||||
if (serialPtr->writeThread) {
|
||||
|
||||
/*
|
||||
* The thread may have already closed on it's own. Check it's exit
|
||||
* code.
|
||||
*/
|
||||
TclPipeThreadStop(&serialPtr->writeTI, serialPtr->writeThread);
|
||||
|
||||
GetExitCodeThread(serialPtr->writeThread, &exitCode);
|
||||
|
||||
if (exitCode == STILL_ACTIVE) {
|
||||
/*
|
||||
* Set the stop event so that if the writer thread is blocked in
|
||||
* SerialWriterThread on WaitForMultipleEvents, it will exit
|
||||
* cleanly.
|
||||
*/
|
||||
|
||||
SetEvent(serialPtr->evStopWriter);
|
||||
|
||||
/*
|
||||
* Wait at most 20 milliseconds for the writer thread to close.
|
||||
*/
|
||||
|
||||
if (WaitForSingleObject(serialPtr->writeThread,
|
||||
20) == WAIT_TIMEOUT) {
|
||||
/*
|
||||
* Forcibly terminate the background thread as a last resort.
|
||||
* Note that we need to guard against terminating the thread
|
||||
* while it is in the middle of Tcl_ThreadAlert because it
|
||||
* won't be able to release the notifier lock.
|
||||
*/
|
||||
|
||||
Tcl_MutexLock(&serialMutex);
|
||||
|
||||
/* BUG: this leaks memory */
|
||||
TerminateThread(serialPtr->writeThread, 0);
|
||||
|
||||
Tcl_MutexUnlock(&serialMutex);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(serialPtr->writeThread);
|
||||
CloseHandle(serialPtr->osWrite.hEvent);
|
||||
CloseHandle(serialPtr->evWritable);
|
||||
CloseHandle(serialPtr->evStartWriter);
|
||||
CloseHandle(serialPtr->evStopWriter);
|
||||
CloseHandle(serialPtr->writeThread);
|
||||
serialPtr->writeThread = NULL;
|
||||
|
||||
PurgeComm(serialPtr->handle, PURGE_TXABORT | PURGE_TXCLEAR);
|
||||
@@ -1076,7 +1027,7 @@ SerialOutputProc(
|
||||
memcpy(infoPtr->writeBuf, buf, (size_t) toWrite);
|
||||
infoPtr->toWrite = toWrite;
|
||||
ResetEvent(infoPtr->evWritable);
|
||||
SetEvent(infoPtr->evStartWriter);
|
||||
TclPipeThreadSignal(&infoPtr->writeTI);
|
||||
bytesWritten = (DWORD) toWrite;
|
||||
|
||||
} else {
|
||||
@@ -1313,34 +1264,21 @@ static DWORD WINAPI
|
||||
SerialWriterThread(
|
||||
LPVOID arg)
|
||||
{
|
||||
SerialInfo *infoPtr = (SerialInfo *)arg;
|
||||
DWORD bytesWritten, toWrite, waitResult;
|
||||
TclPipeThreadInfo *pipeTI = (TclPipeThreadInfo *)arg;
|
||||
SerialInfo *infoPtr = NULL; /* access info only after success init/wait */
|
||||
DWORD bytesWritten, toWrite;
|
||||
char *buf;
|
||||
OVERLAPPED myWrite; /* Have an own OVERLAPPED in this thread. */
|
||||
HANDLE wEvents[2];
|
||||
|
||||
/*
|
||||
* The stop event takes precedence by being first in the list.
|
||||
*/
|
||||
|
||||
wEvents[0] = infoPtr->evStopWriter;
|
||||
wEvents[1] = infoPtr->evStartWriter;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* Wait for the main thread to signal before attempting to write.
|
||||
*/
|
||||
|
||||
waitResult = WaitForMultipleObjects(2, wEvents, FALSE, INFINITE);
|
||||
|
||||
if (waitResult != (WAIT_OBJECT_0 + 1)) {
|
||||
/*
|
||||
* The start event was not signaled. It might be the stop event or
|
||||
* an error, so exit.
|
||||
*/
|
||||
|
||||
if (!TclPipeThreadWaitForSignal(&pipeTI)) {
|
||||
/* exit */
|
||||
break;
|
||||
}
|
||||
infoPtr = (SerialInfo *)pipeTI->clientData;
|
||||
|
||||
buf = infoPtr->writeBuf;
|
||||
toWrite = infoPtr->toWrite;
|
||||
@@ -1404,6 +1342,9 @@ SerialWriterThread(
|
||||
Tcl_MutexUnlock(&serialMutex);
|
||||
}
|
||||
|
||||
/* Worker exit, so inform the main thread or free TI-structure (if owned) */
|
||||
TclPipeThreadExit(&pipeTI);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1477,7 +1418,6 @@ TclWinOpenSerialChannel(
|
||||
int permissions)
|
||||
{
|
||||
SerialInfo *infoPtr;
|
||||
DWORD id;
|
||||
|
||||
SerialInit();
|
||||
|
||||
@@ -1529,10 +1469,9 @@ TclWinOpenSerialChannel(
|
||||
|
||||
infoPtr->osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
infoPtr->evWritable = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||
infoPtr->evStartWriter = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
infoPtr->evStopWriter = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
infoPtr->writeThread = CreateThread(NULL, 256, SerialWriterThread,
|
||||
infoPtr, 0, &id);
|
||||
TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr,
|
||||
infoPtr->evWritable), 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user