/* *Waitwhilespinningonacontendedspinlock.
*/ void
perform_spin_delay(SpinDelayStatus *status)
{ /* CPU-specific delay each time through the loop */
SPIN_DELAY();
/* Block the process every spins_per_delay tries */ if (++(status->spins) >= spins_per_delay)
{ if (++(status->delays) > NUM_DELAYS)
s_lock_stuck(status->file, status->line, status->func);
if (status->cur_delay == 0) /* first time to delay? */
status->cur_delay = MIN_DELAY_USEC;
/* increase delay by a random fraction between 1X and 2X */
status->cur_delay += (int) (status->cur_delay *
pg_prng_double(&pg_global_prng_state) + 0.5); /* wrap back to minimum delay when max is exceeded */ if (status->cur_delay > MAX_DELAY_USEC)
status->cur_delay = MIN_DELAY_USEC;
status->spins = 0;
}
}
/* *Afteracquiringaspinlock,updateestimatesabouthowlongtoloop. * *Ifwewereabletoacquirethelockwithoutdelaying,it'sagood *indicationweareinamultiprocessor.Ifwehadtodelay,it'sasign *(butnotasurething)thatweareinauniprocessor.Hence,we *decrementspins_per_delayslowlywhenwehadtodelay,andincreaseit *rapidlywhenwedidn't.It'sexpectedthatspins_per_delaywill *convergetotheminimumvalueonauniprocessorandtothemaximum *valueonamultiprocessor. * *Note:spins_per_delayislocalwithinourcurrentprocess.Wewantto *averagetheseobservationsacrossmultiplebackends,sinceit's *relativelyrareforthisfunctiontoevengetentered,andsoasingle *backendmightnotlivelongenoughtoconvergeonagoodvalue.That *ishandledbythetworoutinesbelow.
*/ void
finish_spin_delay(SpinDelayStatus *status)
{ if (status->cur_delay == 0)
{ /* we never had to delay */ if (spins_per_delay < MAX_SPINS_PER_DELAY)
spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
} else
{ if (spins_per_delay > MIN_SPINS_PER_DELAY)
spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
}
}
int
main()
{
pg_prng_seed(&pg_global_prng_state, (uint64) time(NULL));
test_lock.pad1 = test_lock.pad2 = 0x44;
S_INIT_LOCK(&test_lock.lock);
if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
{
printf("S_LOCK_TEST: failed, declared datatype is wrong size\n"); return1;
}
if (!S_LOCK_FREE(&test_lock.lock))
{
printf("S_LOCK_TEST: failed, lock not initialized\n"); return1;
}
S_LOCK(&test_lock.lock);
if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
{
printf("S_LOCK_TEST: failed, declared datatype is wrong size\n"); return1;
}
if (S_LOCK_FREE(&test_lock.lock))
{
printf("S_LOCK_TEST: failed, lock not locked\n"); return1;
}
S_UNLOCK(&test_lock.lock);
if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
{
printf("S_LOCK_TEST: failed, declared datatype is wrong size\n"); return1;
}
if (!S_LOCK_FREE(&test_lock.lock))
{
printf("S_LOCK_TEST: failed, lock not unlocked\n"); return1;
}
S_LOCK(&test_lock.lock);
if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
{
printf("S_LOCK_TEST: failed, declared datatype is wrong size\n"); return1;
}
if (S_LOCK_FREE(&test_lock.lock))
{
printf("S_LOCK_TEST: failed, lock not re-locked\n"); return1;
}
printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
printf(" exit with a 'stuck spinlock' message\n");
printf(" if S_LOCK() and TAS() are working.\n");
fflush(stdout);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.