Merge pull request #24581 from vrabaud:tsan

Fix race condition in color_lab.cpp initLabTabs(). #24581

There is a race condition between when the static bool is initialized (which is thread safe) and its value check. This PR changes the static bool to a static lambda call to make it thread safe. The static_cast<void> in the end is to prevent unused variables warnings.

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
pull/24599/head
Vincent Rabaud 1 year ago committed by GitHub
parent 49463c4420
commit 06f62a3dd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 181
      modules/imgproc/src/color_lab.cpp

@ -1223,119 +1223,120 @@ static LABLUVLUT_s16_t initLUTforLABLUVs16(const softfloat & un, const softfloat
}
static void initLabTabs()
static bool createLabTabs()
{
static bool initialized = false;
if(!initialized)
softfloat f[LAB_CBRT_TAB_SIZE+1], g[GAMMA_TAB_SIZE+1], ig[GAMMA_TAB_SIZE+1];
softfloat scale = softfloat::one()/softfloat(LabCbrtTabScale);
int i;
for(i = 0; i <= LAB_CBRT_TAB_SIZE; i++)
{
softfloat f[LAB_CBRT_TAB_SIZE+1], g[GAMMA_TAB_SIZE+1], ig[GAMMA_TAB_SIZE+1];
softfloat scale = softfloat::one()/softfloat(LabCbrtTabScale);
int i;
for(i = 0; i <= LAB_CBRT_TAB_SIZE; i++)
{
softfloat x = scale*softfloat(i);
f[i] = x < lthresh ? mulAdd(x, lscale, lbias) : cbrt(x);
}
LabCbrtTab = splineBuild(f, LAB_CBRT_TAB_SIZE);
softfloat x = scale*softfloat(i);
f[i] = x < lthresh ? mulAdd(x, lscale, lbias) : cbrt(x);
}
LabCbrtTab = splineBuild(f, LAB_CBRT_TAB_SIZE);
scale = softfloat::one()/softfloat(GammaTabScale);
for(i = 0; i <= GAMMA_TAB_SIZE; i++)
{
softfloat x = scale*softfloat(i);
g[i] = applyGamma(x);
ig[i] = applyInvGamma(x);
}
scale = softfloat::one()/softfloat(GammaTabScale);
for(i = 0; i <= GAMMA_TAB_SIZE; i++)
{
softfloat x = scale*softfloat(i);
g[i] = applyGamma(x);
ig[i] = applyInvGamma(x);
}
sRGBGammaTab = splineBuild(g, GAMMA_TAB_SIZE);
sRGBInvGammaTab = splineBuild(ig, GAMMA_TAB_SIZE);
sRGBGammaTab = splineBuild(g, GAMMA_TAB_SIZE);
sRGBInvGammaTab = splineBuild(ig, GAMMA_TAB_SIZE);
static const softfloat intScale(255*(1 << gamma_shift));
for(i = 0; i < 256; i++)
static const softfloat intScale(255*(1 << gamma_shift));
for(i = 0; i < 256; i++)
{
softfloat x = softfloat(i)/f255;
sRGBGammaTab_b[i] = (ushort)(cvRound(intScale*applyGamma(x)));
linearGammaTab_b[i] = (ushort)(i*(1 << gamma_shift));
}
static const softfloat invScale = softfloat::one()/softfloat((int)INV_GAMMA_TAB_SIZE);
for(i = 0; i < INV_GAMMA_TAB_SIZE; i++)
{
softfloat x = invScale*softfloat(i);
sRGBInvGammaTab_b[i] = (ushort)(cvRound(f255*applyInvGamma(x)));
linearInvGammaTab_b[i] = (ushort)(cvTrunc(f255*x));
}
static const softfloat cbTabScale(softfloat::one()/(f255*(1 << gamma_shift)));
static const softfloat lshift2(1 << lab_shift2);
for(i = 0; i < LAB_CBRT_TAB_SIZE_B; i++)
{
softfloat x = cbTabScale*softfloat(i);
LabCbrtTab_b[i] = (ushort)(cvRound(lshift2 * (x < lthresh ? mulAdd(x, lscale, lbias) : cbrt(x))));
}
//Lookup table for L to y and ify calculations
for(i = 0; i < 256; i++)
{
int y, ify;
//8 * 255.0 / 100.0 == 20.4
if( i <= 20)
{
softfloat x = softfloat(i)/f255;
sRGBGammaTab_b[i] = (ushort)(cvRound(intScale*applyGamma(x)));
linearGammaTab_b[i] = (ushort)(i*(1 << gamma_shift));
//yy = li / 903.3f;
//y = L*100/903.3f; 903.3f = (29/3)^3, 255 = 17*3*5
y = cvRound(softfloat(i*LUT_BASE*20*9)/softfloat(17*29*29*29));
//fy = 7.787f * yy + 16.0f / 116.0f; 7.787f = (29/3)^3/(29*4)
ify = cvRound(softfloat((int)LUT_BASE)*(softfloat(16)/softfloat(116) + softfloat(i*5)/softfloat(3*17*29)));
}
static const softfloat invScale = softfloat::one()/softfloat((int)INV_GAMMA_TAB_SIZE);
for(i = 0; i < INV_GAMMA_TAB_SIZE; i++)
else
{
softfloat x = invScale*softfloat(i);
sRGBInvGammaTab_b[i] = (ushort)(cvRound(f255*applyInvGamma(x)));
linearInvGammaTab_b[i] = (ushort)(cvTrunc(f255*x));
//fy = (li + 16.0f) / 116.0f;
softfloat fy = (softfloat(i*100*LUT_BASE)/softfloat(255*116) +
softfloat(16*LUT_BASE)/softfloat(116));
ify = cvRound(fy);
//yy = fy * fy * fy;
y = cvRound(fy*fy*fy/softfloat(LUT_BASE*LUT_BASE));
}
static const softfloat cbTabScale(softfloat::one()/(f255*(1 << gamma_shift)));
static const softfloat lshift2(1 << lab_shift2);
for(i = 0; i < LAB_CBRT_TAB_SIZE_B; i++)
{
softfloat x = cbTabScale*softfloat(i);
LabCbrtTab_b[i] = (ushort)(cvRound(lshift2 * (x < lthresh ? mulAdd(x, lscale, lbias) : cbrt(x))));
}
LabToYF_b[i*2 ] = (ushort)y; // 0 <= y <= BASE
LabToYF_b[i*2+1] = (ushort)ify; // 2260 <= ify <= BASE
}
//Lookup table for L to y and ify calculations
for(i = 0; i < 256; i++)
{
int y, ify;
//8 * 255.0 / 100.0 == 20.4
if( i <= 20)
{
//yy = li / 903.3f;
//y = L*100/903.3f; 903.3f = (29/3)^3, 255 = 17*3*5
y = cvRound(softfloat(i*LUT_BASE*20*9)/softfloat(17*29*29*29));
//fy = 7.787f * yy + 16.0f / 116.0f; 7.787f = (29/3)^3/(29*4)
ify = cvRound(softfloat((int)LUT_BASE)*(softfloat(16)/softfloat(116) + softfloat(i*5)/softfloat(3*17*29)));
}
else
{
//fy = (li + 16.0f) / 116.0f;
softfloat fy = (softfloat(i*100*LUT_BASE)/softfloat(255*116) +
softfloat(16*LUT_BASE)/softfloat(116));
ify = cvRound(fy);
//yy = fy * fy * fy;
y = cvRound(fy*fy*fy/softfloat(LUT_BASE*LUT_BASE));
}
//Lookup table for a,b to x,z conversion
abToXZ_b = initLUTforABXZ();
LabToYF_b[i*2 ] = (ushort)y; // 0 <= y <= BASE
LabToYF_b[i*2+1] = (ushort)ify; // 2260 <= ify <= BASE
}
softfloat dd = D65[0] + D65[1]*softdouble(15) + D65[2]*softdouble(3);
dd = softfloat::one()/max(dd, softfloat::eps());
softfloat un = dd*softfloat(13*4)*D65[0];
softfloat vn = dd*softfloat(13*9)*D65[1];
//Lookup table for a,b to x,z conversion
abToXZ_b = initLUTforABXZ();
//Luv LUT
LUVLUT = initLUTforLUV(un, vn);
softfloat dd = D65[0] + D65[1]*softdouble(15) + D65[2]*softdouble(3);
dd = softfloat::one()/max(dd, softfloat::eps());
softfloat un = dd*softfloat(13*4)*D65[0];
softfloat vn = dd*softfloat(13*9)*D65[1];
//try to suppress warning
static const bool calcLUT = enableRGB2LabInterpolation || enableRGB2LuvInterpolation;
if(calcLUT)
{
//Luv LUT
LUVLUT = initLUTforLUV(un, vn);
LABLUVLUTs16 = initLUTforLABLUVs16(un, vn);
//try to suppress warning
static const bool calcLUT = enableRGB2LabInterpolation || enableRGB2LuvInterpolation;
if(calcLUT)
for(int16_t p = 0; p < TRILINEAR_BASE; p++)
{
LABLUVLUTs16 = initLUTforLABLUVs16(un, vn);
for(int16_t p = 0; p < TRILINEAR_BASE; p++)
int16_t pp = TRILINEAR_BASE - p;
for(int16_t q = 0; q < TRILINEAR_BASE; q++)
{
int16_t pp = TRILINEAR_BASE - p;
for(int16_t q = 0; q < TRILINEAR_BASE; q++)
int16_t qq = TRILINEAR_BASE - q;
for(int16_t r = 0; r < TRILINEAR_BASE; r++)
{
int16_t qq = TRILINEAR_BASE - q;
for(int16_t r = 0; r < TRILINEAR_BASE; r++)
{
int16_t rr = TRILINEAR_BASE - r;
int16_t* w = &trilinearLUT[8*p + 8*TRILINEAR_BASE*q + 8*TRILINEAR_BASE*TRILINEAR_BASE*r];
w[0] = pp * qq * rr; w[1] = pp * qq * r ; w[2] = pp * q * rr; w[3] = pp * q * r ;
w[4] = p * qq * rr; w[5] = p * qq * r ; w[6] = p * q * rr; w[7] = p * q * r ;
}
int16_t rr = TRILINEAR_BASE - r;
int16_t* w = &trilinearLUT[8*p + 8*TRILINEAR_BASE*q + 8*TRILINEAR_BASE*TRILINEAR_BASE*r];
w[0] = pp * qq * rr; w[1] = pp * qq * r ; w[2] = pp * q * rr; w[3] = pp * q * r ;
w[4] = p * qq * rr; w[5] = p * qq * r ; w[6] = p * q * rr; w[7] = p * q * r ;
}
}
}
initialized = true;
}
return true;
}
static bool initLabTabs()
{
static bool initialized = createLabTabs();
return initialized;
}

Loading…
Cancel
Save