| 1 | #include <time.h>
|
|---|
| 2 | #include <stdio.h>
|
|---|
| 3 | #include <stdlib.h>
|
|---|
| 4 | #include <string.h>
|
|---|
| 5 |
|
|---|
| 6 | #ifdef DISABLE_OBSERVATION
|
|---|
| 7 | #include "proglang.h"
|
|---|
| 8 | #define bobs_init(...)
|
|---|
| 9 | #else
|
|---|
| 10 | #include "observation.h"
|
|---|
| 11 | #endif
|
|---|
| 12 |
|
|---|
| 13 | #ifdef TINY_USER_ITEMS
|
|---|
| 14 | #define UDATA_T char
|
|---|
| 15 | #define UDATA_LEN 1
|
|---|
| 16 | #define UDATA_USE_POS 0
|
|---|
| 17 | #else
|
|---|
| 18 | #define UDATA_T int
|
|---|
| 19 | #define UDATA_LEN 64
|
|---|
| 20 | #define UDATA_USE_POS 17
|
|---|
| 21 | #endif
|
|---|
| 22 |
|
|---|
| 23 | typedef struct B_UserItem
|
|---|
| 24 | BFX_EXTRUSION_DECL(B_UserItem)
|
|---|
| 25 | {
|
|---|
| 26 | BFX_INTRUSION(B_UserItem)
|
|---|
| 27 | // BFX_LISTED_ELEM_T(B_UserItem) selfListed;
|
|---|
| 28 | UDATA_T userdata[ UDATA_LEN ];
|
|---|
| 29 | }
|
|---|
| 30 | B_UserItem;
|
|---|
| 31 |
|
|---|
| 32 | BFX_EXTRUSION_FOLLOWUP(B_UserItem)
|
|---|
| 33 |
|
|---|
| 34 | #if defined(NDEBUG) || (defined(__cforall) && !defined(__CFA_DEBUG__))
|
|---|
| 35 | enum { DefaultNumNodes = 1000, DefaultExperimentDurSec = 1, DefaultCheckDonePeriod = 1000, DefaultExperimentDurOpCount = -1, DefaultSeed = 5 };
|
|---|
| 36 | const double DefaultInterleaveFrac = 0.0;
|
|---|
| 37 | #define TRACE(tp)
|
|---|
| 38 | #else
|
|---|
| 39 | enum { DefaultNumNodes = 10, DefaultExperimentDurSec = 1, DefaultCheckDonePeriod = 2, DefaultExperimentDurOpCount = 20, DefaultSeed = 5 };
|
|---|
| 40 | const double DefaultInterleaveFrac = 0.5;
|
|---|
| 41 | static const char * tp_filter
|
|---|
| 42 | // = "";
|
|---|
| 43 | // = "+ea";
|
|---|
| 44 | = "*";
|
|---|
| 45 | #define TRACE(tp) \
|
|---|
| 46 | if (strcmp("*", tp_filter) == 0 || strchr(tp_filter, tp)) { \
|
|---|
| 47 | printf("%c", tp); \
|
|---|
| 48 | bobs_report(); \
|
|---|
| 49 | }
|
|---|
| 50 | #endif
|
|---|
| 51 |
|
|---|
| 52 | static B_UserItem *ui = NULL;
|
|---|
| 53 |
|
|---|
| 54 | static BFX_LISTED_ELEM_T(B_UserItem) *listedItems = NULL;
|
|---|
| 55 | static BFX_LISTED_ELEM_T(B_UserItem) observedItem;
|
|---|
| 56 |
|
|---|
| 57 | static BFX_LIST_HEAD_T(B_UserItem) lst;
|
|---|
| 58 |
|
|---|
| 59 | #ifdef DISABLE_OBSERVATION
|
|---|
| 60 | MAYBE_EXTERN_C (
|
|---|
| 61 | void bobs_seek(unsigned int i) {}
|
|---|
| 62 | void bobs_moveNext() {}
|
|---|
| 63 | void bobs_movePrev() {}
|
|---|
| 64 | int bobs_hasCurrent() { return 0; }
|
|---|
| 65 | void * bobs_getCurrentLoc() { return NULL; }
|
|---|
| 66 | int bobs_getCurrentVal() { return 0; }
|
|---|
| 67 | // enum bobs_op_movement_t bobs_op_movement = OP_MOVEMENT;
|
|---|
| 68 | // enum bobs_op_polarity_t bobs_op_polarity = OP_POLARITY;
|
|---|
| 69 | )
|
|---|
| 70 |
|
|---|
| 71 | #else
|
|---|
| 72 |
|
|---|
| 73 | MAYBE_EXTERN_C (
|
|---|
| 74 |
|
|---|
| 75 | volatile size_t bobs_ops_completed = 0;
|
|---|
| 76 | volatile unsigned int bobs_prog_inserting = 0;
|
|---|
| 77 | volatile unsigned int bobs_prog_removing = 0;
|
|---|
| 78 | volatile unsigned int bobs_prog_removing_end = 0;
|
|---|
| 79 | volatile unsigned int bobs_prog_rollover_flag = 0;
|
|---|
| 80 | // bobs_prog_rem_pos (defined after BOP_REMPROGEND_IS_REMNO_BASED)
|
|---|
| 81 |
|
|---|
| 82 | void bobs_seek(unsigned int i) {
|
|---|
| 83 | observedItem = listedItems[i];
|
|---|
| 84 | }
|
|---|
| 85 |
|
|---|
| 86 | void bobs_moveNext() {
|
|---|
| 87 | observedItem = BFX_GET_AFTER(B_UserItem, lst, observedItem);
|
|---|
| 88 | }
|
|---|
| 89 |
|
|---|
| 90 | void bobs_movePrev() {
|
|---|
| 91 | observedItem = BFX_GET_BEFORE(B_UserItem, lst, observedItem);
|
|---|
| 92 | }
|
|---|
| 93 |
|
|---|
| 94 | int bobs_hasCurrent() {
|
|---|
| 95 | return BFX_IS_VALID_POS(B_UserItem, lst, observedItem);
|
|---|
| 96 | }
|
|---|
| 97 |
|
|---|
| 98 | void * bobs_getCurrentLoc() {
|
|---|
| 99 | return BFX_DEREF_POS(B_UserItem, lst, observedItem);
|
|---|
| 100 | }
|
|---|
| 101 | int bobs_getCurrentVal() {
|
|---|
| 102 | B_UserItem * curUI = BFX_DEREF_POS(B_UserItem, lst, observedItem);
|
|---|
| 103 | return curUI->userdata[ UDATA_USE_POS ];
|
|---|
| 104 | }
|
|---|
| 105 |
|
|---|
| 106 | enum bobs_op_movement_t bobs_op_movement = OP_MOVEMENT;
|
|---|
| 107 | enum bobs_op_polarity_t bobs_op_polarity = OP_POLARITY;
|
|---|
| 108 | )
|
|---|
| 109 | #endif
|
|---|
| 110 |
|
|---|
| 111 |
|
|---|
| 112 | #ifndef DISABLE_OBSERVATION
|
|---|
| 113 |
|
|---|
| 114 | // Remove progress end (number) is based (upon) remove-number
|
|---|
| 115 | // True when an OP's REMELEM used remNo to choose which element to remove
|
|---|
| 116 | // False otherwise; notably including when REMELEM just bases upon first/last
|
|---|
| 117 | // Default to false.
|
|---|
| 118 | #ifndef BOP_REMPROGEND_IS_REMNO_BASED
|
|---|
| 119 | #define BOP_REMPROGEND_IS_REMNO_BASED false
|
|---|
| 120 | #endif
|
|---|
| 121 | MAYBE_EXTERN_C (
|
|---|
| 122 | volatile unsigned int const * bobs_prog_rem_pos
|
|---|
| 123 | = BOP_REMPROGEND_IS_REMNO_BASED ? & bobs_prog_removing_end : & bobs_prog_removing;
|
|---|
| 124 | )
|
|---|
| 125 |
|
|---|
| 126 | #endif // ndef DISABLE_OBSERVATION
|
|---|
| 127 |
|
|---|
| 128 | unsigned int uDefaultPreemption() {
|
|---|
| 129 | return 0;
|
|---|
| 130 | }
|
|---|
| 131 |
|
|---|
| 132 | #ifdef DISABLE_ITERS_AR
|
|---|
| 133 | // Saves on memory accesses, makes element-oriented removals and observation impossible (instead, they crash)
|
|---|
| 134 | static inline BFX_LISTED_ELEM_T(B_UserItem) buhrdice_pass( BFX_LISTED_ELEM_T(B_UserItem) v ) { // prevent eliding, cheaper than volatile
|
|---|
| 135 | __asm__ __volatile__ ( "" : "+r"(v) );
|
|---|
| 136 | return v ;
|
|---|
| 137 | } // pass
|
|---|
| 138 | #define ITERS_SAVE(i, insertElemExpr) buhrdice_pass(insertElemExpr)
|
|---|
| 139 | #endif
|
|---|
| 140 |
|
|---|
| 141 | int main(int argc, const char *argv[]) {
|
|---|
| 142 |
|
|---|
| 143 | #ifdef DISABLE_OBSERVATION
|
|---|
| 144 | // define the outbound dependencies as locals, for compiling into nops
|
|---|
| 145 | size_t bobs_ops_completed = 0;
|
|---|
| 146 | unsigned int bobs_prog_inserting = 0;
|
|---|
| 147 | unsigned int bobs_prog_removing = 0;
|
|---|
| 148 | unsigned int bobs_prog_removing_end = 0;
|
|---|
| 149 | unsigned int bobs_prog_rollover_flag = 0;
|
|---|
| 150 | #endif
|
|---|
| 151 |
|
|---|
| 152 | const char * usage_args = "[ExperimentDurSec [CheckDonePeriod [NumNodes [ExperimentDurOpCount [Seed [InterleaveFrac]]]]]]";
|
|---|
| 153 | const int static_arg_posns = 6;
|
|---|
| 154 |
|
|---|
| 155 | unsigned int ExperimentDurSec = DefaultExperimentDurSec;
|
|---|
| 156 | unsigned int CheckDonePeriod = DefaultCheckDonePeriod;
|
|---|
| 157 | unsigned int NumNodes = DefaultNumNodes;
|
|---|
| 158 | size_t ExperimentDurOpCount = DefaultExperimentDurOpCount;
|
|---|
| 159 | unsigned int Seed = DefaultSeed;
|
|---|
| 160 | double InterleaveFrac = DefaultInterleaveFrac;
|
|---|
| 161 |
|
|---|
| 162 | switch (((argc - 1) < static_arg_posns) ? (argc - 1) : static_arg_posns) {
|
|---|
| 163 | case 6: InterleaveFrac = atof(argv[6]);
|
|---|
| 164 | case 5: Seed = atoi(argv[5]);
|
|---|
| 165 | case 4: ExperimentDurOpCount = atol(argv[4]);
|
|---|
| 166 | case 3: NumNodes = atoi(argv[3]);
|
|---|
| 167 | case 2: CheckDonePeriod = atoi(argv[2]);
|
|---|
| 168 | case 1: ExperimentDurSec = atoi(argv[1]);
|
|---|
| 169 | }
|
|---|
| 170 |
|
|---|
| 171 | // printf("ExperimentDurSec=%d, CheckDonePeriod=%d, NumNodes=%d, ExperimentDurOpCount=%zd, Seed=%d,\n",
|
|---|
| 172 | // ExperimentDurSec, CheckDonePeriod, NumNodes, ExperimentDurOpCount, Seed );
|
|---|
| 173 |
|
|---|
| 174 | if (ExperimentDurSec == 0 || CheckDonePeriod == 0 || NumNodes == 0 || ExperimentDurOpCount == 0 || Seed == 0 ) {
|
|---|
| 175 | printf("usage: %s %s\n", argv[0], usage_args);
|
|---|
| 176 | return -1;
|
|---|
| 177 | }
|
|---|
| 178 |
|
|---|
| 179 | #ifdef DISABLE_CLOCK_RECHECK
|
|---|
| 180 | if (ExperimentDurSec != -1) {
|
|---|
| 181 | printf("Error: experiment compiled as fixed-work only. ExperimentDurSec (currently %d) must be set to -1.\nUsage: %s %s\n", ExperimentDurSec, argv[0], usage_args);
|
|---|
| 182 | return -1;
|
|---|
| 183 | }
|
|---|
| 184 | #endif
|
|---|
| 185 |
|
|---|
| 186 | // Shuffling makes listed items' physical order in memory different from their order within to the list.
|
|---|
| 187 | // Affects insertion: next item to insert picked through insertOrdShuf.
|
|---|
| 188 | #ifdef DISABLE_SHUFFLING_INDIRECTION
|
|---|
| 189 | #define INSERTPOS(insertNum) insertNum
|
|---|
| 190 | #else
|
|---|
| 191 | // To ensure random memory order of nodes being inserted, do so according to a shuffled ordering of them.
|
|---|
| 192 | unsigned int * insertOrdShuf = (unsigned int *) malloc( (size_t)NumNodes * sizeof(unsigned int) );
|
|---|
| 193 | if (!insertOrdShuf) {
|
|---|
| 194 | printf("malloc request for %zd bytes for insertOrdShuf refused\n", (size_t)NumNodes * (size_t)sizeof(unsigned int));
|
|---|
| 195 | return 1;
|
|---|
| 196 | }
|
|---|
| 197 | // Fill with the ordinals (iota)
|
|---|
| 198 | for (int i = 0; i < NumNodes; i++) {
|
|---|
| 199 | insertOrdShuf[i] = i;
|
|---|
| 200 | }
|
|---|
| 201 | // Dummy "Seed" of -1 means skip the shuffle: measure overhead of insertOrdShuf indirection
|
|---|
| 202 | if (Seed != -1) {
|
|---|
| 203 | // Shuffle
|
|---|
| 204 | srand(Seed);
|
|---|
| 205 | for (unsigned int i = 0; i < NumNodes; i++) {
|
|---|
| 206 | unsigned int nodesRemaining = NumNodes - i;
|
|---|
| 207 | unsigned int swapWith = i + rand() % nodesRemaining;
|
|---|
| 208 | unsigned int tempValue = insertOrdShuf[swapWith];
|
|---|
| 209 | insertOrdShuf[swapWith] = insertOrdShuf[i];
|
|---|
| 210 | insertOrdShuf[i] = tempValue;
|
|---|
| 211 | }
|
|---|
| 212 | }
|
|---|
| 213 | #define INSERTPOS(insertNum) insertOrdShuf[insertNum]
|
|---|
| 214 | #endif
|
|---|
| 215 |
|
|---|
| 216 | // Interleaving affects the list position where an element-oriented operation occurs: at an end vs. in the middle.
|
|---|
| 217 | // Perterbs the sequence of logical insert/remove numbers presented to the OP cartridge, e.g. from [0 1 2 3 4 5 6]
|
|---|
| 218 | // to [3 0 4 1 5 2 6], which is [mid end mid end mid end solo], for a perfect-alternation interleave; except that the
|
|---|
| 219 | // end/mid interleave is atually selected randomly.
|
|---|
| 220 | #ifdef DISABLE_INTERLEAVING
|
|---|
| 221 | #define nextInterleave 0
|
|---|
| 222 | #else
|
|---|
| 223 | const unsigned int INTRL_KEYLEN = 64;
|
|---|
| 224 | unsigned char interleaveKey[INTRL_KEYLEN];
|
|---|
| 225 | unsigned char nextInterleavePos = 0;
|
|---|
| 226 | {
|
|---|
| 227 | unsigned int numOnes = INTRL_KEYLEN * InterleaveFrac;
|
|---|
| 228 | unsigned int numZeros = INTRL_KEYLEN - numOnes;
|
|---|
| 229 | // generate randomly drawn 0/1
|
|---|
| 230 | memset( interleaveKey , 0, numZeros ); // zeros then ones
|
|---|
| 231 | memset( interleaveKey+numZeros, 1, numOnes );
|
|---|
| 232 | for (unsigned int i = 0; i < 64; i++) { // shuffle it
|
|---|
| 233 | unsigned int nodesRemaining = 64 - i;
|
|---|
| 234 | unsigned int swapWith = i + rand() % nodesRemaining;
|
|---|
| 235 | unsigned char tempValue = interleaveKey[swapWith];
|
|---|
| 236 | interleaveKey[swapWith] = interleaveKey[i];
|
|---|
| 237 | interleaveKey[i] = tempValue;
|
|---|
| 238 | }
|
|---|
| 239 | #define nextInterleave (interleaveKey[nextInterleavePos = (nextInterleavePos + 1) % 64])
|
|---|
| 240 | }
|
|---|
| 241 | {
|
|---|
| 242 | unsigned int z = 0, o = 0;
|
|---|
| 243 | for ( int i = 0; i < INTRL_KEYLEN; i++ ) {
|
|---|
| 244 | if (interleaveKey[i]) o++;
|
|---|
| 245 | else z++;
|
|---|
| 246 | }
|
|---|
| 247 | // printf("Interleaving with %u in middle and %u at end\n", o, z);
|
|---|
| 248 | }
|
|---|
| 249 | // printf("interleave key begins %016llx\n", *(unsigned long long*)interleaveKey);
|
|---|
| 250 | // printf("interleave key begins %016llx\n", *(unsigned long long*)(interleaveKey+8));
|
|---|
| 251 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 252 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 253 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 254 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 255 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 256 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 257 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 258 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 259 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 260 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 261 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 262 | // printf("sample interleave value %d\n", nextInterleave);
|
|---|
| 263 | #endif
|
|---|
| 264 |
|
|---|
| 265 | ui = (B_UserItem*) malloc( (size_t)NumNodes * (size_t)sizeof(B_UserItem) );
|
|---|
| 266 | if (!ui) {
|
|---|
| 267 | printf("malloc request for %zd bytes for ui refused\n", (size_t)NumNodes * (size_t)sizeof(B_UserItem));
|
|---|
| 268 | return 1;
|
|---|
| 269 | }
|
|---|
| 270 | memset(ui, 0, (size_t)NumNodes * (size_t)sizeof(B_UserItem));
|
|---|
| 271 |
|
|---|
| 272 | #ifndef DISABLE_ITERS_AR
|
|---|
| 273 | listedItems = (BFX_LISTED_ELEM_T(B_UserItem)*)malloc( (size_t)NumNodes * (size_t)sizeof(BFX_LISTED_ELEM_T(B_UserItem)) );
|
|---|
| 274 | if (!listedItems) {
|
|---|
| 275 | printf("malloc request for %zd bytes for listedItems refused\n", (size_t)NumNodes * (size_t)sizeof(BFX_LISTED_ELEM_T(B_UserItem)));
|
|---|
| 276 | return 1;
|
|---|
| 277 | }
|
|---|
| 278 | memset(listedItems, 0, (size_t)NumNodes * (size_t)sizeof(BFX_LISTED_ELEM_T(B_UserItem)));
|
|---|
| 279 | #define ITERS_SAVE(i, insertElemExpr) listedItems[i] = (insertElemExpr)
|
|---|
| 280 | #endif
|
|---|
| 281 |
|
|---|
| 282 | // Construct and fill with demo data
|
|---|
| 283 | for (unsigned int i = 0; i < NumNodes; i++) {
|
|---|
| 284 | B_UserItem * curUI = & ui[INSERTPOS(i)];
|
|---|
| 285 | #ifdef __cforall
|
|---|
| 286 | (*curUI){};
|
|---|
| 287 | #endif
|
|---|
| 288 | curUI->userdata[ UDATA_USE_POS ] = i;
|
|---|
| 289 | }
|
|---|
| 290 |
|
|---|
| 291 | BFX_INIT(B_UserItem, lst);
|
|---|
| 292 |
|
|---|
| 293 | bobs_init(NumNodes);
|
|---|
| 294 |
|
|---|
| 295 | // BOP_ADDFOO(lst, iters, insNo, item)
|
|---|
| 296 | // BOP_REMFOO(lst, iters, remNo)
|
|---|
| 297 | // lst lvalue of the list head being added to / removed from
|
|---|
| 298 | // iters array of ADD return values, in logical-insert order; on ADD, is valid at [0..insNo)
|
|---|
| 299 | // insNo interleave-perterbed counter of the ADD calls (logical insert number)
|
|---|
| 300 | // remNo interleave-perterbed counter of the REM calls (logical remove number)
|
|---|
| 301 | // item lvalue of the item being added
|
|---|
| 302 | // Logical insert number 0 and remove number n-1 are given with a distinguished hook.
|
|---|
| 303 | // Logical insert numbers [1,n) and remove numbers [0,n-1) are pumped by the basic SUT hooks.
|
|---|
| 304 | // This pattern lets BOP cartridges that measure element-level operations know statically when there is a reference element in the list.
|
|---|
| 305 | // The driver owns the relationship between a logical insert number and the location of the `item` argument within `ui`. (Scattered for randomness.)
|
|---|
| 306 | // The BOP cartridge owns the relationship between logical remove number and any choice of an item in iters. (Defines stack vs queue.)
|
|---|
| 307 |
|
|---|
| 308 | // Default init/teardown is insert/remove
|
|---|
| 309 | // Cartridges whose SUT insert/remove actions work on empty lists need not provide special-case ones.
|
|---|
| 310 | #ifndef BOP_INIT
|
|---|
| 311 | #define BOP_INIT(lst, iters, insNo, item) BOP_INSERT(lst, iters, insNo, item)
|
|---|
| 312 | #endif
|
|---|
| 313 | #ifndef BOP_TEARDOWN
|
|---|
| 314 | #define BOP_TEARDOWN(lst, iters, remNo) BOP_REMOVE(lst, iters, remNo)
|
|---|
| 315 | #endif
|
|---|
| 316 |
|
|---|
| 317 | double elapsed_sec = 0;
|
|---|
| 318 | clock_t start = clock();
|
|---|
| 319 |
|
|---|
| 320 | const unsigned int numMiddleNodes = (NumNodes-1) * InterleaveFrac;
|
|---|
| 321 | const unsigned int numEndNodes = NumNodes - numMiddleNodes - 1;
|
|---|
| 322 |
|
|---|
| 323 | // printf("Running with %u in the middle and %u at end\n", numMiddleNodes, numEndNodes);
|
|---|
| 324 |
|
|---|
| 325 | const unsigned int removeBase[] = {0, numEndNodes};
|
|---|
| 326 | const unsigned int removeLimit[] = {numEndNodes, numMiddleNodes};
|
|---|
| 327 |
|
|---|
| 328 | size_t privateOpsCompleted = 0;
|
|---|
| 329 |
|
|---|
| 330 | while (elapsed_sec <= (double) ExperimentDurSec && privateOpsCompleted < ExperimentDurOpCount) {
|
|---|
| 331 | for ( int t = 0; t < CheckDonePeriod; t += 1 ) {
|
|---|
| 332 | TRACE('a') // insert special first
|
|---|
| 333 | ITERS_SAVE( 0,
|
|---|
| 334 | BOP_INIT(lst, listedItems, 0, ui[INSERTPOS(0)]) );
|
|---|
| 335 | TRACE('b') // insert general
|
|---|
| 336 | for ( int privateCurInsert = 1;
|
|---|
| 337 | (bobs_prog_inserting = privateCurInsert, privateCurInsert < NumNodes);
|
|---|
| 338 | privateCurInsert += 1
|
|---|
| 339 | ) {
|
|---|
| 340 | TRACE('-')
|
|---|
| 341 | ITERS_SAVE( privateCurInsert,
|
|---|
| 342 | BOP_INSERT( lst, listedItems, privateCurInsert, ui[INSERTPOS(privateCurInsert)] ) );
|
|---|
| 343 | TRACE('+')
|
|---|
| 344 | }
|
|---|
| 345 | #ifdef DISABLE_INTERLEAVING
|
|---|
| 346 | // interleaving off, simple removes
|
|---|
| 347 | // (remove logic of 2b01f8eb0956)
|
|---|
| 348 | TRACE('c')
|
|---|
| 349 | for ( int privateCurRemove = 1;
|
|---|
| 350 | (bobs_prog_removing = privateCurRemove, privateCurRemove < NumNodes);
|
|---|
| 351 | privateCurRemove += 1
|
|---|
| 352 | ) {
|
|---|
| 353 | TRACE('-')
|
|---|
| 354 | BOP_REMOVE( lst, listedItems, privateCurRemove-1 );
|
|---|
| 355 | TRACE('+')
|
|---|
| 356 | }
|
|---|
| 357 | #else
|
|---|
| 358 | // interleaving on, complex removes
|
|---|
| 359 | TRACE('c') // remove general
|
|---|
| 360 | int removeProgress[] = { 0, 0 };
|
|---|
| 361 | for ( int flip = 0;
|
|---|
| 362 | (bobs_prog_removing = removeProgress[0] + removeProgress[1] + 1,
|
|---|
| 363 | bobs_prog_removing_end = removeProgress[0] + 1,
|
|---|
| 364 | flip = nextInterleave,
|
|---|
| 365 | removeProgress[0] < removeLimit[0] && removeProgress[1] < removeLimit[1] );
|
|---|
| 366 | removeProgress[flip] += 1
|
|---|
| 367 | ) {
|
|---|
| 368 | TRACE('-')
|
|---|
| 369 | BOP_REMOVE( lst, listedItems, removeBase[flip]+removeProgress[flip] );
|
|---|
| 370 | TRACE('+')
|
|---|
| 371 | }
|
|---|
| 372 | TRACE('X') // remove imbalanced
|
|---|
| 373 | // most work done under general; it stops when either flip-side's work finishes
|
|---|
| 374 | // now drain any any stragglers so both flip-sides' work finishes
|
|---|
| 375 | for ( int flip = 0; flip < 2; flip ++ ) {
|
|---|
| 376 | for ( ; (bobs_prog_removing = removeProgress[0] + removeProgress[1] + 1,
|
|---|
| 377 | bobs_prog_removing_end = removeProgress[0] + 1,
|
|---|
| 378 | removeProgress[flip] < removeLimit[flip] )
|
|---|
| 379 | ; removeProgress[flip] += 1
|
|---|
| 380 | ) {
|
|---|
| 381 | TRACE('-')
|
|---|
| 382 | BOP_REMOVE( lst, listedItems, removeBase[flip]+removeProgress[flip] );
|
|---|
| 383 | TRACE('+')
|
|---|
| 384 | }
|
|---|
| 385 | }
|
|---|
| 386 | #endif // DISABLE_INTERLEAVING
|
|---|
| 387 | TRACE('D') // remove special last
|
|---|
| 388 | BOP_TEARDOWN(lst, listedItems, NumNodes-1);
|
|---|
| 389 | TRACE('d')
|
|---|
| 390 |
|
|---|
| 391 | privateOpsCompleted += NumNodes;
|
|---|
| 392 |
|
|---|
| 393 | bobs_prog_rollover_flag = 1;
|
|---|
| 394 | TRACE('e')
|
|---|
| 395 | bobs_prog_inserting = 0;
|
|---|
| 396 | bobs_prog_removing = 0;
|
|---|
| 397 | bobs_prog_removing_end = 0;
|
|---|
| 398 | bobs_ops_completed = privateOpsCompleted;
|
|---|
| 399 | TRACE('f')
|
|---|
| 400 | bobs_prog_rollover_flag = 0;
|
|---|
| 401 | TRACE('g')
|
|---|
| 402 | }
|
|---|
| 403 | #ifndef DISABLE_CLOCK_RECHECK
|
|---|
| 404 | clock_t end = clock();
|
|---|
| 405 | elapsed_sec = ((double)(end - start)) / ((double)CLOCKS_PER_SEC);
|
|---|
| 406 | #endif
|
|---|
| 407 | }
|
|---|
| 408 | #ifdef DISABLE_CLOCK_RECHECK
|
|---|
| 409 | {
|
|---|
| 410 | clock_t end = clock();
|
|---|
| 411 | elapsed_sec = ((double)(end - start)) / ((double)CLOCKS_PER_SEC);
|
|---|
| 412 | }
|
|---|
| 413 | #endif
|
|---|
| 414 |
|
|---|
| 415 | double mean_op_dur_ns = elapsed_sec / ((double)bobs_ops_completed) * 1000 * 1000 * 1000;
|
|---|
| 416 | printf("%s,%zd,%f,%f\n", argv[0], bobs_ops_completed, elapsed_sec, mean_op_dur_ns);
|
|---|
| 417 |
|
|---|
| 418 | free(ui);
|
|---|
| 419 | free(listedItems);
|
|---|
| 420 | #ifndef DISABLE_SHUFFLING_INDIRECTION
|
|---|
| 421 | free(insertOrdShuf);
|
|---|
| 422 | #endif
|
|---|
| 423 | }
|
|---|