@@ -569,8 +569,6 @@ namespace photon
569569 mee = &_default_event_engine;
570570 }
571571
572- std::atomic<vcpu_base*> _qspin_next { nullptr };
573- std::atomic<bool > _qspin_got_lock { false };
574572 static spinlock vcpu_list_lock; // lock when add, remove, iterate next
575573 static rwlock vcpu_list_rwlock; // rlock when iterate, wlock when remove
576574 static intrusive_list<vcpu_t , false > pvcpu;
@@ -1629,33 +1627,44 @@ R"(
16291627 serv.store (successor, std::memory_order_release);
16301628 }
16311629
1630+ struct qspinlock ::holder {
1631+ std::atomic<holder*> next { nullptr };
1632+ std::atomic<bool > got_lock { false };
1633+ };
1634+ static thread_local qspinlock::holder qslholder;
1635+ int qspinlock::try_lock () {
1636+ holder* expected = nullptr ;
1637+ bool ok = _owner_tail.compare_exchange_strong (expected,
1638+ &qslholder, std::memory_order_acq_rel);
1639+ return int (ok) - 1 ;
1640+ }
16321641 int qspinlock::lock () {
1633- auto vcpu = (vcpu_t *)get_vcpu ();
1634- assert (vcpu->_qspin_next == nullptr );
1635- auto old_tail = (vcpu_t *)_owner_tail.exchange (vcpu, std::memory_order_acq_rel);
1642+ // forbid gcc to silly update h
1643+ auto h = &qslholder; asm volatile (" " : " +r" (h));
1644+ assert (h->next == nullptr );
1645+ auto old_tail = _owner_tail.exchange (h, std::memory_order_acq_rel);
16361646 if (!old_tail) return 0 ;
16371647
1638- vcpu-> _qspin_got_lock .store (false , std::memory_order_relaxed);
1639- assert (old_tail->_qspin_next .load (std::memory_order_acquire) == nullptr );
1640- old_tail->_qspin_next .store (vcpu , std::memory_order_release);
1648+ h-> got_lock .store (false , std::memory_order_relaxed);
1649+ assert (old_tail->next .load (std::memory_order_acquire) == nullptr );
1650+ old_tail->next .store (h , std::memory_order_release);
16411651 do { spin_wait (); }
1642- while (vcpu-> _qspin_got_lock .load (std::memory_order_acquire) == false );
1652+ while (h-> got_lock .load (std::memory_order_acquire) == false );
16431653 return 0 ;
16441654 }
1645-
16461655 void qspinlock::unlock () {
1647- auto vcpu = (vcpu_t *)get_vcpu ();
1656+ // forbid gcc to silly update h
1657+ auto h = &qslholder; asm volatile (" " : " +r" (h));
16481658 while (true ) {
1649- auto next = ( vcpu_t *) vcpu-> _qspin_next .load (std::memory_order_acquire);
1659+ auto next = h-> next .load (std::memory_order_acquire);
16501660 if (next) { // resume the next waiter, if there is one
1651- vcpu-> _qspin_next .store (nullptr , std::memory_order_release);
1652- next->_qspin_got_lock .store (true , std::memory_order_release);
1661+ h-> next .store (nullptr , std::memory_order_release);
1662+ next->got_lock .store (true , std::memory_order_release);
16531663 return ;
16541664 } else { // do unlock if there is no waiter
1655- vcpu_base* expected = vcpu;
1656- bool ok = _owner_tail.compare_exchange_strong (expected,
1657- nullptr , std::memory_order_acq_rel);
1658- if (ok) return ;
1665+ auto expected = h;
1666+ if (_owner_tail.compare_exchange_strong (expected,
1667+ nullptr , std::memory_order_acq_rel)) return ;
16591668 spin_wait (); // unlock failed, wait and try again
16601669 }
16611670 }
0 commit comments