Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Feb 2013 13:40:57 -0800
From:      John-Mark Gurney <jmg@funkthat.com>
To:        freebsd-i18n@FreeBSD.org
Subject:   Re: patch for in tree iconv
Message-ID:  <20130227214057.GD55866@funkthat.com>
In-Reply-To: <20130227213200.GB55866@funkthat.com>
References:  <20130227213200.GB55866@funkthat.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--4f28nU6agdXSinmL
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

John-Mark Gurney wrote this message on Wed, Feb 27, 2013 at 13:32 -0800:
> I've worked at fixing a few of iconv's locking issues, and I've attached
> this patch.  This should fix most/all of the locking related issues
> relating to the global lock...

I should of included the patch... Oops...

In case the patch gets stripped:
http://people.FreeBSD.org/~jmg/iconv.patch

-- 
  John-Mark Gurney				Voice: +1 415 225 5579

     "All that I will do, has been done, All that I have, has not."

--4f28nU6agdXSinmL
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="iconv.patch"

Index: lib/libc/iconv/citrus_csmapper.c
===================================================================
--- lib/libc/iconv/citrus_csmapper.c	(revision 247143)
+++ lib/libc/iconv/citrus_csmapper.c	(working copy)
@@ -312,24 +312,36 @@
 get_none(struct _citrus_mapper_area *__restrict ma,
     struct _citrus_csmapper *__restrict *__restrict rcsm)
 {
+	struct _citrus_csmapper *csm_tmp;
 	int ret;
 
-	WLOCK;
-	if (csm_none) {
+	WLOCK();
+	if (csm_none != NULL) {
 		*rcsm = csm_none;
+		UNLOCK();
 		ret = 0;
 		goto quit;
 	}
 
-	ret = _mapper_open_direct(ma, &csm_none, "mapper_none", "");
+	UNLOCK();
+	ret = _mapper_open_direct(ma, &csm_tmp, "mapper_none", "");
 	if (ret)
 		goto quit;
+
 	_mapper_set_persistent(csm_none);
 
+	WLOCK();
+	if (csm_none != NULL) {
+		UNLOCK();
+		_mapper_close(csm_tmp);
+	} else {
+		csm_none = csm_tmp;
+		UNLOCK();
+	}
+
 	*rcsm = csm_none;
 	ret = 0;
 quit:
-	UNLOCK;
 	return (ret);
 }
 
Index: lib/libc/iconv/citrus_iconv.c
===================================================================
--- lib/libc/iconv/citrus_iconv.c	(revision 247143)
+++ lib/libc/iconv/citrus_iconv.c	(working copy)
@@ -72,7 +72,7 @@
 init_cache(void)
 {
 
-	WLOCK;
+	WLOCK();
 	if (!isinit) {
 		_CITRUS_HASH_INIT(&shared_pool, CI_HASH_SIZE);
 		TAILQ_INIT(&shared_unused);
@@ -83,7 +83,7 @@
 			shared_max_reuse = CI_INITIAL_MAX_REUSE;
 		isinit = true;
 	}
-	UNLOCK;
+	UNLOCK();
 }
 
 static __inline void
@@ -189,16 +189,16 @@
 get_shared(struct _citrus_iconv_shared * __restrict * __restrict rci,
     const char *src, const char *dst)
 {
-	struct _citrus_iconv_shared * ci;
+	struct _citrus_iconv_shared * ci, *citmp;
 	char convname[PATH_MAX];
 	int hashval, ret = 0;
 
 	snprintf(convname, sizeof(convname), "%s/%s", src, dst);
 
-	WLOCK;
-
 	/* lookup alread existing entry */
 	hashval = hash_func(convname);
+
+	WLOCK();
 	_CITRUS_HASH_SEARCH(&shared_pool, ci, ci_hash_entry, match_func,
 	    convname, hashval);
 	if (ci != NULL) {
@@ -209,21 +209,32 @@
 		}
 		ci->ci_used_count++;
 		*rci = ci;
+		UNLOCK();
 		goto quit;
 	}
 
+	UNLOCK();
 	/* create new entry */
 	ret = open_shared(&ci, convname, src, dst);
 	if (ret)
 		goto quit;
 
+	WLOCK();
+	_CITRUS_HASH_SEARCH(&shared_pool, citmp, ci_hash_entry, match_func,
+	    convname, hashval);
+	if (citmp != NULL) {
+		UNLOCK();
+		close_shared(ci);
+		ci = citmp;
+		goto quit;
+	}
+
 	_CITRUS_HASH_INSERT(&shared_pool, ci, ci_hash_entry, hashval);
 	ci->ci_used_count = 1;
 	*rci = ci;
 
+	UNLOCK();
 quit:
-	UNLOCK;
-
 	return (ret);
 }
 
