lib9/fmt: avoid racy access to installed fmt formats
This commit is contained in:
parent
d96e9e5dc3
commit
7ba9f9467d
4 changed files with 55 additions and 22 deletions
|
|
@ -72,7 +72,7 @@ static Convfmt knownfmt[] = {
|
||||||
int (*fmtdoquote)(int);
|
int (*fmtdoquote)(int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __fmtlock() must be set
|
* __fmtwlock() must be set
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
__fmtinstall(int c, Fmts f)
|
__fmtinstall(int c, Fmts f)
|
||||||
|
|
@ -106,34 +106,43 @@ fmtinstall(int c, int (*f)(Fmt*))
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
__fmtlock();
|
__fmtwlock();
|
||||||
ret = __fmtinstall(c, f);
|
ret = __fmtinstall(c, f);
|
||||||
__fmtunlock();
|
__fmtwunlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Fmts
|
static Fmts
|
||||||
fmtfmt(int c)
|
fmtfmt(int c)
|
||||||
{
|
{
|
||||||
Convfmt *p, *ep;
|
Convfmt *p, *ep, *kp;
|
||||||
|
|
||||||
|
/* conflict-free check - common case */
|
||||||
|
__fmtrlock();
|
||||||
ep = &fmtalloc.fmt[fmtalloc.nfmt];
|
ep = &fmtalloc.fmt[fmtalloc.nfmt];
|
||||||
for(p=fmtalloc.fmt; p<ep; p++)
|
for(p=fmtalloc.fmt; p<ep; p++)
|
||||||
if(p->c == c){
|
if(p->c == c){
|
||||||
while(p->fmt == nil) /* loop until value is updated */
|
__fmtrunlock();
|
||||||
;
|
|
||||||
return p->fmt;
|
return p->fmt;
|
||||||
}
|
}
|
||||||
|
__fmtrunlock();
|
||||||
|
|
||||||
/* is this a predefined format char? */
|
/* is this a predefined format char? */
|
||||||
__fmtlock();
|
for(kp=knownfmt; kp->c; kp++){
|
||||||
for(p=knownfmt; p->c; p++)
|
if(kp->c == c){
|
||||||
if(p->c == c){
|
__fmtwlock();
|
||||||
__fmtinstall(p->c, p->fmt);
|
/* double-check fmtinstall didn't happen */
|
||||||
__fmtunlock();
|
for(p=fmtalloc.fmt; p<ep; p++){
|
||||||
return p->fmt;
|
if(p->c == c){
|
||||||
|
__fmtwunlock();
|
||||||
|
return p->fmt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__fmtinstall(kp->c, kp->fmt);
|
||||||
|
__fmtwunlock();
|
||||||
|
return kp->fmt;
|
||||||
}
|
}
|
||||||
__fmtunlock();
|
}
|
||||||
|
|
||||||
return __badfmt;
|
return __badfmt;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,13 @@ int __fmtFdFlush(Fmt *f);
|
||||||
int __fmtcpy(Fmt *f, const void *vm, int n, int sz);
|
int __fmtcpy(Fmt *f, const void *vm, int n, int sz);
|
||||||
void* __fmtdispatch(Fmt *f, void *fmt, int isrunes);
|
void* __fmtdispatch(Fmt *f, void *fmt, int isrunes);
|
||||||
void * __fmtflush(Fmt *f, void *t, int len);
|
void * __fmtflush(Fmt *f, void *t, int len);
|
||||||
void __fmtlock(void);
|
|
||||||
int __fmtpad(Fmt *f, int n);
|
int __fmtpad(Fmt *f, int n);
|
||||||
double __fmtpow10(int n);
|
double __fmtpow10(int n);
|
||||||
int __fmtrcpy(Fmt *f, const void *vm, 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 __ifmt(Fmt *f);
|
||||||
int __isInf(double d, int sign);
|
int __isInf(double d, int sign);
|
||||||
int __isNaN(double d);
|
int __isNaN(double d);
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,21 @@
|
||||||
#include "fmtdef.h"
|
#include "fmtdef.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
__fmtlock(void)
|
__fmtrlock(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
__fmtunlock(void)
|
__fmtrunlock(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__fmtwlock(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__fmtwunlock(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,28 @@
|
||||||
#include <u.h>
|
#include <u.h>
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
|
|
||||||
static Lock fmtlock;
|
static RWLock fmtlock;
|
||||||
|
|
||||||
void
|
void
|
||||||
__fmtlock(void)
|
__fmtrlock(void)
|
||||||
{
|
{
|
||||||
lock(&fmtlock);
|
rlock(&fmtlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
__fmtunlock(void)
|
__fmtrunlock(void)
|
||||||
{
|
{
|
||||||
unlock(&fmtlock);
|
runlock(&fmtlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__fmtwlock(void)
|
||||||
|
{
|
||||||
|
wlock(&fmtlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__fmtwunlock(void)
|
||||||
|
{
|
||||||
|
wunlock(&fmtlock);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue