разница между pthread _spinlock и boost ::smart _ptr ::spinlock?

Я нашел следующий код спин-блокировки вboost::smart_ptr:

bool try_lock()
{
    return (__sync_lock_test_and_set(&v_, 1) == 0);
}
void lock()
{    
    for (unsigned k=0; !try_lock(); ++k)
    {
        if (k<4)
            ; // spin
        else if (k < 16)
            __asm__ __volatile__("pause"); // was ("rep; nop" ::: "memory")
        else if (k < 32 || k & 1)
            sched_yield();
        else
        {
            struct timespec rqtp;
            rqtp.tv_sec  = 0;
            rqtp.tv_nsec = 100;
            nanosleep(&rqtp, 0);
        }
    }
}
void unlock()
{
     __sync_lock_release(&v_);
}

Итак, если я правильно понимаю, когда блокировка оспаривается, входящий поток будет экспоненциально -отступать, сначала резко вращаясь, затем приостанавливаясь, затем уступая оставшуюся часть своего временного интервала и, наконец, переключаясь -между спящим и уступающим.

Я также нашел реализацию glibc pthread_spinlock, которая использует ассемблер для выполнения блокировки.

#define LOCK_PREFIX "lock;" // using an SMP machine

int pthread_spin_lock(pthread_spinlock_t *lock)
{
    __asm__ ("\n"
       "1:\t" LOCK_PREFIX "decl %0\n\t"
       "jne 2f\n\t"
       ".subsection 1\n\t"
       ".align 16\n"
       "2:\trep; nop\n\t"
       "cmpl $0, %0\n\t"
       "jg 1b\n\t"
       "jmp 2b\n\t"
       ".previous"
       : "=m" (*lock)
       : "m" (*lock));

    return 0;
}

Я признаю, что мое понимание ассемблера невелико, поэтому я не до конца понимаю, что здесь происходит. (Кто-нибудь может объяснить, что это делает?)

Тем не менее, я провел несколько тестов против спин-блокировки boost и glibc pthread _, и когда ядер больше, чем потоков, код boost превосходит код glibc .

С другой стороны, когда потоков больше, чем ядер, код glibc лучше .

Почему это? В чем разница между этими двумя реализациями спин-блокировки, из-за которой они работают по-разному в каждом сценарии?

7
задан Steve Lorimer 20 June 2012 в 09:59
поделиться