From 7946e043840cfab27940a93f7647d136eda8b6d4 Mon Sep 17 00:00:00 2001 From: hobbs Date: Fri, 8 Feb 2002 09:33:03 +0000 Subject: * unix/tclUnixPort.h: * unix/tclUnixThrd.c: added thread-safe versions of readdir, localtime, gmtime and inet_ntoa for threaded build. (jgdavidson) --- unix/tclUnixPort.h | 10 +++++++- unix/tclUnixThrd.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h index 4ca092a..0fafe9f 100644 --- a/unix/tclUnixPort.h +++ b/unix/tclUnixPort.h @@ -19,7 +19,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUnixPort.h,v 1.18 2001/08/30 08:53:15 vincentdarley Exp $ + * RCS: @(#) $Id: tclUnixPort.h,v 1.19 2002/02/08 09:33:03 hobbs Exp $ */ #ifndef _TCLUNIXPORT @@ -497,6 +497,14 @@ typedef pthread_mutex_t TclpMutex; EXTERN void TclpMutexInit _ANSI_ARGS_((TclpMutex *mPtr)); EXTERN void TclpMutexLock _ANSI_ARGS_((TclpMutex *mPtr)); EXTERN void TclpMutexUnlock _ANSI_ARGS_((TclpMutex *mPtr)); +EXTERN struct dirent * TclpReaddir(DIR *); +EXTERN struct tm * TclpLocaltime(time_t *); +EXTERN struct tm * TclpGmtime(time_t *); +EXTERN char * TclpInetNtoa(struct in_addr); +#define readdir(x) TclpReaddir(x) +#define localtime(x) TclpLocaltime(x) +#define gmtime(x) TclpGmtime(x) +#define inet_ntoa(x) TclpInetNtoa(x) #else typedef int TclpMutex; #define TclpMutexInit(a) diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index ccffe3a..5086b2d 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -19,6 +19,18 @@ #include "tclPort.h" #include "pthread.h" +typedef struct ThreadSpecificData { + char nabuf[16]; + struct tm gtbuf; + struct tm ltbuf; + struct { + struct dirent ent; + char name[PATH_MAX+1]; + } rdbuf; +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; + /* * masterLock is used to serialize creation of mutexes, condition * variables, and thread local storage. @@ -760,8 +772,65 @@ TclpFinalizeCondition(condPtr) *condPtr = NULL; } } + +/* + *---------------------------------------------------------------------- + * + * TclpReaddir, TclpLocaltime, TclpGmtime, TclpInetNtoa -- + * + * These procedures replace core C versions to be used in a + * threaded environment. + * + * Results: + * See documentation of C functions. + * + * Side effects: + * See documentation of C functions. + * + *---------------------------------------------------------------------- + */ +struct dirent * +TclpReaddir(DIR * dir) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + struct dirent *ent; + ent = &tsdPtr->rdbuf.ent; + if (readdir_r(dir, ent, &ent) != 0) { + ent = NULL; + } + return ent; +} -#endif /* TCL_THREADS */ +struct tm * +TclpLocaltime(time_t * clock) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + return localtime_r(clock, &tsdPtr->ltbuf); +} + +struct tm * +TclpGmtime(time_t * clock) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + return gmtime_r(clock, &tsdPtr->gtbuf); +} + +char * +TclpInetNtoa(struct in_addr addr) +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + union { + unsigned long l; + unsigned char b[4]; + } u; + + u.l = (unsigned long) addr.s_addr; + sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", u.b[0], u.b[1], u.b[2], u.b[3]); + return tsdPtr->nabuf; +} + +#endif /* TCL_THREADS */ -- cgit v0.12