133133#define MULTIXACT_MEMBERS_PER_PAGE \
134134 (MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP)
135135
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+
136149/* page in which a member is to be found */
137150#define MXOffsetToMemberPage (xid ) ((xid) / (TransactionId) MULTIXACT_MEMBERS_PER_PAGE)
138151
@@ -2278,6 +2291,7 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
22782291 {
22792292 int flagsoff ;
22802293 int flagsbit ;
2294+ uint32 difference ;
22812295
22822296 /*
22832297 * Only zero when at first entry of a page.
@@ -2299,24 +2313,29 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
22992313 }
23002314
23012315 /*
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.
23042320 */
2305- if (( unsigned int ) ( offset + nmembers ) < offset )
2321+ if (offset + MAX_MEMBERS_IN_LAST_MEMBERS_PAGE < offset )
23062322 {
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 ;
23112329 }
23122330 else
2313- {
2314- int difference ;
2315-
23162331 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 ;
23202339 }
23212340}
23222341
0 commit comments