Commit Diff


commit - d96e9e5dc39a356febed132703e46bf73bac6850
commit + 7ba9f9467d95fa8d05bb04d36fd4c602e497f529
blob - 66093fd0db28376f5df9dcbc5f45fcbc59ff9eef
blob + 9c3f45d3b419d82584dde6d25b786130162a3074
--- src/lib9/fmt/fmt.c
+++ src/lib9/fmt/fmt.c
@@ -72,7 +72,7 @@ static Convfmt knownfmt[] = {
 int	(*fmtdoquote)(int);
 
 /*
- * __fmtlock() must be set
+ * __fmtwlock() must be set
  */
 static int
 __fmtinstall(int c, Fmts f)
@@ -106,34 +106,43 @@ fmtinstall(int c, int (*f)(Fmt*))
 {
 	int ret;
 
-	__fmtlock();
+	__fmtwlock();
 	ret = __fmtinstall(c, f);
-	__fmtunlock();
+	__fmtwunlock();
 	return ret;
 }
 
 static Fmts
 fmtfmt(int c)
 {
-	Convfmt *p, *ep;
+	Convfmt *p, *ep, *kp;
 
+	/* conflict-free check - common case */
+	__fmtrlock();
 	ep = &fmtalloc.fmt[fmtalloc.nfmt];
 	for(p=fmtalloc.fmt; p<ep; p++)
 		if(p->c == c){
-			while(p->fmt == nil)	/* loop until value is updated */
-				;
+			__fmtrunlock();
 			return p->fmt;
 		}
+	__fmtrunlock();
 
 	/* is this a predefined format char? */
-	__fmtlock();
-	for(p=knownfmt; p->c; p++)
-		if(p->c == c){
-			__fmtinstall(p->c, p->fmt);
-			__fmtunlock();
-			return p->fmt;
+	for(kp=knownfmt; kp->c; kp++){
+		if(kp->c == c){
+			__fmtwlock();
+			/* double-check fmtinstall didn't happen */
+			for(p=fmtalloc.fmt; p<ep; p++){
+				if(p->c == c){
+					__fmtwunlock();
+					return p->fmt;
+				}
+			}
+			__fmtinstall(kp->c, kp->fmt);
+			__fmtwunlock();
+			return kp->fmt;
 		}
-	__fmtunlock();
+	}
 
 	return __badfmt;
 }
blob - 5c8eb2cbdc3f02692d3dc65cdf667a18924f3ffe
blob + d547184d3d17833880dc4df6ec00936af8c5bb3a
--- src/lib9/fmt/fmtdef.h
+++ src/lib9/fmt/fmtdef.h
@@ -33,11 +33,13 @@ int          __fmtFdFlush(Fmt *f);
 int          __fmtcpy(Fmt *f, const void *vm, int n, int sz);
 void*        __fmtdispatch(Fmt *f, void *fmt, int isrunes);
 void *       __fmtflush(Fmt *f, void *t, int len);
-void         __fmtlock(void);
 int          __fmtpad(Fmt *f, int n);
 double       __fmtpow10(int n);
 int          __fmtrcpy(Fmt *f, const void *vm, int n);
-void         __fmtunlock(void);
+void         __fmtrlock(void);
+void         __fmtrunlock(void);
+void         __fmtwlock(void);
+void         __fmtwunlock(void);
 int          __ifmt(Fmt *f);
 int          __isInf(double d, int sign);
 int          __isNaN(double d);
blob - cabe05f4a8b439238527e0ffb421a50c162ad7a1
blob + eb9cd84514065b697541664845a04d883d512413
--- src/lib9/fmt/fmtlock.c
+++ src/lib9/fmt/fmtlock.c
@@ -5,11 +5,21 @@
 #include "fmtdef.h"
 
 void
-__fmtlock(void)
+__fmtrlock(void)
 {
 }
 
 void
-__fmtunlock(void)
+__fmtrunlock(void)
 {
 }
+
+void
+__fmtwlock(void)
+{
+}
+
+void
+__fmtwunlock(void)
+{
+}
blob - d711e6d482ec5c34e7f5ecaec3dde84c674b9a01
blob + b755daa385ec91e39ce30712864e1983e0b78ae1
--- src/lib9/fmtlock2.c
+++ src/lib9/fmtlock2.c
@@ -1,16 +1,28 @@
 #include <u.h>
 #include <libc.h>
 
-static Lock fmtlock;
+static RWLock fmtlock;
 
 void
-__fmtlock(void)
+__fmtrlock(void)
 {
-	lock(&fmtlock);
+	rlock(&fmtlock);
 }
 
 void
-__fmtunlock(void)
+__fmtrunlock(void)
 {
-	unlock(&fmtlock);
+	runlock(&fmtlock);
 }
+
+void
+__fmtwlock(void)
+{
+	wlock(&fmtlock);
+}
+
+void
+__fmtwunlock(void)
+{
+	wunlock(&fmtlock);
+}