summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/registry.test4
-rw-r--r--unix/tclEpollNotfy.c225
-rw-r--r--unix/tclKqueueNotfy.c231
-rw-r--r--unix/tclSelectNotfy.c125
-rw-r--r--unix/tclUnixNotfy.c52
-rw-r--r--win/Makefile.in4
-rw-r--r--win/makefile.vc2
7 files changed, 337 insertions, 306 deletions
diff --git a/tests/registry.test b/tests/registry.test
index fec4cc0..539ba2d 100644
--- a/tests/registry.test
+++ b/tests/registry.test
@@ -19,7 +19,7 @@ testConstraint reg 0
if {[testConstraint win]} {
if {![catch {
::tcltest::loadTestedCommands
- set ::regver [package require registry 1.3.2]
+ set ::regver [package require registry 1.3.3]
}]} {
testConstraint reg 1
}
@@ -33,7 +33,7 @@ testConstraint english [expr {
test registry-1.0 {check if we are testing the right dll} {win reg} {
set ::regver
-} {1.3.2}
+} {1.3.3}
test registry-1.1 {argument parsing for registry command} {win reg} {
list [catch {registry} msg] $msg
} {1 {wrong # args: should be "registry ?-32bit|-64bit? option ?arg ...?"}}
diff --git a/unix/tclEpollNotfy.c b/unix/tclEpollNotfy.c
index 0350ae0..a8f2a50 100644
--- a/unix/tclEpollNotfy.c
+++ b/unix/tclEpollNotfy.c
@@ -2,8 +2,8 @@
* tclEpollNotfy.c --
*
* This file contains the implementation of the epoll()-based
- * Linux-specific notifier, which is the lowest-level part of the
- * Tcl event loop. This file works together with generic/tclNotify.c.
+ * Linux-specific notifier, which is the lowest-level part of the Tcl
+ * event loop. This file works together with generic/tclNotify.c.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright (c) 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
@@ -13,11 +13,10 @@
*/
#include "tclInt.h"
-#if defined(NOTIFIER_EPOLL) && TCL_THREADS
-
-#define _GNU_SOURCE /* For pipe2(2) */
#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
* in tclMacOSXNotify.c */
+#if defined(NOTIFIER_EPOLL) && TCL_THREADS
+#define _GNU_SOURCE /* For pipe2(2) */
#include <fcntl.h>
#include <signal.h>
#include <sys/epoll.h>
@@ -54,9 +53,9 @@ typedef struct FileHandler {
} FileHandler;
/*
- * The following structure associates a FileHandler and the thread that owns it
- * with the file descriptors of interest and their event masks passed to epoll_ctl(2)
- * and their corresponding event(s) returned by epoll_wait(2).
+ * The following structure associates a FileHandler and the thread that owns
+ * it with the file descriptors of interest and their event masks passed to
+ * epoll_ctl(2) and their corresponding event(s) returned by epoll_wait(2).
*/
struct ThreadSpecificData;
@@ -105,7 +104,8 @@ typedef struct ThreadSpecificData {
int triggerPipe[2]; /* pipe(2) used by other threads to wake
* up this thread for inter-thread IPC. */
#endif /* HAVE_EVENTFD */
- int eventsFd; /* epoll(7) file descriptor used to wait for fds */
+ int eventsFd; /* epoll(7) file descriptor used to wait for
+ * fds */
struct epoll_event *readyEvents;
/* Pointer to at most maxReadyEvents events
* returned by epoll_wait(2). */
@@ -113,13 +113,23 @@ typedef struct ThreadSpecificData {
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
-
-static void PlatformEventsControl(FileHandler *filePtr, ThreadSpecificData *tsdPtr, int op, int isNew);
-static void PlatformEventsFinalize(void);
-static void PlatformEventsInit(void);
-static int PlatformEventsTranslate(struct epoll_event *event);
-static int PlatformEventsWait(struct epoll_event *events, size_t numEvents, struct timeval *timePtr);
-
+
+/*
+ * Forward declarations.
+ */
+
+static void PlatformEventsControl(FileHandler *filePtr,
+ ThreadSpecificData *tsdPtr, int op, int isNew);
+static void PlatformEventsFinalize(void);
+static void PlatformEventsInit(void);
+static int PlatformEventsTranslate(struct epoll_event *event);
+static int PlatformEventsWait(struct epoll_event *events,
+ size_t numEvents, struct timeval *timePtr);
+
+/*
+ * Incorporate the base notifier API.
+ */
+
#include "tclUnixNotfy.c"
/*
@@ -190,31 +200,32 @@ Tcl_FinalizeNotifier(
* This function registers interest for the file descriptor and the mask
* of TCL_* bits associated with filePtr on the epoll file descriptor
* associated with tsdPtr.
- * Future calls to epoll_wait will return filePtr and tsdPtr alongside with
- * the event registered here via the PlatformEventData struct.
+ *
+ * Future calls to epoll_wait will return filePtr and tsdPtr alongside
+ * with the event registered here via the PlatformEventData struct.
*
* Results:
* None.
*
* Side effects:
- * If adding a new file descriptor, a PlatformEventData struct will be
- * allocated and associated with filePtr.
- * fstat is called on the file descriptor; if it is associated with
- * a regular file (S_IFREG,) filePtr is considered to be ready for I/O
- * and added to or deleted from the corresponding list in tsdPtr.
- * If it is not associated with a regular file, the file descriptor is
- * added, modified concerning its mask of events of interest, or deleted
- * from the epoll file descriptor of the calling thread.
+ * - If adding a new file descriptor, a PlatformEventData struct will be
+ * allocated and associated with filePtr.
+ * - fstat is called on the file descriptor; if it is associated with a
+ * regular file (S_IFREG,) filePtr is considered to be ready for I/O
+ * and added to or deleted from the corresponding list in tsdPtr.
+ * - If it is not associated with a regular file, the file descriptor is
+ * added, modified concerning its mask of events of interest, or
+ * deleted from the epoll file descriptor of the calling thread.
*
*----------------------------------------------------------------------
*/
void
PlatformEventsControl(
- FileHandler *filePtr,
- ThreadSpecificData *tsdPtr,
- int op,
- int isNew)
+ FileHandler *filePtr,
+ ThreadSpecificData *tsdPtr,
+ int op,
+ int isNew)
{
struct epoll_event newEvent;
struct PlatformEventData *newPedPtr;
@@ -236,10 +247,10 @@ PlatformEventsControl(
newEvent.data.ptr = filePtr->pedPtr;
/*
- * N.B. As discussed in Tcl_WaitForEvent(), epoll(7) does not sup-
- * port regular files (S_IFREG.) Therefore, filePtr is in these
- * cases simply added or deleted from the list of FileHandlers
- * associated with regular files belonging to tsdPtr.
+ * N.B. As discussed in Tcl_WaitForEvent(), epoll(7) does not support
+ * regular files (S_IFREG.) Therefore, filePtr is in these cases simply
+ * added or deleted from the list of FileHandlers associated with regular
+ * files belonging to tsdPtr.
*/
if (fstat(filePtr->fd, &fdStat) == -1) {
@@ -248,7 +259,8 @@ PlatformEventsControl(
switch (op) {
case EPOLL_CTL_ADD:
if (isNew) {
- LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr, readyNode);
+ LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr,
+ readyNode);
}
break;
case EPOLL_CTL_DEL:
@@ -267,18 +279,18 @@ PlatformEventsControl(
* PlatformEventsFinalize --
*
* This function closes the eventfd and the epoll file descriptor and
- * frees the epoll_event structs owned by the thread of the caller.
- * The above operations are protected by tsdPtr->notifierMutex, which
- * is destroyed thereafter.
+ * frees the epoll_event structs owned by the thread of the caller. The
+ * above operations are protected by tsdPtr->notifierMutex, which is
+ * destroyed thereafter.
*
* Results:
* None.
*
* Side effects:
* While tsdPtr->notifierMutex is held:
- * The per-thread eventfd(2) is closed, if non-zero, and set to -1.
- * The per-thread epoll(7) fd is closed, if non-zero, and set to 0.
- * The per-thread epoll_event structs are freed, if any, and set to 0.
+ * - The per-thread eventfd(2) is closed, if non-zero, and set to -1.
+ * - The per-thread epoll(7) fd is closed, if non-zero, and set to 0.
+ * - The per-thread epoll_event structs are freed, if any, and set to 0.
*
* tsdPtr->notifierMutex is destroyed.
*
@@ -297,7 +309,7 @@ PlatformEventsFinalize(
close(tsdPtr->triggerEventFd);
tsdPtr->triggerEventFd = -1;
}
-#else
+#else /* !HAVE_EVENTFD */
if (tsdPtr->triggerPipe[0]) {
close(tsdPtr->triggerPipe[0]);
tsdPtr->triggerPipe[0] = -1;
@@ -337,20 +349,20 @@ PlatformEventsFinalize(
*
* Side effects:
* The following per-thread entities are initialised:
- * notifierMutex is initialised.
- * The eventfd(2) is created w/ EFD_CLOEXEC and EFD_NONBLOCK.
- * The epoll(7) fd is created w/ EPOLL_CLOEXEC.
- * A FileHandler struct is allocated and initialised for the event-
- * fd(2), registering interest for TCL_READABLE on it via Platform-
- * EventsControl().
- * readyEvents and maxReadyEvents are initialised with 512 epoll_events.
+ * - notifierMutex is initialised.
+ * - The eventfd(2) is created w/ EFD_CLOEXEC and EFD_NONBLOCK.
+ * - The epoll(7) fd is created w/ EPOLL_CLOEXEC.
+ * - A FileHandler struct is allocated and initialised for the
+ * eventfd(2), registering interest for TCL_READABLE on it via
+ * PlatformEventsControl().
+ * - readyEvents and maxReadyEvents are initialised with 512
+ * epoll_events.
*
*----------------------------------------------------------------------
*/
void
-PlatformEventsInit(
- void)
+PlatformEventsInit(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
FileHandler *filePtr;
@@ -361,16 +373,17 @@ PlatformEventsInit(
}
filePtr = Tcl_Alloc(sizeof(*filePtr));
#ifdef HAVE_EVENTFD
- if ((tsdPtr->triggerEventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) <= 0) {
+ tsdPtr->triggerEventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
+ if (tsdPtr->triggerEventFd <= 0) {
Tcl_Panic("Tcl_InitNotifier: %s", "could not create trigger eventfd");
}
filePtr->fd = tsdPtr->triggerEventFd;
-#else
+#else /* !HAVE_EVENTFD */
if (pipe2(tsdPtr->triggerPipe, O_CLOEXEC | O_NONBLOCK) != 0) {
Tcl_Panic("Tcl_InitNotifier: %s", "could not create trigger pipe");
}
filePtr->fd = tsdPtr->triggerPipe[0];
-#endif
+#endif /* HAVE_EVENTFD */
tsdPtr->triggerFilePtr = filePtr;
if ((tsdPtr->eventsFd = epoll_create1(EPOLL_CLOEXEC)) == -1) {
Tcl_Panic("epoll_create1: %s", strerror(errno));
@@ -379,8 +392,8 @@ PlatformEventsInit(
PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_ADD, 1);
if (!tsdPtr->readyEvents) {
tsdPtr->maxReadyEvents = 512;
- tsdPtr->readyEvents = Tcl_Alloc(tsdPtr->maxReadyEvents
- * sizeof(tsdPtr->readyEvents[0]));
+ tsdPtr->readyEvents = Tcl_Alloc(
+ tsdPtr->maxReadyEvents * sizeof(tsdPtr->readyEvents[0]));
}
LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
}
@@ -390,8 +403,8 @@ PlatformEventsInit(
*
* PlatformEventsTranslate --
*
- * This function translates the platform-specific mask of returned
- * events in eventPtr to a mask of TCL_* bits.
+ * This function translates the platform-specific mask of returned events
+ * in eventPtr to a mask of TCL_* bits.
*
* Results:
* Returns the translated mask.
@@ -404,7 +417,7 @@ PlatformEventsInit(
int
PlatformEventsTranslate(
- struct epoll_event *eventPtr)
+ struct epoll_event *eventPtr)
{
int mask;
@@ -429,16 +442,16 @@ PlatformEventsTranslate(
* This function abstracts waiting for I/O events via epoll_wait.
*
* Results:
- * Returns -1 if epoll_wait failed. Returns 0 if polling and if no
- * events became available whilst polling. Returns a pointer to and
- * the count of all returned events in all other cases.
+ * Returns -1 if epoll_wait failed. Returns 0 if polling and if no events
+ * became available whilst polling. Returns a pointer to and the count of
+ * all returned events in all other cases.
*
* Side effects:
- * gettimeofday(2), epoll_wait(2), and gettimeofday(2) are called,
- * in the specified order.
- * If timePtr specifies a positive value, it is updated to reflect
- * the amount of time that has passed; if its value would {under,
- * over}flow, it is set to zero.
+ * gettimeofday(2), epoll_wait(2), and gettimeofday(2) are called, in the
+ * specified order.
+ * If timePtr specifies a positive value, it is updated to reflect the
+ * amount of time that has passed; if its value would {under, over}flow,
+ * it is set to zero.
*
*----------------------------------------------------------------------
*/
@@ -457,8 +470,8 @@ PlatformEventsWait(
/*
* If timePtr is NULL, epoll_wait(2) will wait indefinitely. If it
- * specifies a timeout of {0,0}, epoll_wait(2) will poll. Otherwise,
- * the timeout will simply be converted to milliseconds.
+ * specifies a timeout of {0,0}, epoll_wait(2) will poll. Otherwise, the
+ * timeout will simply be converted to milliseconds.
*/
if (!timePtr) {
@@ -473,9 +486,9 @@ PlatformEventsWait(
}
/*
- * Call (and possibly block on) epoll_wait(2) and substract the delta
- * of gettimeofday(2) before and after the call from timePtr if the
- * latter is not NULL. Return the number of events returned by epoll_wait(2).
+ * Call (and possibly block on) epoll_wait(2) and substract the delta of
+ * gettimeofday(2) before and after the call from timePtr if the latter is
+ * not NULL. Return the number of events returned by epoll_wait(2).
*/
gettimeofday(&tv0, NULL);
@@ -484,10 +497,10 @@ PlatformEventsWait(
if (timePtr && (timePtr->tv_sec && timePtr->tv_usec)) {
timersub(&tv1, &tv0, &tv_delta);
if (!timercmp(&tv_delta, timePtr, >)) {
- timersub(timePtr, &tv_delta, timePtr);
+ timersub(timePtr, &tv_delta, timePtr);
} else {
- timePtr->tv_sec = 0;
- timePtr->tv_usec = 0;
+ timePtr->tv_sec = 0;
+ timePtr->tv_usec = 0;
}
}
return numFound;
@@ -498,8 +511,8 @@ PlatformEventsWait(
*
* Tcl_CreateFileHandler --
*
- * This function registers a file handler with the epoll notifier
- * of the thread of the caller.
+ * This function registers a file handler with the epoll notifier of the
+ * thread of the caller.
*
* Results:
* None.
@@ -551,8 +564,8 @@ Tcl_CreateFileHandler(
filePtr->clientData = clientData;
filePtr->mask = mask;
- PlatformEventsControl(filePtr, tsdPtr, isNew ?
- EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew);
+ PlatformEventsControl(filePtr, tsdPtr,
+ isNew ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew);
}
}
@@ -561,8 +574,8 @@ Tcl_CreateFileHandler(
*
* Tcl_DeleteFileHandler --
*
- * Cancel a previously-arranged callback arrangement for a file on
- * the epoll file descriptor of the thread of the caller.
+ * Cancel a previously-arranged callback arrangement for a file on the
+ * epoll file descriptor of the thread of the caller.
*
* Results:
* None.
@@ -632,6 +645,7 @@ Tcl_DeleteFileHandler(
* This function is called by Tcl_DoOneEvent to wait for new events on
* the message queue. If the block time is 0, then Tcl_WaitForEvent just
* polls without blocking.
+ *
* The waiting logic is implemented in PlatformEventsWait.
*
* Results:
@@ -646,7 +660,7 @@ Tcl_DeleteFileHandler(
int
Tcl_WaitForEvent(
- const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
+ const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
{
if (tclNotifierHooks.waitForEventProc) {
return tclNotifierHooks.waitForEventProc(timePtr);
@@ -696,10 +710,11 @@ Tcl_WaitForEvent(
* Walk the list of FileHandlers associated with regular files
* (S_IFREG) belonging to tsdPtr, queue Tcl events for them, and
* update their mask of events of interest.
+ *
* As epoll(7) does not support regular files, the behaviour of
* {select,poll}(2) is simply simulated here: fds associated with
- * regular files are added to this list by PlatformEventsControl()
- * and processed here before calling (and possibly blocking) on
+ * regular files are added to this list by PlatformEventsControl() and
+ * processed here before calling (and possibly blocking) on
* PlatformEventsWait().
*/
@@ -720,7 +735,7 @@ Tcl_WaitForEvent(
if (filePtr->readyMask == 0) {
FileHandlerEvent *fileEvPtr =
- Tcl_Alloc(sizeof(FileHandlerEvent));
+ Tcl_Alloc(sizeof(FileHandlerEvent));
fileEvPtr->header.proc = FileHandlerEventProc;
fileEvPtr->fd = filePtr->fd;
@@ -731,9 +746,9 @@ Tcl_WaitForEvent(
}
/*
- * If any events were queued in the above loop, force PlatformEvents-
- * Wait() to poll as there already are events that need to be processed
- * at this point.
+ * If any events were queued in the above loop, force
+ * PlatformEventsWait() to poll as there already are events that need
+ * to be processed at this point.
*/
if (numQueued) {
@@ -751,10 +766,12 @@ Tcl_WaitForEvent(
* to facilitate inter-thread IPC. If another thread intends to wake
* up this thread whilst it's blocking on PlatformEventsWait(), it
* write(2)s to the eventfd(2)/trigger pipe (see Tcl_AlertNotifier(),)
- * which in turn will cause PlatformEventsWait() to return immediately.
+ * which in turn will cause PlatformEventsWait() to return
+ * immediately.
*/
- numFound = PlatformEventsWait(tsdPtr->readyEvents, tsdPtr->maxReadyEvents, timeoutPtr);
+ numFound = PlatformEventsWait(tsdPtr->readyEvents,
+ tsdPtr->maxReadyEvents, timeoutPtr);
for (numEvent = 0; numEvent < numFound; numEvent++) {
pedPtr = tsdPtr->readyEvents[numEvent].data.ptr;
filePtr = pedPtr->filePtr;
@@ -762,21 +779,28 @@ Tcl_WaitForEvent(
#ifdef HAVE_EVENTFD
if (filePtr->fd == tsdPtr->triggerEventFd) {
uint64_t eventFdVal;
- i = read(tsdPtr->triggerEventFd, &eventFdVal, sizeof(eventFdVal));
+ i = read(tsdPtr->triggerEventFd, &eventFdVal,
+ sizeof(eventFdVal));
if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) {
-#else
+ Tcl_Panic(
+ "Tcl_WaitForEvent: read from %p->triggerEventFd: %s",
+ (void *) tsdPtr, strerror(errno));
+ }
+ continue;
+ }
+#else /* !HAVE_EVENTFD */
if (filePtr->fd == tsdPtr->triggerPipe[0]) {
char triggerPipeVal;
- i = read(tsdPtr->triggerPipe[0], &triggerPipeVal, sizeof(triggerPipeVal));
+ i = read(tsdPtr->triggerPipe[0], &triggerPipeVal,
+ sizeof(triggerPipeVal));
if ((i != sizeof(triggerPipeVal)) && (errno != EAGAIN)) {
-#endif
- Tcl_Panic("Tcl_WaitForEvent: "
- "read from %p->triggerEventFd: %s",
- (void *)tsdPtr, strerror(errno));
- } else {
- continue;
+ Tcl_Panic(
+ "Tcl_WaitForEvent: read from %p->triggerPipe[0]: %s",
+ (void *) tsdPtr, strerror(errno));
}
+ continue;
}
+#endif /* HAVE_EVENTFD */
if (!mask) {
continue;
}
@@ -800,9 +824,8 @@ Tcl_WaitForEvent(
}
}
+#endif /* NOTIFIER_EPOLL && TCL_THREADS */
#endif /* !HAVE_COREFOUNDATION */
-
-#endif /* NOTIFIER_EPOLL */
/*
* Local Variables:
diff --git a/unix/tclKqueueNotfy.c b/unix/tclKqueueNotfy.c
index bea1b30..bbb8061 100644
--- a/unix/tclKqueueNotfy.c
+++ b/unix/tclKqueueNotfy.c
@@ -14,10 +14,10 @@
*/
#include "tclInt.h"
-#if defined(NOTIFIER_KQUEUE) && TCL_THREADS
-
#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
* in tclMacOSXNotify.c */
+#if defined(NOTIFIER_KQUEUE) && TCL_THREADS
+
#include <signal.h>
#include <sys/types.h>
#include <sys/event.h>
@@ -51,9 +51,9 @@ typedef struct FileHandler {
} FileHandler;
/*
- * The following structure associates a FileHandler and the thread that owns it
- * with the file descriptors of interest and their event masks passed to kevent(2)
- * and their corresponding event(s) returned by kevent(2).
+ * The following structure associates a FileHandler and the thread that owns
+ * it with the file descriptors of interest and their event masks passed to
+ * kevent(2) and their corresponding event(s) returned by kevent(2).
*/
struct ThreadSpecificData;
@@ -96,20 +96,27 @@ typedef struct ThreadSpecificData {
* PlatformEventsFinalize. */
int triggerPipe[2]; /* pipe(2) used by other threads to wake
* up this thread for inter-thread IPC. */
- int eventsFd; /* kqueue(2) file descriptor used to wait for fds. */
+ int eventsFd; /* kqueue(2) file descriptor used to wait for
+ * fds. */
struct kevent *readyEvents; /* Pointer to at most maxReadyEvents events
* returned by kevent(2). */
size_t maxReadyEvents; /* Count of kevents in readyEvents. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
-
-static void PlatformEventsControl(FileHandler *filePtr, ThreadSpecificData *tsdPtr, int op, int isNew);
-static void PlatformEventsFinalize(void);
-static void PlatformEventsInit(void);
-static int PlatformEventsTranslate(struct kevent *eventPtr);
-static int PlatformEventsWait(struct kevent *events, size_t numEvents, struct timeval *timePtr);
-
+
+/*
+ * Forward declarations of internal functions.
+ */
+
+static void PlatformEventsControl(FileHandler *filePtr,
+ ThreadSpecificData *tsdPtr, int op, int isNew);
+static void PlatformEventsFinalize(void);
+static void PlatformEventsInit(void);
+static int PlatformEventsTranslate(struct kevent *eventPtr);
+static int PlatformEventsWait(struct kevent *events,
+ size_t numEvents, struct timeval *timePtr);
+
#include "tclUnixNotfy.c"
/*
@@ -180,6 +187,7 @@ Tcl_FinalizeNotifier(
* This function registers interest for the file descriptor and the mask
* of TCL_* bits associated with filePtr on the kqueue file descriptor
* associated with tsdPtr.
+ *
* Future calls to kevent will return filePtr and tsdPtr alongside with
* the event registered here via the PlatformEventData struct.
*
@@ -187,26 +195,26 @@ Tcl_FinalizeNotifier(
* None.
*
* Side effects:
- * If adding a new file descriptor, a PlatformEventData struct will be
- * allocated and associated with filePtr.
- * fstat is called on the file descriptor; if it is associated with
- * a regular file (S_IFREG,) filePtr is considered to be ready for I/O
- * and added to or deleted from the corresponding list in tsdPtr.
- * If it is not associated with a regular file, the file descriptor is
- * added, modified concerning its mask of events of interest, or deleted
- * from the epoll file descriptor of the calling thread.
- * If deleting a file descriptor, kevent(2) is called twice specifying
- * EVFILT_READ first and then EVFILT_WRITE (see note below.)
+ * - If adding a new file descriptor, a PlatformEventData struct will be
+ * allocated and associated with filePtr.
+ * - fstat is called on the file descriptor; if it is associated with
+ * a regular file (S_IFREG,) filePtr is considered to be ready for I/O
+ * and added to or deleted from the corresponding list in tsdPtr.
+ * - If it is not associated with a regular file, the file descriptor is
+ * added, modified concerning its mask of events of interest, or
+ * deleted from the epoll file descriptor of the calling thread.
+ * - If deleting a file descriptor, kevent(2) is called twice specifying
+ * EVFILT_READ first and then EVFILT_WRITE (see note below.)
*
*----------------------------------------------------------------------
*/
void
PlatformEventsControl(
- FileHandler *filePtr,
- ThreadSpecificData *tsdPtr,
- int op,
- int isNew)
+ FileHandler *filePtr,
+ ThreadSpecificData *tsdPtr,
+ int op,
+ int isNew)
{
int numChanges;
struct kevent changeList[2];
@@ -221,11 +229,11 @@ PlatformEventsControl(
}
/*
- * N.B. As discussed in Tcl_WaitForEvent(), kqueue(2) does not repro-
- * duce the `always ready' {select,poll}(2) behaviour for regular
- * files (S_IFREG) prior to FreeBSD 11.0-RELEASE. Therefore, file-
- * Ptr is in these cases simply added or deleted from the list of
- * FileHandlers associated with regular files belonging to tsdPtr.
+ * N.B. As discussed in Tcl_WaitForEvent(), kqueue(2) does not reproduce
+ * the `always ready' {select,poll}(2) behaviour for regular files
+ * (S_IFREG) prior to FreeBSD 11.0-RELEASE. Therefore, filePtr is in these
+ * cases simply added or deleted from the list of FileHandlers associated
+ * with regular files belonging to tsdPtr.
*/
if (fstat(filePtr->fd, &fdStat) == -1) {
@@ -234,7 +242,8 @@ PlatformEventsControl(
switch (op) {
case EV_ADD:
if (isNew) {
- LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr, readyNode);
+ LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr,
+ readyNode);
}
break;
case EV_DELETE:
@@ -248,38 +257,41 @@ PlatformEventsControl(
switch (op) {
case EV_ADD:
if (filePtr->mask & (TCL_READABLE | TCL_EXCEPTION)) {
- EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd, EVFILT_READ,
- op, 0, 0, filePtr->pedPtr);
+ EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd,
+ EVFILT_READ, op, 0, 0, filePtr->pedPtr);
numChanges++;
}
if (filePtr->mask & TCL_WRITABLE) {
- EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd, EVFILT_WRITE,
- op, 0, 0, filePtr->pedPtr);
+ EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd,
+ EVFILT_WRITE, op, 0, 0, filePtr->pedPtr);
numChanges++;
}
if (numChanges) {
- if (kevent(tsdPtr->eventsFd, changeList, numChanges, NULL, 0, NULL) == -1) {
+ if (kevent(tsdPtr->eventsFd, changeList, numChanges, NULL, 0,
+ NULL) == -1) {
Tcl_Panic("kevent: %s", strerror(errno));
}
}
break;
case EV_DELETE:
/*
- * N.B. kqueue(2) has separate filters for readability and writabi-
- * lity fd events. We therefore need to ensure that fds are
- * ompletely removed from the kqueue(2) fd when deleting.
- * This is exacerbated by changes to filePtr->mask w/o calls
- * to PlatforEventsControl() after e.g. an exec(3) in a child
- * process.
- * As one of these calls can fail, two separate kevent(2) calls
- * are made for EVFILT_{READ,WRITE}.
+ * N.B. kqueue(2) has separate filters for readability and writability
+ * fd events. We therefore need to ensure that fds are ompletely
+ * removed from the kqueue(2) fd when deleting. This is exacerbated
+ * by changes to filePtr->mask w/o calls to PlatforEventsControl()
+ * after e.g. an exec(3) in a child process.
+ *
+ * As one of these calls can fail, two separate kevent(2) calls are
+ * made for EVFILT_{READ,WRITE}.
*/
- EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_READ, op, 0, 0, NULL);
+ EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_READ, op, 0, 0,
+ NULL);
if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1)
&& (errno != ENOENT)) {
Tcl_Panic("kevent: %s", strerror(errno));
}
- EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_WRITE, op, 0, 0, NULL);
+ EV_SET(&changeList[0], (uintptr_t)filePtr->fd, EVFILT_WRITE, op, 0, 0,
+ NULL);
if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1)
&& (errno != ENOENT)) {
Tcl_Panic("kevent: %s", strerror(errno));
@@ -293,10 +305,10 @@ PlatformEventsControl(
*
* PlatformEventsFinalize --
*
- * This function closes the pipe and the kqueue file descriptors
- * and frees the kevent structs owned by the thread of the caller.
- * The above operations are protected by tsdPtr->notifierMutex, which
- * is destroyed thereafter.
+ * This function closes the pipe and the kqueue file descriptors and
+ * frees the kevent structs owned by the thread of the caller. The above
+ * operations are protected by tsdPtr->notifierMutex, which is destroyed
+ * thereafter.
*
* Results:
* None.
@@ -314,7 +326,7 @@ PlatformEventsControl(
void
PlatformEventsFinalize(
- void)
+ void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -346,31 +358,30 @@ PlatformEventsFinalize(
*
* PlatformEventsInit --
*
- * This function abstracts creating a kqueue fd via the kqueue
- * system call and allocating memory for the kevents structs in
- * tsdPtr for the thread of the caller.
+ * This function abstracts creating a kqueue fd via the kqueue system
+ * call and allocating memory for the kevents structs in tsdPtr for the
+ * thread of the caller.
*
* Results:
* None.
*
* Side effects:
* The following per-thread entities are initialised:
- * notifierMutex is initialised.
- * The pipe(2) is created; fcntl(2) is called on both fds to set
- * FD_CLOEXEC and O_NONBLOCK.
- * The kqueue(2) fd is created; fcntl(2) is called on it to set
- * FD_CLOEXEC.
- * A FileHandler struct is allocated and initialised for the event-
- * fd(2), registering interest for TCL_READABLE on it via Platform-
- * EventsControl().
- * readyEvents and maxReadyEvents are initialised with 512 kevents.
-
+ * - notifierMutex is initialised.
+ * - The pipe(2) is created; fcntl(2) is called on both fds to set
+ * FD_CLOEXEC and O_NONBLOCK.
+ * - The kqueue(2) fd is created; fcntl(2) is called on it to set
+ * FD_CLOEXEC.
+ * - A FileHandler struct is allocated and initialised for the event-
+ * fd(2), registering interest for TCL_READABLE on it via Platform-
+ * EventsControl().
+ * - readyEvents and maxReadyEvents are initialised with 512 kevents.
+ *
*----------------------------------------------------------------------
*/
void
-PlatformEventsInit(
- void)
+PlatformEventsInit(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
int i, fdFl;
@@ -404,8 +415,8 @@ PlatformEventsInit(
PlatformEventsControl(filePtr, tsdPtr, EV_ADD, 1);
if (!tsdPtr->readyEvents) {
tsdPtr->maxReadyEvents = 512;
- tsdPtr->readyEvents = Tcl_Alloc(tsdPtr->maxReadyEvents
- * sizeof(tsdPtr->readyEvents[0]));
+ tsdPtr->readyEvents = Tcl_Alloc(
+ tsdPtr->maxReadyEvents * sizeof(tsdPtr->readyEvents[0]));
}
LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
}
@@ -429,7 +440,7 @@ PlatformEventsInit(
int
PlatformEventsTranslate(
- struct kevent *eventPtr)
+ struct kevent *eventPtr)
{
int mask;
@@ -454,20 +465,20 @@ PlatformEventsTranslate(
*
* PlatformEventsWait --
*
- * This function abstracts waiting for I/O events via the kevent
- * system call.
+ * This function abstracts waiting for I/O events via the kevent system
+ * call.
*
* Results:
* Returns -1 if kevent failed. Returns 0 if polling and if no events
- * became available whilst polling. Returns a pointer to and the count
- * of all returned events in all other cases.
+ * became available whilst polling. Returns a pointer to and the count of
+ * all returned events in all other cases.
*
* Side effects:
- * gettimeofday(2), kevent(2), and gettimeofday(2) are called,
- * in the specified order.
- * If timePtr specifies a positive value, it is updated to reflect
- * the amount of time that has passed; if its value would {under,
- * over}flow, it is set to zero.
+ * gettimeofday(2), kevent(2), and gettimeofday(2) are called, in the
+ * specified order.
+ * If timePtr specifies a positive value, it is updated to reflect the
+ * amount of time that has passed; if its value would {under, over}flow,
+ * it is set to zero.
*
*----------------------------------------------------------------------
*/
@@ -485,9 +496,9 @@ PlatformEventsWait(
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
/*
- * If timePtr is NULL, kevent(2) will wait indefinitely. If it speci-
- * fies a timeout of {0,0}, kevent(2) will poll. Otherwise, the time-
- * out will simply be converted to a timespec.
+ * If timePtr is NULL, kevent(2) will wait indefinitely. If it specifies a
+ * timeout of {0,0}, kevent(2) will poll. Otherwise, the timeout will
+ * simply be converted to a timespec.
*/
if (!timePtr) {
@@ -504,20 +515,21 @@ PlatformEventsWait(
/*
* Call (and possibly block on) kevent(2) and substract the delta of
- * gettimeofday(2) before and after the call from timePtr if the latter
- * is not NULL. Return the number of events returned by kevent(2).
+ * gettimeofday(2) before and after the call from timePtr if the latter is
+ * not NULL. Return the number of events returned by kevent(2).
*/
gettimeofday(&tv0, NULL);
- numFound = kevent(tsdPtr->eventsFd, NULL, 0, events, (int)numEvents, timeoutPtr);
+ numFound = kevent(tsdPtr->eventsFd, NULL, 0, events, (int) numEvents,
+ timeoutPtr);
gettimeofday(&tv1, NULL);
if (timePtr && (timePtr->tv_sec && timePtr->tv_usec)) {
timersub(&tv1, &tv0, &tv_delta);
if (!timercmp(&tv_delta, timePtr, >)) {
- timersub(timePtr, &tv_delta, timePtr);
+ timersub(timePtr, &tv_delta, timePtr);
} else {
- timePtr->tv_sec = 0;
- timePtr->tv_usec = 0;
+ timePtr->tv_sec = 0;
+ timePtr->tv_usec = 0;
}
}
return numFound;
@@ -590,8 +602,8 @@ Tcl_CreateFileHandler(
*
* Tcl_DeleteFileHandler --
*
- * Cancel a previously-arranged callback arrangement for a file on
- * the kqueue of the thread of the caller.
+ * Cancel a previously-arranged callback arrangement for a file on the
+ * kqueue of the thread of the caller.
*
* Results:
* None.
@@ -661,6 +673,7 @@ Tcl_DeleteFileHandler(
* This function is called by Tcl_DoOneEvent to wait for new events on
* the message queue. If the block time is 0, then Tcl_WaitForEvent just
* polls without blocking.
+ *
* The waiting logic is implemented in PlatformEventsWait.
*
* Results:
@@ -726,11 +739,13 @@ Tcl_WaitForEvent(
* Walk the list of FileHandlers associated with regular files
* (S_IFREG) belonging to tsdPtr, queue Tcl events for them, and
* update their mask of events of interest.
+ *
* kqueue(2), unlike epoll(7), does support regular files, but
- * EVFILT_READ only `[r]eturns when the file pointer is not at
- * the end of file' as opposed to unconditionally. While FreeBSD
- * 11.0-RELEASE adds support for this mode (NOTE_FILE_POLL,) this
- * is not used for reasons of compatibility.
+ * EVFILT_READ only `[r]eturns when the file pointer is not at the end
+ * of file' as opposed to unconditionally. While FreeBSD 11.0-RELEASE
+ * adds support for this mode (NOTE_FILE_POLL,) this is not used for
+ * reasons of compatibility.
+ *
* Therefore, the behaviour of {select,poll}(2) is simply simulated
* here: fds associated with regular files are added to this list by
* PlatformEventsControl() and processed here before calling (and
@@ -754,7 +769,7 @@ Tcl_WaitForEvent(
if (filePtr->readyMask == 0) {
FileHandlerEvent *fileEvPtr =
- Tcl_Alloc(sizeof(FileHandlerEvent));
+ Tcl_Alloc(sizeof(FileHandlerEvent));
fileEvPtr->header.proc = FileHandlerEventProc;
fileEvPtr->fd = filePtr->fd;
@@ -788,22 +803,19 @@ Tcl_WaitForEvent(
* cause PlatformEventsWait() to return immediately.
*/
- numFound = PlatformEventsWait(tsdPtr->readyEvents, tsdPtr->maxReadyEvents, timeoutPtr);
+ numFound = PlatformEventsWait(tsdPtr->readyEvents,
+ tsdPtr->maxReadyEvents, timeoutPtr);
for (numEvent = 0; numEvent < numFound; numEvent++) {
- pedPtr = (struct PlatformEventData *)tsdPtr->readyEvents[numEvent].udata;
+ pedPtr = (struct PlatformEventData *)
+ tsdPtr->readyEvents[numEvent].udata;
filePtr = pedPtr->filePtr;
mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
if (filePtr->fd == tsdPtr->triggerPipe[0]) {
- do {
- i = read(tsdPtr->triggerPipe[0], buf, 1);
- if ((i == -1) && (errno != EAGAIN)) {
- Tcl_Panic("Tcl_WaitForEvent: "
- "read from %p->triggerPipe: %s",
- (void *)tsdPtr, strerror(errno));
- } else {
- break;
- }
- } while (1);
+ i = read(tsdPtr->triggerPipe[0], buf, 1);
+ if ((i == -1) && (errno != EAGAIN)) {
+ Tcl_Panic("Tcl_WaitForEvent: read from %p->triggerPipe: %s",
+ (void *) tsdPtr, strerror(errno));
+ }
continue;
}
if (!mask) {
@@ -829,9 +841,8 @@ Tcl_WaitForEvent(
}
}
+#endif /* NOTIFIER_KQUEUE && TCL_THREADS */
#endif /* !HAVE_COREFOUNDATION */
-
-#endif /* NOTIFIER_KQUEUE */
/*
* Local Variables:
diff --git a/unix/tclSelectNotfy.c b/unix/tclSelectNotfy.c
index b237307..f77379b 100644
--- a/unix/tclSelectNotfy.c
+++ b/unix/tclSelectNotfy.c
@@ -1,9 +1,9 @@
/*
* tclSelectNotfy.c --
*
- * This file contains the implementation of the select()-based
- * generic Unix notifier, which is the lowest-level part of the
- * Tcl event loop. This file works together with generic/tclNotify.c.
+ * This file contains the implementation of the select()-based generic
+ * Unix notifier, which is the lowest-level part of the Tcl event loop.
+ * This file works together with generic/tclNotify.c.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
*
@@ -12,10 +12,10 @@
*/
#include "tclInt.h"
-#if (!defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)) || !TCL_THREADS
-
#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
* in tclMacOSXNotify.c */
+#if (!defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)) || !TCL_THREADS
+
#include <signal.h>
/*
@@ -94,16 +94,17 @@ typedef struct ThreadSpecificData {
* notifierMutex lock before accessing these
* fields. */
#ifdef __CYGWIN__
- void *event; /* Any other thread alerts a notifier
- * that an event is ready to be processed
- * by sending this event. */
+ void *event; /* Any other thread alerts a notifier that an
+ * event is ready to be processed by sending
+ * this event. */
void *hwnd; /* Messaging window. */
#else /* !__CYGWIN__ */
pthread_cond_t waitCV; /* Any other thread alerts a notifier that an
* event is ready to be processed by signaling
* this condition variable. */
#endif /* __CYGWIN__ */
- int waitCVinitialized; /* Variable to flag initialization of the structure */
+ int waitCVinitialized; /* Variable to flag initialization of the
+ * structure. */
int eventReady; /* True if an event is ready to be processed.
* Used as condition flag together with waitCV
* above. */
@@ -171,12 +172,14 @@ static int notifierThreadRunning = 0;
static pthread_cond_t notifierCV = PTHREAD_COND_INITIALIZER;
/*
- * The pollState bits
- * POLL_WANT is set by each thread before it waits on its condition
- * variable. It is checked by the notifier before it does select.
- * POLL_DONE is set by the notifier if it goes into select after seeing
- * POLL_WANT. The idea is to ensure it tries a select with the
- * same bits the initial thread had set.
+ * The pollState bits:
+ *
+ * POLL_WANT is set by each thread before it waits on its condition variable.
+ * It is checked by the notifier before it does select.
+ *
+ * POLL_DONE is set by the notifier if it goes into select after seeing
+ * POLL_WANT. The idea is to ensure it tries a select with the same bits
+ * the initial thread had set.
*/
#define POLL_WANT 0x1
@@ -196,24 +199,24 @@ static Tcl_ThreadId notifierThread;
#if TCL_THREADS
static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
#if defined(HAVE_PTHREAD_ATFORK)
-static int atForkInit = 0;
-static void AtForkChild(void);
+static int atForkInit = 0;
+static void AtForkChild(void);
#endif /* HAVE_PTHREAD_ATFORK */
#endif /* TCL_THREADS */
-static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
+static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
/*
- * Import of Windows API when building threaded with Cygwin.
+ * Import of critical bits of Windows API when building threaded with Cygwin.
*/
#if defined(__CYGWIN__)
typedef struct {
- void *hwnd;
- unsigned int *message;
- int wParam;
- int lParam;
- int time;
- int x;
+ void *hwnd; /* Messaging window. */
+ unsigned int *message; /* Message payload. */
+ int wParam; /* Event-specific "word" parameter. */
+ int lParam; /* Event-specific "long" parameter. */
+ int time; /* Event timestamp. */
+ int x; /* Event location (where meaningful). */
int y;
} MSG;
@@ -233,8 +236,9 @@ typedef struct {
extern void __stdcall CloseHandle(void *);
extern void *__stdcall CreateEventW(void *, unsigned char, unsigned char,
void *);
-extern void * __stdcall CreateWindowExW(void *, const void *, const void *,
- DWORD, int, int, int, int, void *, void *, void *, void *);
+extern void *__stdcall CreateWindowExW(void *, const void *, const void *,
+ DWORD, int, int, int, int, void *, void *, void *,
+ void *);
extern DWORD __stdcall DefWindowProcW(void *, int, void *, void *);
extern unsigned char __stdcall DestroyWindow(void *);
extern int __stdcall DispatchMessageW(const MSG *);
@@ -336,7 +340,6 @@ Tcl_InitNotifier(void)
#endif /* HAVE_PTHREAD_ATFORK */
notifierCount++;
-
pthread_mutex_unlock(&notifierInitMutex);
#endif /* TCL_THREADS */
@@ -381,28 +384,25 @@ Tcl_FinalizeNotifier(
* pipe and wait for the background thread to terminate.
*/
- if (notifierCount == 0) {
+ if (notifierCount == 0 && triggerPipe != -1) {
+ if (write(triggerPipe, "q", 1) != 1) {
+ Tcl_Panic("Tcl_FinalizeNotifier: %s",
+ "unable to write 'q' to triggerPipe");
+ }
+ close(triggerPipe);
+ pthread_mutex_lock(&notifierMutex);
+ while(triggerPipe != -1) {
+ pthread_cond_wait(&notifierCV, &notifierMutex);
+ }
+ pthread_mutex_unlock(&notifierMutex);
+ if (notifierThreadRunning) {
+ int result = pthread_join((pthread_t) notifierThread, NULL);
- if (triggerPipe != -1) {
- if (write(triggerPipe, "q", 1) != 1) {
+ if (result) {
Tcl_Panic("Tcl_FinalizeNotifier: %s",
- "unable to write q to triggerPipe");
- }
- close(triggerPipe);
- pthread_mutex_lock(&notifierMutex);
- while(triggerPipe != -1) {
- pthread_cond_wait(&notifierCV, &notifierMutex);
- }
- pthread_mutex_unlock(&notifierMutex);
- if (notifierThreadRunning) {
- int result = pthread_join((pthread_t) notifierThread, NULL);
-
- if (result) {
- Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier "
- "thread");
- }
- notifierThreadRunning = 0;
+ "unable to join notifier thread");
}
+ notifierThreadRunning = 0;
}
}
@@ -645,7 +645,7 @@ Tcl_WaitForEvent(
# ifdef __CYGWIN__
MSG msg;
# endif /* __CYGWIN__ */
-#else
+#else /* !TCL_THREADS */
/*
* Impl. notes: timeout & timeoutPtr are used if, and only if threads
* are not enabled. They are the arguments for the regular select()
@@ -771,18 +771,19 @@ Tcl_WaitForEvent(
MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
pthread_mutex_lock(&notifierMutex);
}
-#else
+#else /* !__CYGWIN__ */
if (timePtr != NULL) {
- Tcl_Time now;
- struct timespec ptime;
+ Tcl_Time now;
+ struct timespec ptime;
- Tcl_GetTime(&now);
- ptime.tv_sec = timePtr->sec + now.sec + (timePtr->usec + now.usec) / 1000000;
- ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
+ Tcl_GetTime(&now);
+ ptime.tv_sec = timePtr->sec + now.sec +
+ (timePtr->usec + now.usec) / 1000000;
+ ptime.tv_nsec = 1000 * ((timePtr->usec + now.usec) % 1000000);
- pthread_cond_timedwait(&tsdPtr->waitCV, &notifierMutex, &ptime);
+ pthread_cond_timedwait(&tsdPtr->waitCV, &notifierMutex, &ptime);
} else {
- pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
+ pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
}
#endif /* __CYGWIN__ */
}
@@ -830,8 +831,7 @@ Tcl_WaitForEvent(
"unable to write to triggerPipe");
}
}
-
-#else
+#else /* !TCL_THREADS */
tsdPtr->readyMasks = tsdPtr->checkMasks;
numFound = select(tsdPtr->numFdBits, &tsdPtr->readyMasks.readable,
&tsdPtr->readyMasks.writable, &tsdPtr->readyMasks.exception,
@@ -892,8 +892,6 @@ Tcl_WaitForEvent(
}
}
-#if TCL_THREADS
-
/*
*----------------------------------------------------------------------
*
@@ -918,6 +916,7 @@ Tcl_WaitForEvent(
*----------------------------------------------------------------------
*/
+#if TCL_THREADS
static TCL_NORETURN void
NotifierThreadProc(
ClientData clientData) /* Not used. */
@@ -1101,12 +1100,10 @@ NotifierThreadProc(
TclpThreadExit(0);
}
-
#endif /* TCL_THREADS */
-
+
+#endif /* (!NOTIFIER_EPOLL && !NOTIFIER_KQUEUE) || !TCL_THREADS */
#endif /* !HAVE_COREFOUNDATION */
-
-#endif /* !NOTIFIER_EPOLL && !NOTIFIER_KQUEUE */
/*
* Local Variables:
diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c
index fb7e569..3817071 100644
--- a/unix/tclUnixNotfy.c
+++ b/unix/tclUnixNotfy.c
@@ -18,7 +18,7 @@
* Static routines defined in this file.
*/
-static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
+static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
#if !TCL_THREADS
# undef NOTIFIER_EPOLL
# undef NOTIFIER_KQUEUE
@@ -27,7 +27,7 @@ static int FileHandlerEventProc(Tcl_Event *evPtr, int flags);
# define NOTIFIER_SELECT
static TCL_NORETURN void NotifierThreadProc(ClientData clientData);
# if defined(HAVE_PTHREAD_ATFORK)
-static void AtForkChild(void);
+static void AtForkChild(void);
# endif /* HAVE_PTHREAD_ATFORK */
/*
@@ -120,7 +120,7 @@ Tcl_AlertNotifier(
# endif /* __CYGWIN__ */
pthread_mutex_unlock(&notifierMutex);
#endif /* TCL_THREADS */
-#else
+#else /* !NOTIFIER_SELECT */
ThreadSpecificData *tsdPtr = clientData;
#if defined(NOTIFIER_EPOLL) && defined(HAVE_EVENTFD)
uint64_t eventFdVal = 1;
@@ -128,12 +128,13 @@ Tcl_AlertNotifier(
sizeof(eventFdVal)) != sizeof(eventFdVal)) {
Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerEventFd",
(void *)tsdPtr);
+ }
#else
if (write(tsdPtr->triggerPipe[1], "", 1) != 1) {
Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerPipe",
(void *)tsdPtr);
-#endif /* NOTIFIER_EPOLL && HAVE_EVENTFD */
}
+#endif /* NOTIFIER_EPOLL && HAVE_EVENTFD */
#endif /* NOTIFIER_SELECT */
}
}
@@ -301,15 +302,15 @@ FileHandlerEventProc(
static void
AlertSingleThread(
- ThreadSpecificData *tsdPtr)
+ ThreadSpecificData *tsdPtr)
{
tsdPtr->eventReady = 1;
if (tsdPtr->onList) {
/*
- * Remove the ThreadSpecificData structure of this thread
- * from the waiting list. This prevents us from
- * continuously spinning on epoll_wait until the other
- * threads runs and services the file event.
+ * Remove the ThreadSpecificData structure of this thread from the
+ * waiting list. This prevents us from continuously spinning on
+ * epoll_wait until the other threads runs and services the file
+ * event.
*/
if (tsdPtr->prevPtr) {
@@ -326,7 +327,7 @@ AlertSingleThread(
}
#ifdef __CYGWIN__
PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
-#else /* __CYGWIN__ */
+#else /* !__CYGWIN__ */
pthread_cond_broadcast(&tsdPtr->waitCV);
#endif /* __CYGWIN__ */
}
@@ -359,9 +360,10 @@ AtForkChild(void)
pthread_cond_init(&notifierCV, NULL);
/*
- * notifierThreadRunning == 1: thread is running, (there might be data in notifier lists)
+ * notifierThreadRunning == 1: thread is running, (there might be data in
+ * notifier lists)
* atForkInit == 0: InitNotifier was never called
- * notifierCount != 0: unbalanced InitNotifier() / FinalizeNotifier calls
+ * notifierCount != 0: unbalanced InitNotifier() / FinalizeNotifier calls
* waitingListPtr != 0: there are threads currently waiting for events.
*/
@@ -382,8 +384,8 @@ AtForkChild(void)
waitingListPtr = NULL;
/*
- * The tsdPtr from before the fork is copied as well. But since
- * we are paranoic, we don't trust its condvar and reset it.
+ * The tsdPtr from before the fork is copied as well. But since we
+ * are paranoic, we don't trust its condvar and reset it.
*/
#ifdef __CYGWIN__
DestroyWindow(tsdPtr->hwnd);
@@ -391,10 +393,10 @@ AtForkChild(void)
className, 0, 0, 0, 0, 0, NULL, NULL,
TclWinGetTclInstance(), NULL);
ResetEvent(tsdPtr->event);
-#else
+#else /* !__CYGWIN__ */
pthread_cond_destroy(&tsdPtr->waitCV);
pthread_cond_init(&tsdPtr->waitCV, NULL);
-#endif
+#endif /* __CYGWIN__ */
/*
* In case, we had multiple threads running before the fork,
@@ -465,8 +467,8 @@ TclUnixWaitForFile(
if (timeout > 0) {
Tcl_GetTime(&now);
- abortTime.sec = now.sec + timeout/1000;
- abortTime.usec = now.usec + (timeout%1000)*1000;
+ abortTime.sec = now.sec + timeout / 1000;
+ abortTime.usec = now.usec + (timeout % 1000) * 1000;
if (abortTime.usec >= 1000000) {
abortTime.usec -= 1000000;
abortTime.sec += 1;
@@ -501,7 +503,7 @@ TclUnixWaitForFile(
* become ready or a timeout to occur.
*/
- while (1) {
+ do {
if (timeout > 0) {
blockTime.tv_sec = abortTime.sec - now.sec;
blockTime.tv_usec = abortTime.usec - now.usec;
@@ -524,9 +526,9 @@ TclUnixWaitForFile(
} else if (!timeoutPtr->tv_sec && !timeoutPtr->tv_usec) {
pollTimeout = 0;
} else {
- pollTimeout = (int)timeoutPtr->tv_sec * 1000;
+ pollTimeout = (int) timeoutPtr->tv_sec * 1000;
if (timeoutPtr->tv_usec) {
- pollTimeout += ((int)timeoutPtr->tv_usec / 1000);
+ pollTimeout += (int) timeoutPtr->tv_usec / 1000;
}
}
numFound = poll(pollFds, 1, pollTimeout);
@@ -557,13 +559,11 @@ TclUnixWaitForFile(
*/
Tcl_GetTime(&now);
- if ((abortTime.sec < now.sec)
- || (abortTime.sec==now.sec && abortTime.usec<=now.usec)) {
- break;
- }
- }
+ } while ((abortTime.sec > now.sec)
+ || (abortTime.sec == now.sec && abortTime.usec > now.usec));
return result;
}
+
#endif /* !HAVE_COREFOUNDATION */
/*
diff --git a/win/Makefile.in b/win/Makefile.in
index 6a09343..24158f4 100644
--- a/win/Makefile.in
+++ b/win/Makefile.in
@@ -869,7 +869,7 @@ test-tcl: binaries $(TCLSH) $(CAT32) $(TEST_DLL_FILE)
-load "package ifneeded Tcltest ${VERSION}@TCL_PATCH_LEVEL@ [list load [file normalize ${TEST_DLL_FILE}] Tcltest]; \
package ifneeded tcltests 0.1 \"[list source [file normalize $(ROOT_DIR_NATIVE)/tests/tcltests.tcl]];package provide tcltests 0.1\"; \
package ifneeded dde 1.4.0 [list load [file normalize ${DDE_DLL_FILE}] dde]; \
- package ifneeded registry 1.3.2 [list load [file normalize ${REG_DLL_FILE}] registry]" | $(WINE) ./$(CAT32)
+ package ifneeded registry 1.3.3 [list load [file normalize ${REG_DLL_FILE}] registry]" | $(WINE) ./$(CAT32)
# Useful target to launch a built tclsh with the proper path,...
runtest: binaries $(TCLSH) $(TEST_DLL_FILE)
@@ -877,7 +877,7 @@ runtest: binaries $(TCLSH) $(TEST_DLL_FILE)
$(WINE) ./$(TCLSH) $(TESTFLAGS) -load "package ifneeded Tcltest ${VERSION}@TCL_PATCH_LEVEL@ [list load [file normalize ${TEST_DLL_FILE}] Tcltest]; \
package ifneeded tcltests 0.1 \"[list source [file normalize $(ROOT_DIR_NATIVE)/tests/tcltests.tcl]];package provide tcltests 0.1\"; \
package ifneeded dde 1.4.0 [list load [file normalize ${DDE_DLL_FILE}] dde]; \
- package ifneeded registry 1.3.2 [list load [file normalize ${REG_DLL_FILE}] registry]" $(SCRIPT)
+ package ifneeded registry 1.3.3 [list load [file normalize ${REG_DLL_FILE}] registry]" $(SCRIPT)
# This target can be used to run tclsh from the build directory via
# `make shell SCRIPT=foo.tcl`
diff --git a/win/makefile.vc b/win/makefile.vc
index 824d8e3..8c5e93d 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -393,7 +393,7 @@ test-core: setup $(TCLTEST) dlls
set TCL_LIBRARY=$(ROOT:\=/)/library
$(DEBUGGER) $(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile <<
package ifneeded dde 1.4.0 [list load "$(TCLDDELIB:\=/)" dde]
- package ifneeded registry 1.3.2 [list load "$(TCLREGLIB:\=/)" registry]
+ package ifneeded registry 1.3.3 [list load "$(TCLREGLIB:\=/)" registry]
<<
runtest: setup $(TCLTEST) dlls