Commit Diff


commit - d28913a9e6609fef96f5baf6e9f4d5055ede744c
commit + 9505cd15a64933bf58ec50548339cf98b1854646
blob - 9c3f45d3b419d82584dde6d25b786130162a3074
blob + a86482c32dad636c6039065337c8e713c03acac8
--- src/lib9/fmt/fmt.c
+++ src/lib9/fmt/fmt.c
@@ -1,102 +1,107 @@
 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
 #include <stdarg.h>
 #include <string.h>
+#include <stdatomic.h>
 #include "plan9.h"
 #include "fmt.h"
 #include "fmtdef.h"
 
 enum
 {
-	Maxfmt = 64
+	Maxfmt = 128
 };
 
 typedef struct Convfmt Convfmt;
 struct Convfmt
 {
 	int	c;
-	volatile	Fmts	fmt;	/* for spin lock in fmtfmt; avoids race due to write order */
+	Fmts	fmt;
 };
 
 static struct
 {
-	/* lock by calling __fmtlock, __fmtunlock */
-	int	nfmt;
+	/*
+	 * lock updates to fmt by calling __fmtlock, __fmtunlock.
+	 * reads can start at nfmt and work backward without
+	 * further locking. later fmtinstalls take priority over earlier
+	 * ones because of the backwards loop.
+	 * once installed, a format is never overwritten.
+	 */
+	_Atomic int	nfmt;
 	Convfmt	fmt[Maxfmt];
-} fmtalloc;
-
-static Convfmt knownfmt[] = {
-	' ',	__flagfmt,
-	'#',	__flagfmt,
-	'%',	__percentfmt,
-	'\'',	__flagfmt,
-	'+',	__flagfmt,
-	',',	__flagfmt,
-	'-',	__flagfmt,
-	'C',	__runefmt,	/* Plan 9 addition */
-	'E',	__efgfmt,
-#ifndef PLAN9PORT
-	'F',	__efgfmt,	/* ANSI only */
-#endif
-	'G',	__efgfmt,
-#ifndef PLAN9PORT
-	'L',	__flagfmt,	/* ANSI only */
-#endif
-	'S',	__runesfmt,	/* Plan 9 addition */
-	'X',	__ifmt,
-	'b',	__ifmt,		/* Plan 9 addition */
-	'c',	__charfmt,
-	'd',	__ifmt,
-	'e',	__efgfmt,
-	'f',	__efgfmt,
-	'g',	__efgfmt,
-	'h',	__flagfmt,
-#ifndef PLAN9PORT
-	'i',	__ifmt,		/* ANSI only */
-#endif
-	'l',	__flagfmt,
-	'n',	__countfmt,
-	'o',	__ifmt,
-	'p',	__ifmt,
-	'r',	__errfmt,
-	's',	__strfmt,
-#ifdef PLAN9PORT
-	'u',	__flagfmt,
-#else
-	'u',	__ifmt,
-#endif
-	'x',	__ifmt,
-	0,	nil,
+} fmtalloc = {
+	#ifdef PLAN9PORT
+		ATOMIC_VAR_INIT(27),
+	#else
+		ATOMIC_VAR_INIT(30),
+	#endif
+	{
+		{' ',	__flagfmt},
+		{'#',	__flagfmt},
+		{'%',	__percentfmt},
+		{'\'',	__flagfmt},
+		{'+',	__flagfmt},
+		{',',	__flagfmt},
+		{'-',	__flagfmt},
+		{'C',	__runefmt},	/* Plan 9 addition */
+		{'E',	__efgfmt},
+	#ifndef PLAN9PORT
+		{'F',	__efgfmt},	/* ANSI only */
+	#endif
+		{'G',	__efgfmt},
+	#ifndef PLAN9PORT
+		{'L',	__flagfmt},	/* ANSI only */
+	#endif
+		{'S',	__runesfmt},	/* Plan 9 addition */
+		{'X',	__ifmt},
+		{'b',	__ifmt},		/* Plan 9 addition */
+		{'c',	__charfmt},
+		{'d',	__ifmt},
+		{'e',	__efgfmt},
+		{'f',	__efgfmt},
+		{'g',	__efgfmt},
+		{'h',	__flagfmt},
+	#ifndef PLAN9PORT
+		{'i',	__ifmt},		/* ANSI only */
+	#endif
+		{'l',	__flagfmt},
+		{'n',	__countfmt},
+		{'o',	__ifmt},
+		{'p',	__ifmt},
+		{'r',	__errfmt},
+		{'s',	__strfmt},
+	#ifdef PLAN9PORT
+		{'u',	__flagfmt},
+	#else
+		{'u',	__ifmt},
+	#endif
+		{'x',	__ifmt},
+	}
 };
 
