133
133
#define MULTIXACT_MEMBERS_PER_PAGE \
134
134
(MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP)
135
135
136
+ /*
137
+ * Because the number of items per page is not a divisor of the last item
138
+ * number (member 0xFFFFFFFF), the last segment does not use the maximum number
139
+ * of pages, and moreover the last used page therein does not use the same
140
+ * number of items as previous pages. (Another way to say it is that the
141
+ * 0xFFFFFFFF member is somewhere in the middle of the last page, so the page
142
+ * has some empty space after that item.)
143
+ *
144
+ * This constant is the number of members in the last page of the last segment.
145
+ */
146
+ #define MAX_MEMBERS_IN_LAST_MEMBERS_PAGE \
147
+ ((uint32) ((0xFFFFFFFF % MULTIXACT_MEMBERS_PER_PAGE) + 1))
148
+
136
149
/* page in which a member is to be found */
137
150
#define MXOffsetToMemberPage (xid ) ((xid) / (TransactionId) MULTIXACT_MEMBERS_PER_PAGE)
138
151
@@ -2278,6 +2291,7 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
2278
2291
{
2279
2292
int flagsoff ;
2280
2293
int flagsbit ;
2294
+ uint32 difference ;
2281
2295
2282
2296
/*
2283
2297
* Only zero when at first entry of a page.
@@ -2299,24 +2313,29 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
2299
2313
}
2300
2314
2301
2315
/*
2302
- * Advance to next page, taking care to properly handle the wraparound
2303
- * case. OK if nmembers goes negative.
2316
+ * Compute the number of items till end of current page. Careful: if
2317
+ * addition of unsigned ints wraps around, we're at the last page of
2318
+ * the last segment; since that page holds a different number of items
2319
+ * than other pages, we need to do it differently.
2304
2320
*/
2305
- if (( unsigned int ) ( offset + nmembers ) < offset )
2321
+ if (offset + MAX_MEMBERS_IN_LAST_MEMBERS_PAGE < offset )
2306
2322
{
2307
- uint32 difference = offset + MULTIXACT_MEMBERS_PER_PAGE ;
2308
-
2309
- nmembers -= (unsigned int ) (MULTIXACT_MEMBERS_PER_PAGE - difference );
2310
- offset = 0 ;
2323
+ /*
2324
+ * This is the last page of the last segment; we can compute the
2325
+ * number of items left to allocate in it without modulo
2326
+ * arithmetic.
2327
+ */
2328
+ difference = MaxMultiXactOffset - offset + 1 ;
2311
2329
}
2312
2330
else
2313
- {
2314
- int difference ;
2315
-
2316
2331
difference = MULTIXACT_MEMBERS_PER_PAGE - offset % MULTIXACT_MEMBERS_PER_PAGE ;
2317
- nmembers -= difference ;
2318
- offset += difference ;
2319
- }
2332
+
2333
+ /*
2334
+ * Advance to next page, taking care to properly handle the wraparound
2335
+ * case. OK if nmembers goes negative.
2336
+ */
2337
+ nmembers -= difference ;
2338
+ offset += difference ;
2320
2339
}
2321
2340
}
2322
2341
0 commit comments