8 // Generates a PadInfo struct from padStr. If padStr is NULL then a NULL
9 // pointer is returned.
11 // Padding string is either "auto" or in the format of
12 // <modulus>+<remainder>(,<modulus>+<remainder>)*.
14 // If modulus is 0 then the remainder will just be added and no modulo will be
17 // Returned PadInfo structs must be freed with PadInfoFree.
19 PadInfo * PadInfoFromStr(const char * padStr)
24 else if (!strncmp("auto", padStr, 4)) {
26 PadInfo * padInfo = (PadInfo *)malloc(sizeof(PadInfo) + 4 * sizeof(int));
27 Assert(padInfo != NULL);
29 padInfo->nEntries = 2;
30 padInfo->Modulus = (int *)(padInfo + 1);
31 padInfo->Offset = ((int *)(padInfo + 1)) + 2;
33 // Intel TLB 2 MiB pages
34 padInfo->Modulus[0] = 2 * 1024 * 1024 * 8;
35 padInfo->Offset[0] = 2 * 1024 * 1024 + 512;
38 padInfo->Modulus[1] = 256 * 64;
39 padInfo->Offset[1] = 128;
43 else if (!strncmp("no", padStr, 2) || !strncmp("off", padStr, 3)) {
44 PadInfo * padInfo = (PadInfo *)malloc(sizeof(PadInfo));
45 Assert(padInfo != NULL);
47 padInfo->nEntries = 0;
48 padInfo->Modulus = NULL;
49 padInfo->Offset = NULL;
54 // Count number of commas. Number of commas + 1 gives us the number of
56 const char * tmp = padStr;
59 while (*tmp != 0x00) {
60 if (*tmp == ',') ++nCommas;
64 // Number of padding entries = nCommas + 1.
65 size_t padInfoSize = sizeof(PadInfo) + (nCommas + 1) * 2 * sizeof(int);
66 PadInfo * padInfo = (PadInfo *)malloc(padInfoSize);
67 Assert(padInfo != NULL);
69 memset(padInfo, 0x00, padInfoSize);
71 padInfo->Modulus = (int *)(padInfo + 1);
72 padInfo->Offset = ((int *)(padInfo + 1)) + nCommas + 1;
76 int padEntryIndex = 0;
82 // TODO: parsing is currently a mess. We assume a fixed format, which
83 // should be easier to parse now.
84 while (*tmp != 0x00) {
87 // Check if modulus was seen in this section, then move to the next.
90 fprintf(stderr, "ERROR: modulus missing before next section in padding string.\n");
99 else if (*tmp == '+') {
100 // Check if modulus was seen in this section and no offset yet.
103 fprintf(stderr, "ERROR: modulus missing before offset in padding string.\n");
108 fprintf(stderr, "ERROR: offset is only allowed to be specified once per section in padding string.\n");
114 else if (*tmp >= '0' && *tmp <= '9') {
115 // Parse number and check for all the errors.
121 int value = strtol(tmp, &endPtr, 10);
123 if ((value == LONG_MIN || value == LONG_MAX) && errno != 0) {
124 fprintf(stderr, "ERROR: over- or underflow in modulus/offset of padding string.\n");
127 else if (value == 0 && errno != 0) {
128 fprintf(stderr, "ERROR: error parsing modulus/offset of padding string: %d - %s\n", errno, strerror(errno));
131 else if (tmp == endPtr) {
132 // No digits found: empty string or invalid pad string.
133 fprintf(stderr, "ERROR: modulus or offset missing in padding string.\n");
138 fprintf(stderr, "ERROR: modulus and offset must be >= 0 in padding string.\n");
144 fprintf(stderr, "ERROR: offset already seen, but not modulus in padding string.\n");
148 Verify(padEntryIndex < (nCommas + 1));
150 padInfo->Modulus[padEntryIndex] = value;
157 fprintf(stderr, "ERROR: offset is only allowed to be specified once per section in padding string.\n");
161 Verify(padEntryIndex < (nCommas + 1));
163 padInfo->Offset[padEntryIndex] = value;
167 // No increment of tmp needed, as endPtr points already to the first
168 // character which is not part of the number.
172 fprintf(stderr, "ERROR: padding string contains invalid characters.\n");
178 if (entriesSeen != nCommas + 1) {
179 fprintf(stderr, "ERROR: did not find all padding entries.\n");
183 for (int i = 0; i < nCommas + 1; ++i) {
184 if (padInfo->Offset[i] >= padInfo->Modulus[i]) {
185 fprintf(stderr, "ERROR: offset in padding entry %d is equal or larger than modulus.\n", i);
190 padInfo->nEntries = entriesSeen;
195 int PadCells(int nCells, int cellSizeBytes, PadInfo ** padInfoPtr)
197 Assert(padInfoPtr != NULL);
199 // If the padInfo is NULL determine if we use the "auto" configuration.
200 const int defaultAutoPadding = 1;
203 if (*padInfoPtr == NULL) {
204 if (!defaultAutoPadding) {
208 *padInfoPtr = PadInfoFromStr("auto");
211 PadInfo * padInfo = *padInfoPtr;
213 Assert(padInfo->nEntries >= 0);
215 for (int i = 0; i < padInfo->nEntries; ++i) {
216 Assert(padInfo->Modulus[i] >= 0);
217 Assert(padInfo->Offset[i] >= 0);
221 if (padInfo->Modulus[i] == 0) {
222 // When the modulus is just zero then we only add the offset.
223 nPadCells = padInfo->Offset[i] * cellSizeBytes;
226 int nModCells = padInfo->Modulus[i] / cellSizeBytes;
228 if (nModCells == 0) {
229 fprintf(stderr, "ERROR: modulus of %d byte in padding entry %d becomes zero for PDF size %d byte.\n",
230 padInfo->Modulus[i], i, cellSizeBytes);
234 int nOffsetCells = padInfo->Offset[i] / cellSizeBytes;
235 int nRemainder = nCells % nModCells;
237 nPadCells = (nOffsetCells + nModCells - nRemainder) % nModCells;
246 void PadInfoPrint(PadInfo * padInfo, FILE * f, const char * prefix)
248 Assert(padInfo != NULL);
249 Assert(padInfo->nEntries >= 0);
251 Assert(prefix != NULL);
253 for (int i = 0; i < padInfo->nEntries; ++i) {
254 fprintf(f, "%sm: %10d b o: %10d b m: %f KiB o: %f KiB m: %f MiB o: %f MiB\n",
256 padInfo->Modulus[i], padInfo->Offset[i],
257 padInfo->Modulus[i] / 1024.0, padInfo->Offset[i] / 1024.0,
258 padInfo->Modulus[i] / 1024.0 / 1024.0, padInfo->Offset[i] / 1024.0 / 1024.0);
264 void PadInfoFree(PadInfo * padInfo)
266 if (padInfo != NULL) {
273 // Returns the new padded cell size and reports if padding was performed and how.
275 int PadCellsAndReport(int nCells, int cellSizeBytes, PadInfo ** padInfoPtr)
278 int nNewCells = PadCells(nCells, sizeof(PdfT), padInfoPtr);
280 if (nCells != nNewCells) {
281 printf("# padding info:\n");
282 PadInfoPrint(*padInfoPtr, stdout, "# ");
283 // int nPaddedCells = nNewCells - nCells;
284 // printf("# padding per dir.: %10d nodes (%f MiB)\n", nPaddedCells, nPaddedCells / 1024.0 / 1024.0 * sizeof(PdfT));
285 // printf("# padding total: %10d nodes (%f MiB)\n", 19 * nPaddedCells, 19 * nPaddedCells / 1024.0 / 1024.0 * sizeof(PdfT));
287 int nPadCells = nNewCells - nCells;
289 printf("#\n# padding %d nodes with %d nodes, %f MiB per direction, %f MiB in total\n",
292 nPadCells * sizeof(PdfT) / 1024.0 / 1024.0,
293 nPadCells * sizeof(PdfT) / 1024.0 / 1024.0 * 19);
296 printf("# padding info: no padding used\n");