@@ -231,7 +242,7 @@
 release_shared(struct _citrus_iconv_shared * __restrict ci)
 {
 
-	WLOCK;
+	WLOCK();
 	ci->ci_used_count--;
 	if (ci->ci_used_count == 0) {
 		/* put it into unused list */
@@ -243,11 +254,13 @@
 			TAILQ_REMOVE(&shared_unused, ci, ci_tailq_entry);
 			_CITRUS_HASH_REMOVE(ci, ci_hash_entry);
 			shared_num_unused--;
+			UNLOCK();
 			close_shared(ci);
+			WLOCK();
 		}
 	}
 
-	UNLOCK;
+	UNLOCK();
 }
 
 /*
@@ -273,6 +286,7 @@
 		dst = nl_langinfo(CODESET);
 
 	/* resolve codeset name aliases */
+	path[0] = '\x0';	/* XXX - just copy src/dst to realsrc/dst? */
 	strlcpy(realsrc, _lookup_alias(path, src, buf, (size_t)PATH_MAX,
 	    _LOOKUP_CASE_IGNORE), (size_t)PATH_MAX);
 	strlcpy(realdst, _lookup_alias(path, dst, buf, (size_t)PATH_MAX,
Index: lib/libc/iconv/citrus_lock.c
===================================================================
--- lib/libc/iconv/citrus_lock.c	(revision 0)
+++ lib/libc/iconv/citrus_lock.c	(working copy)
@@ -0,0 +1,3 @@
+#include "citrus_lock.h"
+
+pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
Index: lib/libc/iconv/citrus_lock.h
===================================================================
--- lib/libc/iconv/citrus_lock.h	(revision 247143)
+++ lib/libc/iconv/citrus_lock.h	(working copy)
@@ -27,9 +27,13 @@
 
 #include <pthread.h>
 
-static pthread_rwlock_t	lock;
+extern pthread_rwlock_t	lock;
 
-#define WLOCK	if (__isthreaded)		\
-		    pthread_rwlock_wrlock(&lock);
-#define UNLOCK	if (__isthreaded)		\
-		    pthread_rwlock_unlock(&lock);
+#define WLOCK()		do {						\
+				if (__isthreaded)			\
+					pthread_rwlock_wrlock(&lock);	\
+			} while (0)
+#define UNLOCK()	do {						\
+				if (__isthreaded)			\
+					pthread_rwlock_unlock(&lock);	\
+			} while (0)
Index: lib/libc/iconv/citrus_mapper.c
===================================================================
--- lib/libc/iconv/citrus_mapper.c	(revision 247143)
+++ lib/libc/iconv/citrus_mapper.c	(working copy)
@@ -75,7 +75,7 @@
 	char path[PATH_MAX];
 	int ret;
 
-	WLOCK;
+	WLOCK();
 
 	if (*rma != NULL) {
 		ret = 0;
@@ -104,7 +104,7 @@
 	*rma = ma;
 	ret = 0;
 quit:
-	UNLOCK;
+	UNLOCK();
 
 	return (ret);
 }
@@ -309,14 +309,14 @@
     struct _citrus_mapper * __restrict * __restrict rcm,
     const char * __restrict mapname)
 {
-	struct _citrus_mapper *cm;
+	struct _citrus_mapper *cm, *cmtmp;
 	char linebuf[PATH_MAX];
 	const char *module, *variable;
 	int hashval, ret;
 
 	variable = NULL;
 
-	WLOCK;
+	WLOCK();
 
 	/* search in the cache */
 	hashval = hash_func(mapname);
@@ -325,9 +325,11 @@
 	if (cm) {
 		/* found */
 		cm->cm_refcount++;
+		UNLOCK();
+foundwref:
 		*rcm = cm;
 		ret = 0;
-		goto quit;
+		goto quitnolock;
 	}
 
 	/* search mapper entry */
@@ -337,16 +339,28 @@
 		goto quit;
 
 	/* open mapper */
-	UNLOCK;
+	UNLOCK();
 	ret = mapper_open(ma, &cm, module, variable);
-	WLOCK;
 	if (ret)
-		goto quit;
+		goto quitnolock;
+
+	WLOCK();
+	_CITRUS_HASH_SEARCH(&ma->ma_cache, cmtmp, cm_entry, match_func, mapname,
+	    hashval);
+	if (cmtmp) {
+		cmtmp->cm_refcount++;
+		UNLOCK();
+		_mapper_close(cm);
+		cm = cmtmp;
+		goto foundwref;
+	}
+
 	cm->cm_key = strdup(mapname);
 	if (cm->cm_key == NULL) {
 		ret = errno;
+		UNLOCK();
 		_mapper_close(cm);
-		goto quit;	
+		goto quitnolock;
 	}
 
 	/* insert to the cache */
@@ -356,8 +370,9 @@
 	*rcm = cm;
 	ret = 0;
 quit:
-	UNLOCK;
+	UNLOCK();
 
+quitnolock:
 	return (ret);
 }
 
