سؤال

كيف يمكنك كتابة وظيفة في C والتي تقارنها ذرية ومبادلة على قيمة عدد صحيح ، باستخدام رمز الجهاز المدمج (على افتراض ، على سبيل المثال ، الهندسة المعمارية x86)؟ هل يمكن أن يكون أكثر تحديداً إذا كان مكتوبًا فقط لمعالج i7؟

هل تعمل الترجمة كسياج للذاكرة ، أم أنها تضمن فقط طلب العلاقة على موقع الذاكرة المدرج في المقارنة والمبادلة؟ ما مدى تكلفة مكلفة سياج الذاكرة؟

شكرًا لك.

هل كانت مفيدة؟

المحلول

أسهل طريقة للقيام بذلك هي ربما مع أ المترجم الجوهري مثل _interlockedcompareexchange (). يبدو الأمر وكأنه وظيفة ولكنه في الواقع حالة خاصة في المترجمات التي تتلخص في جهاز One Machine OP. في حالة MSVC X86 internics ، يعمل ذلك كسياج للقراءة/الكتابة أيضًا ، ولكن هذا ليس صحيحًا بالضرورة على منصات أخرى. (على سبيل المثال ، على PowerPC ، ستحتاج إلى إصدار صريح أ lwsync لإعادة ترتيب ذاكرة السياج.)

بشكل عام ، في العديد من الأنظمة المشتركة ، عادة ما تفرض عملية المقارنة والسلسلة معاملة ذرية فقط على العنوان الذي يلمسه. يمكن إعادة ترتيب وصول الذاكرة الأخرى ، وفي أنظمة متعددة ، قد لا تكون عناوين الذاكرة بخلاف تلك التي قمت بتبديلها متماسكة بين النوى.

نصائح أخرى

يمكنك استعمال ال CMPXCHG تعليمات مع LOCK بادئة للتنفيذ الذري.

على سبيل المثال

lock cmpxchg DWORD PTR [ebx], edx

أو

lock cmpxchgl %edx, (%ebx)

يقارن هذا القيمة في سجل EAX مع القيمة الموجودة في العنوان المخزّن في سجل EBX ويخزن القيمة في سجل EDX إلى هذا الموقع إذا كانت هي نفسها ، وإلا فإنها تقوم بتحميل القيمة في العنوان المخزن في سجل EBX في إيكس.

يجب أن يكون لديك 486 أو في وقت لاحق لتكون هذه التعليمات متاحة.

إذا كانت قيمة عدد صحيحك 64 بت من استخدام CMPXCHG8B 8 بايت مقارنة وتبادل تحت IA32 x86. يجب أن يكون المتغير 8 بايت.

Example:
      mov   eax, OldDataA           //load Old first 32 bits
      mov   edx, OldDataB           //load Old second 32 bits
      mov   ebx, NewDataA           //load first 32 bits
      mov   ecx, NewDataB           //load second 32 bits
      mov   edi, Destination        //load destination pointer
      lock cmpxchg8b qword ptr [edi]
      setz  al                      //if transfer is succesful the al is 1 else 0

إذا تم حذف بادئة القفل في تعليمات المعالج الذري ، فإن التشغيل الذري عبر البيئة متعددة المعالجات سوف لا تكون مضمونة.

في بيئة متعددة المعالجات ، تضمن إشارة القفل# أن المعالج لديه استخدام حصري لأي ذاكرة مشتركة أثناء تأكيد الإشارة. مجموعة تعليمات Intel مرجع

بدون بادئة القفل ، ستضمن العملية عدم مقاطعة أي حدث (مقاطعة) على المعالج/الأساس الحالي فقط.

من المثير للاهتمام أن نلاحظ أن بعض المعالجات لا توفر تبادلًا للمقارنة ، ولكن بدلاً من ذلك يقدمون بعض الإرشادات الأخرى ("Load Linked" و "Store Store") التي يمكن استخدامها لتوليف المقارنة والسلع للأسف ( يبدو أن الاسم يجب أن يكون مشابهًا لـ "مقارنة التبادل" ولكن يجب أن يطلق عليه حقًا "مقارنة ومتجر" لأنه يقوم بالمقارنة ، والمتاجر إذا كانت القيمة تتطابق ، وتشير إلى ما إذا كانت القيمة المتطابقة والمتجر قد تم تنفيذها). لا يمكن أن تقوم التعليمات بتجميع دلالات التبادل المقارنة (والتي توفر القيمة التي تمت قراءتها في حالة فشل المقارنة) ، ولكن في بعض الحالات تجنب مشكلة ABA الموجودة مع التبادل المقارنة. يتم وصف العديد من الخوارزميات من حيث عمليات "CAS" لأنه يمكن استخدامها على كلا أساليب وحدة المعالجة المركزية.

تخبر تعليمات "Load Linked" المعالج بقراءة موقع الذاكرة ومشاهدة بطريقة ما لمعرفة ما إذا كان قد يتم كتابته. يرشد تعليمات "المتجر الشرطي" المعالج لكتابة موقع ذاكرة فقط إذا كان لا شيء يمكن أن يكتبه منذ آخر عملية "تحميل". لاحظ أن العزم قد يكون متشائمًا ؛ معالجة المقاطعة ، على سبيل المثال ، قد تبطل تسلسل "المتجر الشرطي" المرتبط ". وبالمثل في نظام متعدد المعالجات ، قد يتم إبطال تسلسل LL/CS بواسطة وحدة المعالجة المركزية الأخرى التي تصل إلى موقع على خط ذاكرة التخزين المؤقت نفسه مثل الموقع الذي يتم مراقبته ، حتى لو لم يتم لمس الموقع الفعلي الذي يتم مراقبته. في الاستخدام النموذجي ، يتم استخدام LL/CS بالقرب من بعضها البعض ، مع حلقة إعادة المحاولة ، بحيث قد يؤدي عدم إبطاء الخاطئة إلى إبطاء الأمور قليلاً ولكنها لن تسبب الكثير من المتاعب.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top