Commit e378f82e authored by Tom Lane's avatar Tom Lane

Make use of qsort_arg in several places that were formerly using klugy

static variables.  This avoids any risk of potential non-reentrancy,
and in particular offers a much cleaner workaround for the Intel compiler
bug that was affecting ginutil.c.
parent f2332ea1
...@@ -439,18 +439,14 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree ...@@ -439,18 +439,14 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree
} }
/*
* Fortunately, this sort comparison routine needn't be reentrant...
*/
static const gbtree_vinfo *gbt_vsrt_cmp_tinfo;
static int static int
gbt_vsrt_cmp(const void *a, const void *b) gbt_vsrt_cmp(const void *a, const void *b, void *arg)
{ {
GBT_VARKEY_R ar = gbt_var_key_readable(((const Vsrt *) a)->t); GBT_VARKEY_R ar = gbt_var_key_readable(((const Vsrt *) a)->t);
GBT_VARKEY_R br = gbt_var_key_readable(((const Vsrt *) b)->t); GBT_VARKEY_R br = gbt_var_key_readable(((const Vsrt *) b)->t);
const gbtree_vinfo *tinfo = (const gbtree_vinfo *) arg;
return (*gbt_vsrt_cmp_tinfo->f_cmp) (ar.lower, br.lower); return (*tinfo->f_cmp) (ar.lower, br.lower);
} }
GIST_SPLITVEC * GIST_SPLITVEC *
...@@ -496,11 +492,11 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre ...@@ -496,11 +492,11 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtre
} }
/* sort */ /* sort */
gbt_vsrt_cmp_tinfo = tinfo; qsort_arg((void *) &arr[FirstOffsetNumber],
qsort((void *) &arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1,
maxoff - FirstOffsetNumber + 1, sizeof(Vsrt),
sizeof(Vsrt), gbt_vsrt_cmp,
gbt_vsrt_cmp); (void *) tinfo);
/* We do simply create two parts */ /* We do simply create two parts */
......
...@@ -122,14 +122,14 @@ find_wordentry(tsvector * t, QUERYTYPE * q, ITEM * item) ...@@ -122,14 +122,14 @@ find_wordentry(tsvector * t, QUERYTYPE * q, ITEM * item)
} }
static char *SortAndUniqOperand = NULL;
static int static int
compareITEM(const void *a, const void *b) compareITEM(const void *a, const void *b, void *arg)
{ {
char *operand = (char *) arg;
if ((*(ITEM **) a)->length == (*(ITEM **) b)->length) if ((*(ITEM **) a)->length == (*(ITEM **) b)->length)
return strncmp(SortAndUniqOperand + (*(ITEM **) a)->distance, return strncmp(operand + (*(ITEM **) a)->distance,
SortAndUniqOperand + (*(ITEM **) b)->distance, operand + (*(ITEM **) b)->distance,
(*(ITEM **) b)->length); (*(ITEM **) b)->length);
return ((*(ITEM **) a)->length > (*(ITEM **) b)->length) ? 1 : -1; return ((*(ITEM **) a)->length > (*(ITEM **) b)->length) ? 1 : -1;
...@@ -158,15 +158,14 @@ SortAndUniqItems(char *operand, ITEM * item, int *size) ...@@ -158,15 +158,14 @@ SortAndUniqItems(char *operand, ITEM * item, int *size)
if (*size < 2) if (*size < 2)
return res; return res;
SortAndUniqOperand = operand; qsort_arg(res, *size, sizeof(ITEM **), compareITEM, (void *) operand);
qsort(res, *size, sizeof(ITEM **), compareITEM);
ptr = res + 1; ptr = res + 1;
prevptr = res; prevptr = res;
while (ptr - res < *size) while (ptr - res < *size)
{ {
if (compareITEM((void *) ptr, (void *) prevptr) != 0) if (compareITEM((void *) ptr, (void *) prevptr, (void *) operand) != 0)
{ {
prevptr++; prevptr++;
*prevptr = *ptr; *prevptr = *ptr;
...@@ -551,10 +550,11 @@ get_docrep(tsvector * txt, QUERYTYPE * query, int *doclen) ...@@ -551,10 +550,11 @@ get_docrep(tsvector * txt, QUERYTYPE * query, int *doclen)
int len = query->size * 4, int len = query->size * 4,
cur = 0; cur = 0;
DocRepresentation *doc; DocRepresentation *doc;
char *operand;
*(uint16 *) POSNULL = lengthof(POSNULL) - 1; *(uint16 *) POSNULL = lengthof(POSNULL) - 1;
doc = (DocRepresentation *) palloc(sizeof(DocRepresentation) * len); doc = (DocRepresentation *) palloc(sizeof(DocRepresentation) * len);
SortAndUniqOperand = GETOPERAND(query); operand = GETOPERAND(query);
reset_istrue_flag(query); reset_istrue_flag(query);
for (i = 0; i < query->size; i++) for (i = 0; i < query->size; i++)
...@@ -598,7 +598,9 @@ get_docrep(tsvector * txt, QUERYTYPE * query, int *doclen) ...@@ -598,7 +598,9 @@ get_docrep(tsvector * txt, QUERYTYPE * query, int *doclen)
for (k = 0; k < query->size; k++) for (k = 0; k < query->size; k++)
{ {
kptr = item + k; kptr = item + k;
if (k == i || (item[k].type == VAL && compareITEM(&kptr, &iptr) == 0)) if (k == i ||
(item[k].type == VAL &&
compareITEM(&kptr, &iptr, operand) == 0))
{ {
doc[cur].item[doc[cur].nitem] = item + k; doc[cur].item[doc[cur].nitem] = item + k;
doc[cur].nitem++; doc[cur].nitem++;
......
...@@ -85,14 +85,14 @@ uniquePos(WordEntryPos * a, int4 l) ...@@ -85,14 +85,14 @@ uniquePos(WordEntryPos * a, int4 l)
return res + 1 - a; return res + 1 - a;
} }
static char *BufferStr;
static int static int
compareentry(const void *a, const void *b) compareentry(const void *a, const void *b, void *arg)
{ {
char *BufferStr = (char *) arg;
if (((WordEntryIN *) a)->entry.len == ((WordEntryIN *) b)->entry.len) if (((WordEntryIN *) a)->entry.len == ((WordEntryIN *) b)->entry.len)
{ {
return strncmp( return strncmp(&BufferStr[((WordEntryIN *) a)->entry.pos],
&BufferStr[((WordEntryIN *) a)->entry.pos],
&BufferStr[((WordEntryIN *) b)->entry.pos], &BufferStr[((WordEntryIN *) b)->entry.pos],
((WordEntryIN *) a)->entry.len); ((WordEntryIN *) a)->entry.len);
} }
...@@ -117,8 +117,7 @@ uniqueentry(WordEntryIN * a, int4 l, char *buf, int4 *outbuflen) ...@@ -117,8 +117,7 @@ uniqueentry(WordEntryIN * a, int4 l, char *buf, int4 *outbuflen)
} }
ptr = a + 1; ptr = a + 1;
BufferStr = buf; qsort_arg((void *) a, l, sizeof(WordEntryIN), compareentry, (void *) buf);
qsort((void *) a, l, sizeof(WordEntryIN), compareentry);
while (ptr - a < l) while (ptr - a < l)
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.7 2006/10/04 00:29:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.8 2006/10/05 17:57:40 tgl Exp $
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -129,62 +129,48 @@ compareEntries(GinState *ginstate, Datum a, Datum b) ...@@ -129,62 +129,48 @@ compareEntries(GinState *ginstate, Datum a, Datum b)
); );
} }
static FmgrInfo *cmpDatumPtr = NULL; typedef struct
{
#if defined(__INTEL_COMPILER) && (defined(__ia64__) || defined(__ia64)) FmgrInfo *cmpDatumFunc;
/* bool *needUnique;
* Intel Compiler on Intel Itanium with -O2 has a bug around } cmpEntriesData;
* change static variable by user function called from
* libc func: it doesn't change. So mark it as volatile.
*
* It's a pity, but it's impossible to define optimization
* level here.
*/
#define VOLATILE volatile
#else
#define VOLATILE
#endif
static bool VOLATILE needUnique = FALSE;
static int static int
cmpEntries(const void *a, const void *b) cmpEntries(const Datum *a, const Datum *b, cmpEntriesData *arg)
{ {
int res = DatumGetInt32( int res = DatumGetInt32(FunctionCall2(arg->cmpDatumFunc,
FunctionCall2( *a, *b));
cmpDatumPtr,
*(Datum *) a,
*(Datum *) b
)
);
if (res == 0) if (res == 0)
needUnique = TRUE; *(arg->needUnique) = TRUE;
return res; return res;
} }
Datum * Datum *
extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries) extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries,
bool *needUnique)
{ {
Datum *entries; Datum *entries;
entries = (Datum *) DatumGetPointer( entries = (Datum *) DatumGetPointer(FunctionCall2(
FunctionCall2(
&ginstate->extractValueFn, &ginstate->extractValueFn,
value, value,
PointerGetDatum(nentries) PointerGetDatum(nentries)
) ));
);
if (entries == NULL) if (entries == NULL)
*nentries = 0; *nentries = 0;
*needUnique = FALSE;
if (*nentries > 1) if (*nentries > 1)
{ {
cmpDatumPtr = &ginstate->compareFn; cmpEntriesData arg;
needUnique = FALSE;
qsort(entries, *nentries, sizeof(Datum), cmpEntries); arg.cmpDatumFunc = &ginstate->compareFn;
arg.needUnique = needUnique;
qsort_arg(entries, *nentries, sizeof(Datum),
(qsort_arg_comparator) cmpEntries, (void *) &arg);
} }
return entries; return entries;
...@@ -194,9 +180,11 @@ extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries) ...@@ -194,9 +180,11 @@ extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries)
Datum * Datum *
extractEntriesSU(GinState *ginstate, Datum value, uint32 *nentries) extractEntriesSU(GinState *ginstate, Datum value, uint32 *nentries)
{ {
Datum *entries = extractEntriesS(ginstate, value, nentries); bool needUnique;
Datum *entries = extractEntriesS(ginstate, value, nentries,
&needUnique);
if (*nentries > 1 && needUnique) if (needUnique)
{ {
Datum *ptr, Datum *ptr,
*res; *res;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.99 2006/10/04 00:29:50 momjian Exp $ * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.100 2006/10/05 17:57:40 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1294,11 +1294,12 @@ typedef struct ...@@ -1294,11 +1294,12 @@ typedef struct
int first; /* values[] index of first occurrence */ int first; /* values[] index of first occurrence */
} ScalarMCVItem; } ScalarMCVItem;
typedef struct
/* context information for compare_scalars() */ {
static FmgrInfo *datumCmpFn; FmgrInfo *cmpFn;
static SortFunctionKind datumCmpFnKind; SortFunctionKind cmpFnKind;
static int *datumCmpTupnoLink; int *tupnoLink;
} CompareScalarsContext;
static void compute_minimal_stats(VacAttrStatsP stats, static void compute_minimal_stats(VacAttrStatsP stats,
...@@ -1309,7 +1310,7 @@ static void compute_scalar_stats(VacAttrStatsP stats, ...@@ -1309,7 +1310,7 @@ static void compute_scalar_stats(VacAttrStatsP stats,
AnalyzeAttrFetchFunc fetchfunc, AnalyzeAttrFetchFunc fetchfunc,
int samplerows, int samplerows,
double totalrows); double totalrows);
static int compare_scalars(const void *a, const void *b); static int compare_scalars(const void *a, const void *b, void *arg);
static int compare_mcvs(const void *a, const void *b); static int compare_mcvs(const void *a, const void *b);
...@@ -1828,13 +1829,14 @@ compute_scalar_stats(VacAttrStatsP stats, ...@@ -1828,13 +1829,14 @@ compute_scalar_stats(VacAttrStatsP stats,
num_hist, num_hist,
dups_cnt; dups_cnt;
int slot_idx = 0; int slot_idx = 0;
CompareScalarsContext cxt;
/* Sort the collected values */ /* Sort the collected values */
datumCmpFn = &f_cmpfn; cxt.cmpFn = &f_cmpfn;
datumCmpFnKind = cmpFnKind; cxt.cmpFnKind = cmpFnKind;
datumCmpTupnoLink = tupnoLink; cxt.tupnoLink = tupnoLink;
qsort((void *) values, values_cnt, qsort_arg((void *) values, values_cnt, sizeof(ScalarItem),
sizeof(ScalarItem), compare_scalars); compare_scalars, (void *) &cxt);
/* /*
* Now scan the values in order, find the most common ones, and also * Now scan the values in order, find the most common ones, and also
...@@ -2183,35 +2185,36 @@ compute_scalar_stats(VacAttrStatsP stats, ...@@ -2183,35 +2185,36 @@ compute_scalar_stats(VacAttrStatsP stats,
} }
/* /*
* qsort comparator for sorting ScalarItems * qsort_arg comparator for sorting ScalarItems
* *
* Aside from sorting the items, we update the datumCmpTupnoLink[] array * Aside from sorting the items, we update the tupnoLink[] array
* whenever two ScalarItems are found to contain equal datums. The array * whenever two ScalarItems are found to contain equal datums. The array
* is indexed by tupno; for each ScalarItem, it contains the highest * is indexed by tupno; for each ScalarItem, it contains the highest
* tupno that that item's datum has been found to be equal to. This allows * tupno that that item's datum has been found to be equal to. This allows
* us to avoid additional comparisons in compute_scalar_stats(). * us to avoid additional comparisons in compute_scalar_stats().
*/ */
static int static int
compare_scalars(const void *a, const void *b) compare_scalars(const void *a, const void *b, void *arg)
{ {
Datum da = ((ScalarItem *) a)->value; Datum da = ((ScalarItem *) a)->value;
int ta = ((ScalarItem *) a)->tupno; int ta = ((ScalarItem *) a)->tupno;
Datum db = ((ScalarItem *) b)->value; Datum db = ((ScalarItem *) b)->value;
int tb = ((ScalarItem *) b)->tupno; int tb = ((ScalarItem *) b)->tupno;
CompareScalarsContext *cxt = (CompareScalarsContext *) arg;
int32 compare; int32 compare;
compare = ApplySortFunction(datumCmpFn, datumCmpFnKind, compare = ApplySortFunction(cxt->cmpFn, cxt->cmpFnKind,
da, false, db, false); da, false, db, false);
if (compare != 0) if (compare != 0)
return compare; return compare;
/* /*
* The two datums are equal, so update datumCmpTupnoLink[]. * The two datums are equal, so update cxt->tupnoLink[].
*/ */
if (datumCmpTupnoLink[ta] < tb) if (cxt->tupnoLink[ta] < tb)
datumCmpTupnoLink[ta] = tb; cxt->tupnoLink[ta] = tb;
if (datumCmpTupnoLink[tb] < ta) if (cxt->tupnoLink[tb] < ta)
datumCmpTupnoLink[tb] = ta; cxt->tupnoLink[tb] = ta;
/* /*
* For equal datums, sort by tupno * For equal datums, sort by tupno
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* header file for postgres inverted index access method implementation. * header file for postgres inverted index access method implementation.
* *
* Copyright (c) 2006, PostgreSQL Global Development Group * Copyright (c) 2006, PostgreSQL Global Development Group
* $PostgreSQL: pgsql/src/include/access/gin.h,v 1.8 2006/10/04 00:30:06 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/gin.h,v 1.9 2006/10/05 17:57:40 tgl Exp $
*-------------------------------------------------------------------------- *--------------------------------------------------------------------------
*/ */
...@@ -232,7 +232,8 @@ extern Buffer GinNewBuffer(Relation index); ...@@ -232,7 +232,8 @@ extern Buffer GinNewBuffer(Relation index);
extern void GinInitBuffer(Buffer b, uint32 f); extern void GinInitBuffer(Buffer b, uint32 f);
extern void GinInitPage(Page page, uint32 f, Size pageSize); extern void GinInitPage(Page page, uint32 f, Size pageSize);
extern int compareEntries(GinState *ginstate, Datum a, Datum b); extern int compareEntries(GinState *ginstate, Datum a, Datum b);
extern Datum *extractEntriesS(GinState *ginstate, Datum value, uint32 *nentries); extern Datum *extractEntriesS(GinState *ginstate, Datum value,
uint32 *nentries, bool *needUnique);
extern Datum *extractEntriesSU(GinState *ginstate, Datum value, uint32 *nentries); extern Datum *extractEntriesSU(GinState *ginstate, Datum value, uint32 *nentries);
extern Page GinPageGetCopyPage(Page page); extern Page GinPageGetCopyPage(Page page);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment