Skip to content

Commit a5ab34a

Browse files
committed
Rewrite allocation functions
* Rename them * Make allocation count operations atomic
1 parent 69d0588 commit a5ab34a

File tree

2 files changed

+90
-72
lines changed

2 files changed

+90
-72
lines changed

ext/bigdecimal/bigdecimal.c

Lines changed: 90 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,77 @@ static struct {
112112
#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
113113
#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
114114

115+
/*
116+
* ================== Memory allocation ============================
117+
*/
118+
119+
#ifdef BIGDECIMAL_DEBUG
120+
static size_t rbd_allocation_count = 0; /* Memory allocation counter */
121+
static inline void
122+
atomic_allocation_count_inc(void)
123+
{
124+
RUBY_ATOMIC_SIZE_INC(rbd_allocation_count);
125+
}
126+
static inline void
127+
atomic_allocation_count_dec_nounderflow(void)
128+
{
129+
if (rbd_allocation_count == 0) return;
130+
RUBY_ATOMIC_SIZE_DEC(rbd_allocation_count);
131+
}
132+
static void
133+
check_allocation_count_nonzero(void)
134+
{
135+
if (rbd_allocation_count != 0) return;
136+
rb_bug("[bigdecimal][rbd_free_struct] Too many memory free calls");
137+
}
138+
#else
139+
# define atomic_allocation_count_inc() /* nothing */
140+
# define atomic_allocation_count_dec_nounderflow() /* nothing */
141+
# define check_allocation_count_nonzero() /* nothing */
142+
#endif /* BIGDECIMAL_DEBUG */
143+
144+
PUREFUNC(static inline size_t rbd_struct_size(size_t const));
145+
146+
static inline size_t
147+
rbd_struct_size(size_t const internal_digits)
148+
{
149+
return offsetof(Real, frac) + sizeof(DECDIG) * internal_digits;
150+
}
151+
152+
static inline Real *
153+
rbd_allocate_struct(size_t const internal_digits)
154+
{
155+
size_t const size = rbd_struct_size(internal_digits);
156+
Real *real = ruby_xcalloc(1, size);
157+
atomic_allocation_count_inc();
158+
return real;
159+
}
160+
161+
static VALUE BigDecimal_wrap_struct(VALUE obj, Real *vp);
162+
163+
static inline Real *
164+
rbd_reallocate_struct(Real *real, size_t const internal_digits)
165+
{
166+
size_t const size = rbd_struct_size(internal_digits);
167+
VALUE obj = real ? real->obj : 0;
168+
Real *new_real = (Real *)ruby_xrealloc(real, size);
169+
if (obj) {
170+
new_real->obj = 0;
171+
BigDecimal_wrap_struct(obj, new_real);
172+
}
173+
return new_real;
174+
}
175+
176+
static void
177+
rbd_free_struct(Real *real)
178+
{
179+
if (real != NULL) {
180+
check_allocation_count_nonzero();
181+
ruby_xfree(real);
182+
atomic_allocation_count_dec_nounderflow();
183+
}
184+
}
185+
115186
/*
116187
* ================== Ruby Interface part ==========================
117188
*/
@@ -145,7 +216,7 @@ static VALUE BigDecimal_negative_zero(void);
145216
static void
146217
BigDecimal_delete(void *pv)
147218
{
148-
VpFree(pv);
219+
rbd_free_struct(pv);
149220
}
150221

151222
static size_t
@@ -980,26 +1051,12 @@ VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
9801051
return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
9811052
}
9821053

983-
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(DECDIG))
984-
985-
static Real *
986-
VpReallocReal(Real *pv, size_t prec)
987-
{
988-
VALUE obj = pv ? pv->obj : 0;
989-
Real *new_pv = (Real *)VpMemRealloc(pv, offsetof(Real, frac) + prec * sizeof(DECDIG));
990-
if (obj) {
991-
new_pv->obj = 0;
992-
BigDecimal_wrap_struct(obj, new_pv);
993-
}
994-
return new_pv;
995-
}
996-
9971054
static Real *
9981055
VpCopy(Real *pv, Real const* const x)
9991056
{
10001057
assert(x != NULL);
10011058

1002-
pv = VpReallocReal(pv, x->MaxPrec);
1059+
pv = rbd_reallocate_struct(pv, x->MaxPrec);
10031060
pv->MaxPrec = x->MaxPrec;
10041061
pv->Prec = x->Prec;
10051062
pv->exponent = x->exponent;
@@ -1825,7 +1882,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
18251882

18261883
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
18271884
/* result adjustment for negative case */
1828-
res = VpReallocReal(res, d->MaxPrec);
1885+
res = rbd_reallocate_struct(res, d->MaxPrec);
18291886
res->MaxPrec = d->MaxPrec;
18301887
VpAddSub(res, d, VpOne(), -1);
18311888
GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b) * 2*BASE_FIG, "0", true));
@@ -3116,15 +3173,15 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
31163173

31173174
Real *vp;
31183175
if (uval == 0) {
3119-
vp = VpAllocReal(1);
3176+
vp = rbd_allocate_struct(1);
31203177
vp->MaxPrec = 1;
31213178
vp->Prec = 1;
31223179
vp->exponent = 1;
31233180
VpSetZero(vp, 1);
31243181
vp->frac[0] = 0;
31253182
}
31263183
else if (uval < BASE) {
3127-
vp = VpAllocReal(1);
3184+
vp = rbd_allocate_struct(1);
31283185
vp->MaxPrec = 1;
31293186
vp->Prec = 1;
31303187
vp->exponent = 1;
@@ -3150,7 +3207,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
31503207
}
31513208