-
 int	(*fmtdoquote)(int);
 
 /*
- * __fmtwlock() must be set
+ * __fmtlock() must be set
  */
 static int
 __fmtinstall(int c, Fmts f)
 {
-	Convfmt *p, *ep;
+	Convfmt *p;
+	int i;
 
 	if(c<=0 || c>=65536)
 		return -1;
 	if(!f)
 		f = __badfmt;
 
-	ep = &fmtalloc.fmt[fmtalloc.nfmt];
-	for(p=fmtalloc.fmt; p<ep; p++)
-		if(p->c == c)
-			break;
-
-	if(p == &fmtalloc.fmt[Maxfmt])
+	i = atomic_load(&fmtalloc.nfmt);
+	if(i == Maxfmt)
 		return -1;
-
+	p = &fmtalloc.fmt[i];
+	p->c = c;
 	p->fmt = f;
-	if(p == ep){	/* installing a new format character */
-		fmtalloc.nfmt++;
-		p->c = c;
-	}
+	atomic_store(&fmtalloc.nfmt, i+1);
 
 	return 0;
 }
@@ -106,44 +111,22 @@ fmtinstall(int c, int (*f)(Fmt*))
 {
 	int ret;
 
-	__fmtwlock();
+	__fmtlock();
 	ret = __fmtinstall(c, f);
-	__fmtwunlock();
+	__fmtunlock();
 	return ret;
 }
 
 static Fmts
 fmtfmt(int c)
 {
-	Convfmt *p, *ep, *kp;
+	Convfmt *p, *ep;
 
-	/* conflict-free check - common case */
-	__fmtrlock();
-	ep = &fmtalloc.fmt[fmtalloc.nfmt];
-	for(p=fmtalloc.fmt; p<ep; p++)
-		if(p->c == c){
-			__fmtrunlock();
+	ep = &fmtalloc.fmt[atomic_load(&fmtalloc.nfmt)];
+	for(p=ep; p-- > fmtalloc.fmt; )
+		if(p->c == c)
 			return p->fmt;
-		}
-	__fmtrunlock();
 
-	/* is this a predefined format char? */
-	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;
-		}
-	}
-
 	return __badfmt;
 }
 
blob - d547184d3d17833880dc4df6ec00936af8c5bb3a
blob + 2bafd36d83afdbd80ad95c81fcc8bbec43538007
--- src/lib9/fmt/fmtdef.h
+++ src/lib9/fmt/fmtdef.h
@@ -36,10 +36,8 @@ void *       __fmtflush(Fmt *f, void *t, int len);
 int          __fmtpad(Fmt *f, int n);
 double       __fmtpow10(int n);
 int          __fmtrcpy(Fmt *f, const void *vm, int n);
-void         __fmtrlock(void);
-void         __fmtrunlock(void);
-void         __fmtwlock(void);
-void         __fmtwunlock(void);
+void         __fmtlock(void);
+void         __fmtunlock(void);
 int          __ifmt(Fmt *f);
 int          __isInf(double d, int sign);
 int          __isNaN(double d);
blob - eb9cd84514065b697541664845a04d883d512413
blob + cabe05f4a8b439238527e0ffb421a50c162ad7a1
--- src/lib9/fmt/fmtlock.c
+++ src/lib9/fmt/fmtlock.c
@@ -5,21 +5,11 @@
 #include "fmtdef.h"
 
 void
-__fmtrlock(void)
+__fmtlock(void)
 {
 }
 
 void
-__fmtrunlock(void)
+__fmtunlock(void)
 {
 }
-
-void
-__fmtwlock(void)
-{
-}
-
-void
-__fmtwunlock(void)
-{
-}
blob - b755daa385ec91e39ce30712864e1983e0b78ae1
blob + d711e6d482ec5c34e7f5ecaec3dde84c674b9a01
--- src/lib9/fmtlock2.c
+++ src/lib9/fmtlock2.c
@@ -1,28 +1,16 @@
 #include <u.h>
 #include <libc.h>
 
-static RWLock fmtlock;
+static Lock fmtlock;
 
 void
-__fmtrlock(void)
+__fmtlock(void)
 {
-	rlock(&fmtlock);
+	lock(&fmtlock);
 }
 
 void
-__fmtrunlock(void)
+__fmtunlock(void)
 {
-	runlock(&fmtlock);
+	unlock(&fmtlock);
 }
-
-void
-__fmtwlock(void)
-{
-	wlock(&fmtlock);
-}
-
-void
-__fmtwunlock(void)
-{
-	wunlock(&fmtlock);
-}