2012-07-17 12 views
11

यहां स्पिन लॉक का मेरा कार्यान्वयन है, लेकिन ऐसा लगता है कि यह महत्वपूर्ण कोड की रक्षा नहीं कर सकता है। क्या मेरे कार्यान्वयन में कुछ गड़बड़ है?क्या मेरे स्पिन लॉक में कुछ गड़बड़ है?

static __inline__ int xchg_asm(int* lock, int val) 
{ 
    int ret; 
    __asm__ __volatile__(
    LOCK "movl (%1),%%eax; 
    xchg (%1),%2; 
    movl %%eax, %0" :"=m" (ret) :"d"(lock), "c"(val) 
); 
    return ret; 
} 
void spin_init(spinlock_t* sl) 
{ 
    sl->val = 0; 
} 
void spin_lock(spinlock_t* sl) 
{ 
    int ret; 
    do { 
    ret = xchg_asm(&(sl->val), 1); 
    } while (ret==0); 
} 

void spin_unlock(spinlock_t* sl) 
{ 
    xchg_asm(&(sl->val), 0); 
} 
+0

मेरा जोड़ा ऊपर है। –

+0

उत्कृष्ट; यह शायद बग नहीं है, लेकिन यह 'spin_destroy()' फ़ंक्शन के लिए 'spin_init() 'द्वारा आवंटित नहीं किया गया था, जो मुक्त स्मृति के लिए मेरे लिए बहुत अजीब लगता है। (क्या कोई 'spin_alloc()' फ़ंक्शन भी है?) – sarnold

+0

spin_destory शायद अधिक है। –

उत्तर

11

आपका कोड के बराबर होती है करने के लिए:

static __inline__ int xchg_asm(int* lock, int val) { 
    int save_old_value_at_eax; 

    save_old_value_at_eax = *lock;  /* with a wrong lock prefix */ 
    xchg *lock with val and discard the original value of *lock. 
    return save_old_value_at_eax;   /* but it not the real original value of *lock */ 
} 

आप कोड से देख सकते हैं, save_old_value_at_eax कोई वास्तविक मूल मूल्य जबकि cpu xchg प्रदर्शन करते हैं। आपको xchg निर्देश द्वारा पुराना/मूल मान प्राप्त करना चाहिए, xchg करने से पहले इसे सहेजकर नहीं। ("यह असली पुराना/मूल मूल्य नहीं है" का अर्थ है, यदि कोई सीपीयू लॉक लेता है तो इस सीपीयू के मूल्य को बचाता है लेकिन इससे पहले कि यह सीपीयू xchg निर्देश करता है, तो इस सीपीयू को गलत पुराना मान मिलेगा, और ऐसा लगता है कि उसने इसे लिया लॉक सफल, इस प्रकार, दो सीपीयू एक ही समय में सीएस में प्रवेश करते हैं)। आपने तीन निर्देशों के लिए एक पठन-संशोधित-लेखन निर्देश अलग कर दिया है, पूरे तीन निर्देश परमाणु रूप से नहीं हैं (यहां तक ​​कि आप लॉक उपसर्ग को xchg पर ले जाते हैं)।

मैं तुम्हें सोचा ताला उपसर्ग पूरे तीन निर्देश लॉक हो जाएगा, लेकिन वास्तव में ताला उपसर्ग केवल केवल अनुदेश जो यह जुड़ा हुआ है (सभी निर्देशों संलग्न किया जा सकता है नहीं) के लिए इस्तेमाल किया जा सकता है लगता है और हम नहीं xchg के लिए एसएमपी पर लॉक उपसर्ग की आवश्यकता है। linux_kernel_src/चाप से उद्धरण/86 ///एएसएम/cmpxchg.h

/* 
* Note: no "lock" prefix even on SMP: xchg always implies lock anyway. 
* Since this is generally used to protect other memory information, we 
* use "asm volatile" and "memory" clobbers to prevent gcc from moving 
* information around. 
*/ 

मेरे सुझावों में शामिल हैं:

  1. अपने आप को दोहराना नहीं है, लिनक्स कर्नेल की स्पिन ताला का इस्तेमाल करें।
  2. अपने आप को दोबारा न दें, कृपया लिनक्स कर्नेल के xchg(), cmpxchg() का उपयोग करें यदि आप स्पिन लॉक को कार्यान्वित करना चाहते हैं।
  3. निर्देशों के बारे में और जानें। आप यह भी पता लगा सकते हैं कि लिनक्स कर्नेल इसे कैसे कार्यान्वित करता है।
2

मुझे विश्वास है कि समस्या यह है कि लॉक निर्देश उपसर्ग केवल निम्नलिखित निर्देशों पर लागू होता है, इसलिए आपका एक्सचेंज परमाणु नहीं है। अधिक जानकारी के लिए SO पर यह अन्य उत्तर देखें: What does the "lock" instruction mean in x86 assembly?

मुझे लगता है कि यदि आप लॉक निर्देश उपसर्ग को xchg पर ले जाते हैं, तो यह काम करेगा।

संपादित करें: http://locklessinc.com/articles/locks/

नोट मुझे लगता है कि मेरी मूल जवाब वास्तव में गलत है, आगे से पता चलता है कि xchg लॉक होने पर स्मृति 386 के बाद से स्वचालित रूप से संदर्भित है googling: यह उपयोगी (जीसीसी विधानसभा में उदाहरण के परमाणु विनिमय) हो सकता है।

संबंधित मुद्दे