2012-08-10 18 views
12

पर परमाणु संचालन मैं एआरएम के लिए एक एम्बेडेड ओएस पर काम कर रहा हूं, हालांकि कुछ ऐसी चीजें हैं जिन्हें आर्किटेक्चर के बारे में एआरएमएआरएम और लिनक्स स्रोत का जिक्र करने के बाद भी समझ में नहीं आया।एआरएम

परमाणु संचालन।

एआरएम एआरएम का कहना है कि लोड और स्टोर निर्देश परमाणु हैं और हस्तक्षेप को बाधित करने से पहले निष्पादन पूर्ण होने की गारंटी है।

arch/arm/include/asm/atomic.h : 
    #define atomic_read(v) (*(volatile int *)&(v)->counter) 
    #define atomic_set(v,i) (((v)->counter) = (i)) 

हालांकि को देखकर सत्यापित, समस्या में जब मैं atomically इस मूल्य में हेरफेर करने के सीपीयू निर्देश (atomic_inc, atomic_dec, atomic_cmpxchg आदि ..) जो ARMv7 के लिए LDREX और STREX (मेरा लक्षित) का उपयोग का उपयोग कर चाहते हैं आता है ।

ARMARM इस खंड में अवरुद्ध होने वाले इंटरप्ट्स के बारे में कुछ भी नहीं कहता है, इसलिए मुझे लगता है कि एलडीआरईएक्स और स्ट्रेक्स के बीच एक बाधा उत्पन्न हो सकती है। जिस चीज का उल्लेख है वह मेमोरी बस को लॉक करने के बारे में है जो मुझे लगता है कि एमपी सिस्टम के लिए केवल सहायक है जहां एक ही समय में एक ही स्थान तक पहुंचने की कोशिश कर रहे अधिक CPUs हो सकते हैं। लेकिन यूपी (और संभवतः एमपी) के लिए, यदि टाइमर इंटरप्ट (या एसएमपी के लिए आईपीआई) एलडीआरईएक्स और एसटीईआरएक्स की इस छोटी सी खिड़की में आग लगती है, अपवाद हैंडलर निष्पादन संभवतः सीपीयू संदर्भ बदलता है और नए कार्य में लौटता है, हालांकि चौंकाने वाला हिस्सा अब आता है , यह 'CLREX' निष्पादित करता है और इसलिए पिछले धागे द्वारा आयोजित किसी विशेष लॉक को हटा देता है। तो एक यूपी सिस्टम पर परमाणु के लिए एलडीआरएक्स और एसटीआर की तुलना में एलडीआरईएक्स और एसटीईआरएक्स का उपयोग करना कितना बेहतर है?

मैंने एक विशेष लॉक मॉनीटर के बारे में कुछ पढ़ा है, इसलिए मेरे पास एक संभावित सिद्धांत है कि जब थ्रेड फिर से शुरू होता है और STREX निष्पादित करता है, तो ओएस मॉनीटर इस कॉल को विफल करने का कारण बनता है जिसे पता लगाया जा सकता है और लूप फिर से हो सकता है। प्रक्रिया में नए मूल्य (एलडीआरईएक्स पर वापस शाखा) का उपयोग करके निष्पादित, क्या मैं यहां हूं?

उत्तर

9

ठीक है, उनके website से उत्तर मिला।

यदि कोई संदर्भ स्विच प्रक्रिया के बाद एक प्रक्रिया को शेड्यूल करता है तो लोड-एक्सक्लूसिव किया जाता है लेकिन स्टोर-एक्सक्लूसिव करने से पहले, स्टोर-एक्सक्लूसिव प्रक्रिया फिर से शुरू होने पर गलत नकारात्मक परिणाम देता है, और स्मृति अपडेट नहीं होती है। यह प्रोग्राम कार्यक्षमता को प्रभावित नहीं करता है, क्योंकि प्रक्रिया तुरंत ऑपरेशन को पुनः प्रयास कर सकती है।