@@ -369,20 +384,21 @@
 _citrus_mapper_close(struct _citrus_mapper *cm)
 {
 
-	if (cm) {
-		WLOCK;
-		if (cm->cm_refcount == REFCOUNT_PERSISTENT)
-			goto quit;
-		if (cm->cm_refcount > 0) {
-			if (--cm->cm_refcount > 0)
-				goto quit;
-			_CITRUS_HASH_REMOVE(cm, cm_entry);
-			free(cm->cm_key);
-		}
-		mapper_close(cm);
-quit:
-		UNLOCK;
+	if (cm == NULL)
+		return;
+
+	WLOCK();
+	if (cm->cm_refcount == REFCOUNT_PERSISTENT || --cm->cm_refcount != 0) {
+		UNLOCK();
+		return;
 	}
+
+	_CITRUS_HASH_REMOVE(cm, cm_entry);
+	free(cm->cm_key);
+	cm->cm_key = NULL;
+
+	UNLOCK();
+	mapper_close(cm);
 }
 
 /*
@@ -393,7 +409,7 @@
 _citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)
 {
 
-	WLOCK;
+	WLOCK();
 	cm->cm_refcount = REFCOUNT_PERSISTENT;
-	UNLOCK;
+	UNLOCK();
 }
Index: lib/libc/iconv/citrus_module.c
===================================================================
--- lib/libc/iconv/citrus_module.c	(revision 247143)
+++ lib/libc/iconv/citrus_module.c	(working copy)
@@ -109,7 +109,6 @@
 #include "citrus_namespace.h"
 #include "citrus_bcs.h"
 #include "citrus_module.h"
-#include "libc_private.h"
 
 static int		 _getdewey(int[], char *);
 static int		 _cmpndewey(int[], int, int[], int);
@@ -293,11 +292,11 @@
 	maj = I18NMODULE_MAJOR;
 	min = -1;
 	p = _findshlib(path, &maj, &min);
-	if (!p)
+	if (p == NULL)
 		return (EINVAL);
-	handle = libc_dlopen(p, RTLD_LAZY);
-	if (!handle) {
-		printf("%s", dlerror());
+	handle = dlopen(p, RTLD_LAZY);
+	if (handle == NULL) {
+		printf("%s", dlerror());	/* XXX */
 		return (EINVAL);
 	}
 
Index: lib/libiconv/Makefile
===================================================================
--- lib/libiconv/Makefile	(revision 247143)
+++ lib/libiconv/Makefile	(working copy)
@@ -14,11 +14,11 @@
 SRCS=	citrus_bcs.c citrus_bcs_strtol.c citrus_bcs_strtoul.c \
 	citrus_csmapper.c citrus_db.c citrus_db_factory.c \
 	citrus_db_hash.c citrus_esdb.c citrus_hash.c \
-	citrus_iconv.c citrus_lookup.c citrus_lookup_factory.c \
+	citrus_iconv.c citrus_lock.c citrus_lookup.c citrus_lookup_factory.c \
 	citrus_mapper.c citrus_memstream.c citrus_mmap.c \
 	citrus_module.c citrus_none.c citrus_pivot_factory.c \
 	citrus_prop.c citrus_stdenc.c iconv.c
 
-CFLAGS+= --param max-inline-insns-single=128 -I ${.CURDIR}/../../include -I${.CURDIR}/../libc/include
+CFLAGS+= -I ${.CURDIR}/../../include
 
 .include <bsd.lib.mk>

--4f28nU6agdXSinmL--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130227214057.GD55866>