|
|
- Description: Handle unaligned buffers in connect's TYPBLK class
- On MIPS platforms (and probably others) unaligned memory access results in a
- bus error. In the connect storage engine, block data for some data formats is
- stored packed in memory and the TYPBLK class is used to read values from it.
- Since TYPBLK does not have special handling for this packed memory, it can
- quite easily result in unaligned memory accesses.
- .
- The simple way to fix this is to perform all accesses to the main buffer
- through memcpy. With GCC and optimizations turned on, this call to memcpy is
- completely optimized away on architectures where unaligned accesses are ok
- (like x86).
- Author: James Cowgill <jcowgill@debian.org>
- ---
- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
- --- a/storage/connect/valblk.h
- +++ b/storage/connect/valblk.h
- @@ -139,6 +139,7 @@ class VALBLK : public BLOCK {
- int Prec; // Precision of float values
- }; // end of class VALBLK
-
- +
- /***********************************************************************/
- /* Class TYPBLK: represents a block of typed values. */
- /***********************************************************************/
- @@ -151,40 +152,41 @@ class TYPBLK : public VALBLK {
- // Implementation
- virtual bool Init(PGLOBAL g, bool check);
- virtual int GetVlen(void) {return sizeof(TYPE);}
- - virtual char GetTinyValue(int n) {return (char)Typp[n];}
- - virtual uchar GetUTinyValue(int n) {return (uchar)Typp[n];}
- - virtual short GetShortValue(int n) {return (short)Typp[n];}
- - virtual ushort GetUShortValue(int n) {return (ushort)Typp[n];}
- - virtual int GetIntValue(int n) {return (int)Typp[n];}
- - virtual uint GetUIntValue(int n) {return (uint)Typp[n];}
- - virtual longlong GetBigintValue(int n) {return (longlong)Typp[n];}
- - virtual ulonglong GetUBigintValue(int n) {return (ulonglong)Typp[n];}
- - virtual double GetFloatValue(int n) {return (double)Typp[n];}
- +
- + virtual char GetTinyValue(int n) {return (char)UnalignedRead(n);}
- + virtual uchar GetUTinyValue(int n) {return (uchar)UnalignedRead(n);}
- + virtual short GetShortValue(int n) {return (short)UnalignedRead(n);}
- + virtual ushort GetUShortValue(int n) {return (ushort)UnalignedRead(n);}
- + virtual int GetIntValue(int n) {return (int)UnalignedRead(n);}
- + virtual uint GetUIntValue(int n) {return (uint)UnalignedRead(n);}
- + virtual longlong GetBigintValue(int n) {return (longlong)UnalignedRead(n);}
- + virtual ulonglong GetUBigintValue(int n) {return (ulonglong)UnalignedRead(n);}
- + virtual double GetFloatValue(int n) {return (double)UnalignedRead(n);}
- virtual char *GetCharString(char *p, int n);
- - virtual void Reset(int n) {Typp[n] = 0;}
- + virtual void Reset(int n) {UnalignedWrite(n, 0);}
-
- // Methods
- using VALBLK::SetValue;
- virtual void SetValue(PCSZ sp, int n);
- virtual void SetValue(const char *sp, uint len, int n);
- virtual void SetValue(short sval, int n)
- - {Typp[n] = (TYPE)sval; SetNull(n, false);}
- + {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);}
- virtual void SetValue(ushort sval, int n)
- - {Typp[n] = (TYPE)sval; SetNull(n, false);}
- + {UnalignedWrite(n, (TYPE)sval); SetNull(n, false);}
- virtual void SetValue(int lval, int n)
- - {Typp[n] = (TYPE)lval; SetNull(n, false);}
- + {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
- virtual void SetValue(uint lval, int n)
- - {Typp[n] = (TYPE)lval; SetNull(n, false);}
- + {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
- virtual void SetValue(longlong lval, int n)
- - {Typp[n] = (TYPE)lval; SetNull(n, false);}
- + {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
- virtual void SetValue(ulonglong lval, int n)
- - {Typp[n] = (TYPE)lval; SetNull(n, false);}
- + {UnalignedWrite(n, (TYPE)lval); SetNull(n, false);}
- virtual void SetValue(double fval, int n)
- - {Typp[n] = (TYPE)fval; SetNull(n, false);}
- + {UnalignedWrite(n, (TYPE)fval); SetNull(n, false);}
- virtual void SetValue(char cval, int n)
- - {Typp[n] = (TYPE)cval; SetNull(n, false);}
- + {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);}
- virtual void SetValue(uchar cval, int n)
- - {Typp[n] = (TYPE)cval; SetNull(n, false);}
- + {UnalignedWrite(n, (TYPE)cval); SetNull(n, false);}
- virtual void SetValue(PVAL valp, int n);
- virtual void SetValue(PVBLK pv, int n1, int n2);
- virtual void SetMin(PVAL valp, int n);
- @@ -206,6 +208,17 @@ class TYPBLK : public VALBLK {
- // Members
- TYPE* const &Typp;
- const char *Fmt;
- +
- + // Unaligned access
- + TYPE UnalignedRead(int n) const {
- + TYPE result;
- + memcpy(&result, Typp + n, sizeof(TYPE));
- + return result;
- + }
- +
- + void UnalignedWrite(int n, TYPE value) {
- + memcpy(Typp + n, &value, sizeof(TYPE));
- + }
- }; // end of class TYPBLK
-
- /***********************************************************************/
- --- a/storage/connect/valblk.cpp
- +++ b/storage/connect/valblk.cpp
- @@ -266,14 +266,14 @@ bool TYPBLK<TYPE>::Init(PGLOBAL g, bool
- template <class TYPE>
- char *TYPBLK<TYPE>::GetCharString(char *p, int n)
- {
- - sprintf(p, Fmt, Typp[n]);
- + sprintf(p, Fmt, UnalignedRead(n));
- return p;
- } // end of GetCharString
-
- template <>
- char *TYPBLK<double>::GetCharString(char *p, int n)
- {
- - sprintf(p, Fmt, Prec, Typp[n]);
- + sprintf(p, Fmt, Prec, UnalignedRead(n));
- return p;
- } // end of GetCharString
-
- @@ -289,7 +289,7 @@ void TYPBLK<TYPE>::SetValue(PVAL valp, i
- ChkTyp(valp);
-
- if (!(b = valp->IsNull()))
- - Typp[n] = GetTypedValue(valp);
- + UnalignedWrite(n, GetTypedValue(valp));
- else
- Reset(n);
-
- @@ -351,9 +351,9 @@ void TYPBLK<TYPE>::SetValue(PCSZ p, int
- ulonglong val = CharToNumber(p, strlen(p), maxval, Unsigned, &minus);
-
- if (minus && val < maxval)
- - Typp[n] = (TYPE)(-(signed)val);
- + UnalignedWrite(n, (TYPE)(-(signed)val));
- else
- - Typp[n] = (TYPE)val;
- + UnalignedWrite(n, (TYPE)val);
-
- SetNull(n, false);
- } // end of SetValue
- @@ -396,7 +396,7 @@ void TYPBLK<double>::SetValue(PCSZ p, in
- throw Type;
- } // endif Check
-
- - Typp[n] = atof(p);
- + UnalignedWrite(n, atof(p));
- SetNull(n, false);
- } // end of SetValue
-
- @@ -428,7 +428,7 @@ void TYPBLK<TYPE>::SetValue(PVBLK pv, in
- ChkTyp(pv);
-
- if (!(b = pv->IsNull(n2) && Nullable))
- - Typp[n1] = GetTypedValue(pv, n2);
- + UnalignedWrite(n1, GetTypedValue(pv, n2));
- else
- Reset(n1);
-
- @@ -479,10 +479,10 @@ void TYPBLK<TYPE>::SetMin(PVAL valp, int
- {
- CheckParms(valp, n)
- TYPE tval = GetTypedValue(valp);
- - TYPE& tmin = Typp[n];
- + TYPE tmin = UnalignedRead(n);
-
- if (tval < tmin)
- - tmin = tval;
- + UnalignedWrite(n, tval);
-
- } // end of SetMin
-
- @@ -494,10 +494,10 @@ void TYPBLK<TYPE>::SetMax(PVAL valp, int
- {
- CheckParms(valp, n)
- TYPE tval = GetTypedValue(valp);
- - TYPE& tmin = Typp[n];
- + TYPE tmin = UnalignedRead(n);
-
- if (tval > tmin)
- - tmin = tval;
- + UnalignedWrite(n, tval);
-
- } // end of SetMax
-
- @@ -511,8 +511,7 @@ void TYPBLK<TYPE>::SetValues(PVBLK pv, i
- CheckType(pv)
- TYPE *lp = ((TYPBLK*)pv)->Typp;
-
- - for (int i = k; i < n; i++) // TODO
- - Typp[i] = lp[i];
- + memcpy(Typp + k, lp + k, sizeof(TYPE) * n);
-
- } // end of SetValues
- #endif // 0
- @@ -523,7 +522,7 @@ void TYPBLK<TYPE>::SetValues(PVBLK pv, i
- template <class TYPE>
- void TYPBLK<TYPE>::Move(int i, int j)
- {
- - Typp[j] = Typp[i];
- + UnalignedWrite(j, UnalignedRead(i));
- MoveNull(i, j);
- } // end of Move
-
- @@ -537,7 +536,7 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n
- ChkIndx(n);
- ChkTyp(vp);
- #endif // _DEBUG
- - TYPE mlv = Typp[n];
- + TYPE mlv = UnalignedRead(n);
- TYPE vlv = GetTypedValue(vp);
-
- return (vlv > mlv) ? 1 : (vlv < mlv) ? (-1) : 0;
- @@ -549,8 +548,8 @@ int TYPBLK<TYPE>::CompVal(PVAL vp, int n
- template <class TYPE>
- int TYPBLK<TYPE>::CompVal(int i1, int i2)
- {
- - TYPE lv1 = Typp[i1];
- - TYPE lv2 = Typp[i2];
- + TYPE lv1 = UnalignedRead(i1);
- + TYPE lv2 = UnalignedRead(i2);
-
- return (lv1 > lv2) ? 1 : (lv1 < lv2) ? (-1) : 0;
- } // end of CompVal
- @@ -587,7 +586,7 @@ int TYPBLK<TYPE>::Find(PVAL vp)
- TYPE n = GetTypedValue(vp);
-
- for (i = 0; i < Nval; i++)
- - if (n == Typp[i])
- + if (n == UnalignedRead(i))
- break;
-
- return (i < Nval) ? i : (-1);
- @@ -603,7 +602,7 @@ int TYPBLK<TYPE>::GetMaxLength(void)
- int i, n, m;
-
- for (i = n = 0; i < Nval; i++) {
- - m = sprintf(buf, Fmt, Typp[i]);
- + m = sprintf(buf, Fmt, UnalignedRead(i));
- n = MY_MAX(n, m);
- } // endfor i
-
- @@ -1333,7 +1332,7 @@ char *DATBLK::GetCharString(char *p, int
- char *vp;
-
- if (Dvalp) {
- - Dvalp->SetValue(Typp[n]);
- + Dvalp->SetValue(UnalignedRead(n));
- vp = Dvalp->GetCharString(p);
- } else
- vp = TYPBLK<int>::GetCharString(p, n);
- @@ -1349,7 +1348,7 @@ void DATBLK::SetValue(PCSZ p, int n)
- if (Dvalp) {
- // Decode the string according to format
- Dvalp->SetValue_psz(p);
- - Typp[n] = Dvalp->GetIntValue();
- + UnalignedWrite(n, Dvalp->GetIntValue());
- } else
- TYPBLK<int>::SetValue(p, n);
-
|