8

लोड से जुड़े/स्टोर अनन्य प्रतिमान के पीछे विचार यह है कि अगर अगर दुकान लोड के बाद बहुत जल्द ही, कोई हस्तक्षेप स्मृति कार्यों के साथ, और इस प्रकार अगर और कुछ नहीं स्थान को छुआ है, दुकान है संभवतः सफल होने के लिए, लेकिन यदि कुछ और स्थान को छुआ है तो स्टोर कुछ विफल होने के लिए है। इस बात की कोई गारंटी नहीं है कि स्टोर कभी-कभी किसी स्पष्ट कारण के लिए विफल नहीं होंगे;

do 
{ 
    new_value = __LDREXW(dest) + 1; 
} while (__STREXW(new_value, dest)); 

आम तौर पर भरोसा किया जा सकता कुछ प्रयास के भीतर सफल होने के लिए: अगर लोड और दुकान के बीच का समय कम से कम रखा है, तथापि, और वहाँ कोई स्मृति एक पाश की तरह उन दोनों के बीच पहुंचता है, तो कर रहे हैं।यदि कंप्यूटिंग वर्ष मूल्य के आधार पर नया मान कुछ महत्वपूर्ण गणना की आवश्यकता है, एक पाश को फिर से लिखने चाहिए के रूप में:

do 
{ 
    old_value = *dest; 

    new_value = complicated_function(old_value); 
} while (CompareAndStore(dest, new_value, old_value) != 0); 

... Assuming CompareAndStore is something like: 

