summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorderaadt <>2006-10-29 18:45:56 +0000
committerderaadt <>2006-10-29 18:45:56 +0000
commitaede99584cb0d715ac3f7c41068bc88f09d2a61b (patch)
treee411f8b9691e52e1f9798a36d7cf41201ee8300d
parent182ec138408d8727b97aa8a6b7faef3a1c05037b (diff)
downloadopenbsd-aede99584cb0d715ac3f7c41068bc88f09d2a61b.tar.gz
openbsd-aede99584cb0d715ac3f7c41068bc88f09d2a61b.tar.bz2
openbsd-aede99584cb0d715ac3f7c41068bc88f09d2a61b.zip
make __dtoa & strtod() thread-safe useing the same method as newer gdtoa
codebase. tested mostly by ckuethe and myself. __dtoa() use now requires a call to __freedtoa()
-rw-r--r--src/lib/libc/stdlib/ecvt.c14
-rw-r--r--src/lib/libc/stdlib/gcvt.c5
-rw-r--r--src/lib/libc/stdlib/strtod.c106
3 files changed, 89 insertions, 36 deletions
diff --git a/src/lib/libc/stdlib/ecvt.c b/src/lib/libc/stdlib/ecvt.c
index eb0e428996..719370a8f3 100644
--- a/src/lib/libc/stdlib/ecvt.c
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ecvt.c,v 1.5 2006/01/10 16:18:37 millert Exp $ */ 1/* $OpenBSD: ecvt.c,v 1.6 2006/10/29 18:45:56 deraadt Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com> 4 * Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -25,13 +25,14 @@
25#include <string.h> 25#include <string.h>
26 26
27extern char *__dtoa(double, int, int, int *, int *, char **); 27extern char *__dtoa(double, int, int, int *, int *, char **);
28extern void __freedtoa(char *);
28static char *__cvt(double, int, int *, int *, int, int); 29static char *__cvt(double, int, int *, int *, int, int);
29 30
30static char * 31static char *
31__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad) 32__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
32{ 33{
33 static char *s; 34 static char *s;
34 char *p, *rve; 35 char *p, *rve, c;
35 size_t siz; 36 size_t siz;
36 37
37 if (ndigit == 0) { 38 if (ndigit == 0) {
@@ -64,15 +65,20 @@ __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
64 if (*decpt == 9999) { 65 if (*decpt == 9999) {
65 /* Infinity or Nan, convert to inf or nan like printf */ 66 /* Infinity or Nan, convert to inf or nan like printf */
66 *decpt = 0; 67 *decpt = 0;
67 return(*p == 'I' ? "inf" : "nan"); 68 c = *p;
69 __freedtoa(p);
70 return(c == 'I' ? "inf" : "nan");
68 } 71 }
69 /* Make a local copy and adjust rve to be in terms of s */ 72 /* Make a local copy and adjust rve to be in terms of s */
70 if (pad && fmode) 73 if (pad && fmode)
71 siz += *decpt; 74 siz += *decpt;
72 if ((s = (char *)malloc(siz)) == NULL) 75 if ((s = (char *)malloc(siz)) == NULL) {
76 __freedtoa(p);
73 return(NULL); 77 return(NULL);
78 }
74 (void) strlcpy(s, p, siz); 79 (void) strlcpy(s, p, siz);
75 rve = s + (rve - p); 80 rve = s + (rve - p);
81 __freedtoa(p);
76 } 82 }
77 83
78 /* Add trailing zeros */ 84 /* Add trailing zeros */
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
index bc6295c03d..c24157e465 100644
--- a/src/lib/libc/stdlib/gcvt.c
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: gcvt.c,v 1.9 2006/01/10 16:18:37 millert Exp $ */ 1/* $OpenBSD: gcvt.c,v 1.10 2006/10/29 18:45:56 deraadt Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002, 2003, 2006 Todd C. Miller <Todd.Miller@courtesan.com> 4 * Copyright (c) 2002, 2003, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -26,6 +26,7 @@
26#include <string.h> 26#include <string.h>
27 27
28extern char *__dtoa(double, int, int, int *, int *, char **); 28extern char *__dtoa(double, int, int, int *, int *, char **);
29extern void __freedtoa(char *);
29 30
30char * 31char *
31gcvt(double value, int ndigit, char *buf) 32gcvt(double value, int ndigit, char *buf)
@@ -48,6 +49,7 @@ gcvt(double value, int ndigit, char *buf)
48 */ 49 */
49 snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "", 50 snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "",
50 *digits == 'I' ? "inf" : "nan"); 51 *digits == 'I' ? "inf" : "nan");
52 __freedtoa(digits);
51 return (buf); 53 return (buf);
52 } 54 }
53 55
@@ -104,5 +106,6 @@ gcvt(double value, int ndigit, char *buf)
104 } 106 }
105 *dst = '\0'; 107 *dst = '\0';
106 } 108 }
109 __freedtoa(digits);
107 return (buf); 110 return (buf);
108} 111}
diff --git a/src/lib/libc/stdlib/strtod.c b/src/lib/libc/stdlib/strtod.c
index a8a52e02c5..253bc4ddc0 100644
--- a/src/lib/libc/stdlib/strtod.c
+++ b/src/lib/libc/stdlib/strtod.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: strtod.c,v 1.28 2006/10/13 03:50:14 deraadt Exp $ */ 1/* $OpenBSD: strtod.c,v 1.29 2006/10/29 18:45:56 deraadt Exp $ */
2/**************************************************************** 2/****************************************************************
3 * 3 *
4 * The author of this software is David M. Gay. 4 * The author of this software is David M. Gay.
@@ -125,6 +125,11 @@
125#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} 125#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
126#endif 126#endif
127 127
128#include "thread_private.h"
129
130_THREAD_PRIVATE_KEY(dtoa);
131_THREAD_PRIVATE_KEY(pow5mult);
132
128#ifdef __cplusplus 133#ifdef __cplusplus
129#include "malloc.h" 134#include "malloc.h"
130#include "memory.h" 135#include "memory.h"
@@ -365,21 +370,35 @@ Bigint {
365 370
366 static Bigint *freelist[Kmax+1]; 371 static Bigint *freelist[Kmax+1];
367 372
373#define PRIVATE_MEM 2304
374#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
375 static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
376
368 static Bigint * 377 static Bigint *
369Balloc(int k) 378Balloc(int k)
370{ 379{
371 int x; 380 int x;
381 unsigned int len;
372 Bigint *rv; 382 Bigint *rv;
373 383
384 _THREAD_PRIVATE_MUTEX_LOCK(dtoa);
374 if ((rv = freelist[k])) { 385 if ((rv = freelist[k])) {
375 freelist[k] = rv->next; 386 freelist[k] = rv->next;
376 } 387 }
377 else { 388 else {
378 x = 1 << k; 389 x = 1 << k;
379 rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long)); 390 len = (sizeof(Bigint) + (x-1)*sizeof(Long) + sizeof(double) - 1)
391 /sizeof(double);
392 if (pmem_next - private_mem + len <= PRIVATE_mem) {
393 rv = (Bigint *)pmem_next;
394 pmem_next += len;
395 }
396 else
397 rv = (Bigint *)MALLOC(len *sizeof(double));
380 rv->k = k; 398 rv->k = k;
381 rv->maxwds = x; 399 rv->maxwds = x;
382 } 400 }
401 _THREAD_PRIVATE_MUTEX_UNLOCK(dtoa);
383 rv->sign = rv->wds = 0; 402 rv->sign = rv->wds = 0;
384 return rv; 403 return rv;
385 } 404 }
@@ -388,14 +407,55 @@ Balloc(int k)
388Bfree(Bigint *v) 407Bfree(Bigint *v)
389{ 408{
390 if (v) { 409 if (v) {
410 _THREAD_PRIVATE_MUTEX_LOCK(dtoa);
391 v->next = freelist[v->k]; 411 v->next = freelist[v->k];
392 freelist[v->k] = v; 412 freelist[v->k] = v;
413 _THREAD_PRIVATE_MUTEX_UNLOCK(dtoa);
393 } 414 }
394 } 415 }
395 416
396#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ 417#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
397y->wds*sizeof(Long) + 2*sizeof(int)) 418y->wds*sizeof(Long) + 2*sizeof(int))
398 419
420/* return value is only used as a simple string, so mis-aligned parts
421 * inside the Bigint are not at risk on strict align architectures
422 */
423 static char *
424rv_alloc(int i)
425{
426 int j, k, *r;
427
428 j = sizeof(ULong);
429 for(k = 0;
430 sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
431 j <<= 1)
432 k++;
433 r = (int*)Balloc(k);
434 *r = k;
435 return (char *)(r+1);
436 }
437
438 static char *
439nrv_alloc(char *s, char **rve, int n)
440{
441 char *rv, *t;
442
443 t = rv = rv_alloc(n);
444 while((*t = *s++) !=0)
445 t++;
446 if (rve)
447 *rve = t;
448 return rv;
449 }
450
451 void
452__freedtoa(char *s)
453{
454 Bigint *b = (Bigint *)((int *)s - 1);
455 b->maxwds = 1 << (b->k = *(int*)b);
456 Bfree(b);
457 }
458
399 static Bigint * 459 static Bigint *
400multadd(Bigint *b, int m, int a) /* multiply by m and add a */ 460multadd(Bigint *b, int m, int a) /* multiply by m and add a */
401{ 461{
@@ -651,8 +711,10 @@ pow5mult(Bigint *b, int k)
651 return b; 711 return b;
652 if (!(p5 = p5s)) { 712 if (!(p5 = p5s)) {
653 /* first time */ 713 /* first time */
714 _THREAD_PRIVATE_MUTEX_LOCK(pow5mult);
654 p5 = p5s = i2b(625); 715 p5 = p5s = i2b(625);
655 p5->next = 0; 716 p5->next = 0;
717 _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult);
656 } 718 }
657 for(;;) { 719 for(;;) {
658 if (k & 1) { 720 if (k & 1) {
@@ -663,8 +725,12 @@ pow5mult(Bigint *b, int k)
663 if (!(k >>= 1)) 725 if (!(k >>= 1))
664 break; 726 break;
665 if (!(p51 = p5->next)) { 727 if (!(p51 = p5->next)) {
666 p51 = p5->next = mult(p5,p5); 728 _THREAD_PRIVATE_MUTEX_LOCK(pow5mult);
667 p51->next = 0; 729 if (!(p51 = p5->next)) {
730 p51 = p5->next = mult(p5,p5);
731 p51->next = 0;
732 }
733 _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult);
668 } 734 }
669 p5 = p51; 735 p5 = p51;
670 } 736 }
@@ -1848,17 +1914,9 @@ __dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1848 Bigint *b, *b1, *delta, *mlo, *mhi, *S; 1914 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1849 double ds; 1915 double ds;
1850 char *s, *s0; 1916 char *s, *s0;
1851 static Bigint *result;
1852 static int result_k;
1853 _double d, d2, eps; 1917 _double d, d2, eps;
1854 1918
1855 value(d) = _d; 1919 value(d) = _d;
1856 if (result) {
1857 result->k = result_k;
1858 result->maxwds = 1 << result_k;
1859 Bfree(result);
1860 result = 0;
1861 }
1862 1920
1863 if (word0(d) & Sign_bit) { 1921 if (word0(d) & Sign_bit) {
1864 /* set sign for everything, including 0's and NaNs */ 1922 /* set sign for everything, including 0's and NaNs */
@@ -1877,18 +1935,11 @@ __dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1877 { 1935 {
1878 /* Infinity or NaN */ 1936 /* Infinity or NaN */
1879 *decpt = 9999; 1937 *decpt = 9999;
1880 s =
1881#ifdef IEEE_Arith 1938#ifdef IEEE_Arith
1882 !word1(d) && !(word0(d) & 0xfffff) ? ndigits < 8 ? "Inf" : "Infinity" : 1939 if (!word1(d) && !(word0(d) & 0xfffff))
1940 return nrv_alloc("Infinity", rve, 8);
1883#endif 1941#endif
1884 "NaN"; 1942 return nrv_alloc("NaN", rve, 3);
1885 if (rve)
1886 *rve =
1887#ifdef IEEE_Arith
1888 s[3] ? s + 8 :
1889#endif
1890 s + 3;
1891 return s;
1892 } 1943 }
1893#endif 1944#endif
1894#ifdef IBM 1945#ifdef IBM
@@ -1896,10 +1947,7 @@ __dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1896#endif 1947#endif
1897 if (!value(d)) { 1948 if (!value(d)) {
1898 *decpt = 1; 1949 *decpt = 1;
1899 s = "0"; 1950 return nrv_alloc("0", rve, 1);
1900 if (rve)
1901 *rve = s + 1;
1902 return s;
1903 } 1951 }
1904 1952
1905 b = d2b(value(d), &be, &bbits); 1953 b = d2b(value(d), &be, &bbits);
@@ -2021,11 +2069,7 @@ __dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
2021 if (i <= 0) 2069 if (i <= 0)
2022 i = 1; 2070 i = 1;
2023 } 2071 }
2024 j = sizeof(ULong); 2072 s = s0 = rv_alloc(i);
2025 for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i;
2026 j <<= 1) result_k++;
2027 result = Balloc(result_k);
2028 s = s0 = (char *)result;
2029 2073
2030 if (ilim >= 0 && ilim <= Quick_max && try_quick) { 2074 if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2031 2075