31523209
const size_t exp = len + ntz;
3153-
vp = VpAllocReal(len);
3210+
vp = rbd_allocate_struct(len);
31543211
vp->MaxPrec = len;
31553212
vp->Prec = len;
31563213
vp->exponent = exp;
@@ -4494,42 +4551,6 @@ static int VpRdup(Real *m, size_t ind_m);
44944551
static int gnAlloc = 0; /* Memory allocation counter */
44954552
#endif /* BIGDECIMAL_DEBUG */
44964553

4497-
VP_EXPORT void *
4498-
VpMemAlloc(size_t mb)
4499-
{
4500-
void *p = xmalloc(mb);
4501-
memset(p, 0, mb);
4502-
#ifdef BIGDECIMAL_DEBUG
4503-
gnAlloc++; /* Count allocation call */
4504-
#endif /* BIGDECIMAL_DEBUG */
4505-
return p;
4506-
}
4507-
4508-
VP_EXPORT void *
4509-
VpMemRealloc(void *ptr, size_t mb)
4510-
{
4511-
return xrealloc(ptr, mb);
4512-
}
4513-
4514-
VP_EXPORT void
4515-
VpFree(Real *pv)
4516-
{
4517-
if (pv != NULL) {
4518-
xfree(pv);
4519-
#ifdef BIGDECIMAL_DEBUG
4520-
gnAlloc--; /* Decrement allocation count */
4521-
if (gnAlloc == 0) {
4522-
printf(" *************** All memories allocated freed ****************\n");
4523-
/*getchar();*/
4524-
}
4525-
if (gnAlloc < 0) {
4526-
printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
4527-
/*getchar();*/
4528-
}
4529-
#endif /* BIGDECIMAL_DEBUG */
4530-
}
4531-
}
4532-
45334554
/*
45344555
* EXCEPTION Handling.
45354556
*/
@@ -5009,7 +5030,7 @@ bigdecimal_parse_special_string(const char *str)
50095030
p = str + table[i].len;
50105031
while (*p && ISSPACE(*p)) ++p;
50115032
if (*p == '\0') {
5012-
Real *vp = VpAllocReal(1);
5033+
Real *vp = rbd_allocate_struct(1);
50135034
vp->MaxPrec = 1;
50145035
switch (table[i].sign) {
50155036
default:
@@ -5079,7 +5100,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
50795100
/* necessary to be able to store */
50805101
/* at least mx digits. */
50815102
/* szVal==NULL ==> allocate zero value. */
5082-
vp = VpAllocReal(mx);
5103+
vp = rbd_allocate_struct(mx);
50835104
vp->MaxPrec = mx; /* set max precision */
50845105
VpSetZero(vp, 1); /* initialize vp to zero. */
50855106
return vp;
@@ -5254,7 +5275,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
52545275
if (mx == 0) mx = 1;
52555276
nalloc = Max(nalloc, mx);
52565277
mx = nalloc;
5257-
vp = VpAllocReal(mx);
5278+
vp = rbd_allocate_struct(mx);
52585279
vp->MaxPrec = mx; /* set max precision */
52595280
VpSetZero(vp, sign);
52605281
VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
@@ -5828,8 +5849,8 @@ VpMult(Real *c, Real *a, Real *b)
58285849

58295850
c->exponent = a->exponent; /* set exponent */
58305851
if (!AddExponent(c, b->exponent)) {
5831-
if (w) VpFree(c);
5832-
return 0;
5852+
if (w) rbd_free_struct(c);
5853+
return 0;
58335854
}
58345855
VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
58355856
carry = 0;
@@ -5879,10 +5900,10 @@ VpMult(Real *c, Real *a, Real *b)
58795900
}
58805901
}
58815902
if (w != NULL) { /* free work variable */
5882-
VpNmlz(c);
5883-
VpAsgn(w, c, 1);
5884-
VpFree(c);
5885-
c = w;
5903+
VpNmlz(c);
5904+
VpAsgn(w, c, 1);
5905+
rbd_free_struct(c);
5906+
c = w;
58865907
}
58875908
else {
58885909
VpLimitRound(c,0);
@@ -7047,8 +7068,8 @@ VpSqrt(Real *y, Real *x)
70477068
y->MaxPrec = y_prec;
70487069

70497070
Exit:
7050-
VpFree(f);
7051-
VpFree(r);
7071+
rbd_free_struct(f);
7072+
rbd_free_struct(r);
70527073
return 1;
70537074
}
70547075

@@ -7470,8 +7491,8 @@ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
74707491
printf(" n=%"PRIdVALUE"\n", n);
74717492
}
74727493
#endif /* BIGDECIMAL_DEBUG */
7473-
VpFree(w2);
7474-
VpFree(w1);
7494+
rbd_free_struct(w2);
7495+
rbd_free_struct(w1);
74757496
return 1;
74767497
}
74777498

ext/bigdecimal/bigdecimal.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,6 @@ VP_EXPORT int VpIsNegDoubleZero(double v);
224224
#endif
225225
VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt);
226226
VP_EXPORT size_t VpInit(DECDIG BaseVal);
227-
VP_EXPORT void *VpMemAlloc(size_t mb);
228-
VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
229-
VP_EXPORT void VpFree(Real *pv);
230227
VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal, int strict_p, int exc);
231228
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw);
232229
VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation);

0 commit comments

Comments
 (0)