2013-02-19 10 views
36

मूल रूप से __asm__ __volatile__() क्या करता है और "memory" एआरएम आर्किटेक्चर के लिए क्या महत्व है?__asm__ __volatile__ का काम ("":: "स्मृति")

+5

'एएसएम _volatile_' (http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.4) में विस्तार से बताया। लेकिन क्या यह दो अलग-अलग प्रश्न नहीं होना चाहिए? – phoeagon

+1

@phoeagon: यह लाइन, जैसा कि है, एक कंपाइलर मेमोरी एक्सेस शेड्यूलिंग बाधा का एक एकीकृत संचालन है - जबकि दोनों प्रश्न अलग-अलग प्रासंगिक हो सकते हैं, इसलिए पूछे गए प्रश्न का उत्तर देने की संभावना नहीं होगी। – unixsmurf

उत्तर

52
asm volatile("" ::: "memory"); 

एक कंपाइलर स्तर मेमोरी बाधा बनाता है जो अनुकूलक को मजबूर करता है ताकि बाधा में मेमोरी एक्सेस को फिर से ऑर्डर न किया जा सके।

उदाहरण के लिए, यदि आपको किसी विशिष्ट क्रम में कुछ पता तक पहुंचने की आवश्यकता है (संभवतः क्योंकि स्मृति क्षेत्र वास्तव में स्मृति के बजाए किसी भिन्न डिवाइस द्वारा समर्थित है) तो आपको इसे कंपाइलर को यह बताने में सक्षम होना चाहिए अन्यथा यह केवल दक्षता के लिए अपने कदम अनुकूलित करें।

इस परिदृश्य में मान लें कि आपको पते में एक मूल्य बढ़ाना चाहिए, कुछ पढ़ना चाहिए और आसन्न पते में एक और मूल्य बढ़ाना चाहिए।

int c(int *d, int *e) { 
     int r; 
     d[0] += 1; 
     r = e[0]; 
     d[1] += 1; 
     return r; 
} 

समस्या (इस मामले में gcc) संकलक बेहतर प्रदर्शन प्राप्त करने के लिए यदि आप इसे (-O) के लिए पूछने के लिए अपनी स्मृति का उपयोग पुनर्व्यवस्थित कर सकते हैं है। शायद नीचे की तरह निर्देश के अनुक्रम को प्रेरित किया:

00000000 <c>: 
    0: 4603  mov r3, r0 
    2: c805  ldmia r0, {r0, r2} 
    4: 3001  adds r0, #1 
    6: 3201  adds r2, #1 
    8: 6018  str r0, [r3, #0] 
    a: 6808  ldr r0, [r1, #0] 
    c: 605a  str r2, [r3, #4] 
    e: 4770  bx lr 

d[0] और d[1] के लिए ऊपर मूल्यों एक ही समय में लोड किए गए हैं। आइए मान लें कि यह ऐसा कुछ है जिसे आप टालना चाहते हैं तो आपको संकलक को बताना होगा कि मेमोरी एक्सेस को पुन: व्यवस्थित न करें और asm volatile("" ::: "memory") का उपयोग करना है।

00000000 <c>: 
    0: 6802  ldr r2, [r0, #0] 
    2: 4603  mov r3, r0 
    4: 3201  adds r2, #1 
    6: 6002  str r2, [r0, #0] 
    8: 6808  ldr r0, [r1, #0] 
    a: 685a  ldr r2, [r3, #4] 
    c: 3201  adds r2, #1 
    e: 605a  str r2, [r3, #4] 
    10: 4770  bx lr 
    12: bf00  nop 

ऐसा लगता है कि यह केवल समय स्मृति बाधा संकलन है संकलक से बचने के लिए स्मृति तक पहुँचता को पुन: व्यवस्थित करने के लिए के रूप में,:

int c(int *d, int *e) { 
     int r; 
     d[0] += 1; 
     r = e[0]; 
     asm volatile("" ::: "memory"); 
     d[1] += 1; 
     return r; 
} 

इसलिए आप जितने चाहें वैसा अपने अनुदेश अनुक्रम मिल जाएगा यह यादों को फ्लश करने या लोड या स्टोर को पूरा करने के लिए प्रतीक्षा करने के लिए कोई अतिरिक्त हार्डवेयर स्तर के निर्देश नहीं रखता है। CPUs अभी भी मेमोरी एक्सेस को पुन: व्यवस्थित कर सकते हैं यदि उनके पास आर्किटेक्चरल क्षमताएं हैं और मेमोरी पते strongly ordered या device (ref) के बजाय normal पर हैं।

+2

इस विशेष मामले में इस तरह के पैरामीटर घोषित करके मानक सी में समान प्रभाव प्राप्त किया जा सकता है : 'int c (अस्थिर int * d, अस्थिर int * e)' –

9

अर्थ यहां समझाया गया है:

http://en.wikipedia.org/wiki/Memory_ordering

मूल रूप से यह संकेत मिलता है कि विधानसभा कोड निष्पादित किया जाएगा जहां आप इसकी अपेक्षा। यह संकलक को इसके चारों ओर निर्देशों को पुन: व्यवस्थित करने के लिए नहीं कहता है। कोड के इस टुकड़े को पहले निष्पादित किया जाएगा और उसके बाद कोडित किए जाने के बाद कोडित किया जाएगा।

17

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

__asm__ असेंबली भाषा विवरणों को आपके सी कोड में घोंसला दर्ज करने की अनुमति देने का एक जीसीसी विस्तार है - यहां पर साइड इफेक्ट्स निर्दिष्ट करने में सक्षम होने की अपनी संपत्ति के लिए उपयोग किया जाता है जो संकलक को कुछ प्रकार के अनुकूलन करने से रोकता है (जो इस मामले में गलत कोड उत्पन्न करना समाप्त हो सकता है)।

__volatile__ सुनिश्चित करना है कि एएसएम बयान ही किसी अन्य अस्थिर साथ पुनर्क्रमित नहीं है की आवश्यकता होती है किसी भी (सी भाषा में एक गारंटी) तक पहुँचता है।

memory जीसीसी के लिए एक निर्देश है कि (प्रकार) कहता है कि इनलाइन एएसएम अनुक्रम का वैश्विक स्मृति पर दुष्प्रभाव है, और इसलिए स्थानीय चरों पर केवल प्रभावों को ध्यान में रखना आवश्यक नहीं है।

+0

+1 यह उत्तर प्लस ** उडो ** सही है। यह केवल * कंपाइलर * के लिए एक स्मृति बाधा है। यह एसएमपी हार्डवेयर के लिए काम नहीं करेगा। –

+0

तो आप कैसे निर्णय लेते हैं, एएसएम अस्थिर कथन कहां डालें? – Soundararajan

+1

@ साउंडराराजन: उस प्रश्न का कोई संक्षिप्त जवाब नहीं है। मैं पॉल मैकनेनी के मेमोरी एक्सेस ऑर्डरिंग आवश्यकताओं पर उत्कृष्ट पेपर पढ़ने की सिफारिश करता हूं: http://www.rdrop.com/~paulmck/scalability/paper/whymb.2009.04.05a.pdf और मेमोरी बाधाओं के लिनक्स कर्नेल अवलोकन: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/memory-barriers.txt – unixsmurf

0
static inline unsigned long arch_local_irq_save(void) 
{ 
    unsigned long flags; 

    asm volatile(
     " mrs %0, cpsr @ arch_local_irq_save\n" 
     " cpsid i"  //disabled irq 
     : "=r" (flags) : : "memory", "cc"); 
return flags; 
} 
+0

यदि आप वास्तव में पृष्ठ के शीर्ष पर प्रश्न का उत्तर दे रहे हैं तो कृपया केवल उत्तर पोस्ट करें। यहां सवाल स्पष्टीकरण के लिए पूछता है, आपने ऐसा कुछ भी नहीं दिया है। – Mat

+0

जबकि यह कोड स्निपेट प्रश्न हल कर सकता है, [एक स्पष्टीकरण सहित] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और वे लोग आपके कोड सुझाव के कारणों को नहीं जानते हैं। –

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