.\" -*- coding: UTF-8 -*- '\" t .\" Copyright, the authors of the Linux man-pages project .\" .\" SPDX-License-Identifier: Linux-man-pages-copyleft .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH membarrier 2 "21 سبتمبر 2025" "صفحات دليل لينكس 6.18" .SH الاسم membarrier \- إصدار حواجز ذاكرة على مجموعة من الخيوط .SH المكتبة مكتبة سي المعيارية (\fIlibc\fP،\ \fI\-lc\fP) .SH موجز .nf .P \fB#include \fP /* تعريف ثوابت \fBMEMBARRIER_*\fP */ \fB#include \fP /* تعريف ثوابت \fBSYS_*\fP */ \fB#include \fP .P \fBint syscall(SYS_membarrier, int \fP\fIcmd\fP\fB, unsigned int \fP\fIflags\fP\fB, int \fP\fIcpu_id\fP\fB);\fP .fi .P \fIملاحظة\fP: لا توفر glibc غلافًا لـ \fBmembarrier\fP()، مما يستلزم استخدام \fBsyscall\fP(2). .SH الوصف يساعد استدعاء النظام \fBmembarrier\fP() في تقليل الحمل الزائد لتعليمات حاجز الذاكرة المطلوبة لترتيب وصولات الذاكرة على الأنظمة متعددة النوى. ومع ذلك، فإن استدعاء النظام هذا أثقل من حاجز الذاكرة، لذا فإن استخدامه بفعالية \fIليس\fP بسيطًا مثل استبدال حواجز الذاكرة باستدعاء النظام هذا، بل يتطلب فهم التفاصيل أدناه. .P يجب أن يتم استخدام حواجز الذاكرة مع مراعاة أن حاجز الذاكرة يحتاج دائمًا إما إلى أن يكون متطابقًا مع نظائره من حواجز الذاكرة، أو أن نموذج ذاكرة البنية لا يتطلب الحواجز المتطابقة. .P هناك حالات حيث يتم تنفيذ أحد جانبي الحواجز المتطابقة (والذي سنشير إليه باسم "الجانب السريع") بشكل متكرر أكثر بكثير من الآخر (والذي سنشير إليه باسم "الجانب البطيء"). هذا هدف رئيسي لاستخدام \fBmembarrier\fP(). الفكرة الأساسية هي استبدال، لهذه الحواجز المتطابقة، حواجز الذاكرة في الجانب السريع بحواجز مترجم بسيطة، على سبيل المثال: .P .in +4n .EX asm volatile ("" : : : "memory") .EE .in .P واستبدال حواجز الذاكرة في الجانب البطيء باستدعاءات لـ \fBmembarrier\fP(). .P سيضيف هذا حملًا زائدًا إلى الجانب البطيء، ويزيل الحمل الزائد من الجانب السريع، مما يؤدي إلى زيادة في الأداء الكلي طالما أن الجانب البطيء غير متكرر بما يكفي بحيث لا يفوق الحمل الزائد لاستدعاءات \fBmembarrier\fP() مكسب الأداء في الجانب السريع. .P وسيطة \fIcmd\fP هي واحدة مما يلي: .TP \fBMEMBARRIER_CMD_QUERY\fP (منذ Linux 4.3) الاستعلام عن مجموعة الأوامر المدعومة. قيمة إرجاع الاستدعاء هي قناع بت للأوامر المدعومة. \fBMEMBARRIER_CMD_QUERY\fP، الذي له القيمة 0، ليس مدرجًا بحد ذاته في قناع البت هذا. هذا الأمر مدعوم دائمًا (على النوى حيث يتم توفير \fBmembarrier\fP()). .TP \fBMEMBARRIER_CMD_GLOBAL\fP (منذ Linux 4.16) ضمان أن جميع الخيوط من جميع العمليات على النظام تمر عبر حالة حيث تتطابق جميع وصولات الذاكرة إلى عناوين مساحة المستخدم مع ترتيب البرنامج بين الدخول إلى والعودة من استدعاء النظام \fBmembarrier\fP(). جميع الخيوط على النظام مستهدفة بهذا الأمر. .TP \fBMEMBARRIER_CMD_GLOBAL_EXPEDITED\fP (منذ Linux 4.16) تنفيذ حاجز ذاكرة على جميع الخيوط الجارية لجميع العمليات التي سجلت سابقًا مع \fBMEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED\fP. .IP عند العودة من استدعاء النظام، يكون لدى الخيط المستدعي ضمان بأن جميع الخيوط الجارية قد مرت عبر حالة حيث تتطابق جميع وصولات الذاكرة إلى عناوين مساحة المستخدم مع ترتيب البرنامج بين الدخول إلى والعودة من استدعاء النظام (الخيوط غير الجارية هي بحكم الواقع في مثل هذه الحالة). يتم توفير هذا الضمان فقط لخيوط العمليات التي سجلت سابقًا مع \fBMEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED\fP. .IP نظرًا لأن التسجيل يتعلق بالقصد من تلقي الحواجز، فمن الصحيح استدعاء \fBMEMBARRIER_CMD_GLOBAL_EXPEDITED\fP من عملية لم تستخدم \fBMEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED\fP. .IP الأوامر "المعجلة" تكتمل بشكل أسرع من الأوامر غير المعجلة؛ فهي لا تمنع أبدًا، ولكن لها الجانب السلبي المتمثل في التسبب في حمل زائد إضافي. .TP \fBMEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED\fP (منذ Linux 4.16) تسجيل نية العملية لتلقي حواجز ذاكرة \fBMEMBARRIER_CMD_GLOBAL_EXPEDITED\fP. .TP \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED\fP (منذ Linux 4.14) تنفيذ حاجز ذاكرة على كل خيط جارٍ ينتمي إلى نفس عملية الخيط المستدعي. .IP عند العودة من استدعاء النظام، يكون لدى الخيط المستدعي ضمان بأن جميع خيوطه الشقيقة الجارية قد مرت عبر حالة حيث تتطابق جميع وصولات الذاكرة إلى عناوين مساحة المستخدم مع ترتيب البرنامج بين الدخول إلى والعودة من استدعاء النظام (الخيوط غير الجارية هي بحكم الواقع في مثل هذه الحالة). يتم توفير هذا الضمان فقط للخيوط في نفس عملية الخيط المستدعي. .IP الأوامر "المعجلة" تكتمل بشكل أسرع من الأوامر غير المعجلة؛ فهي لا تمنع أبدًا، ولكن لها الجانب السلبي المتمثل في التسبب في حمل زائد إضافي. .IP يجب على العملية تسجيل نيتها لاستخدام الأمر المعجل الخاص قبل استخدامه. .TP \fBMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED\fP (منذ Linux 4.14) تسجيل نية العملية لاستخدام \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED\fP. .TP \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE\fP (منذ Linux 4.16) بالإضافة إلى توفير ضمانات ترتيب الذاكرة الموصوفة في \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED\fP، عند العودة من استدعاء النظام، يكون لدى الخيط المستدعي ضمان بأن جميع أشقائه الخيوط الجارية قد نفذوا تعليمة تسلسل أساسية. يُقدم هذا الضمان فقط للخيوط في نفس العملية التي ينتمي إليها الخيط المستدعي. .IP الأوامر "المعجلة" تكتمل أسرع من الأوامر غير المعجلة، ولا تتعطل أبدًا، ولكن لها عيب التسبب في عبء إضافي. .IP يجب على العملية تسجيل نيتها لاستخدام أمر النواة المتزامن المعجل الخاص قبل استخدامه. .TP \fBMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE\fP (منذ لينكس 4.16) سجل نية العملية لاستخدام \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE\fP. .TP \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ\fP (منذ لينكس 5.10) تأكد من أن الخيط المستدعي، عند العودة من استدعاء النظام، أن جميع أشقائه الخيوط الجارية قد أعيد تشغيل أي أقسام حرجة rseq قيد التشغيل حاليًا إذا كانت معلمة \fIflags\fP تساوي 0؛ إذا كانت معلمة \fIflags\fP هي \fBMEMBARRIER_CMD_FLAG_CPU\fP، فسيتم تنفيذ هذه العملية فقط على وحدة المعالجة المركزية المشار إليها بواسطة \fIcpu_id\fP. يُقدم هذا الضمان فقط للخيوط في نفس العملية التي ينتمي إليها الخيط المستدعي. .IP حاجز الذاكرة RSEQ متاح فقط في الشكل "المعجل الخاص". .IP يجب على العملية تسجيل نيتها لاستخدام أمر rseq المعجل الخاص قبل استخدامه. .TP \fBMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ\fP (منذ لينكس 5.10) سجل نية العملية لاستخدام \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ\fP. .TP \fBMEMBARRIER_CMD_SHARED\fP (منذ لينكس 4.3) هذا اسم مستعار لـ \fBMEMBARRIER_CMD_GLOBAL\fP موجود للتوافق العكسي مع الرأس. .P يجب تحديد وسيطة \fIflags\fP كـ 0 ما لم يكن الأمر هو \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ\fP، وفي هذه الحالة يمكن أن تكون \fIflags\fP إما 0 أو \fBMEMBARRIER_CMD_FLAG_CPU\fP. .P يتم تجاهل وسيطة \fIcpu_id\fP ما لم تكن \fIflags\fP هي \fBMEMBARRIER_CMD_FLAG_CPU\fP، وفي هذه الحالة يجب أن تحدد وحدة المعالجة المركزية المستهدفة بواسطة أمر حاجز الذاكرة هذا. .P جميع عمليات الوصول إلى الذاكرة التي يتم إجراؤها بترتيب البرنامج من كل خيط مستهدف مضمونة أن تكون مرتبة فيما يتعلق بـ \fBmembarrier\fP(). .P إذا استخدمنا الدلالة \fIbarrier()\fP لتمثيل حاجز مترجم يجبر عمليات الوصول إلى الذاكرة على التنفيذ بترتيب البرنامج عبر الحاجز، و \fIsmp_mb()\fP لتمثيل حواجز الذاكرة الصريحة التي تجبر ترتيب الذاكرة الكامل عبر الحاجز، فلدينا جدول الترتيب التالي لكل زوج من \fIbarrier()\fP و \fBmembarrier\fP() و \fIsmp_mb()\fP. يتم تفصيل ترتيب الزوج على النحو التالي (O: مرتب، X: غير مرتب): .P .RS .TS l c c c. \& barrier() smp_mb() membarrier() barrier() X X O smp_mb() X O O membarrier() O O O .TE .RE .SH "قيمة الإرجاع" عند النجاح، تُرجع عملية \fBMEMBARRIER_CMD_QUERY\fP قناع بت للأوامر المدعومة، وتُرجع عمليات \fBMEMBARRIER_CMD_GLOBAL\fP و \fBMEMBARRIER_CMD_GLOBAL_EXPEDITED\fP و \fBMEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED\fP و \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED\fP و \fBMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED\fP و \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE\fP و \fBMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE\fP صفرًا. عند الخطأ، يُرجع \-1، ويتم تعيين \fIerrno\fP للإشارة إلى الخطأ. .P لأمر معين، مع ضبط \fIflags\fP على 0، يُضمن أن استدعاء النظام هذا سيعيد دائمًا نفس القيمة حتى إعادة التشغيل. ستؤدي الاستدعاءات الإضافية بنفس الوسائط إلى نفس النتيجة. لذلك، مع ضبط \fIflags\fP على 0، تكون معالجة الأخطاء مطلوبة فقط لأول استدعاء لـ \fBmembarrier\fP(). .SH الأخطاء .TP \fBEINVAL\fP \fIcmd\fP غير صالح، أو \fIflags\fP غير صفرية، أو تم تعطيل أمر \fBMEMBARRIER_CMD_GLOBAL\fP لأنه تم تعيين معلمة وحدة المعالجة المركزية \fInohz_full\fP، أو أن أوامر \fBMEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE\fP و \fBMEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE\fP غير منفذة بواسطة البنية. .TP \fBENOSYS\fP استدعاء النظام \fBmembarrier\fP() غير منفذ بواسطة هذه النواة. .TP \fBEPERM\fP لم يتم تسجيل العملية الحالية قبل استخدام الأوامر المعجلة الخاصة. .SH المعايير لينكس. .SH التاريخ لينكس 4.3. .P قبل لينكس 5.10، كان النموذج الأولي: .P .in +4n .EX \fBint membarrier(int \fP\fIcmd\fP\fB, int \fP\fIflags\fP\fB);\fP .EE .in .SH ملاحظات تعليمة حاجز الذاكرة هي جزء من مجموعة تعليمات البنى ذات نماذج الذاكرة ضعيفة الترتيب. إنها ترتب عمليات الوصول إلى الذاكرة قبل الحاجز وبعده فيما يتعلق بالحواجز المتطابقة على النوى الأخرى. على سبيل المثال، يمكن لحاجز التحميل ترتيب التحميلات قبل وبعد ذلك الحاجز فيما يتعلق بالتخزينات المرتبة بواسطة حواجز التخزين. .P ترتيب البرنامج هو الترتيب الذي يتم به ترتيب التعليمات في كود التجميع للبرنامج. .P تشمل الأمثلة حيث يمكن أن يكون \fBmembarrier\fP() مفيدًا تطبيقات مكتبات القراءة\-النسخ\-التحديث ومجمّعي القمامة. .SH أمثلة بافتراض تطبيق متعدد الخيوط حيث يُنفّذ "fast_path()" بشكل متكرر جدًا، وحيث يُنفّذ "slow_path()" بشكل نادر، يمكن تحويل الكود التالي (x86) باستخدام \fBmembarrier\fP(): .P .in +4n .\" SRC BEGIN (membarrier.c) .EX #include \& static volatile int a, b; \& static void fast_path(int *read_b) { a = 1; asm volatile ("mfence" : : : "memory"); *read_b = b; } \& static void slow_path(int *read_a) { b = 1; asm volatile ("mfence" : : : "memory"); *read_a = a; } \& int main(void) { int read_a, read_b; \& /* * Real applications would call fast_path() and slow_path() * from different threads. Call those from main() to keep * this example short. */ \& slow_path(&read_a); fast_path(&read_b); \& /* * read_b == 0 implies read_a == 1 and * read_a == 0 implies read_b == 1. */ \& if (read_b == 0 && read_a == 0) abort(); \& exit(EXIT_SUCCESS); } .EE .\" SRC END .in .P الكود أعلاه بعد تحويله لاستخدام \fBmembarrier\fP() يصبح: .P .in +4n .EX #define _GNU_SOURCE #include #include #include #include #include \& static volatile int a, b; \& static int membarrier(int cmd, unsigned int flags, int cpu_id) { return syscall(__NR_membarrier, cmd, flags, cpu_id); } \& static int init_membarrier(void) { int ret; \& /* Check that membarrier() is supported. */ \& ret = membarrier(MEMBARRIER_CMD_QUERY, 0, 0); if (ret < 0) { perror("membarrier"); return \-1; } \& if (!(ret & MEMBARRIER_CMD_GLOBAL)) { fprintf(stderr, "membarrier does not support MEMBARRIER_CMD_GLOBAL\[rs]n"); return \-1; } \& return 0; } \& static void fast_path(int *read_b) { a = 1; asm volatile ("" : : : "memory"); *read_b = b; } \& static void slow_path(int *read_a) { b = 1; membarrier(MEMBARRIER_CMD_GLOBAL, 0, 0); *read_a = a; } \& int main(int argc, char *argv[]) { int read_a, read_b; \& if (init_membarrier()) exit(EXIT_FAILURE); \& /* * Real applications would call fast_path() and slow_path() * from different threads. Call those from main() to keep * this example short. */ \& slow_path(&read_a); fast_path(&read_b); \& /* * read_b == 0 implies read_a == 1 and * read_a == 0 implies read_b == 1. */ \& if (read_b == 0 && read_a == 0) abort(); \& exit(EXIT_SUCCESS); } .EE .in .\" .SH SEE ALSO .\" FIXME See if the following syscalls make it into Linux 4.15 or later .\" .BR cpu_opv (2), .\" .BR rseq (2) .PP .SH ترجمة تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي . .PP هذه الترجمة هي وثيقة مجانية؛ راجع .UR https://www.gnu.org/licenses/gpl-3.0.html رخصة جنو العامة الإصدار 3 .UE أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات. .PP إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: .MT kde-l10n-ar@kde.org .ME .