diff options
author | tegge <tegge@FreeBSD.org> | 2001-02-08 20:22:28 +0000 |
---|---|---|
committer | tegge <tegge@FreeBSD.org> | 2001-02-08 20:22:28 +0000 |
commit | d93ead21a255a62c38001766d61df898b36ab17c (patch) | |
tree | 4760265ec840bde82891f5eeab2b04d730a4416b | |
parent | 4ec3558a81aeeb7159323cb34e0c0198478256e2 (diff) | |
download | FreeBSD-src-d93ead21a255a62c38001766d61df898b36ab17c.zip FreeBSD-src-d93ead21a255a62c38001766d61df898b36ab17c.tar.gz |
Protect freelists managed by Balloc/Bfree with a spinlock.
Change __dtoa to not free the string it allocated the previous time it was
called. The caller now frees the string after usage if appropiate.
PR: 15070
-rw-r--r-- | lib/libc/stdio/vfprintf.c | 23 | ||||
-rw-r--r-- | lib/libc/stdlib/netbsd_strtod.c | 40 | ||||
-rw-r--r-- | lib/libc/stdlib/strtod.c | 40 |
3 files changed, 63 insertions, 40 deletions
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c index fff9aa8..afb10b0 100644 --- a/lib/libc/stdio/vfprintf.c +++ b/lib/libc/stdio/vfprintf.c @@ -267,7 +267,7 @@ vfprintf(FILE *fp, const char *fmt0, va_list ap) #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ #define DEFPREC 6 -static char *cvt __P((double, int, int, char *, int *, int, int *)); +static char *cvt __P((double, int, int, char *, int *, int, int *, char **)); static int exponent __P((char *, int, int)); #else /* no FLOATING_POINT */ @@ -313,6 +313,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) int expsize; /* character count for expstr */ int ndig; /* actual number of digits returned by cvt */ char expstr[7]; /* buffer for exponent string */ + char *dtoaresult; /* buffer allocated by dtoa */ #endif u_long ulval; /* integer arguments %[diouxX] */ u_quad_t uqval; /* %q integers */ @@ -421,6 +422,9 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) } +#ifdef FLOATING_POINT + dtoaresult = NULL; +#endif /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ if (cantwrite(fp)) return (EOF); @@ -606,8 +610,12 @@ fp_begin: if (prec == -1) break; } flags |= FPT; + if (dtoaresult != NULL) { + free(dtoaresult); + dtoaresult = NULL; + } cp = cvt(_double, prec, flags, &softsign, - &expt, ch, &ndig); + &expt, ch, &ndig, &dtoaresult); if (ch == 'g' || ch == 'G') { if (expt <= -4 || expt > prec) ch = (ch == 'g') ? 'e' : 'E'; @@ -863,6 +871,10 @@ number: if ((dprec = prec) >= 0) done: FLUSH(); error: +#ifdef FLOATING_POINT + if (dtoaresult != NULL) + free(dtoaresult); +#endif if (__sferror(fp)) ret = EOF; if ((argtable != NULL) && (argtable != statargtable)) @@ -1194,11 +1206,11 @@ __grow_type_table (int nextarg, unsigned char **typetable, int *tablesize) #ifdef FLOATING_POINT -extern char *__dtoa __P((double, int, int, int *, int *, char **)); +extern char *__dtoa __P((double, int, int, int *, int *, char **, char **)); static char * cvt(double value, int ndigits, int flags, char *sign, int *decpt, - int ch, int *length) + int ch, int *length, char **dtoaresultp) { int mode, dsgn; char *digits, *bp, *rve; @@ -1220,7 +1232,8 @@ cvt(double value, int ndigits, int flags, char *sign, int *decpt, *sign = '-'; } else *sign = '\000'; - digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); + digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve, + dtoaresultp); if ((ch != 'g' && ch != 'G') || flags & ALT) { /* print trailing zeros */ bp = digits + ndigits; diff --git a/lib/libc/stdlib/netbsd_strtod.c b/lib/libc/stdlib/netbsd_strtod.c index a402b68..ea0dbcd 100644 --- a/lib/libc/stdlib/netbsd_strtod.c +++ b/lib/libc/stdlib/netbsd_strtod.c @@ -142,7 +142,7 @@ __RCSID("$NetBSD: strtod.c,v 1.26 1998/02/03 18:44:21 perry Exp $"); #include "memory.h" #endif #endif -char *__dtoa __P((double, int, int, int *, int *, char **)); +char *__dtoa __P((double, int, int, int *, int *, char **, char **)); #ifdef MALLOC #ifdef KR_headers @@ -384,6 +384,16 @@ Bigint { static Bigint *freelist[Kmax+1]; + /* + * Make Balloc/Bfree thread-safe in libc for use with + * kernel threads. + */ +#include "libc_private.h" +#include "spinlock.h" +static spinlock_t thread_lock = _SPINLOCK_INITIALIZER; +#define THREAD_LOCK() if (__isthreaded) _SPINLOCK(&thread_lock); +#define THREAD_UNLOCK() if (__isthreaded) _SPINUNLOCK(&thread_lock); + static Bigint * Balloc #ifdef KR_headers @@ -395,10 +405,13 @@ Balloc int x; Bigint *rv; + THREAD_LOCK(); if ((rv = freelist[k]) != NULL) { freelist[k] = rv->next; + THREAD_UNLOCK(); } else { + THREAD_UNLOCK(); x = 1 << k; rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long)); rv->k = k; @@ -417,8 +430,10 @@ Bfree #endif { if (v) { + THREAD_LOCK(); v->next = freelist[v->k]; freelist[v->k] = v; + THREAD_UNLOCK(); } } @@ -1900,10 +1915,11 @@ quorem char * __dtoa #ifdef KR_headers - (d, mode, ndigits, decpt, sign, rve) - double d; int mode, ndigits, *decpt, *sign; char **rve; + (d, mode, ndigits, decpt, sign, rve, resultp) + double d; int mode, ndigits, *decpt, *sign; char **rve, **resultp; #else - (double d, int mode, int ndigits, int *decpt, int *sign, char **rve) + (double d, int mode, int ndigits, int *decpt, int *sign, char **rve, + char **resultp) #endif { /* Arguments ndigits, decpt, sign are similar to those @@ -1953,15 +1969,6 @@ __dtoa Bigint *mlo = NULL; /* pacify gcc */ double d2, ds, eps; char *s, *s0; - static Bigint *result; - static int result_k; - - if (result) { - result->k = result_k; - result->maxwds = 1 << result_k; - Bfree(result); - result = 0; - } if (word0(d) & Sign_bit) { /* set sign for everything, including 0's and NaNs */ @@ -2123,11 +2130,8 @@ __dtoa if (i <= 0) i = 1; } - j = sizeof(ULong); - for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i; - j <<= 1) result_k++; - result = Balloc(result_k); - s = s0 = (char *)result; + *resultp = (char *) malloc(i + 1); + s = s0 = *resultp; if (ilim >= 0 && ilim <= Quick_max && try_quick) { diff --git a/lib/libc/stdlib/strtod.c b/lib/libc/stdlib/strtod.c index 27fb499..e70a965 100644 --- a/lib/libc/stdlib/strtod.c +++ b/lib/libc/stdlib/strtod.c @@ -29,6 +29,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ #if defined(LIBC_SCCS) && !defined(lint) @@ -371,6 +373,16 @@ Bigint { static Bigint *freelist[Kmax+1]; + /* + * Make Balloc/Bfree thread-safe in libc for use with + * kernel threads. + */ +#include "libc_private.h" +#include "spinlock.h" +static spinlock_t thread_lock = _SPINLOCK_INITIALIZER; +#define THREAD_LOCK() if (__isthreaded) _SPINLOCK(&thread_lock); +#define THREAD_UNLOCK() if (__isthreaded) _SPINUNLOCK(&thread_lock); + static Bigint * Balloc #ifdef KR_headers @@ -382,9 +394,12 @@ Balloc int x; Bigint *rv; + THREAD_LOCK(); if ( (rv = freelist[k]) ) { freelist[k] = rv->next; + THREAD_UNLOCK(); } else { + THREAD_UNLOCK(); x = 1 << k; rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(long)); rv->k = k; @@ -403,8 +418,10 @@ Bfree #endif { if (v) { + THREAD_LOCK(); v->next = freelist[v->k]; freelist[v->k] = v; + THREAD_UNLOCK(); } } @@ -1839,10 +1856,11 @@ quorem char * __dtoa #ifdef KR_headers - (d, mode, ndigits, decpt, sign, rve) - double d; int mode, ndigits, *decpt, *sign; char **rve; + (d, mode, ndigits, decpt, sign, rve, resultp) + double d; int mode, ndigits, *decpt, *sign; char **rve, **resultp; #else - (double d, int mode, int ndigits, int *decpt, int *sign, char **rve) + (double d, int mode, int ndigits, int *decpt, int *sign, char **rve, + char **resultp) #endif { /* Arguments ndigits, decpt, sign are similar to those @@ -1890,15 +1908,6 @@ __dtoa Bigint *b, *b1, *delta, *mlo, *mhi, *S; double d2, ds, eps; char *s, *s0; - static Bigint *result; - static int result_k; - - if (result) { - result->k = result_k; - result->maxwds = 1 << result_k; - Bfree(result); - result = 0; - } if (word0(d) & Sign_bit) { /* set sign for everything, including 0's and NaNs */ @@ -2057,11 +2066,8 @@ __dtoa if (i <= 0) i = 1; } - j = sizeof(unsigned long); - for (result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j < i; - j <<= 1) result_k++; - result = Balloc(result_k); - s = s0 = (char *)result; + *resultp = (char *) malloc(i + 1); + s = s0 = *resultp; if (ilim >= 0 && ilim <= Quick_max && try_quick) { |