summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2021-06-10 10:59:50 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2021-06-10 10:59:50 (GMT)
commit179a97b763c7f1ea393680661106815915cef816 (patch)
treec19f3c038ede7c5bc881a391d81f2bf2e719a695 /unix
parent552e9c654253de9ba497a6f05f41ef13cf93d82a (diff)
parentf271e62139957e6137efb528670436c4a9393818 (diff)
downloadtcl-179a97b763c7f1ea393680661106815915cef816.zip
tcl-179a97b763c7f1ea393680661106815915cef816.tar.gz
tcl-179a97b763c7f1ea393680661106815915cef816.tar.bz2
Merge 8.7
Diffstat (limited to 'unix')
-rw-r--r--unix/Makefile.in57
-rwxr-xr-xunix/configure46
-rw-r--r--unix/configure.ac8
-rw-r--r--unix/dltest/pkgooa.c7
-rw-r--r--unix/dltest/pkgua.c53
-rw-r--r--unix/tcl.m431
-rw-r--r--unix/tclAppInit.c15
-rw-r--r--unix/tclEpollNotfy.c461
-rw-r--r--unix/tclKqueueNotfy.c473
-rw-r--r--unix/tclLoadDyld.c6
-rw-r--r--unix/tclLoadNext.c2
-rw-r--r--unix/tclLoadOSF.c4
-rw-r--r--unix/tclLoadShl.c2
-rw-r--r--unix/tclSelectNotfy.c779
-rw-r--r--unix/tclUnixChan.c13
-rw-r--r--unix/tclUnixCompat.c3
-rw-r--r--unix/tclUnixEvent.c4
-rw-r--r--unix/tclUnixFCmd.c2
-rw-r--r--unix/tclUnixFile.c4
-rw-r--r--unix/tclUnixNotfy.c141
-rw-r--r--unix/tclUnixPort.h2
-rw-r--r--unix/tclUnixTime.c51
-rw-r--r--unix/tclXtNotify.c8
-rw-r--r--unix/tclXtTest.c3
24 files changed, 1079 insertions, 1096 deletions
diff --git a/unix/Makefile.in b/unix/Makefile.in
index 00e29be..79dad02 100644
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -209,7 +209,7 @@ TCL_LIB_FLAG = @TCL_LIB_FLAG@
#TCL_LIB_FLAG = -ltcl
# support for embedded libraries on Darwin / Mac OS X
-DYLIB_INSTALL_DIR = ${LIB_RUNTIME_DIR}
+DYLIB_INSTALL_DIR = $(libdir)
#--------------------------------------------------------------------------
# The information below is modified by the configure script when Makefile is
@@ -268,6 +268,7 @@ TRACE_OPTS =
VALGRIND = valgrind
VALGRINDARGS = --tool=memcheck --num-callers=24 \
--leak-resolution=high --leak-check=yes --show-reachable=yes -v \
+ --keep-debuginfo=yes \
--suppressions=$(TOOL_DIR)/valgrind_suppress
#--------------------------------------------------------------------------
@@ -671,7 +672,8 @@ UNIX_SRCS = \
NOTIFY_SRCS = \
$(UNIX_DIR)/tclEpollNotfy.c \
$(UNIX_DIR)/tclKqueueNotfy.c \
- $(UNIX_DIR)/tclSelectNotfy.c
+ $(UNIX_DIR)/tclSelectNotfy.c \
+ $(UNIX_DIR)/tclUnixNotfy.c
DL_SRCS = \
$(UNIX_DIR)/tclLoadAix.c \
@@ -727,6 +729,7 @@ HOST_CC = @CC_FOR_BUILD@
HOST_EXEEXT = @EXEEXT_FOR_BUILD@
HOST_OBJEXT = @OBJEXT_FOR_BUILD@
ZIPFS_BUILD = @ZIPFS_BUILD@
+MACHER = @MACHER_PROG@
NATIVE_ZIP = @ZIP_PROG@
ZIP_PROG_OPTIONS = @ZIP_PROG_OPTIONS@
ZIP_PROG_VFSSEARCH = @ZIP_PROG_VFSSEARCH@
@@ -777,7 +780,7 @@ ${TCL_ZIP_FILE}: ${ZIP_INSTALL_OBJS}
cp -a $(TOP_DIR)/library/* ${TCL_VFS_PATH}; \
fi
mv ${TCL_VFS_PATH}/manifest.txt ${TCL_VFS_PATH}/pkgIndex.tcl
- rm -rf ${TCL_VFS_PATH}/dde ${TCL_VFS_PATH}/reg
+ rm -rf ${TCL_VFS_PATH}/dde ${TCL_VFS_PATH}/registry
@find ${TCL_VFS_ROOT} -type d -empty -delete
@echo "creating ${TCL_ZIP_FILE} from ${TCL_VFS_PATH}"
@(zip=`(realpath '${NATIVE_ZIP}' || readlink -m '${NATIVE_ZIP}' || \
@@ -792,7 +795,11 @@ ${LIB_FILE}: ${STUB_LIB_FILE} ${OBJS} ${TCL_ZIP_FILE}
rm -f $@
@MAKE_LIB@
@if test "${ZIPFS_BUILD}" = "1" ; then \
+ if test "x$(MACHER)" = "x" ; then \
cat ${TCL_ZIP_FILE} >> ${LIB_FILE}; \
+ else $(MACHER) append ${LIB_FILE} ${TCL_ZIP_FILE} /tmp/macher_output; \
+ mv /tmp/macher_output ${LIB_FILE}; chmod u+x ${LIB_FILE}; \
+ fi; \
${NATIVE_ZIP} -A ${LIB_FILE} \
|| echo 'ignore zip-error by adjust sfx process (not executable?)'; \
fi
@@ -819,7 +826,11 @@ ${TCL_EXE}: ${TCLSH_OBJS} ${TCL_LIB_FILE} ${TCL_STUB_LIB_FILE} ${TCL_ZIP_FILE}
@TCL_BUILD_LIB_SPEC@ ${TCL_STUB_LIB_FILE} ${LIBS} @EXTRA_TCLSH_LIBS@ \
${CC_SEARCH_FLAGS} -o ${TCL_EXE}
@if test "${ZIPFS_BUILD}" = "2" ; then \
+ if test "x$(MACHER)" = "x" ; then \
cat ${TCL_ZIP_FILE} >> ${TCL_EXE}; \
+ else $(MACHER) append ${TCL_EXE} ${TCL_ZIP_FILE} /tmp/macher_output; \
+ mv /tmp/macher_output ${TCL_EXE}; chmod u+x ${TCL_EXE}; \
+ fi; \
${NATIVE_ZIP} -A ${TCL_EXE} \
|| echo 'ignore zip-error by adjust sfx process (not executable?)'; \
fi
@@ -892,18 +903,13 @@ test-tcl: ${TCLTEST_EXE}
$(SHELL_ENV) ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl $(TESTFLAGS)
gdb-test: ${TCLTEST_EXE}
- @echo "set env @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}" > gdb.run
- @echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
- @echo "set args $(TOP_DIR)/tests/all.tcl $(TESTFLAGS) -singleproc 1" >> gdb.run
- $(GDB) ./${TCLTEST_EXE} --command=gdb.run
- @rm gdb.run
+ $(SHELL_ENV) $(GDB) --args ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl \
+ $(TESTFLAGS) -singleproc 1
lldb-test: ${TCLTEST_EXE}
- @echo "settings set target.env-vars @LD_LIBRARY_PATH_VAR@=`pwd`:$${@LD_LIBRARY_PATH_VAR@}" > lldb.run
- @echo "settings set target.env-vars TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> lldb.run
- $(LLDB) --source lldb.run ./${TCLTEST_EXE} -- $(TOP_DIR)/tests/all.tcl \
+ $(SHELL_ENV) $(LLDB) -- ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl \
$(TESTFLAGS) -singleproc 1
- @rm lldb.run
+
# Useful target to launch a built tcltest with the proper path,...
runtest: ${TCLTEST_EXE}
@@ -936,6 +942,9 @@ shell: ${TCL_EXE}
gdb: ${TCL_EXE}
$(SHELL_ENV) $(GDB) ./${TCL_EXE}
+lldb: ${TCL_EXE}
+ $(SHELL_ENV) $(LLDB) ./${TCL_EXE}
+
valgrind: ${TCL_EXE} ${TCLTEST_EXE}
$(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCLTEST_EXE} \
$(TOP_DIR)/tests/all.tcl -singleproc 1 -constraints valgrind \
@@ -1030,9 +1039,9 @@ install-libraries: libraries
@for i in $(TOP_DIR)/library/cookiejar/*.gz; do \
$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \
done
- @echo "Installing package http 2.10.0a1 as a Tcl Module"
+ @echo "Installing package http 2.10a1 as a Tcl Module"
@$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl \
- "$(MODULE_INSTALL_DIR)/8.6/http-2.10.0a1.tm"
+ "$(MODULE_INSTALL_DIR)/8.6/http-2.10a1.tm"
@echo "Installing package opt 0.4.7"
@for i in $(TOP_DIR)/library/opt/*.tcl; do \
$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
@@ -1514,7 +1523,6 @@ tclZipfs.o: $(GENERIC_DIR)/tclZipfs.c
$(CC) -c $(CC_SWITCHES) \
-DCFG_RUNTIME_DLLFILE="\"$(TCL_LIB_FILE)\"" \
-DCFG_RUNTIME_LIBDIR="\"$(libdir)\"" \
- -DCFG_RUNTIME_SCRDIR="\"$(TCL_LIBRARY)\"" \
-I$(ZLIB_DIR) -I$(ZLIB_DIR)/contrib/minizip \
$(GENERIC_DIR)/tclZipfs.c
@@ -1761,13 +1769,13 @@ tclUnixFCmd.o: $(UNIX_DIR)/tclUnixFCmd.c
tclUnixFile.o: $(UNIX_DIR)/tclUnixFile.c $(FSHDR)
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclUnixFile.c
-tclEpollNotfy.o: $(UNIX_DIR)/tclEpollNotfy.c
+tclEpollNotfy.o: $(UNIX_DIR)/tclEpollNotfy.c $(UNIX_DIR)/tclUnixNotfy.c
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclEpollNotfy.c
-tclKqueueNotfy.o: $(UNIX_DIR)/tclKqueueNotfy.c
+tclKqueueNotfy.o: $(UNIX_DIR)/tclKqueueNotfy.c $(UNIX_DIR)/tclUnixNotfy.c
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclKqueueNotfy.c
-tclSelectNotfy.o: $(UNIX_DIR)/tclSelectNotfy.c
+tclSelectNotfy.o: $(UNIX_DIR)/tclSelectNotfy.c $(UNIX_DIR)/tclUnixNotfy.c
$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclSelectNotfy.c
tclUnixPipe.o: $(UNIX_DIR)/tclUnixPipe.c
@@ -2209,7 +2217,7 @@ DISTROOT = /tmp/dist
DISTNAME = tcl${VERSION}${PATCH_LEVEL}
ZIPNAME = tcl${MAJOR_VERSION}${MINOR_VERSION}${PATCH_LEVEL}-src.zip
DISTDIR = $(DISTROOT)/$(DISTNAME)
-BUILTIN_PACKAGE_LIST = cookiejar http opt msgcat reg dde tcltest platform
+BUILTIN_PACKAGE_LIST = cookiejar http opt msgcat registry dde tcltest platform
$(UNIX_DIR)/configure: $(UNIX_DIR)/configure.ac $(UNIX_DIR)/tcl.m4 \
$(UNIX_DIR)/aclocal.m4
@@ -2256,7 +2264,7 @@ dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in gen
mkdir $(DISTDIR)/library/$$i;\
cp -p $(TOP_DIR)/library/$$i/*.tcl $(DISTDIR)/library/$$i; \
done
- cp -p $(TOP_DIR)/library/cookiejar/*.txt.gz $(DISTDIR)/library/cookiejar
+ cp -p $(TOP_DIR)/library/cookiejar/*.dat.gz $(DISTDIR)/library/cookiejar
@mkdir $(DISTDIR)/library/encoding
cp -p $(TOP_DIR)/library/encoding/*.enc $(DISTDIR)/library/encoding
@mkdir $(DISTDIR)/library/msgs
@@ -2276,11 +2284,16 @@ dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in gen
@( cd $(COMPAT_DIR)/zlib; find . -type f -print ) \
| ( cd $(COMPAT_DIR)/zlib ; xargs tar cf - ) \
| ( cd $(DISTDIR)/compat/zlib ; tar xfp - )
+ @mkdir $(DISTDIR)/libtommath
+ @echo cp -r $(TOP_DIR)/libtommath $(DISTDIR)/libtommath
+ @( cd $(TOP_DIR)/libtommath; find . -type f -print ) \
+ | ( cd $(TOP_DIR)/libtommath ; xargs tar cf - ) \
+ | ( cd $(DISTDIR)/libtommath ; tar xfp - )
@mkdir $(DISTDIR)/tests
cp -p $(TOP_DIR)/license.terms $(DISTDIR)/tests
cp -p $(TOP_DIR)/tests/*.test $(TOP_DIR)/tests/README \
$(TOP_DIR)/tests/httpd $(TOP_DIR)/tests/*.tcl \
- $(DISTDIR)/tests
+ $(TOP_DIR)/tests/auto-files.zip $(DISTDIR)/tests
@mkdir $(DISTDIR)/tests/auto0
for i in auto1 auto2 ; \
do \
@@ -2329,8 +2342,6 @@ dist: $(UNIX_DIR)/configure $(UNIX_DIR)/tclConfig.h.in $(UNIX_DIR)/tcl.pc.in gen
cp -p $(TOOL_DIR)/README $(TOOL_DIR)/*.c $(TOOL_DIR)/*.svg \
$(TOOL_DIR)/*.tcl $(TOOL_DIR)/*.bmp \
$(TOOL_DIR)/valgrind_suppress $(DISTDIR)/tools
- @mkdir $(DISTDIR)/libtommath
- cp -p $(TOMMATH_SRCS) $(TOMMATH_DIR)/*.h $(DISTDIR)/libtommath
@mkdir $(DISTDIR)/pkgs
cp -p $(TOP_DIR)/pkgs/README $(DISTDIR)/pkgs
cp -p $(TOP_DIR)/pkgs/package.list.txt $(DISTDIR)/pkgs
diff --git a/unix/configure b/unix/configure
index 50a035b..dbfb800 100755
--- a/unix/configure
+++ b/unix/configure
@@ -698,6 +698,7 @@ ZIP_INSTALL_OBJS
ZIP_PROG_VFSSEARCH
ZIP_PROG_OPTIONS
ZIP_PROG
+MACHER_PROG
EXEEXT_FOR_BUILD
CC_FOR_BUILD
DTRACE
@@ -7203,12 +7204,12 @@ then :
AIX-*) ;;
BSD/OS*) ;;
CYGWIN_*|MINGW32_*|MSYS_*) ;;
- HP_UX*) ;;
+ HP-UX*) ;;
Darwin-*) ;;
IRIX*) ;;
Linux*|GNU*) ;;
- NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
- OSF1-V*) ;;
+ NetBSD-*|OpenBSD-*) ;;
+ OSF1-*) ;;
SCO_SV-3.2*) ;;
*) SHLIB_CFLAGS="-fPIC" ;;
esac
@@ -11097,11 +11098,41 @@ printf "%s\n" "$bfd_cv_build_exeext" >&6; }
# Find a native zip implementation
#
+ MACHER_PROG=""
ZIP_PROG=""
ZIP_PROG_OPTIONS=""
ZIP_PROG_VFSSEARCH=""
ZIP_INSTALL_OBJS=""
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for macher" >&5
+printf %s "checking for macher... " >&6; }
+ if test ${ac_cv_path_macher+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ search_path=`echo ${PATH} | sed -e 's/:/ /g'`
+ for dir in $search_path ; do
+ for j in `ls -r $dir/macher 2> /dev/null` \
+ `ls -r $dir/macher 2> /dev/null` ; do
+ if test x"$ac_cv_path_macher" = x ; then
+ if test -f "$j" ; then
+ ac_cv_path_macher=$j
+ break
+ fi
+ fi
+ done
+ done
+
+fi
+
+ if test -f "$ac_cv_path_macher" ; then
+ MACHER_PROG="$ac_cv_path_macher"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MACHER_PROG" >&5
+printf "%s\n" "$MACHER_PROG" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Found macher in environment" >&5
+printf "%s\n" "Found macher in environment" >&6; }
+ fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zip" >&5
printf %s "checking for zip... " >&6; }
if test ${ac_cv_path_zip+y}
@@ -11148,11 +11179,12 @@ printf "%s\n" "No zip found on PATH. Building minizip" >&6; }
- ZIPFS_BUILD=1
- TCL_ZIP_FILE=libtcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_PATCH_LEVEL}.zip
+
+ ZIPFS_BUILD=1
+ TCL_ZIP_FILE=libtcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_PATCH_LEVEL}.zip
else
- ZIPFS_BUILD=0
- TCL_ZIP_FILE=
+ ZIPFS_BUILD=0
+ TCL_ZIP_FILE=
fi
# Do checking message here to not mess up interleaved configure output
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for building with zipfs" >&5
diff --git a/unix/configure.ac b/unix/configure.ac
index edf5f6d..067fc70 100644
--- a/unix/configure.ac
+++ b/unix/configure.ac
@@ -887,11 +887,11 @@ if test "$tcl_ok" = "yes" -a "x$enable_framework" != "xyes"; then
# Find a native zip implementation
#
SC_ZIPFS_SUPPORT
- ZIPFS_BUILD=1
- TCL_ZIP_FILE=libtcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_PATCH_LEVEL}.zip
+ ZIPFS_BUILD=1
+ TCL_ZIP_FILE=libtcl${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_PATCH_LEVEL}.zip
else
- ZIPFS_BUILD=0
- TCL_ZIP_FILE=
+ ZIPFS_BUILD=0
+ TCL_ZIP_FILE=
fi
# Do checking message here to not mess up interleaved configure output
AC_MSG_CHECKING([for building with zipfs])
diff --git a/unix/dltest/pkgooa.c b/unix/dltest/pkgooa.c
index ff1cf1f..5aa48a5 100644
--- a/unix/dltest/pkgooa.c
+++ b/unix/dltest/pkgooa.c
@@ -84,10 +84,13 @@ static TclOOStubs stubsCopy = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL
+#ifdef Tcl_MethodIsPrivate
+ ,NULL
+#endif
};
-extern DLLEXPORT int
+DLLEXPORT int
Pkgooa_Init(
Tcl_Interp *interp) /* Interpreter in which the package is to be
* made available. */
diff --git a/unix/dltest/pkgua.c b/unix/dltest/pkgua.c
index 0ab3e23..a822541 100644
--- a/unix/dltest/pkgua.c
+++ b/unix/dltest/pkgua.c
@@ -21,6 +21,7 @@ static int PkguaEqObjCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int PkguaQuoteObjCmd(ClientData clientData,
Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+static void CommandDeleted(ClientData clientData);
/*
* In the following hash table we are going to store a struct that holds all
@@ -30,23 +31,32 @@ static int PkguaQuoteObjCmd(ClientData clientData,
* need to keep the various command tokens we have registered, as they are the
* only safe way to unregister our registered commands, even if they have been
* renamed.
- *
- * Note that this code is utterly single-threaded.
*/
-static Tcl_HashTable interpTokenMap;
-static int interpTokenMapInitialised = 0;
+typedef struct ThreadSpecificData {
+ int interpTokenMapInitialised;
+ Tcl_HashTable interpTokenMap;
+} ThreadSpecificData;
+static Tcl_ThreadDataKey dataKey;
#define MAX_REGISTERED_COMMANDS 2
+static void
+CommandDeleted(ClientData clientData)
+{
+ Tcl_Command *cmdToken = (Tcl_Command *)clientData;
+ *cmdToken = NULL;
+}
static void
PkguaInitTokensHashTable(void)
{
- if (interpTokenMapInitialised) {
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData((&dataKey), sizeof(ThreadSpecificData));
+
+ if (tsdPtr->interpTokenMapInitialised) {
return;
}
- Tcl_InitHashTable(&interpTokenMap, TCL_ONE_WORD_KEYS);
- interpTokenMapInitialised = 1;
+ Tcl_InitHashTable(&tsdPtr->interpTokenMap, TCL_ONE_WORD_KEYS);
+ tsdPtr->interpTokenMapInitialised = 1;
}
static void
@@ -54,12 +64,13 @@ PkguaFreeTokensHashTable(void)
{
Tcl_HashSearch search;
Tcl_HashEntry *entryPtr;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData((&dataKey), sizeof(ThreadSpecificData));
- for (entryPtr = Tcl_FirstHashEntry(&interpTokenMap, &search);
+ for (entryPtr = Tcl_FirstHashEntry(&tsdPtr->interpTokenMap, &search);
entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
}
- interpTokenMapInitialised = 0;
+ tsdPtr->interpTokenMapInitialised = 0;
}
static Tcl_Command *
@@ -68,13 +79,14 @@ PkguaInterpToTokens(
{
int newEntry;
Tcl_Command *cmdTokens;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData((&dataKey), sizeof(ThreadSpecificData));
Tcl_HashEntry *entryPtr =
- Tcl_CreateHashEntry(&interpTokenMap, interp, &newEntry);
+ Tcl_CreateHashEntry(&tsdPtr->interpTokenMap, (char *) interp, &newEntry);
if (newEntry) {
cmdTokens = (Tcl_Command *)
- Tcl_Alloc(sizeof(Tcl_Command) * (MAX_REGISTERED_COMMANDS+1));
- for (newEntry=0 ; newEntry<MAX_REGISTERED_COMMANDS+1 ; ++newEntry) {
+ Tcl_Alloc(sizeof(Tcl_Command) * (MAX_REGISTERED_COMMANDS));
+ for (newEntry=0 ; newEntry<MAX_REGISTERED_COMMANDS ; ++newEntry) {
cmdTokens[newEntry] = NULL;
}
Tcl_SetHashValue(entryPtr, cmdTokens);
@@ -88,8 +100,9 @@ static void
PkguaDeleteTokens(
Tcl_Interp *interp)
{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)Tcl_GetThreadData((&dataKey), sizeof(ThreadSpecificData));
Tcl_HashEntry *entryPtr =
- Tcl_FindHashEntry(&interpTokenMap, interp);
+ Tcl_FindHashEntry(&tsdPtr->interpTokenMap, (char *) interp);
if (entryPtr) {
Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
@@ -199,7 +212,7 @@ Pkgua_Init(
Tcl_Interp *interp) /* Interpreter in which the package is to be
* made available. */
{
- int code, cmdIndex = 0;
+ int code;
Tcl_Command *cmdTokens;
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
@@ -207,7 +220,7 @@ Pkgua_Init(
}
/*
- * Initialise our Hash table, where we store the registered command tokens
+ * Initialize our Hash table, where we store the registered command tokens
* for each interpreter.
*/
@@ -221,12 +234,12 @@ Pkgua_Init(
Tcl_SetVar2(interp, "::pkgua_loaded", NULL, ".", TCL_APPEND_VALUE);
cmdTokens = PkguaInterpToTokens(interp);
- cmdTokens[cmdIndex++] =
- Tcl_CreateObjCommand(interp, "pkgua_eq", PkguaEqObjCmd, NULL,
- NULL);
- cmdTokens[cmdIndex++] =
+ cmdTokens[0] =
+ Tcl_CreateObjCommand(interp, "pkgua_eq", PkguaEqObjCmd, &cmdTokens[0],
+ CommandDeleted);
+ cmdTokens[1] =
Tcl_CreateObjCommand(interp, "pkgua_quote", PkguaQuoteObjCmd,
- NULL, NULL);
+ &cmdTokens[1], CommandDeleted);
return TCL_OK;
}
diff --git a/unix/tcl.m4 b/unix/tcl.m4
index a8911f8..9cfec6b 100644
--- a/unix/tcl.m4
+++ b/unix/tcl.m4
@@ -1782,12 +1782,12 @@ dnl # preprocessing tests use only CPPFLAGS.
AIX-*) ;;
BSD/OS*) ;;
CYGWIN_*|MINGW32_*|MSYS_*) ;;
- HP_UX*) ;;
+ HP-UX*) ;;
Darwin-*) ;;
IRIX*) ;;
Linux*|GNU*) ;;
- NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;;
- OSF1-V*) ;;
+ NetBSD-*|OpenBSD-*) ;;
+ OSF1-*) ;;
SCO_SV-3.2*) ;;
*) SHLIB_CFLAGS="-fPIC" ;;
esac])
@@ -3011,18 +3011,40 @@ AC_DEFUN([AX_CC_FOR_BUILD],[# Put a plausible default for CC_FOR_BUILD in Makefi
#
# Results:
# Substitutes the following vars:
-# ZIP_PROG
+# MACHER_PROG
+# ZIP_PROG
# ZIP_PROG_OPTIONS
# ZIP_PROG_VFSSEARCH
# ZIP_INSTALL_OBJS
#------------------------------------------------------------------------
AC_DEFUN([SC_ZIPFS_SUPPORT], [
+ MACHER_PROG=""
ZIP_PROG=""
ZIP_PROG_OPTIONS=""
ZIP_PROG_VFSSEARCH=""
ZIP_INSTALL_OBJS=""
+ AC_MSG_CHECKING([for macher])
+ AC_CACHE_VAL(ac_cv_path_macher, [
+ search_path=`echo ${PATH} | sed -e 's/:/ /g'`
+ for dir in $search_path ; do
+ for j in `ls -r $dir/macher 2> /dev/null` \
+ `ls -r $dir/macher 2> /dev/null` ; do
+ if test x"$ac_cv_path_macher" = x ; then
+ if test -f "$j" ; then
+ ac_cv_path_macher=$j
+ break
+ fi
+ fi
+ done
+ done
+ ])
+ if test -f "$ac_cv_path_macher" ; then
+ MACHER_PROG="$ac_cv_path_macher"
+ AC_MSG_RESULT([$MACHER_PROG])
+ AC_MSG_RESULT([Found macher in environment])
+ fi
AC_MSG_CHECKING([for zip])
AC_CACHE_VAL(ac_cv_path_zip, [
search_path=`echo ${PATH} | sed -e 's/:/ /g'`
@@ -3054,6 +3076,7 @@ AC_DEFUN([SC_ZIPFS_SUPPORT], [
ZIP_INSTALL_OBJS="minizip${EXEEXT_FOR_BUILD}"
AC_MSG_RESULT([No zip found on PATH. Building minizip])
fi
+ AC_SUBST(MACHER_PROG)
AC_SUBST(ZIP_PROG)
AC_SUBST(ZIP_PROG_OPTIONS)
AC_SUBST(ZIP_PROG_VFSSEARCH)
diff --git a/unix/tclAppInit.c b/unix/tclAppInit.c
index 3587f35..f3caae7 100644
--- a/unix/tclAppInit.c
+++ b/unix/tclAppInit.c
@@ -15,15 +15,19 @@
#undef BUILD_tcl
#undef STATIC_BUILD
#include "tcl.h"
+#if TCL_MAJOR_VERSION < 9 && TCL_MINOR_VERSION < 7
+# define Tcl_LibraryInitProc Tcl_PackageInitProc
+# define Tcl_StaticLibrary Tcl_StaticPackage
+#endif
#ifdef TCL_TEST
-extern Tcl_PackageInitProc Tcltest_Init;
-extern Tcl_PackageInitProc Tcltest_SafeInit;
+extern Tcl_LibraryInitProc Tcltest_Init;
+extern Tcl_LibraryInitProc Tcltest_SafeInit;
#endif /* TCL_TEST */
#ifdef TCL_XT_TEST
extern void XtToolkitInitialize(void);
-extern Tcl_PackageInitProc Tclxttest_Init;
+extern Tcl_LibraryInitProc Tclxttest_Init;
#endif /* TCL_XT_TEST */
/*
@@ -79,7 +83,8 @@ main(
#ifdef TCL_LOCAL_MAIN_HOOK
TCL_LOCAL_MAIN_HOOK(&argc, &argv);
-#else
+#elif !defined(_WIN32) || defined(UNICODE)
+ /* This doesn't work on Windows without UNICODE */
TclZipfs_AppHook(&argc, &argv);
#endif
@@ -124,7 +129,7 @@ Tcl_AppInit(
if (Tcltest_Init(interp) == TCL_ERROR) {
return TCL_ERROR;
}
- Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit);
+ Tcl_StaticLibrary(interp, "Tcltest", Tcltest_Init, Tcltest_SafeInit);
#endif /* TCL_TEST */
/*
diff --git a/unix/tclEpollNotfy.c b/unix/tclEpollNotfy.c
index 3a99e6d..23c88b2 100644
--- a/unix/tclEpollNotfy.c
+++ b/unix/tclEpollNotfy.c
@@ -97,7 +97,7 @@ typedef struct ThreadSpecificData {
* that are ready for I/O. */
pthread_mutex_t notifierMutex;
/* Mutex protecting notifier termination in
- * PlatformEventsFinalize. */
+ * TclpFinalizeNotifier. */
#ifdef HAVE_EVENTFD
int triggerEventFd; /* eventfd(2) used by other threads to wake
* up this thread for inter-thread IPC. */
@@ -121,14 +121,13 @@ 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);
-
+
/*
- * Incorporate the base notifier API.
+ * Incorporate the base notifier implementation.
*/
#include "tclUnixNotfy.c"
@@ -136,7 +135,7 @@ static int PlatformEventsWait(struct epoll_event *events,
/*
*----------------------------------------------------------------------
*
- * Tcl_InitNotifier --
+ * TclpInitNotifier --
*
* Initializes the platform specific notifier state.
*
@@ -144,54 +143,21 @@ static int PlatformEventsWait(struct epoll_event *events,
* Returns a handle to the notifier state for this thread.
*
* Side effects:
- * If no initNotifierProc notifier hook exists, PlatformEventsInit
- * is called.
+ * If no initNotifierProc notifier hook exists, PlatformEventsInit is
+ * called.
*
*----------------------------------------------------------------------
*/
ClientData
-Tcl_InitNotifier(void)
+TclpInitNotifier(void)
{
- if (tclNotifierHooks.initNotifierProc) {
- return tclNotifierHooks.initNotifierProc();
- } else {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- PlatformEventsInit();
- return tsdPtr;
- }
+ PlatformEventsInit();
+ return tsdPtr;
}
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_FinalizeNotifier --
- *
- * This function is called to cleanup the notifier state before a thread
- * is terminated.
- *
- * Results:
- * None.
- *
- * Side effects:
- * If no finalizeNotifierProc notifier hook exists, PlatformEvents-
- * Finalize is called.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_FinalizeNotifier(
- ClientData clientData)
-{
- if (tclNotifierHooks.finalizeNotifierProc) {
- tclNotifierHooks.finalizeNotifierProc(clientData);
- return;
- } else {
- PlatformEventsFinalize();
- }
-}
/*
*----------------------------------------------------------------------
@@ -221,7 +187,7 @@ Tcl_FinalizeNotifier(
*----------------------------------------------------------------------
*/
-void
+static void
PlatformEventsControl(
FileHandler *filePtr,
ThreadSpecificData *tsdPtr,
@@ -240,7 +206,8 @@ PlatformEventsControl(
newEvent.events |= EPOLLOUT;
}
if (isNew) {
- newPedPtr = (struct PlatformEventData *)ckalloc(sizeof(struct PlatformEventData));
+ newPedPtr = (struct PlatformEventData *)
+ ckalloc(sizeof(struct PlatformEventData));
newPedPtr->filePtr = filePtr;
newPedPtr->tsdPtr = tsdPtr;
filePtr->pedPtr = newPedPtr;
@@ -249,7 +216,7 @@ PlatformEventsControl(
/*
* N.B. As discussed in Tcl_WaitForEvent(), epoll(7) does not support
- * regular files (S_IFREG.) Therefore, filePtr is in these cases simply
+ * 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.
*/
@@ -277,7 +244,7 @@ PlatformEventsControl(
/*
*----------------------------------------------------------------------
*
- * PlatformEventsFinalize --
+ * TclpFinalizeNotifier --
*
* This function closes the eventfd and the epoll file descriptor and
* frees the epoll_event structs owned by the thread of the caller. The
@@ -299,8 +266,8 @@ PlatformEventsControl(
*/
void
-PlatformEventsFinalize(
- void)
+TclpFinalizeNotifier(
+ TCL_UNUSED(ClientData))
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -362,7 +329,7 @@ PlatformEventsFinalize(
*----------------------------------------------------------------------
*/
-void
+static void
PlatformEventsInit(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -372,7 +339,7 @@ PlatformEventsInit(void)
if (errno) {
Tcl_Panic("Tcl_InitNotifier: %s", "could not create mutex");
}
- filePtr = (FileHandler *)ckalloc(sizeof(FileHandler));
+ filePtr = (FileHandler *) ckalloc(sizeof(FileHandler));
#ifdef HAVE_EVENTFD
tsdPtr->triggerEventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
if (tsdPtr->triggerEventFd <= 0) {
@@ -393,7 +360,7 @@ PlatformEventsInit(void)
PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_ADD, 1);
if (!tsdPtr->readyEvents) {
tsdPtr->maxReadyEvents = 512;
- tsdPtr->readyEvents = (struct epoll_event *)ckalloc(
+ tsdPtr->readyEvents = (struct epoll_event *) ckalloc(
tsdPtr->maxReadyEvents * sizeof(tsdPtr->readyEvents[0]));
}
LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
@@ -416,7 +383,7 @@ PlatformEventsInit(void)
*----------------------------------------------------------------------
*/
-int
+static int
PlatformEventsTranslate(
struct epoll_event *eventPtr)
{
@@ -457,7 +424,7 @@ PlatformEventsTranslate(
*----------------------------------------------------------------------
*/
-int
+static int
PlatformEventsWait(
struct epoll_event *events,
size_t numEvents,
@@ -480,9 +447,9 @@ PlatformEventsWait(
} else if (!timePtr->tv_sec && !timePtr->tv_usec) {
timeout = 0;
} else {
- timeout = (int)timePtr->tv_sec * 1000;
+ timeout = (int) timePtr->tv_sec * 1000;
if (timePtr->tv_usec) {
- timeout += (int)timePtr->tv_usec / 1000;
+ timeout += (int) timePtr->tv_usec / 1000;
}
}
@@ -493,7 +460,7 @@ PlatformEventsWait(
*/
gettimeofday(&tv0, NULL);
- numFound = epoll_wait(tsdPtr->eventsFd, events, (int)numEvents, timeout);
+ numFound = epoll_wait(tsdPtr->eventsFd, events, (int) numEvents, timeout);
gettimeofday(&tv1, NULL);
if (timePtr && (timePtr->tv_sec && timePtr->tv_usec)) {
timersub(&tv1, &tv0, &tv_delta);
@@ -510,7 +477,7 @@ PlatformEventsWait(
/*
*----------------------------------------------------------------------
*
- * Tcl_CreateFileHandler --
+ * TclpCreateFileHandler --
*
* This function registers a file handler with the epoll notifier of the
* thread of the caller.
@@ -526,7 +493,7 @@ PlatformEventsWait(
*/
void
-Tcl_CreateFileHandler(
+TclpCreateFileHandler(
int fd, /* Handle of stream to watch. */
int mask, /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, and TCL_EXCEPTION: indicates
@@ -536,44 +503,29 @@ Tcl_CreateFileHandler(
* event. */
ClientData clientData) /* Arbitrary data to pass to proc. */
{
- int isNew;
-
- if (tclNotifierHooks.createFileHandlerProc) {
- tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
- return;
- } else {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- FileHandler *filePtr;
-
- for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
- filePtr = filePtr->nextPtr) {
- if (filePtr->fd == fd) {
- break;
- }
- }
- if (filePtr == NULL) {
- filePtr = (FileHandler *)ckalloc(sizeof(FileHandler));
- filePtr->fd = fd;
- filePtr->readyMask = 0;
- filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
- tsdPtr->firstFileHandlerPtr = filePtr;
- isNew = 1;
- } else {
- isNew = 0;
- }
- filePtr->proc = proc;
- filePtr->clientData = clientData;
- filePtr->mask = mask;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);
+ int isNew = (filePtr == NULL);
- PlatformEventsControl(filePtr, tsdPtr,
- isNew ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew);
+ if (isNew) {
+ filePtr = (FileHandler *) ckalloc(sizeof(FileHandler));
+ filePtr->fd = fd;
+ filePtr->readyMask = 0;
+ filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
+ tsdPtr->firstFileHandlerPtr = filePtr;
}
+ filePtr->proc = proc;
+ filePtr->clientData = clientData;
+ filePtr->mask = mask;
+
+ PlatformEventsControl(filePtr, tsdPtr,
+ isNew ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew);
}
/*
*----------------------------------------------------------------------
*
- * Tcl_DeleteFileHandler --
+ * TclpDeleteFileHandler --
*
* Cancel a previously-arranged callback arrangement for a file on the
* epoll file descriptor of the thread of the caller.
@@ -591,60 +543,50 @@ Tcl_CreateFileHandler(
*/
void
-Tcl_DeleteFileHandler(
+TclpDeleteFileHandler(
int fd) /* Stream id for which to remove callback
* function. */
{
- if (tclNotifierHooks.deleteFileHandlerProc) {
- tclNotifierHooks.deleteFileHandlerProc(fd);
- return;
- } else {
- FileHandler *filePtr, *prevPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr, *prevPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- /*
- * Find the entry for the given file (and return if there isn't one).
- */
+ /*
+ * Find the entry for the given file (and return if there isn't one).
+ */
- for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
- prevPtr = filePtr, filePtr = filePtr->nextPtr) {
- if (filePtr == NULL) {
- return;
- }
- if (filePtr->fd == fd) {
- break;
- }
- }
+ filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
+ if (filePtr == NULL) {
+ return;
+ }
- /*
- * Update the check masks for this file.
- */
+ /*
+ * Update the check masks for this file.
+ */
- PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_DEL, 0);
- if (filePtr->pedPtr) {
- ckfree(filePtr->pedPtr);
- }
+ PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_DEL, 0);
+ if (filePtr->pedPtr) {
+ ckfree(filePtr->pedPtr);
+ }
- /*
- * Clean up information in the callback record.
- */
+ /*
+ * Clean up information in the callback record.
+ */
- if (prevPtr == NULL) {
- tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
- } else {
- prevPtr->nextPtr = filePtr->nextPtr;
- }
- ckfree(filePtr);
+ if (prevPtr == NULL) {
+ tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = filePtr->nextPtr;
}
+ ckfree(filePtr);
}
/*
*----------------------------------------------------------------------
*
- * Tcl_WaitForEvent --
+ * TclpWaitForEvent --
*
* 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
+ * the message queue. If the block time is 0, then TclpWaitForEvent just
* polls without blocking.
*
* The waiting logic is implemented in PlatformEventsWait.
@@ -660,172 +602,165 @@ Tcl_DeleteFileHandler(
*/
int
-Tcl_WaitForEvent(
+TclpWaitForEvent(
const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
{
- if (tclNotifierHooks.waitForEventProc) {
- return tclNotifierHooks.waitForEventProc(timePtr);
- } else {
- FileHandler *filePtr;
- int mask;
- Tcl_Time vTime;
- /*
- * Impl. notes: timeout & timeoutPtr are used if, and only if threads
- * are not enabled. They are the arguments for the regular epoll_wait()
- * used when the core is not thread-enabled.
- */
+ FileHandler *filePtr;
+ Tcl_Time vTime;
+ struct timeval timeout, *timeoutPtr;
+ /* Impl. notes: timeout & timeoutPtr are used
+ * if, and only if threads are not enabled.
+ * They are the arguments for the regular
+ * epoll_wait() used when the core is not
+ * thread-enabled. */
+ int mask, numFound, numEvent;
+ struct PlatformEventData *pedPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ int numQueued;
+ ssize_t i;
- struct timeval timeout, *timeoutPtr;
- int numFound, numEvent;
- struct PlatformEventData *pedPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- int numQueued;
- ssize_t i;
+ /*
+ * Set up the timeout structure. Note that if there are no events to check
+ * for, we return with a negative result rather than blocking forever.
+ */
+ if (timePtr != NULL) {
/*
- * Set up the timeout structure. Note that if there are no events to
- * check for, we return with a negative result rather than blocking
- * forever.
+ * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
+ * actually have something to scale? If yes to both then we call the
+ * handler to do this scaling.
*/
- if (timePtr != NULL) {
- /*
- * TIP #233 (Virtualized Time). Is virtual time in effect? And do
- * we actually have something to scale? If yes to both then we
- * call the handler to do this scaling.
- */
-
- if (timePtr->sec != 0 || timePtr->usec != 0) {
- vTime = *timePtr;
- tclScaleTimeProcPtr(&vTime, tclTimeClientData);
- timePtr = &vTime;
- }
- timeout.tv_sec = timePtr->sec;
- timeout.tv_usec = timePtr->usec;
- timeoutPtr = &timeout;
- } else {
- timeoutPtr = NULL;
+ if (timePtr->sec != 0 || timePtr->usec != 0) {
+ vTime = *timePtr;
+ TclScaleTime(&vTime);
+ timePtr = &vTime;
}
+ timeout.tv_sec = timePtr->sec;
+ timeout.tv_usec = timePtr->usec;
+ timeoutPtr = &timeout;
+ } else {
+ timeoutPtr = NULL;
+ }
- /*
- * 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
- * PlatformEventsWait().
- */
-
- numQueued = 0;
- LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
- mask = 0;
- if (filePtr->mask & TCL_READABLE) {
- mask |= TCL_READABLE;
- }
- if (filePtr->mask & TCL_WRITABLE) {
- mask |= TCL_WRITABLE;
- }
-
- /*
- * Don't bother to queue an event if the mask was previously
- * non-zero since an event must still be on the queue.
- */
-
- if (filePtr->readyMask == 0) {
- FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
- ckalloc(sizeof(FileHandlerEvent));
+ /*
+ * 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 PlatformEventsWait().
+ */
- fileEvPtr->header.proc = FileHandlerEventProc;
- fileEvPtr->fd = filePtr->fd;
- Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
- numQueued++;
- }
- filePtr->readyMask = mask;
+ numQueued = 0;
+ LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
+ mask = 0;
+ if (filePtr->mask & TCL_READABLE) {
+ mask |= TCL_READABLE;
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ mask |= TCL_WRITABLE;
}
/*
- * 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.
+ * Don't bother to queue an event if the mask was previously non-zero
+ * since an event must still be on the queue.
*/
- if (numQueued) {
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- timeoutPtr = &timeout;
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
+ ckalloc(sizeof(FileHandlerEvent));
+
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+ numQueued++;
}
+ filePtr->readyMask = mask;
+ }
- /*
- * Wait or poll for new events, queue Tcl events for the FileHandlers
- * corresponding to them, and update the FileHandlers' mask of events
- * of interest registered by the last call to Tcl_CreateFileHandler().
- *
- * Events for the eventfd(2)/trigger pipe are processed here in order
- * 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.
- */
+ /*
+ * 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) {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ timeoutPtr = &timeout;
+ }
+
+ /*
+ * Wait or poll for new events, queue Tcl events for the FileHandlers
+ * corresponding to them, and update the FileHandlers' mask of events of
+ * interest registered by the last call to Tcl_CreateFileHandler().
+ *
+ * Events for the eventfd(2)/trigger pipe are processed here in order 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.
+ */
- numFound = PlatformEventsWait(tsdPtr->readyEvents,
- tsdPtr->maxReadyEvents, timeoutPtr);
- for (numEvent = 0; numEvent < numFound; numEvent++) {
- pedPtr = (struct PlatformEventData*)tsdPtr->readyEvents[numEvent].data.ptr;
- filePtr = pedPtr->filePtr;
- mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
+ numFound = PlatformEventsWait(tsdPtr->readyEvents,
+ tsdPtr->maxReadyEvents, timeoutPtr);
+ for (numEvent = 0; numEvent < numFound; numEvent++) {
+ pedPtr = (struct PlatformEventData *)
+ tsdPtr->readyEvents[numEvent].data.ptr;
+ filePtr = pedPtr->filePtr;
+ mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
#ifdef HAVE_EVENTFD
- if (filePtr->fd == tsdPtr->triggerEventFd) {
- uint64_t eventFdVal;
- i = read(tsdPtr->triggerEventFd, &eventFdVal,
- sizeof(eventFdVal));
- if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) {
- Tcl_Panic(
- "Tcl_WaitForEvent: read from %p->triggerEventFd: %s",
- (void *) tsdPtr, strerror(errno));
- }
- continue;
+ if (filePtr->fd == tsdPtr->triggerEventFd) {
+ uint64_t eventFdVal;
+
+ i = read(tsdPtr->triggerEventFd, &eventFdVal, sizeof(eventFdVal));
+ if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) {
+ Tcl_Panic("%s: read from %p->triggerEventFd: %s",
+ "Tcl_WaitForEvent", (void *) tsdPtr, strerror(errno));
}
+ continue;
+ }
#else /* !HAVE_EVENTFD */
- if (filePtr->fd == tsdPtr->triggerPipe[0]) {
- char triggerPipeVal;
- i = read(tsdPtr->triggerPipe[0], &triggerPipeVal,
- sizeof(triggerPipeVal));
- if ((i != sizeof(triggerPipeVal)) && (errno != EAGAIN)) {
- Tcl_Panic(
- "Tcl_WaitForEvent: read from %p->triggerPipe[0]: %s",
- (void *) tsdPtr, strerror(errno));
- }
- continue;
+ if (filePtr->fd == tsdPtr->triggerPipe[0]) {
+ char triggerPipeVal;
+
+ i = read(tsdPtr->triggerPipe[0], &triggerPipeVal,
+ sizeof(triggerPipeVal));
+ if ((i != sizeof(triggerPipeVal)) && (errno != EAGAIN)) {
+ Tcl_Panic("%s: read from %p->triggerPipe[0]: %s",
+ "Tcl_WaitForEvent", (void *) tsdPtr, strerror(errno));
}
+ continue;
+ }
#endif /* HAVE_EVENTFD */
- if (!mask) {
- continue;
- }
+ if (!mask) {
+ continue;
+ }
- /*
- * Don't bother to queue an event if the mask was previously
- * non-zero since an event must still be on the queue.
- */
+ /*
+ * Don't bother to queue an event if the mask was previously non-zero
+ * since an event must still be on the queue.
+ */
- if (filePtr->readyMask == 0) {
- FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
- ckalloc(sizeof(FileHandlerEvent));
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
+ ckalloc(sizeof(FileHandlerEvent));
- fileEvPtr->header.proc = FileHandlerEventProc;
- fileEvPtr->fd = filePtr->fd;
- Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
- }
- filePtr->readyMask = mask;
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
}
- return 0;
+ filePtr->readyMask = mask;
}
+ return 0;
}
#endif /* NOTIFIER_EPOLL && TCL_THREADS */
+#else
+TCL_MAC_EMPTY_FILE(unix_tclEpollNotfy_c)
#endif /* !HAVE_COREFOUNDATION */
/*
diff --git a/unix/tclKqueueNotfy.c b/unix/tclKqueueNotfy.c
index 2f1d8e6..ab3732d 100644
--- a/unix/tclKqueueNotfy.c
+++ b/unix/tclKqueueNotfy.c
@@ -31,7 +31,8 @@
struct PlatformEventData;
typedef struct FileHandler {
- int fd;
+ int fd; /* File descriptor that this is describing a
+ * handler for. */
int mask; /* Mask of desired events: TCL_READABLE,
* etc. */
int readyMask; /* Mask of events that have been seen since
@@ -93,7 +94,7 @@ typedef struct ThreadSpecificData {
* that are ready for I/O. */
pthread_mutex_t notifierMutex;
/* Mutex protecting notifier termination in
- * PlatformEventsFinalize. */
+ * TclpFinalizeNotifier. */
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
@@ -111,73 +112,15 @@ 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);
-
-#include "tclUnixNotfy.c"
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_InitNotifier --
- *
- * Initializes the platform specific notifier state.
- *
- * Results:
- * Returns a handle to the notifier state for this thread.
- *
- * Side effects:
- * If no initNotifierProc notifier hook exists, PlatformEventsInit
- * is called.
- *
- *----------------------------------------------------------------------
- */
-
-ClientData
-Tcl_InitNotifier(void)
-{
- if (tclNotifierHooks.initNotifierProc) {
- return tclNotifierHooks.initNotifierProc();
- } else {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
- PlatformEventsInit();
- return tsdPtr;
- }
-}
/*
- *----------------------------------------------------------------------
- *
- * Tcl_FinalizeNotifier --
- *
- * This function is called to cleanup the notifier state before a thread
- * is terminated.
- *
- * Results:
- * None.
- *
- * Side effects:
- * If no finalizeNotifierProc notifier hook exists, PlatformEvents-
- * Finalize is called.
- *
- *----------------------------------------------------------------------
+ * Incorporate the base notifier implementation.
*/
-void
-Tcl_FinalizeNotifier(
- ClientData clientData)
-{
- if (tclNotifierHooks.finalizeNotifierProc) {
- tclNotifierHooks.finalizeNotifierProc(clientData);
- return;
- } else {
- PlatformEventsFinalize();
- }
-}
+#include "tclUnixNotfy.c"
/*
*----------------------------------------------------------------------
@@ -209,7 +152,7 @@ Tcl_FinalizeNotifier(
*----------------------------------------------------------------------
*/
-void
+static void
PlatformEventsControl(
FileHandler *filePtr,
ThreadSpecificData *tsdPtr,
@@ -222,7 +165,8 @@ PlatformEventsControl(
struct stat fdStat;
if (isNew) {
- newPedPtr = (struct PlatformEventData *)ckalloc(sizeof(struct PlatformEventData));
+ newPedPtr = (struct PlatformEventData *)
+ ckalloc(sizeof(struct PlatformEventData));
newPedPtr->filePtr = filePtr;
newPedPtr->tsdPtr = tsdPtr;
filePtr->pedPtr = newPedPtr;
@@ -257,12 +201,12 @@ PlatformEventsControl(
switch (op) {
case EV_ADD:
if (filePtr->mask & (TCL_READABLE | TCL_EXCEPTION)) {
- EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd,
+ 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,
+ EV_SET(&changeList[numChanges], (uintptr_t) filePtr->fd,
EVFILT_WRITE, op, 0, 0, filePtr->pedPtr);
numChanges++;
}
@@ -284,13 +228,13 @@ PlatformEventsControl(
* 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,
+ 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,
+ 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)) {
@@ -303,7 +247,7 @@ PlatformEventsControl(
/*
*----------------------------------------------------------------------
*
- * PlatformEventsFinalize --
+ * TclpFinalizeNotifier --
*
* This function closes the pipe and the kqueue file descriptors and
* frees the kevent structs owned by the thread of the caller. The above
@@ -325,8 +269,8 @@ PlatformEventsControl(
*/
void
-PlatformEventsFinalize(
- void)
+TclpFinalizeNotifier(
+ TCL_UNUSED(ClientData))
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -356,14 +300,16 @@ PlatformEventsFinalize(
/*
*----------------------------------------------------------------------
*
- * PlatformEventsInit --
+ * TclpInitNotifier --
+ *
+ * Initializes the platform specific notifier state.
*
* 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.
+ * Returns a handle to the notifier state for this thread.
*
* Side effects:
* The following per-thread entities are initialised:
@@ -380,8 +326,8 @@ PlatformEventsFinalize(
*----------------------------------------------------------------------
*/
-void
-PlatformEventsInit(void)
+ClientData
+TclpInitNotifier(void)
{
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
int i, fdFl;
@@ -409,16 +355,18 @@ PlatformEventsInit(void)
} else if (fcntl(tsdPtr->eventsFd, F_SETFD, FD_CLOEXEC) == -1) {
Tcl_Panic("fcntl: %s", strerror(errno));
}
- filePtr = (FileHandler *)ckalloc(sizeof(FileHandler));
+ filePtr = (FileHandler *) ckalloc(sizeof(FileHandler));
filePtr->fd = tsdPtr->triggerPipe[0];
filePtr->mask = TCL_READABLE;
PlatformEventsControl(filePtr, tsdPtr, EV_ADD, 1);
if (!tsdPtr->readyEvents) {
tsdPtr->maxReadyEvents = 512;
- tsdPtr->readyEvents = (struct kevent *)ckalloc(
+ tsdPtr->readyEvents = (struct kevent *) ckalloc(
tsdPtr->maxReadyEvents * sizeof(tsdPtr->readyEvents[0]));
}
LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
+
+ return tsdPtr;
}
/*
@@ -438,7 +386,7 @@ PlatformEventsInit(void)
*----------------------------------------------------------------------
*/
-int
+static int
PlatformEventsTranslate(
struct kevent *eventPtr)
{
@@ -459,7 +407,7 @@ PlatformEventsTranslate(
}
return mask;
}
-
+
/*
*----------------------------------------------------------------------
*
@@ -483,7 +431,7 @@ PlatformEventsTranslate(
*----------------------------------------------------------------------
*/
-int
+static int
PlatformEventsWait(
struct kevent *events,
size_t numEvents,
@@ -538,7 +486,7 @@ PlatformEventsWait(
/*
*----------------------------------------------------------------------
*
- * Tcl_CreateFileHandler --
+ * TclpCreateFileHandler --
*
* This function registers a file handler with the kqueue notifier
* of the thread of the caller.
@@ -554,7 +502,7 @@ PlatformEventsWait(
*/
void
-Tcl_CreateFileHandler(
+TclpCreateFileHandler(
int fd, /* Handle of stream to watch. */
int mask, /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, and TCL_EXCEPTION: indicates
@@ -564,43 +512,28 @@ Tcl_CreateFileHandler(
* event. */
ClientData clientData) /* Arbitrary data to pass to proc. */
{
- int isNew;
-
- if (tclNotifierHooks.createFileHandlerProc) {
- tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
- return;
- } else {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- FileHandler *filePtr;
-
- for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
- filePtr = filePtr->nextPtr) {
- if (filePtr->fd == fd) {
- break;
- }
- }
- if (filePtr == NULL) {
- filePtr = (FileHandler *)ckalloc(sizeof(FileHandler));
- filePtr->fd = fd;
- filePtr->readyMask = 0;
- filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
- tsdPtr->firstFileHandlerPtr = filePtr;
- isNew = 1;
- } else {
- isNew = 0;
- }
- filePtr->proc = proc;
- filePtr->clientData = clientData;
- filePtr->mask = mask;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);
+ int isNew = (filePtr == NULL);
- PlatformEventsControl(filePtr, tsdPtr, EV_ADD, isNew);
+ if (isNew) {
+ filePtr = (FileHandler *) ckalloc(sizeof(FileHandler));
+ filePtr->fd = fd;
+ filePtr->readyMask = 0;
+ filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
+ tsdPtr->firstFileHandlerPtr = filePtr;
}
+ filePtr->proc = proc;
+ filePtr->clientData = clientData;
+ filePtr->mask = mask;
+
+ PlatformEventsControl(filePtr, tsdPtr, EV_ADD, isNew);
}
/*
*----------------------------------------------------------------------
*
- * Tcl_DeleteFileHandler --
+ * TclpDeleteFileHandler --
*
* Cancel a previously-arranged callback arrangement for a file on the
* kqueue of the thread of the caller.
@@ -618,60 +551,50 @@ Tcl_CreateFileHandler(
*/
void
-Tcl_DeleteFileHandler(
+TclpDeleteFileHandler(
int fd) /* Stream id for which to remove callback
* function. */
{
- if (tclNotifierHooks.deleteFileHandlerProc) {
- tclNotifierHooks.deleteFileHandlerProc(fd);
- return;
- } else {
- FileHandler *filePtr, *prevPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr, *prevPtr;
- /*
- * Find the entry for the given file (and return if there isn't one).
- */
+ /*
+ * Find the entry for the given file (and return if there isn't one).
+ */
- for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
- prevPtr = filePtr, filePtr = filePtr->nextPtr) {
- if (filePtr == NULL) {
- return;
- }
- if (filePtr->fd == fd) {
- break;
- }
- }
+ filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
+ if (filePtr == NULL) {
+ return;
+ }
- /*
- * Update the check masks for this file.
- */
+ /*
+ * Update the check masks for this file.
+ */
- PlatformEventsControl(filePtr, tsdPtr, EV_DELETE, 0);
- if (filePtr->pedPtr) {
- ckfree(filePtr->pedPtr);
- }
+ PlatformEventsControl(filePtr, tsdPtr, EV_DELETE, 0);
+ if (filePtr->pedPtr) {
+ ckfree(filePtr->pedPtr);
+ }
- /*
- * Clean up information in the callback record.
- */
+ /*
+ * Clean up information in the callback record.
+ */
- if (prevPtr == NULL) {
- tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
- } else {
- prevPtr->nextPtr = filePtr->nextPtr;
- }
- ckfree(filePtr);
+ if (prevPtr == NULL) {
+ tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = filePtr->nextPtr;
}
+ ckfree(filePtr);
}
/*
*----------------------------------------------------------------------
*
- * Tcl_WaitForEvent --
+ * TclpWaitForEvent --
*
* 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
+ * the message queue. If the block time is 0, then TclpWaitForEvent just
* polls without blocking.
*
* The waiting logic is implemented in PlatformEventsWait.
@@ -687,161 +610,157 @@ Tcl_DeleteFileHandler(
*/
int
-Tcl_WaitForEvent(
- const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
+TclpWaitForEvent(
+ const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
{
- if (tclNotifierHooks.waitForEventProc) {
- return tclNotifierHooks.waitForEventProc(timePtr);
- } else {
- FileHandler *filePtr;
- int mask;
- Tcl_Time vTime;
- /*
- * Impl. notes: timeout & timeoutPtr are used if, and only if threads
- * are not enabled. They are the arguments for the regular epoll_wait()
- * used when the core is not thread-enabled.
- */
+ FileHandler *filePtr;
+ int mask;
+ Tcl_Time vTime;
+ struct timeval timeout, *timeoutPtr;
+ /* Impl. notes: timeout & timeoutPtr are used
+ * if, and only if threads are not enabled.
+ * They are the arguments for the regular
+ * epoll_wait() used when the core is not
+ * thread-enabled. */
+ int numFound, numEvent;
+ struct PlatformEventData *pedPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ int numQueued;
+ ssize_t i;
+ char buf[1];
- struct timeval timeout, *timeoutPtr;
- int numFound, numEvent;
- struct PlatformEventData *pedPtr;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- int numQueued;
- ssize_t i;
- char buf[1];
+ /*
+ * Set up the timeout structure. Note that if there are no events to check
+ * for, we return with a negative result rather than blocking forever.
+ */
+ if (timePtr != NULL) {
/*
- * Set up the timeout structure. Note that if there are no events to
- * check for, we return with a negative result rather than blocking
- * forever.
+ * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
+ * actually have something to scale? If yes to both then we call the
+ * handler to do this scaling.
*/
- if (timePtr != NULL) {
- /*
- * TIP #233 (Virtualized Time). Is virtual time in effect? And do
- * we actually have something to scale? If yes to both then we
- * call the handler to do this scaling.
- */
-
- if (timePtr->sec != 0 || timePtr->usec != 0) {
- vTime = *timePtr;
- tclScaleTimeProcPtr(&vTime, tclTimeClientData);
- timePtr = &vTime;
- }
- timeout.tv_sec = timePtr->sec;
- timeout.tv_usec = timePtr->usec;
- timeoutPtr = &timeout;
- } else {
- timeoutPtr = NULL;
+ if (timePtr->sec != 0 || timePtr->usec != 0) {
+ vTime = *timePtr;
+ TclScaleTime(&vTime);
+ timePtr = &vTime;
+ }
+ timeout.tv_sec = timePtr->sec;
+ timeout.tv_usec = timePtr->usec;
+ timeoutPtr = &timeout;
+ } else {
+ timeoutPtr = NULL;
+ }
+
+ /*
+ * 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.
+ *
+ * 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 possibly
+ * blocking) on PlatformEventsWait().
+ */
+
+ numQueued = 0;
+ LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
+ mask = 0;
+ if (filePtr->mask & TCL_READABLE) {
+ mask |= TCL_READABLE;
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ mask |= TCL_WRITABLE;
}
/*
- * 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.
- *
- * 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
- * possibly blocking) on PlatformEventsWait().
+ * Don't bother to queue an event if the mask was previously non-zero
+ * since an event must still be on the queue.
*/
- numQueued = 0;
- LIST_FOREACH(filePtr, &tsdPtr->firstReadyFileHandlerPtr, readyNode) {
- mask = 0;
- if (filePtr->mask & TCL_READABLE) {
- mask |= TCL_READABLE;
- }
- if (filePtr->mask & TCL_WRITABLE) {
- mask |= TCL_WRITABLE;
- }
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
+ ckalloc(sizeof(FileHandlerEvent));
- /*
- * Don't bother to queue an event if the mask was previously
- * non-zero since an event must still be on the queue.
- */
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
+ numQueued++;
+ }
+ filePtr->readyMask = mask;
+ }
- if (filePtr->readyMask == 0) {
- FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
- ckalloc(sizeof(FileHandlerEvent));
+ /*
+ * 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.
+ */
- fileEvPtr->header.proc = FileHandlerEventProc;
- fileEvPtr->fd = filePtr->fd;
- Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
- numQueued++;
- }
- filePtr->readyMask = mask;
- }
+ if (numQueued) {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ timeoutPtr = &timeout;
+ }
- /*
- * 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.
- */
+ /*
+ * Wait or poll for new events, queue Tcl events for the FileHandlers
+ * corresponding to them, and update the FileHandlers' mask of events of
+ * interest registered by the last call to Tcl_CreateFileHandler().
+ *
+ * Events for the trigger pipe are processed here in order 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 other
+ * end of the pipe (see Tcl_AlertNotifier(),) which in turn will cause
+ * PlatformEventsWait() to return immediately.
+ */
- if (numQueued) {
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- timeoutPtr = &timeout;
+ numFound = PlatformEventsWait(tsdPtr->readyEvents,
+ tsdPtr->maxReadyEvents, timeoutPtr);
+ for (numEvent = 0; numEvent < numFound; numEvent++) {
+ pedPtr = (struct PlatformEventData *)
+ tsdPtr->readyEvents[numEvent].udata;
+ filePtr = pedPtr->filePtr;
+ mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
+ if (filePtr->fd == tsdPtr->triggerPipe[0]) {
+ 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) {
+ continue;
}
/*
- * Wait or poll for new events, queue Tcl events for the FileHandlers
- * corresponding to them, and update the FileHandlers' mask of events
- * of interest registered by the last call to Tcl_CreateFileHandler().
- *
- * Events for the trigger pipe are processed here in order 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
- * other end of the pipe (see Tcl_AlertNotifier(),) which in turn will
- * cause PlatformEventsWait() to return immediately.
+ * Don't bother to queue an event if the mask was previously non-zero
+ * since an event must still be on the queue.
*/
- numFound = PlatformEventsWait(tsdPtr->readyEvents,
- tsdPtr->maxReadyEvents, timeoutPtr);
- for (numEvent = 0; numEvent < numFound; numEvent++) {
- pedPtr = (struct PlatformEventData *)
- tsdPtr->readyEvents[numEvent].udata;
- filePtr = pedPtr->filePtr;
- mask = PlatformEventsTranslate(&tsdPtr->readyEvents[numEvent]);
- if (filePtr->fd == tsdPtr->triggerPipe[0]) {
- 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) {
- continue;
- }
-
- /*
- * Don't bother to queue an event if the mask was previously
- * non-zero since an event must still be on the queue.
- */
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
+ ckalloc(sizeof(FileHandlerEvent));
- if (filePtr->readyMask == 0) {
- FileHandlerEvent *fileEvPtr = (FileHandlerEvent *)
- ckalloc(sizeof(FileHandlerEvent));
-
- fileEvPtr->header.proc = FileHandlerEventProc;
- fileEvPtr->fd = filePtr->fd;
- Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
- }
- filePtr->readyMask |= mask;
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
}
- return 0;
+ filePtr->readyMask |= mask;
}
+ return 0;
}
#endif /* NOTIFIER_KQUEUE && TCL_THREADS */
+#else
+TCL_MAC_EMPTY_FILE(unix_tclKqueueNotfy_c)
#endif /* !HAVE_COREFOUNDATION */
/*
diff --git a/unix/tclLoadDyld.c b/unix/tclLoadDyld.c
index 017793d..7cd48f2 100644
--- a/unix/tclLoadDyld.c
+++ b/unix/tclLoadDyld.c
@@ -336,7 +336,7 @@ FindSymbol(
const char *symbol) /* Symbol name to look up. */
{
Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *)loadHandle->clientData;
- Tcl_PackageInitProc *proc = NULL;
+ Tcl_LibraryInitProc *proc = NULL;
const char *errMsg = NULL;
Tcl_DString ds;
const char *native;
@@ -344,7 +344,7 @@ FindSymbol(
native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
if (dyldLoadHandle->dlHandle) {
#if TCL_DYLD_USE_DLFCN
- proc = (Tcl_PackageInitProc *)dlsym(dyldLoadHandle->dlHandle, native);
+ proc = (Tcl_LibraryInitProc *)dlsym(dyldLoadHandle->dlHandle, native);
if (!proc) {
errMsg = dlerror();
}
@@ -400,7 +400,7 @@ FindSymbol(
dyldLoadHandle->modulePtr->module, native);
}
if (nsSymbol) {
- proc = (Tcl_PackageInitProc *)NSAddressOfSymbol(nsSymbol);
+ proc = (Tcl_LibraryInitProc *)NSAddressOfSymbol(nsSymbol);
}
Tcl_DStringFree(&newName);
#endif /* TCL_DYLD_USE_NSMODULE */
diff --git a/unix/tclLoadNext.c b/unix/tclLoadNext.c
index ee39326..2055210 100644
--- a/unix/tclLoadNext.c
+++ b/unix/tclLoadNext.c
@@ -133,7 +133,7 @@ FindSymbol(
Tcl_LoadHandle loadHandle,
const char *symbol)
{
- Tcl_PackageInitProc *proc = NULL;
+ Tcl_LibraryInitProc *proc = NULL;
if (symbol) {
char sym[strlen(symbol) + 2];
diff --git a/unix/tclLoadOSF.c b/unix/tclLoadOSF.c
index 7fd0cf3..bb58871 100644
--- a/unix/tclLoadOSF.c
+++ b/unix/tclLoadOSF.c
@@ -89,7 +89,7 @@ TclpDlopen(
*/
native = Tcl_FSGetNativePath(pathPtr);
- lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS);
+ lm = (Tcl_LibraryInitProc *) load(native, LDR_NOFLAGS);
if (lm == LDR_NULL_MODULE) {
/*
@@ -101,7 +101,7 @@ TclpDlopen(
Tcl_DString ds;
native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
- lm = (Tcl_PackageInitProc *) load(native, LDR_NOFLAGS);
+ lm = (Tcl_LibraryInitProc *) load(native, LDR_NOFLAGS);
Tcl_DStringFree(&ds);
}
diff --git a/unix/tclLoadShl.c b/unix/tclLoadShl.c
index 11eaa83..5bf97eb 100644
--- a/unix/tclLoadShl.c
+++ b/unix/tclLoadShl.c
@@ -128,7 +128,7 @@ FindSymbol(
const char *symbol)
{
Tcl_DString newName;
- Tcl_PackageInitProc *proc = NULL;
+ Tcl_LibraryInitProc *proc = NULL;
shl_t handle = (shl_t) loadHandle->clientData;
/*
diff --git a/unix/tclSelectNotfy.c b/unix/tclSelectNotfy.c
index 1d16114..82f2ef7 100644
--- a/unix/tclSelectNotfy.c
+++ b/unix/tclSelectNotfy.c
@@ -216,8 +216,8 @@ extern "C" {
typedef struct {
void *hwnd; /* Messaging window. */
unsigned int *message; /* Message payload. */
- size_t wParam; /* Event-specific "word" parameter. */
- size_t lParam; /* Event-specific "long" parameter. */
+ size_t wParam; /* Event-specific "word" parameter. */
+ size_t lParam; /* Event-specific "long" parameter. */
int time; /* Event timestamp. */
int x; /* Event location (where meaningful). */
int y;
@@ -244,8 +244,8 @@ extern void __stdcall CloseHandle(void *);
extern void *__stdcall CreateEventW(void *, unsigned char, unsigned char,
void *);
extern void *__stdcall CreateWindowExW(void *, const void *, const void *,
- unsigned int, int, int, int, int, void *, void *, void *,
- void *);
+ unsigned int, int, int, int, int, void *, void *,
+ void *, void *);
extern unsigned int __stdcall DefWindowProcW(void *, int, void *, void *);
extern unsigned char __stdcall DestroyWindow(void *);
extern int __stdcall DispatchMessageW(const MSG *);
@@ -271,14 +271,17 @@ static unsigned int __stdcall NotifierProc(void *hwnd, unsigned int message,
}
#endif
#endif /* TCL_THREADS && __CYGWIN__ */
-
+/*
+ * Incorporate the base notifier implementation.
+ */
+
#include "tclUnixNotfy.c"
/*
*----------------------------------------------------------------------
*
- * Tcl_InitNotifier --
+ * TclpInitNotifier --
*
* Initializes the platform specific notifier state.
*
@@ -292,75 +295,72 @@ static unsigned int __stdcall NotifierProc(void *hwnd, unsigned int message,
*/
ClientData
-Tcl_InitNotifier(void)
+TclpInitNotifier(void)
{
- if (tclNotifierHooks.initNotifierProc) {
- return tclNotifierHooks.initNotifierProc();
- } else {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#if TCL_THREADS
- tsdPtr->eventReady = 0;
+ tsdPtr->eventReady = 0;
- /*
- * Initialize thread specific condition variable for this thread.
- */
- if (tsdPtr->waitCVinitialized == 0) {
+ /*
+ * Initialize thread specific condition variable for this thread.
+ */
+
+ if (tsdPtr->waitCVinitialized == 0) {
#ifdef __CYGWIN__
- WNDCLASSW clazz;
-
- clazz.style = 0;
- clazz.cbClsExtra = 0;
- clazz.cbWndExtra = 0;
- clazz.hInstance = TclWinGetTclInstance();
- clazz.hbrBackground = NULL;
- clazz.lpszMenuName = NULL;
- clazz.lpszClassName = className;
- clazz.lpfnWndProc = (void *)NotifierProc;
- clazz.hIcon = NULL;
- clazz.hCursor = NULL;
-
- RegisterClassW(&clazz);
- tsdPtr->hwnd = CreateWindowExW(NULL, clazz.lpszClassName,
- clazz.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL,
- clazz.hInstance, NULL);
- tsdPtr->event = CreateEventW(NULL, 1 /* manual */,
- 0 /* !signaled */, NULL);
-#else
- pthread_cond_init(&tsdPtr->waitCV, NULL);
+ WNDCLASSW clazz;
+
+ clazz.style = 0;
+ clazz.cbClsExtra = 0;
+ clazz.cbWndExtra = 0;
+ clazz.hInstance = TclWinGetTclInstance();
+ clazz.hbrBackground = NULL;
+ clazz.lpszMenuName = NULL;
+ clazz.lpszClassName = className;
+ clazz.lpfnWndProc = (void *) NotifierProc;
+ clazz.hIcon = NULL;
+ clazz.hCursor = NULL;
+
+ RegisterClassW(&clazz);
+ tsdPtr->hwnd = CreateWindowExW(NULL, clazz.lpszClassName,
+ clazz.lpszClassName, 0, 0, 0, 0, 0, NULL, NULL,
+ clazz.hInstance, NULL);
+ tsdPtr->event = CreateEventW(NULL, 1 /* manual */,
+ 0 /* !signaled */, NULL);
+#else /* !__CYGWIN__ */
+ pthread_cond_init(&tsdPtr->waitCV, NULL);
#endif /* __CYGWIN__ */
- tsdPtr->waitCVinitialized = 1;
- }
+ tsdPtr->waitCVinitialized = 1;
+ }
- pthread_mutex_lock(&notifierInitMutex);
+ pthread_mutex_lock(&notifierInitMutex);
#if defined(HAVE_PTHREAD_ATFORK)
- /*
- * Install pthread_atfork handlers to clean up the notifier in the
- * child of a fork.
- */
+ /*
+ * Install pthread_atfork handlers to clean up the notifier in the child
+ * of a fork.
+ */
- if (!atForkInit) {
- int result = pthread_atfork(NULL, NULL, AtForkChild);
+ if (!atForkInit) {
+ int result = pthread_atfork(NULL, NULL, AtForkChild);
- if (result) {
- Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
- }
- atForkInit = 1;
+ if (result) {
+ Tcl_Panic("Tcl_InitNotifier: %s", "pthread_atfork failed");
}
+ atForkInit = 1;
+ }
#endif /* HAVE_PTHREAD_ATFORK */
- notifierCount++;
- pthread_mutex_unlock(&notifierInitMutex);
-
+ notifierCount++;
+ pthread_mutex_unlock(&notifierInitMutex);
#endif /* TCL_THREADS */
- return tsdPtr;
- }
+
+ return tsdPtr;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_FinalizeNotifier --
+ * TclpFinalizeNotifier --
*
* This function is called to cleanup the notifier state before a thread
* is terminated.
@@ -376,67 +376,62 @@ Tcl_InitNotifier(void)
*/
void
-Tcl_FinalizeNotifier(
- ClientData clientData)
+TclpFinalizeNotifier(
+ TCL_UNUSED(void *))
{
- if (tclNotifierHooks.finalizeNotifierProc) {
- tclNotifierHooks.finalizeNotifierProc(clientData);
- return;
- } else {
#if TCL_THREADS
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- pthread_mutex_lock(&notifierInitMutex);
- notifierCount--;
+ pthread_mutex_lock(&notifierInitMutex);
+ notifierCount--;
- /*
- * If this is the last thread to use the notifier, close the notifier
- * pipe and wait for the background thread to terminate.
- */
+ /*
+ * If this is the last thread to use the notifier, close the notifier pipe
+ * and wait for the background thread to terminate.
+ */
- 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 (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 (result) {
- Tcl_Panic("Tcl_FinalizeNotifier: %s",
- "unable to join notifier thread");
- }
- notifierThreadRunning = 0;
+ if (result) {
+ Tcl_Panic("Tcl_FinalizeNotifier: %s",
+ "unable to join notifier thread");
}
+ notifierThreadRunning = 0;
}
+ }
- /*
- * Clean up any synchronization objects in the thread local storage.
- */
+ /*
+ * Clean up any synchronization objects in the thread local storage.
+ */
#ifdef __CYGWIN__
- DestroyWindow(tsdPtr->hwnd);
- CloseHandle(tsdPtr->event);
-#else /* __CYGWIN__ */
- pthread_cond_destroy(&tsdPtr->waitCV);
+ DestroyWindow(tsdPtr->hwnd);
+ CloseHandle(tsdPtr->event);
+#else /* !__CYGWIN__ */
+ pthread_cond_destroy(&tsdPtr->waitCV);
#endif /* __CYGWIN__ */
- tsdPtr->waitCVinitialized = 0;
+ tsdPtr->waitCVinitialized = 0;
- pthread_mutex_unlock(&notifierInitMutex);
+ pthread_mutex_unlock(&notifierInitMutex);
#endif /* TCL_THREADS */
- }
}
/*
*----------------------------------------------------------------------
*
- * Tcl_CreateFileHandler --
+ * TclpCreateFileHandler --
*
* This function registers a file handler with the select notifier.
*
@@ -450,7 +445,7 @@ Tcl_FinalizeNotifier(
*/
void
-Tcl_CreateFileHandler(
+TclpCreateFileHandler(
int fd, /* Handle of stream to watch. */
int mask, /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, and TCL_EXCEPTION: indicates
@@ -460,59 +455,48 @@ Tcl_CreateFileHandler(
* event. */
ClientData clientData) /* Arbitrary data to pass to proc. */
{
- if (tclNotifierHooks.createFileHandlerProc) {
- tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
- return;
- } else {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- FileHandler *filePtr;
-
- for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL;
- filePtr = filePtr->nextPtr) {
- if (filePtr->fd == fd) {
- break;
- }
- }
- if (filePtr == NULL) {
- filePtr = (FileHandler *)ckalloc(sizeof(FileHandler));
- filePtr->fd = fd;
- filePtr->readyMask = 0;
- filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
- tsdPtr->firstFileHandlerPtr = filePtr;
- }
- filePtr->proc = proc;
- filePtr->clientData = clientData;
- filePtr->mask = mask;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);
+
+ if (filePtr == NULL) {
+ filePtr = (FileHandler *) ckalloc(sizeof(FileHandler));
+ filePtr->fd = fd;
+ filePtr->readyMask = 0;
+ filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
+ tsdPtr->firstFileHandlerPtr = filePtr;
+ }
+ filePtr->proc = proc;
+ filePtr->clientData = clientData;
+ filePtr->mask = mask;
- /*
- * Update the check masks for this file.
- */
+ /*
+ * Update the check masks for this file.
+ */
- if (mask & TCL_READABLE) {
- FD_SET(fd, &tsdPtr->checkMasks.readable);
- } else {
- FD_CLR(fd, &tsdPtr->checkMasks.readable);
- }
- if (mask & TCL_WRITABLE) {
- FD_SET(fd, &tsdPtr->checkMasks.writable);
- } else {
- FD_CLR(fd, &tsdPtr->checkMasks.writable);
- }
- if (mask & TCL_EXCEPTION) {
- FD_SET(fd, &tsdPtr->checkMasks.exception);
- } else {
- FD_CLR(fd, &tsdPtr->checkMasks.exception);
- }
- if (tsdPtr->numFdBits <= fd) {
- tsdPtr->numFdBits = fd+1;
- }
+ if (mask & TCL_READABLE) {
+ FD_SET(fd, &tsdPtr->checkMasks.readable);
+ } else {
+ FD_CLR(fd, &tsdPtr->checkMasks.readable);
+ }
+ if (mask & TCL_WRITABLE) {
+ FD_SET(fd, &tsdPtr->checkMasks.writable);
+ } else {
+ FD_CLR(fd, &tsdPtr->checkMasks.writable);
+ }
+ if (mask & TCL_EXCEPTION) {
+ FD_SET(fd, &tsdPtr->checkMasks.exception);
+ } else {
+ FD_CLR(fd, &tsdPtr->checkMasks.exception);
+ }
+ if (tsdPtr->numFdBits <= fd) {
+ tsdPtr->numFdBits = fd + 1;
}
}
/*
*----------------------------------------------------------------------
*
- * Tcl_DeleteFileHandler --
+ * TclpDeleteFileHandler --
*
* Cancel a previously-arranged callback arrangement for a file.
*
@@ -526,75 +510,65 @@ Tcl_CreateFileHandler(
*/
void
-Tcl_DeleteFileHandler(
+TclpDeleteFileHandler(
int fd) /* Stream id for which to remove callback
* function. */
{
- if (tclNotifierHooks.deleteFileHandlerProc) {
- tclNotifierHooks.deleteFileHandlerProc(fd);
- return;
- } else {
- FileHandler *filePtr, *prevPtr;
- int i;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr, *prevPtr;
+ int i;
- /*
- * Find the entry for the given file (and return if there isn't one).
- */
+ /*
+ * Find the entry for the given file (and return if there isn't one).
+ */
- for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
- prevPtr = filePtr, filePtr = filePtr->nextPtr) {
- if (filePtr == NULL) {
- return;
- }
- if (filePtr->fd == fd) {
- break;
- }
- }
+ filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
+ if (filePtr == NULL) {
+ return;
+ }
- /*
- * Update the check masks for this file.
- */
+ /*
+ * Update the check masks for this file.
+ */
- if (filePtr->mask & TCL_READABLE) {
- FD_CLR(fd, &tsdPtr->checkMasks.readable);
- }
- if (filePtr->mask & TCL_WRITABLE) {
- FD_CLR(fd, &tsdPtr->checkMasks.writable);
- }
- if (filePtr->mask & TCL_EXCEPTION) {
- FD_CLR(fd, &tsdPtr->checkMasks.exception);
- }
+ if (filePtr->mask & TCL_READABLE) {
+ FD_CLR(fd, &tsdPtr->checkMasks.readable);
+ }
+ if (filePtr->mask & TCL_WRITABLE) {
+ FD_CLR(fd, &tsdPtr->checkMasks.writable);
+ }
+ if (filePtr->mask & TCL_EXCEPTION) {
+ FD_CLR(fd, &tsdPtr->checkMasks.exception);
+ }
- /*
- * Find current max fd.
- */
+ /*
+ * Find current max fd.
+ */
- if (fd+1 == tsdPtr->numFdBits) {
- int numFdBits = 0;
+ if (fd + 1 == tsdPtr->numFdBits) {
+ int numFdBits = 0;
- for (i = fd-1; i >= 0; i--) {
- if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
- || FD_ISSET(i, &tsdPtr->checkMasks.writable)
- || FD_ISSET(i, &tsdPtr->checkMasks.exception)) {
- numFdBits = i+1;
- break;
- }
+ for (i = fd - 1; i >= 0; i--) {
+ if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
+ || FD_ISSET(i, &tsdPtr->checkMasks.writable)
+ || FD_ISSET(i, &tsdPtr->checkMasks.exception)) {
+ numFdBits = i + 1;
+ break;
}
- tsdPtr->numFdBits = numFdBits;
}
+ tsdPtr->numFdBits = numFdBits;
+ }
- /*
- * Clean up information in the callback record.
- */
+ /*
+ * Clean up information in the callback record.
+ */
- if (prevPtr == NULL) {
- tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
- } else {
- prevPtr->nextPtr = filePtr->nextPtr;
- }
- ckfree(filePtr);
+ if (prevPtr == NULL) {
+ tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
+ } else {
+ prevPtr->nextPtr = filePtr->nextPtr;
}
+ ckfree(filePtr);
}
#if defined(__CYGWIN__)
@@ -625,7 +599,7 @@ NotifierProc(
/*
*----------------------------------------------------------------------
*
- * Tcl_WaitForEvent --
+ * TclpWaitForEvent --
*
* 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
@@ -641,265 +615,261 @@ NotifierProc(
*/
int
-Tcl_WaitForEvent(
+TclpWaitForEvent(
const Tcl_Time *timePtr) /* Maximum block time, or NULL. */
{
- if (tclNotifierHooks.waitForEventProc) {
- return tclNotifierHooks.waitForEventProc(timePtr);
- } else {
- FileHandler *filePtr;
- int mask;
- Tcl_Time vTime;
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ FileHandler *filePtr;
+ int mask;
+ Tcl_Time vTime;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#if TCL_THREADS
- int waitForFiles;
+ int waitForFiles;
# ifdef __CYGWIN__
- MSG msg;
+ MSG msg;
# endif /* __CYGWIN__ */
#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()
- * used when the core is not thread-enabled.
- */
+ /*
+ * Impl. notes: timeout & timeoutPtr are used if, and only if threads are
+ * not enabled. They are the arguments for the regular select() used when
+ * the core is not thread-enabled.
+ */
- struct timeval timeout, *timeoutPtr;
- int numFound;
+ struct timeval timeout, *timeoutPtr;
+ int numFound;
#endif /* TCL_THREADS */
+ /*
+ * Set up the timeout structure. Note that if there are no events to check
+ * for, we return with a negative result rather than blocking forever.
+ */
+
+ if (timePtr != NULL) {
/*
- * Set up the timeout structure. Note that if there are no events to
- * check for, we return with a negative result rather than blocking
- * forever.
+ * TIP #233 (Virtualized Time). Is virtual time in effect? And do we
+ * actually have something to scale? If yes to both then we call the
+ * handler to do this scaling.
*/
- if (timePtr != NULL) {
- /*
- * TIP #233 (Virtualized Time). Is virtual time in effect? And do
- * we actually have something to scale? If yes to both then we
- * call the handler to do this scaling.
- */
-
- if (timePtr->sec != 0 || timePtr->usec != 0) {
- vTime = *timePtr;
- tclScaleTimeProcPtr(&vTime, tclTimeClientData);
- timePtr = &vTime;
- }
+ if (timePtr->sec != 0 || timePtr->usec != 0) {
+ vTime = *timePtr;
+ TclScaleTime(&vTime);
+ timePtr = &vTime;
+ }
#if !TCL_THREADS
- timeout.tv_sec = timePtr->sec;
- timeout.tv_usec = timePtr->usec;
- timeoutPtr = &timeout;
- } else if (tsdPtr->numFdBits == 0) {
- /*
- * If there are no threads, no timeout, and no fds registered,
- * then there are no events possible and we must avoid deadlock.
- * Note that this is not entirely correct because there might be a
- * signal that could interrupt the select call, but we don't
- * handle that case if we aren't using threads.
- */
+ timeout.tv_sec = timePtr->sec;
+ timeout.tv_usec = timePtr->usec;
+ timeoutPtr = &timeout;
+ } else if (tsdPtr->numFdBits == 0) {
+ /*
+ * If there are no threads, no timeout, and no fds registered, then
+ * there are no events possible and we must avoid deadlock. Note that
+ * this is not entirely correct because there might be a signal that
+ * could interrupt the select call, but we don't handle that case if
+ * we aren't using threads.
+ */
- return -1;
- } else {
- timeoutPtr = NULL;
+ return -1;
+ } else {
+ timeoutPtr = NULL;
#endif /* !TCL_THREADS */
- }
+ }
#if TCL_THREADS
- /*
- * Start notifier thread and place this thread on the list of
- * interested threads, signal the notifier thread, and wait for a
- * response or a timeout.
- */
- StartNotifierThread("Tcl_WaitForEvent");
+ /*
+ * Start notifier thread and place this thread on the list of interested
+ * threads, signal the notifier thread, and wait for a response or a
+ * timeout.
+ */
- pthread_mutex_lock(&notifierMutex);
+ StartNotifierThread("Tcl_WaitForEvent");
+
+ pthread_mutex_lock(&notifierMutex);
- if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0
+ if (timePtr != NULL && timePtr->sec == 0 && (timePtr->usec == 0
#if defined(__APPLE__) && defined(__LP64__)
- /*
- * On 64-bit Darwin, pthread_cond_timedwait() appears to have
- * a bug that causes it to wait forever when passed an
- * absolute time which has already been exceeded by the system
- * time; as a workaround, when given a very brief timeout,
- * just do a poll. [Bug 1457797]
- */
- || timePtr->usec < 10
-#endif /* __APPLE__ && __LP64__ */
- )) {
/*
- * Cannot emulate a polling select with a polling condition
- * variable. Instead, pretend to wait for files and tell the
- * notifier thread what we are doing. The notifier thread makes
- * sure it goes through select with its select mask in the same
- * state as ours currently is. We block until that happens.
+ * On 64-bit Darwin, pthread_cond_timedwait() appears to have a
+ * bug that causes it to wait forever when passed an absolute time
+ * which has already been exceeded by the system time; as a
+ * workaround, when given a very brief timeout, just do a poll.
+ * [Bug 1457797]
*/
+ || timePtr->usec < 10
+#endif /* __APPLE__ && __LP64__ */
+ )) {
+ /*
+ * Cannot emulate a polling select with a polling condition variable.
+ * Instead, pretend to wait for files and tell the notifier thread
+ * what we are doing. The notifier thread makes sure it goes through
+ * select with its select mask in the same state as ours currently is.
+ * We block until that happens.
+ */
- waitForFiles = 1;
- tsdPtr->pollState = POLL_WANT;
- timePtr = NULL;
- } else {
- waitForFiles = (tsdPtr->numFdBits > 0);
- tsdPtr->pollState = 0;
- }
+ waitForFiles = 1;
+ tsdPtr->pollState = POLL_WANT;
+ timePtr = NULL;
+ } else {
+ waitForFiles = (tsdPtr->numFdBits > 0);
+ tsdPtr->pollState = 0;
+ }
- if (waitForFiles) {
- /*
- * Add the ThreadSpecificData structure of this thread to the list
- * of ThreadSpecificData structures of all threads that are
- * waiting on file events.
- */
+ if (waitForFiles) {
+ /*
+ * Add the ThreadSpecificData structure of this thread to the list of
+ * ThreadSpecificData structures of all threads that are waiting on
+ * file events.
+ */
- tsdPtr->nextPtr = waitingListPtr;
- if (waitingListPtr) {
- waitingListPtr->prevPtr = tsdPtr;
- }
- tsdPtr->prevPtr = 0;
- waitingListPtr = tsdPtr;
- tsdPtr->onList = 1;
+ tsdPtr->nextPtr = waitingListPtr;
+ if (waitingListPtr) {
+ waitingListPtr->prevPtr = tsdPtr;
+ }
+ tsdPtr->prevPtr = 0;
+ waitingListPtr = tsdPtr;
+ tsdPtr->onList = 1;
- if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
- Tcl_Panic("Tcl_WaitForEvent: %s",
- "unable to write to triggerPipe");
- }
+ if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
+ Tcl_Panic("Tcl_WaitForEvent: %s",
+ "unable to write to triggerPipe");
}
+ }
- FD_ZERO(&tsdPtr->readyMasks.readable);
- FD_ZERO(&tsdPtr->readyMasks.writable);
- FD_ZERO(&tsdPtr->readyMasks.exception);
+ FD_ZERO(&tsdPtr->readyMasks.readable);
+ FD_ZERO(&tsdPtr->readyMasks.writable);
+ FD_ZERO(&tsdPtr->readyMasks.exception);
- if (!tsdPtr->eventReady) {
+ if (!tsdPtr->eventReady) {
#ifdef __CYGWIN__
- if (!PeekMessageW(&msg, NULL, 0, 0, 0)) {
- unsigned int timeout;
+ if (!PeekMessageW(&msg, NULL, 0, 0, 0)) {
+ unsigned int timeout;
- if (timePtr) {
- timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
- } else {
- timeout = 0xFFFFFFFF;
- }
- pthread_mutex_unlock(&notifierMutex);
- MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
- pthread_mutex_lock(&notifierMutex);
+ if (timePtr) {
+ timeout = timePtr->sec * 1000 + timePtr->usec / 1000;
+ } else {
+ timeout = 0xFFFFFFFF;
}
+ pthread_mutex_unlock(&notifierMutex);
+ MsgWaitForMultipleObjects(1, &tsdPtr->event, 0, timeout, 1279);
+ pthread_mutex_lock(&notifierMutex);
+ }
#else /* !__CYGWIN__ */
- if (timePtr != NULL) {
- Tcl_Time now;
- struct timespec ptime;
+ if (timePtr != NULL) {
+ 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);
- } else {
- pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
- }
-#endif /* __CYGWIN__ */
+ pthread_cond_timedwait(&tsdPtr->waitCV, &notifierMutex, &ptime);
+ } else {
+ pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
}
- tsdPtr->eventReady = 0;
+#endif /* __CYGWIN__ */
+ }
+ tsdPtr->eventReady = 0;
#ifdef __CYGWIN__
- while (PeekMessageW(&msg, NULL, 0, 0, 0)) {
- /*
- * Retrieve and dispatch the message.
- */
+ while (PeekMessageW(&msg, NULL, 0, 0, 0)) {
+ /*
+ * Retrieve and dispatch the message.
+ */
- unsigned int result = GetMessageW(&msg, NULL, 0, 0);
+ unsigned int result = GetMessageW(&msg, NULL, 0, 0);
- if (result == 0) {
- PostQuitMessage(msg.wParam);
- /* What to do here? */
- } else if (result != (unsigned int) -1) {
- TranslateMessage(&msg);
- DispatchMessageW(&msg);
- }
+ if (result == 0) {
+ PostQuitMessage(msg.wParam);
+ /* What to do here? */
+ } else if (result != (unsigned int) -1) {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
}
- ResetEvent(tsdPtr->event);
+ }
+ ResetEvent(tsdPtr->event);
#endif /* __CYGWIN__ */
- if (waitForFiles && tsdPtr->onList) {
- /*
- * Remove the ThreadSpecificData structure of this thread from the
- * waiting list. Alert the notifier thread to recompute its select
- * masks - skipping this caused a hang when trying to close a pipe
- * which the notifier thread was still doing a select on.
- */
+ if (waitForFiles && tsdPtr->onList) {
+ /*
+ * Remove the ThreadSpecificData structure of this thread from the
+ * waiting list. Alert the notifier thread to recompute its select
+ * masks - skipping this caused a hang when trying to close a pipe
+ * which the notifier thread was still doing a select on.
+ */
- if (tsdPtr->prevPtr) {
- tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
- } else {
- waitingListPtr = tsdPtr->nextPtr;
- }
- if (tsdPtr->nextPtr) {
- tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
- }
- tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
- tsdPtr->onList = 0;
- if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
- Tcl_Panic("Tcl_WaitForEvent: %s",
- "unable to write to triggerPipe");
- }
+ if (tsdPtr->prevPtr) {
+ tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;
+ } else {
+ waitingListPtr = tsdPtr->nextPtr;
+ }
+ if (tsdPtr->nextPtr) {
+ tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr;
}
+ tsdPtr->nextPtr = tsdPtr->prevPtr = NULL;
+ tsdPtr->onList = 0;
+ if ((write(triggerPipe, "", 1) == -1) && (errno != EAGAIN)) {
+ Tcl_Panic("Tcl_WaitForEvent: %s",
+ "unable to write to triggerPipe");
+ }
+ }
#else /* !TCL_THREADS */
- tsdPtr->readyMasks = tsdPtr->checkMasks;
- numFound = select(tsdPtr->numFdBits, &tsdPtr->readyMasks.readable,
- &tsdPtr->readyMasks.writable, &tsdPtr->readyMasks.exception,
- timeoutPtr);
+ tsdPtr->readyMasks = tsdPtr->checkMasks;
+ numFound = select(tsdPtr->numFdBits, &tsdPtr->readyMasks.readable,
+ &tsdPtr->readyMasks.writable, &tsdPtr->readyMasks.exception,
+ timeoutPtr);
- /*
- * Some systems don't clear the masks after an error, so we have to do
- * it here.
- */
+ /*
+ * Some systems don't clear the masks after an error, so we have to do it
+ * here.
+ */
- if (numFound == -1) {
- FD_ZERO(&tsdPtr->readyMasks.readable);
- FD_ZERO(&tsdPtr->readyMasks.writable);
- FD_ZERO(&tsdPtr->readyMasks.exception);
- }
+ if (numFound == -1) {
+ FD_ZERO(&tsdPtr->readyMasks.readable);
+ FD_ZERO(&tsdPtr->readyMasks.writable);
+ FD_ZERO(&tsdPtr->readyMasks.exception);
+ }
#endif /* TCL_THREADS */
- /*
- * Queue all detected file events before returning.
- */
+ /*
+ * Queue all detected file events before returning.
+ */
- for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
- filePtr = filePtr->nextPtr) {
- mask = 0;
- if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.readable)) {
- mask |= TCL_READABLE;
- }
- if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.writable)) {
- mask |= TCL_WRITABLE;
- }
- if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.exception)) {
- mask |= TCL_EXCEPTION;
- }
+ for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL);
+ filePtr = filePtr->nextPtr) {
+ mask = 0;
+ if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.readable)) {
+ mask |= TCL_READABLE;
+ }
+ if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.writable)) {
+ mask |= TCL_WRITABLE;
+ }
+ if (FD_ISSET(filePtr->fd, &tsdPtr->readyMasks.exception)) {
+ mask |= TCL_EXCEPTION;
+ }
- if (!mask) {
- continue;
- }
+ if (!mask) {
+ continue;
+ }
- /*
- * Don't bother to queue an event if the mask was previously
- * non-zero since an event must still be on the queue.
- */
+ /*
+ * Don't bother to queue an event if the mask was previously non-zero
+ * since an event must still be on the queue.
+ */
- if (filePtr->readyMask == 0) {
- FileHandlerEvent *fileEvPtr =
- (FileHandlerEvent *)ckalloc(sizeof(FileHandlerEvent));
+ if (filePtr->readyMask == 0) {
+ FileHandlerEvent *fileEvPtr =
+ (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent));
- fileEvPtr->header.proc = FileHandlerEventProc;
- fileEvPtr->fd = filePtr->fd;
- Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
- }
- filePtr->readyMask = mask;
+ fileEvPtr->header.proc = FileHandlerEventProc;
+ fileEvPtr->fd = filePtr->fd;
+ Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
}
+ filePtr->readyMask = mask;
+ }
#if TCL_THREADS
- pthread_mutex_unlock(&notifierMutex);
+ pthread_mutex_unlock(&notifierMutex);
#endif /* TCL_THREADS */
- return 0;
- }
+ return 0;
}
/*
@@ -916,8 +886,9 @@ Tcl_WaitForEvent(
* byte to a special pipe that the notifier thread is monitoring.
*
* Result:
- * None. Once started, this routine never exits. It dies with the overall
- * process.
+ * None. Once started, this routine normally never exits and usually dies
+ * with the overall process, but it can be shut down if the Tcl library
+ * is finalized.
*
* Side effects:
* The trigger pipe used to signal the notifier thread is created when
@@ -1048,7 +1019,7 @@ NotifierThreadProc(
for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) {
found = 0;
- for (i = tsdPtr->numFdBits-1; i >= 0; --i) {
+ for (i = tsdPtr->numFdBits - 1; i >= 0; --i) {
if (FD_ISSET(i, &tsdPtr->checkMasks.readable)
&& FD_ISSET(i, &readableMask)) {
FD_SET(i, &tsdPtr->readyMasks.readable);
@@ -1113,6 +1084,8 @@ NotifierThreadProc(
#endif /* TCL_THREADS */
#endif /* (!NOTIFIER_EPOLL && !NOTIFIER_KQUEUE) || !TCL_THREADS */
+#else
+TCL_MAC_EMPTY_FILE(unix_tclSelectNotfy_c)
#endif /* !HAVE_COREFOUNDATION */
/*
diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c
index 837aa59..4cb9af0 100644
--- a/unix/tclUnixChan.c
+++ b/unix/tclUnixChan.c
@@ -282,12 +282,15 @@ FileInputProc(
* nonblocking, the read will never block.
*/
- bytesRead = read(fsPtr->fd, buf, (size_t) toRead);
- if (bytesRead >= 0) {
- return bytesRead;
+ do {
+ bytesRead = read(fsPtr->fd, buf, (size_t) toRead);
+ } while ((bytesRead < 0) && (errno == EINTR));
+
+ if (bytesRead < 0) {
+ *errorCodePtr = errno;
+ return -1;
}
- *errorCodePtr = errno;
- return -1;
+ return bytesRead;
}
/*
diff --git a/unix/tclUnixCompat.c b/unix/tclUnixCompat.c
index 74b4bf3..9e43c01 100644
--- a/unix/tclUnixCompat.c
+++ b/unix/tclUnixCompat.c
@@ -1009,6 +1009,9 @@ TclWinCPUID(
: "a"(index));
#endif
status = TCL_OK;
+#else
+ (void)index;
+ (void)regsPtr;
#endif
return status;
}
diff --git a/unix/tclUnixEvent.c b/unix/tclUnixEvent.c
index aff7797..0047dd9 100644
--- a/unix/tclUnixEvent.c
+++ b/unix/tclUnixEvent.c
@@ -64,7 +64,7 @@ Tcl_Sleep(
}
if ((vdelay.sec != 0) || (vdelay.usec != 0)) {
- tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
+ TclScaleTime(&vdelay);
}
delay.tv_sec = vdelay.sec;
@@ -85,6 +85,8 @@ Tcl_Sleep(
}
}
+#else
+TCL_MAC_EMPTY_FILE(unix_tclUnixEvent_c)
#endif /* HAVE_COREFOUNDATION */
/*
* Local Variables:
diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c
index 4d08c1d..9e9a493 100644
--- a/unix/tclUnixFCmd.c
+++ b/unix/tclUnixFCmd.c
@@ -2350,7 +2350,7 @@ StatError(
Tcl_Obj *fileName) /* The name of the file which caused the
* error. */
{
- TclWinConvertError(GetLastError());
+ Tcl_WinConvertError(GetLastError());
Tcl_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s",
TclGetString(fileName), Tcl_PosixError(interp)));
}
diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c
index 203a118..1ab5d14 100644
--- a/unix/tclUnixFile.c
+++ b/unix/tclUnixFile.c
@@ -44,8 +44,8 @@ TclpFindExecutable(
wchar_t buf[PATH_MAX];
char name[PATH_MAX * 3 + 1];
- GetModuleFileNameW(NULL, buf, PATH_MAX);
- cygwin_conv_path(3, buf, name, PATH_MAX);
+ GetModuleFileNameW(NULL, buf, sizeof(buf)/sizeof(wchar_t));
+ cygwin_conv_path(3, buf, name, sizeof(name));
length = strlen(name);
if ((length > 4) && !strcasecmp(name + length - 4, ".exe")) {
/* Strip '.exe' part. */
diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c
index d992d65..c1f00d5 100644
--- a/unix/tclUnixNotfy.c
+++ b/unix/tclUnixNotfy.c
@@ -2,10 +2,12 @@
* tclUnixNotfy.c --
*
* This file contains subroutines shared by all notifier backend
- * implementations on *nix platforms.
+ * implementations on *nix platforms. It is *included* by the epoll,
+ * kqueue and select notifier implementation files.
*
* Copyright © 1995-1997 Sun Microsystems, Inc.
* Copyright © 2016 Lucio Andrés Illanes Albornoz <l.illanes@gmx.de>
+ * Copyright © 2021 Donal K. Fellows
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -45,8 +47,10 @@ static void AtForkChild(void);
*
*----------------------------------------------------------------------
*/
+
static void
-StartNotifierThread(const char *proc)
+StartNotifierThread(
+ const char *proc)
{
if (!notifierThreadRunning) {
pthread_mutex_lock(&notifierInitMutex);
@@ -57,6 +61,7 @@ StartNotifierThread(const char *proc)
}
pthread_mutex_lock(&notifierMutex);
+
/*
* Wait for the notifier pipe to be created.
*/
@@ -76,7 +81,7 @@ StartNotifierThread(const char *proc)
/*
*----------------------------------------------------------------------
*
- * Tcl_AlertNotifier --
+ * TclpAlertNotifier --
*
* Wake up the specified notifier from any thread. This routine is called
* by the platform independent notifier code whenever the Tcl_ThreadAlert
@@ -99,50 +104,97 @@ StartNotifierThread(const char *proc)
*/
void
-Tcl_AlertNotifier(
+TclpAlertNotifier(
ClientData clientData)
{
- if (tclNotifierHooks.alertNotifierProc) {
- tclNotifierHooks.alertNotifierProc(clientData);
- return;
- } else {
#ifdef NOTIFIER_SELECT
#if TCL_THREADS
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
- pthread_mutex_lock(&notifierMutex);
- tsdPtr->eventReady = 1;
+ pthread_mutex_lock(&notifierMutex);
+ tsdPtr->eventReady = 1;
# ifdef __CYGWIN__
- PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
+ PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
# else
- pthread_cond_broadcast(&tsdPtr->waitCV);
+ pthread_cond_broadcast(&tsdPtr->waitCV);
# endif /* __CYGWIN__ */
- pthread_mutex_unlock(&notifierMutex);
+ pthread_mutex_unlock(&notifierMutex);
#endif /* TCL_THREADS */
#else /* !NOTIFIER_SELECT */
- ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData;
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;
#if defined(NOTIFIER_EPOLL) && defined(HAVE_EVENTFD)
- uint64_t eventFdVal = 1;
- if (write(tsdPtr->triggerEventFd, &eventFdVal,
- sizeof(eventFdVal)) != sizeof(eventFdVal)) {
- Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerEventFd",
- (void *)tsdPtr);
- }
+ uint64_t eventFdVal = 1;
+
+ if (write(tsdPtr->triggerEventFd, &eventFdVal,
+ 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);
- }
+ 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_SELECT */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * LookUpFileHandler --
+ *
+ * Look up the file handler structure (and optionally the previous one in
+ * the chain) associated with a file descriptor.
+ *
+ * Returns:
+ * A pointer to the file handler, or NULL if it can't be found.
+ *
+ * Side effects:
+ * If prevPtrPtr is non-NULL, it will be written to if the file handler
+ * is found.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static inline FileHandler *
+LookUpFileHandler(
+ ThreadSpecificData *tsdPtr, /* Where to look things up. */
+ int fd, /* What we are looking for. */
+ FileHandler **prevPtrPtr) /* If non-NULL, where to report the previous
+ * pointer. */
+{
+ FileHandler *filePtr, *prevPtr;
+
+ /*
+ * Find the entry for the given file (and return if there isn't one).
+ */
+
+ for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
+ prevPtr = filePtr, filePtr = filePtr->nextPtr) {
+ if (filePtr == NULL) {
+ return NULL;
+ }
+ if (filePtr->fd == fd) {
+ break;
+ }
+ }
+
+ /*
+ * Report what we've found to our caller.
+ */
+
+ if (prevPtrPtr) {
+ *prevPtrPtr = prevPtr;
}
+ return filePtr;
}
/*
*----------------------------------------------------------------------
*
- * Tcl_SetTimer --
+ * TclpSetTimer --
*
* This function sets the current notifier timer value. This interface is
* not implemented in this notifier because we are always running inside
@@ -158,19 +210,14 @@ Tcl_AlertNotifier(
*/
void
-Tcl_SetTimer(
- const Tcl_Time *timePtr) /* Timeout value, may be NULL. */
+TclpSetTimer(
+ TCL_UNUSED(const Tcl_Time *)) /* Timeout value, may be NULL. */
{
- if (tclNotifierHooks.setTimerProc) {
- tclNotifierHooks.setTimerProc(timePtr);
- return;
- } else {
- /*
- * The interval timer doesn't do anything in this implementation,
- * because the only event loop is via Tcl_DoOneEvent, which passes
- * timeout values to Tcl_WaitForEvent.
- */
- }
+ /*
+ * The interval timer doesn't do anything in this implementation, because
+ * the only event loop is via Tcl_DoOneEvent, which passes timeout values
+ * to Tcl_WaitForEvent.
+ */
}
/*
@@ -190,14 +237,11 @@ Tcl_SetTimer(
*/
void
-Tcl_ServiceModeHook(
+TclpServiceModeHook(
int mode) /* Either TCL_SERVICE_ALL, or
* TCL_SERVICE_NONE. */
{
- if (tclNotifierHooks.serviceModeHookProc) {
- tclNotifierHooks.serviceModeHookProc(mode);
- return;
- } else if (mode == TCL_SERVICE_ALL) {
+ if (mode == TCL_SERVICE_ALL) {
#ifdef NOTIFIER_SELECT
#if TCL_THREADS
StartNotifierThread("Tcl_ServiceModeHook");
@@ -414,12 +458,9 @@ AtForkChild(void)
Tcl_InitNotifier();
}
#endif /* HAVE_PTHREAD_ATFORK */
-
#endif /* TCL_THREADS */
-
#endif /* NOTIFIER_SELECT */
-#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
- * in tclMacOSXNotify.c */
+
/*
*----------------------------------------------------------------------
*
@@ -443,6 +484,9 @@ AtForkChild(void)
*----------------------------------------------------------------------
*/
+#ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is
+ * in tclMacOSXNotify.c */
+
int
TclUnixWaitForFile(
int fd, /* Handle for file on which to wait. */
@@ -563,9 +607,8 @@ TclUnixWaitForFile(
|| (abortTime.sec == now.sec && abortTime.usec > now.usec));
return result;
}
-
#endif /* !HAVE_COREFOUNDATION */
-
+
/*
* Local Variables:
* mode: c
diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h
index e2f1104..ece0202 100644
--- a/unix/tclUnixPort.h
+++ b/unix/tclUnixPort.h
@@ -95,6 +95,8 @@ extern "C" {
# define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004
# define HANDLE void *
# define HINSTANCE void *
+# define HMODULE void *
+# define MAX_PATH 260
# define SOCKET unsigned int
# define WSAEWOULDBLOCK 10035
typedef unsigned short WCHAR;
diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c
index adeacb6..e0c7ac8 100644
--- a/unix/tclUnixTime.c
+++ b/unix/tclUnixTime.c
@@ -61,6 +61,23 @@ Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime;
void *tclTimeClientData = NULL;
/*
+ * Inlined version of Tcl_GetTime.
+ */
+
+static inline void
+GetTime(
+ Tcl_Time *timePtr)
+{
+ tclGetTimeProcPtr(timePtr, tclTimeClientData);
+}
+
+static inline int
+IsTimeNative(void)
+{
+ return tclGetTimeProcPtr == NativeGetTime;
+}
+
+/*
*----------------------------------------------------------------------
*
* TclpGetSeconds --
@@ -105,8 +122,8 @@ TclpGetMicroseconds(void)
{
Tcl_Time time;
- tclGetTimeProcPtr(&time, tclTimeClientData);
- return ((long long)time.sec)*1000000 + time.usec;
+ GetTime(&time);
+ return ((long long) time.sec)*1000000 + time.usec;
}
/*
@@ -134,10 +151,10 @@ TclpGetClicks(void)
unsigned long now;
#ifdef NO_GETTOD
- if (tclGetTimeProcPtr != NativeGetTime) {
+ if (!IsTimeNative()) {
Tcl_Time time;
- tclGetTimeProcPtr(&time, tclTimeClientData);
+ GetTime(&time);
now = time.sec*1000000 + time.usec;
} else {
/*
@@ -147,12 +164,12 @@ TclpGetClicks(void)
now = (unsigned long) times(&dummy);
}
-#else
+#else /* !NO_GETTOD */
Tcl_Time time;
- tclGetTimeProcPtr(&time, tclTimeClientData);
+ GetTime(&time);
now = time.sec*1000000 + time.usec;
-#endif
+#endif /* NO_GETTOD */
return now;
}
@@ -182,17 +199,17 @@ TclpGetWideClicks(void)
{
long long now;
- if (tclGetTimeProcPtr != NativeGetTime) {
+ if (!IsTimeNative()) {
Tcl_Time time;
- tclGetTimeProcPtr(&time, tclTimeClientData);
- now = ((long long)time.sec)*1000000 + time.usec;
+ GetTime(&time);
+ now = ((long long) time.sec)*1000000 + time.usec;
} else {
#ifdef MAC_OSX_TCL
now = (long long) (mach_absolute_time() & INT64_MAX);
#else
#error Wide high-resolution clicks not implemented on this platform
-#endif
+#endif /* MAC_OSX_TCL */
}
return now;
@@ -221,7 +238,7 @@ TclpWideClicksToNanoseconds(
{
double nsec;
- if (tclGetTimeProcPtr != NativeGetTime) {
+ if (!IsTimeNative()) {
nsec = clicks * 1000;
} else {
#ifdef MAC_OSX_TCL
@@ -239,7 +256,7 @@ TclpWideClicksToNanoseconds(
}
#else
#error Wide high-resolution clicks not implemented on this platform
-#endif
+#endif /* MAC_OSX_TCL */
}
return nsec;
@@ -266,7 +283,7 @@ TclpWideClicksToNanoseconds(
double
TclpWideClickInMicrosec(void)
{
- if (tclGetTimeProcPtr != NativeGetTime) {
+ if (!IsTimeNative()) {
return 1.0;
} else {
#ifdef MAC_OSX_TCL
@@ -286,7 +303,7 @@ TclpWideClickInMicrosec(void)
}
#else
#error Wide high-resolution clicks not implemented on this platform
-#endif
+#endif /* MAC_OSX_TCL */
}
}
#endif /* TCL_WIDE_CLICKS */
@@ -315,7 +332,7 @@ void
Tcl_GetTime(
Tcl_Time *timePtr) /* Location to store time information. */
{
- tclGetTimeProcPtr(timePtr, tclTimeClientData);
+ GetTime(timePtr);
}
/*
@@ -578,7 +595,7 @@ SetTZIfNecessary(void)
} else {
ckfree(lastTZ);
}
- lastTZ = (char *)ckalloc(strlen(newTZ) + 1);
+ lastTZ = (char *) ckalloc(strlen(newTZ) + 1);
strcpy(lastTZ, newTZ);
}
Tcl_MutexUnlock(&tmMutex);
diff --git a/unix/tclXtNotify.c b/unix/tclXtNotify.c
index 68ee578..3d90135 100644
--- a/unix/tclXtNotify.c
+++ b/unix/tclXtNotify.c
@@ -132,7 +132,7 @@ TclSetAppContext(
* after initialization, so we panic.
*/
- Tcl_Panic("TclSetAppContext: multiple application contexts");
+ Tcl_Panic("TclSetAppContext: multiple application contexts");
}
} else {
/*
@@ -359,7 +359,7 @@ CreateFileHandler(
}
}
if (filePtr == NULL) {
- filePtr = (FileHandler *)ckalloc(sizeof(FileHandler));
+ filePtr = (FileHandler *) ckalloc(sizeof(FileHandler));
filePtr->fd = fd;
filePtr->read = 0;
filePtr->write = 0;
@@ -496,7 +496,7 @@ FileProc(
int *fd,
XtInputId *id)
{
- FileHandler *filePtr = (FileHandler *)clientData;
+ FileHandler *filePtr = (FileHandler *) clientData;
FileHandlerEvent *fileEvPtr;
int mask = 0;
@@ -525,7 +525,7 @@ FileProc(
*/
filePtr->readyMask |= mask;
- fileEvPtr = (FileHandlerEvent *)ckalloc(sizeof(FileHandlerEvent));
+ fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent));
fileEvPtr->header.proc = FileHandlerEventProc;
fileEvPtr->fd = filePtr->fd;
Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
diff --git a/unix/tclXtTest.c b/unix/tclXtTest.c
index afac493..882f497 100644
--- a/unix/tclXtTest.c
+++ b/unix/tclXtTest.c
@@ -16,7 +16,6 @@
#include "tcl.h"
static Tcl_ObjCmdProc TesteventloopCmd;
-extern DLLEXPORT Tcl_PackageInitProc Tclxttest_Init;
/*
* Functions defined in tclXtNotify.c for use by users of the Xt Notifier:
@@ -44,7 +43,7 @@ extern XtAppContext TclSetAppContext(XtAppContext ctx);
*----------------------------------------------------------------------
*/
-int
+DLLEXPORT int
Tclxttest_Init(
Tcl_Interp *interp) /* Interpreter for application. */
{