uint32_t CompareAndStore(uint32_t *dest, uint32_t new_value, uint_32 old_value) 
{ 
    do 
    { 
    if (__LDREXW(dest) != old_value) return 1; // Failure 
    } while(__STREXW(new_value, dest); 
    return 0; 
} 

इस कोड को अपने मुख्य पाश * गंतव्य को फिर से चलाएं करने के लिए अगर कुछ बदल जाता है, जबकि नए मूल्य का अभिकलन किया जा रहा है होगा है, लेकिन केवल छोटे पाश को फिर से चलाएं जा सकता है अगर __STREXW किसी अन्य कारण से विफल रहता है [जो उम्मीद है कि बहुत संभावना नहीं है, यह देखते हुए कि वहाँ केवल __LDREXW और __STREXW के बीच के बारे में दो निर्देश दिए जाएंगे कि] की आवश्यकता होगी

परिशिष्ट ऐसी परिस्थिति का एक उदाहरण जहां "पुराने पर आधारित नए मूल्य की गणना करें" जटिल हो सकता है, जहां "मान" ar होगा ई प्रभावी रूप से एक जटिल डेटा संरचना के संदर्भ। कोड पुराना संदर्भ प्राप्त कर सकता है, पुराने से एक नई डेटा संरचना प्राप्त कर सकता है, और उसके बाद संदर्भ अद्यतन कर सकते हैं। यह पैटर्न "नंगे धातु" प्रोग्रामिंग की तुलना में कचरे से एकत्रित ढांचे में अधिक बार आता है, लेकिन प्रोग्रामिंग नंगे धातु के दौरान भी कई तरह के तरीके सामने आ सकते हैं। सामान्य मॉलोक/कॉलोक आवंटक आमतौर पर थ्रेड-सुरक्षित/इंटरप्ट-सुरक्षित नहीं होते हैं, लेकिन निश्चित आकार संरचनाओं के लिए आवंटक अक्सर होते हैं। एक एक कुछ सत्ता के-दो डेटा संरचनाओं की संख्या का "पूल" है (255 कहते हैं), एक तरह कुछ इस्तेमाल कर सकते हैं:

#define FOO_POOL_SIZE_SHIFT 8 
#define FOO_POOL_SIZE (1 << FOO_POOL_SIZE_SHIFT) 
#define FOO_POOL_SIZE_MASK (FOO_POOL_SIZE-1) 

void do_update(void) 
{ 
    // The foo_pool_alloc() method should return a slot number in the lower bits and 
    // some sort of counter value in the upper bits so that once some particular 
    // uint32_t value is returned, that same value will not be returned again unless 
    // there are at least (UINT_MAX)/(FOO_POOL_SIZE) intervening allocations (to avoid 
    // the possibility that while one task is performing its update, a second task 
    // changes the thing to a new one and releases the old one, and a third task gets 
    // given the newly-freed item and changes the thing to that, such that from the 
    // point of view of the first task, the thing never changed.) 

    uint32_t new_thing = foo_pool_alloc(); 
    uint32_t old_thing; 
    do 
    { 
    // Capture old reference 
    old_thing = foo_current_thing; 

    // Compute new thing based on old one 
    update_thing(&foo_pool[new_thing & FOO_POOL_SIZE_MASK], 
     &foo_pool[old_thing & FOO_POOL_SIZE_MASK); 
    } while(CompareAndSwap(&foo_current_thing, new_thing, old_thing) != 0); 
    foo_pool_free(old_thing); 
} 

अगर वहाँ अक्सर एक से अधिक थ्रेड/बीच में आता है/जो कुछ भी करने की कोशिश कर नहीं होगा एक ही समय में एक ही चीज़ को अपडेट करें, इस दृष्टिकोण को अद्यतनों को सुरक्षित रूप से निष्पादित करने की अनुमति देनी चाहिए। यदि उन चीजों में प्राथमिकता संबंध मौजूद होगा जो एक ही आइटम को अद्यतन करने का प्रयास कर सकते हैं, तो सर्वोच्च प्राथमिकता वाले को अपने पहले प्रयास में सफल होने की गारंटी दी जाती है, अगली उच्चतम प्राथमिकता किसी भी प्रयास पर सफल होगी जिसे पूर्ववत नहीं किया जाता है उच्चतम प्राथमिकता वाला एक, आदि। यदि कोई लॉकिंग का उपयोग कर रहा था, तो उच्चतम प्राथमिकता वाले कार्य जो अद्यतन करना चाहते थे, को निम्न प्राथमिकता अद्यतन को समाप्त करने की प्रतीक्षा करनी होगी; तुलना और स्नैप प्रतिमान का उपयोग करके, उच्चतम प्राथमिकता कार्य निचले हिस्से से अप्रभावित होगा (लेकिन निचले व्यक्ति को बर्बाद काम करना होगा)।

+0

मैं वही काम कर रहा हूं लेकिन वह हिस्सा जहां नए मूल्य के लिए महत्वपूर्ण कंप्यूटिंग की आवश्यकता है, मुझे अभी भी पहेली। Cmxchg लूप का उपयोग करना समझ में आता है क्योंकि तब विशेष मॉनिटर को एक संदर्भ स्विच द्वारा साफ़ नहीं किया जाएगा, लेकिन महत्वपूर्ण कंप्यूटिंग को फिर से करने के लिए बहुत अधिक ओवरहेड की आवश्यकता होती है क्योंकि मैंने सड़क को बिना किसी स्पष्ट कारणों से विफल करने के लिए देखा है (पीएसआर में आईआरक्यू के साथ यूपी) जैसा कि आपकी पोस्ट में उल्लिखित है। – sgupta

+0

@ user1075375: इन्हें देखें – supercat

+0

ये (__LDREXW और __STREXW) कोर्टेक्स-एम श्रृंखला माइक्रोक्रोनरोलर-स्तरीय प्रोसेसर के लिए केइल कंपाइलर्स में समर्थित इंट्रिनिक्स हैं, जो आम तौर पर मुख्यधारा के एआरएम लक्ष्यों (उदाहरण के लिए, एएआरएच 64) और कंपाइलर्स (उदाहरण के लिए, जीसीसी, एलएलवीएम) के लिए उपलब्ध नहीं हैं।) सही? http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABDEEJC.html – ahcox