.\" -*- coding: UTF-8 -*- .\" Copyright 2015, Michael Kerrisk .\" Copyright, the authors of the Linux man-pages project .\" .\" %%%LICENSE_START(FREELY_REDISTRIBUTABLE) .\" may be freely modified and distributed .\" %%%LICENSE_END .\" .\" FIXME Still to integrate are some points from Torvald Riegel's mail of .\" 2015-01-23: .\" https://lore.kernel.org/lkml/1422037145.27573.0.camel@triegel.csb .\" .\" FIXME Do we need to add some text regarding Torvald Riegel's 2015-01-24 mail .\" https://lore.kernel.org/lkml/1422105142.29655.16.camel@triegel.csb .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH futex 2 "14 فبراير 2026" "صفحات دليل لينكس 6.18" .SH الاسم futex \- قفل سريع في مساحة المستخدم .SH المكتبة مكتبة سي المعيارية (\fIlibc\fP،\ \fI\-lc\fP) .SH موجز .nf \fB#include \fP /* تعريف ثوابت \fBFUTEX_*\fP */ \fB#include \fP /* تعريف ثوابت \fBSYS_*\fP */ \fB#include \fP .P \fBlong syscall(SYS_futex, uint32_t *\fP\fIuaddr\fP\fB, int \fP\fIop\fP\fB, ...);\fP .fi .SH الوصف يوفر استدعاء النظام \fBfutex\fP() وسيلة للانتظار حتى يتحقق شرط معين. يُستخدم عادةً كبنية حابسة في سياق مزامنة الذاكرة المشتركة. عند استخدام الـ futexes، تُنفذ أغلبية عمليات المزامنة في مساحة المستخدم. يوظف برنامج مساحة المستخدم استدعاء النظام \fBfutex\fP() فقط عندما يُرجح أن البرنامج سيُحبس لفترة طويلة حتى يتحقق الشرط. يمكن استخدام عمليات \fBfutex\fP() الأخرى لإيقاظ أي عمليات أو خيوط تنتظر شرطًا محددًا. .P الـ futex هو قيمة بحجم 32 بتًا —يُشار إليها أدناه باسم \fIكلمة futex\fP— يُزود استدعاء النظام \fBfutex\fP() بعنوانها. (يبلغ حجم الـ futexes حوالي 32 بتًا في جميع المنصات، بما في ذلك الأنظمة بمعمارية 64 بتًا). تُحكم جميع عمليات الـ futex بهذه القيمة. ولمشاركة futex بين العمليات، يُوضع في منطقة من الذاكرة المشتركة، تُنشأ باستخدام (على سبيل المثال) \fBmmap\fP(2) أو \fBshmat\fP(2). (وبذلك، قد تملك كلمة الـ futex عناوين افتراضية مختلفة في عمليات مختلفة، ولكن هذه العناوين تشير جميعها إلى الموقع نفسه في الذاكرة الفيزيائية). في البرامج متعددة الخيوط، يكفي وضع كلمة الـ futex في متغير عام مشترك بين جميع الخيوط. .P .\" Notes from Darren Hart (Dec 2015): .\" Totally ordered with respect futex operations refers to semantics .\" of the ACQUIRE/RELEASE operations and how they impact ordering of .\" memory reads and writes. The kernel futex operations are protected .\" by spinlocks, which ensure that all operations are serialized .\" with respect to one another. .\" .\" This is a lot to attempt to define in this document. Perhaps a .\" reference to linux/Documentation/memory-barriers.txt as a footnote .\" would be sufficient? Or perhaps for this manual, "serialized" would .\" be sufficient, with a footnote regarding "totally ordered" and a .\" pointer to the memory-barrier documentation? .\" FIXME(Torvald Riegel): .\" Eventually we want to have some text in NOTES to satisfy .\" the reference in the following sentence .\" See NOTES for a detailed specification of .\" the synchronization semantics. عند تنفيذ عملية futex تطلب حبس خيط، ستحبسه النواة فقط إذا كانت كلمة futex تملك القيمة التي قدمها \fIالمستدعِي\fP (كأحد معطيات استدعاء \fBfutex\fP()) بصفتها القيمة المتوقعة لكلمة futex. عملية تحميل قيمة كلمة futex، ومقارنة تلك القيمة مع القيمة المتوقعة، والحبس الفعلي ستحدث بشكل ذري وستكون مرتبة كليًا بالنسبة للعمليات المتزامنة التي تجريها الخيوط الأخرى على كلمة futex نفسها. وبذلك، تُستخدم كلمة futex لربط المزامنة في مساحة المستخدم بتنفيذ الحبس من قبل النواة. وعلى غرار عملية المقارنة والتبديل (compare\-and\-exchange) الذرية التي قد تغير الذاكرة المشتركة، فإن الحبس عبر futex هو عملية مقارنة وحبس ذرية. .P أحد استخدامات الـ futexes هو تنفيذ الأقفال. حالة القفل (أي: مستحوذ عليه أو غير مستحوذ عليه) يمكن تمثيلها كراية يُوصَل إليها ذريًا في الذاكرة المشتركة. في حالة عدم التنازع، يمكن للخيط الوصول إلى حالة القفل أو تعديلها باستخدام تعليمات ذرية، على سبيل المثال تغييره ذريًا من غير مستحوذ عليه إلى مستحوذ عليه باستخدام تعليمات مقارنة وتبديل ذرية. (تُنفذ مثل هذه التعليمات بالكامل في وضع المستخدم، ولا تحتفظ النواة بأي معلومات عن حالة القفل). ومن ناحية أخرى، قد يتعذر على خيط الاستحواذ على قفل لأنه مستحوذ عليه بالفعل من قبل خيط آخر. يمكنه حينئذٍ تمرير راية القفل ككلمة futex والقيمة التي تمثل حالة الاستحواذ كقيمة متوقعة لعملية انتظار \fBfutex\fP(). ستقوم عملية \fBfutex\fP() هذه بالحبس إذا وفقط إذا كان القفل لا يزال مستحوذًا عليه (أي أن القيمة في كلمة futex لا تزال تطابق "حالة الاستحواذ"). عند تحرير القفل، يجب على الخيط أولاً إعادة ضبط حالة القفل إلى غير مستحوذ عليه ثم تنفيذ عملية futex توقظ الخيوط المحبوسة على راية القفل المستخدمة ككلمة futex (يمكن تحسين ذلك لاحقًا لتجنب عمليات الإيقاظ غير الضرورية). انظر \fBfutex\fP(7) لمزيد من التفاصيل حول كيفية استخدام الـ futexes. .P إلى جانب وظائف الانتظار والإيقاظ الأساسية في futex، هناك عمليات futex إضافية تهدف إلى دعم حالات استخدام أكثر تعقيدًا. .P .\" لاحظ أنه لا يلزم تهيئة أو تدمير صريح لاستخدام الـ futexes؛ تحتفظ النواة بالـ futex (أي أثر التنفيذ الداخلي للنواة) فقط أثناء تنفيذ عمليات مثل \fBFUTEX_WAIT\fP(2const) على كلمة futex معينة. .SS المعطيات .\" .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" يشير المعطى \fIuaddr\fP إلى كلمة futex. في جميع المنصات، تكون الـ futexes أعدادًا صحيحة بحجم أربعة بايتات ويجب أن تكون محاذية على حدود أربعة بايتات. تُحدد العملية المراد تنفيذها على الـ futex في المعطى \fIop\fP. .SS "عمليات Futex" يتكون المعطى \fIop\fP من جزأين: أمر يحدد العملية المراد تنفيذها، مدمجًا عبر عملية OR بتية مع خيار واحد أو أكثر يعدل سلوك العملية. الخيارات التي قد تُضمن في \fIop\fP هي كما يلي: .TP \fBFUTEX_PRIVATE_FLAG\fP (منذ لينكس 2.6.22) .\" commit 34f01cc1f512fa783302982776895c73714ebbc2 .\" I.e., It allows the kernel choose the fast path for validating .\" the user-space address and avoids expensive VMA lookups, .\" taking reference counts on file backing store, and so on. يمكن استخدام بت الخيار هذا مع جميع عمليات futex. يخبر النواة أن الـ futex خاص بالعملية وليس مشتركًا مع عملية أخرى (أي يُستخدم للمزامنة فقط بين خيوط العملية نفسها). يسمح هذا للنواة بإجراء بعض تحسينات الأداء الإضافية. .IP .\" except the obsolete FUTEX_FD(2const), for which the "private" flag was .\" meaningless من باب التسهيل، يعرّف \fI\fP مجموعة من الثوابت باللاحقة \fB_PRIVATE\fP التي تكافئ جميع العمليات المدرجة أدناه، ولكن مع دمج \fBFUTEX_PRIVATE_FLAG\fP في قيمة الثابت عبر عملية OR. وبذلك، توجد \fBFUTEX_WAIT_PRIVATE\fP و\fBFUTEX_WAKE_PRIVATE\fP، وهكذا. .TP \fBFUTEX_CLOCK_REALTIME\fP (منذ لينكس 2.6.28) .\" commit 1acdac104668a0834cfa267de9946fac7764d486 .\" commit 337f13046ff03717a9e99675284a817527440a49 .\" commit bf22a6976897977b0a3f1aeba6823c959fc4fdae يمكن استخدام بت الخيار هذا فقط مع عمليات \fBFUTEX_WAIT_BITSET\fP(2const)، و\fBFUTEX_WAIT_REQUEUE_PI\fP(2const)، و(منذ لينكس 4.5) \fBFUTEX_WAIT\fP(2const)، و(منذ لينكس 5.14) \fBFUTEX_LOCK_PI2\fP(2const). .IP إذا ضُبط هذا الخيار، تقيس النواة مهلة الانتظار \fItimeout\fP مقابل ساعة الوقت الحقيقي \fBCLOCK_REALTIME\fP. .IP إذا لم يُضبط هذا الخيار، تقيس النواة مهلة الانتظار \fItimeout\fP مقابل ساعة الوقت الرتيب \fBCLOCK_MONOTONIC\fP. .P .\" .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" العملية المحددة في \fIop\fP هي واحدة مما يلي: .TP \fBFUTEX_WAIT\fP(2const) .TQ \fBFUTEX_WAKE\fP(2const) .TQ \fBFUTEX_FD\fP(2const) .TQ \fBFUTEX_REQUEUE\fP(2const) .TQ \fBFUTEX_CMP_REQUEUE\fP(2const) .TQ \fBFUTEX_WAKE_OP\fP(2const) .TQ \fBFUTEX_WAIT_BITSET\fP(2const) .TQ \fBFUTEX_WAKE_BITSET\fP(2const) .\" .SS "Futexes توريث الأولويات" يدعم لينكس futexes توريث الأولويات (PI) للتعامل مع مشكلات انعكاس الأولويات التي قد تواجه أقفال futex العادية. انعكاس الأولويات هو المشكلة التي تحدث عندما تُحبس مهمة عالية الأولوية بانتظار الاستحواذ على قفل تملكه مهمة منخفضة الأولوية، بينما تقوم مهام ذات أولوية متوسطة باستمرار بإزاحة المهمة منخفضة الأولوية من المعالج. ونتيجة لذلك، لا تحرز المهمة منخفضة الأولوية أي تقدم نحو تحرير القفل، وتظل المهمة عالية الأولوية محبوسة. .P توريث الأولويات هو آلية للتعامل مع مشكلة انعكاس الأولويات. بموجب هذه الآلية، عندما تُحبس مهمة عالية الأولوية بسبب قفل تملكه مهمة منخفضة الأولوية، تُرفع أولوية المهمة منخفضة الأولوية مؤقتًا إلى مستوى أولوية المهمة عالية الأولوية، بحيث لا تزيحها أي مهام ذات مستوى متوسط، وبذلك يمكنها إحراز تقدم نحو تحرير القفل. ليكون توريث الأولويات فعالاً، يجب أن يكون متعديًا، مما يعني أنه إذا حُبست مهمة عالية الأولوية بسبب قفل تملكه مهمة منخفضة الأولوية والمحبوسة هي نفسها بسبب قفل تملكه مهمة أخرى متوسطة الأولوية (وهكذا، لسلاسل بأي طول)، فإن كلتا المهمتين (أو بشكل أعم، جميع المهام في سلسلة القفل) تُرفع أولوياتها لتصبح مماثلة للمهمة عالية الأولوية. .P .\" .\" Quoting Darren Hart: .\" These opcodes paired with the PI futex value policy (described below) .\" defines a "futex" as PI aware. These were created very specifically .\" in support of PI pthread_mutexes, so it makes a lot more sense to .\" talk about a PI aware pthread_mutex, than a PI aware futex, since .\" there is a lot of policy and scaffolding that has to be built up .\" around it to use it properly (this is what a PI pthread_mutex is). من منظور مساحة المستخدم، ما يجعل الـ futex مدركًا لتوريث الأولويات (PI\-aware) هو اتفاق سياسة (موصوف أدناه) بين مساحة المستخدم والنواة حول قيمة كلمة futex، مقترنًا باستخدام عمليات PI\-futex الموضحة أدناه. (على عكس عمليات futex الأخرى الموضحة أعلاه، صُممت عمليات PI\-futex لتنفيذ آليات اتصال بين العمليات (IPC) محددة للغاية). .P .\" mtk: The following text is drawn from the Hart/Guniguntala paper .\" (listed in SEE ALSO), but I have reworded some pieces .\" significantly. .\" تختلف عمليات PI\-futex الموضحة أدناه عن عمليات futex الأخرى في أنها تفرض سياسة على استخدام قيمة كلمة futex: .IP \[bu] 3 إذا لم يُستحوذ على القفل، يجب أن تكون قيمة كلمة futex هي 0. .IP \[bu] إذا استُحوذ على القفل، يجب أن تكون قيمة كلمة futex هي معرف الخيط (TID؛ انظر \fBgettid\fP(2)) للخيط المالك. .IP \[bu] إذا كان القفل مملوكًا وهناك خيوط تتنازع عليه، يجب ضبط بت \fBFUTEX_WAITERS\fP في قيمة كلمة futex؛ بعبارة أخرى، هذه القيمة هي: .IP .in +4n .EX FUTEX_WAITERS | TID .EE .in .IP (لاحظ أنه من غير الصالح أن تكون كلمة PI futex بلا مالك مع ضبط \fBFUTEX_WAITERS\fP). .P مع تطبيق هذه السياسة، يمكن لتطبيق مساحة المستخدم الاستحواذ على قفل غير مستحوذ عليه أو تحرير قفل باستخدام تعليمات ذرية تُنفذ في وضع المستخدم (على سبيل المثال، عملية مقارنة وتبديل مثل \fIcmpxchg\fP في معمارية x86). يتكون الاستحواذ على قفل ببساطة من استخدام المقارنة والتبديل لضبط قيمة كلمة futex ذريًا إلى معرف خيط (TID) المستدعي إذا كانت قيمتها السابقة 0. يتطلب تحرير القفل استخدام المقارنة والتبديل لضبط قيمة كلمة futex إلى 0 إذا كانت القيمة السابقة هي TID المتوقع. .P إذا كان الـ futex مستحوذًا عليه بالفعل (أي يملك قيمة غير صفرية)، يجب على المنتظرين توظيف عمليات \fBFUTEX_LOCK_PI\fP(2const) أو \fBFUTEX_LOCK_PI2\fP(2const) للاستحواذ على القفل. إذا كانت هناك خيوط أخرى تنتظر القفل، يُضبط بت \fBFUTEX_WAITERS\fP في قيمة الـ futex؛ في هذه الحالة، يجب على مالك القفل توظيف عملية \fBFUTEX_UNLOCK_PI\fP(2const) لتحرير القفل. .P في الحالات التي يُجبر فيها المستدعون على الدخول إلى النواة (أي يُطلب منهم إجراء استدعاء \fBfutex\fP())، فإنهم يتعاملون مباشرة مع ما يسمى RT\-mutex، وهي آلية إقفال في النواة تنفذ دلالات توريث الأولويات المطلوبة. بعد الاستحواذ على RT\-mutex، تُحدث قيمة الـ futex وفقًا لذلك، قبل أن يعود الخيط المستدعي إلى مساحة المستخدم. .P .\" tglx (July 2015): .\" If there are multiple waiters on a pi futex then a wake pi operation .\" will wake the first waiter and hand over the lock to this waiter. This .\" includes handing over the rtmutex which represents the futex in the .\" kernel. The strict requirement is that the futex owner and the rtmutex .\" owner must be the same, except for the update period which is .\" serialized by the futex internal locking. That means the kernel must .\" update the user-space value prior to returning to user space من المهم ملاحظة أن النواة ستحدث قيمة كلمة futex قبل العودة إلى مساحة المستخدم. (يمنع هذا احتمال انتهاء قيمة كلمة futex في حالة غير صالحة، مثل وجود مالك بينما القيمة هي 0، أو وجود منتظرين دون ضبط بت \fBFUTEX_WAITERS\fP). .P .\" tglx (July 2015): .\" The FUTEX_OWNER_DIED bit can also be set on uncontended futexes, where .\" the kernel has no state associated. This happens via the robust futex .\" mechanism. In that case the futex value will be set to .\" FUTEX_OWNER_DIED. The robust futex mechanism is also available for non .\" PI futexes. إذا كان لـ futex ما يقابله من RT\-mutex في النواة (أي يوجد منتظرون محبوسون) ومات مالك الـ futex/RT\-mutex بشكل غير متوقع، تقوم النواة بتنظيف الـ RT\-mutex وتسليمه للمنتظر التالي. وهذا بدوره يتطلب تحديث قيمة مساحة المستخدم وفقًا لذلك. وللإشارة إلى أن هذا مطلوب، تضبط النواة بت \fBFUTEX_OWNER_DIED\fP في كلمة futex مع معرف الخيط للمالك الجديد. يمكن لمساحة المستخدم اكتشاف هذا الموقف عبر وجود بت \fBFUTEX_OWNER_DIED\fP وهي المسؤولة حينئذٍ عن تنظيف الحالة القديمة التي تركها المالك الميت. .P تُجرى العمليات على PI futexes عبر تحديد إحدى القيم المدرجة أدناه في \fIop\fP. لاحظ أنه يجب استخدام عمليات PI futex كعمليات مزدوجة وتخضع لبعض المتطلبات الإضافية: .IP \[bu] 3 تزدوج \fBFUTEX_LOCK_PI\fP(2const) و\fBFUTEX_LOCK_PI2\fP(2const) و \fBFUTEX_TRYLOCK_PI\fP(2const) مع \fBFUTEX_UNLOCK_PI\fP(2const). يجب استدعاء \fBFUTEX_UNLOCK_PI\fP(2const) فقط على futex يملكه الخيط المستدعي، كما هو محدد في سياسة القيمة، وإلا سينتج الخطأ \fBEPERM\fP. .IP \[bu] تزدوج \fBFUTEX_WAIT_REQUEUE_PI\fP(2const) مع \fBFUTEX_CMP_REQUEUE_PI\fP(2const). يجب أن يتم ذلك من futex ليس PI إلى PI futex مختلف (وإلا سينتج الخطأ \fBEINVAL\fP). بالإضافة إلى ذلك، يجب أن يكون عدد المنتظرين المراد إيقاظهم 1 (وإلا سينتج الخطأ \fBEINVAL\fP). .P .\" .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" عمليات PI futex هي كما يلي: .TP \fBFUTEX_LOCK_PI\fP(2const) .TQ \fBFUTEX_LOCK_PI2\fP(2const) .TQ \fBFUTEX_TRYLOCK_PI\fP(2const) .TQ \fBFUTEX_UNLOCK_PI\fP(2const) .TQ \fBFUTEX_CMP_REQUEUE_PI\fP(2const) .TQ \fBFUTEX_WAIT_REQUEUE_PI\fP(2const) .P .\" .\" Darren Hart notes that a patch to allow glibc to fully support .\" PI-aware pthreads condition variables has not yet been accepted into .\" glibc. The story is complex, and can be found at .\" https://sourceware.org/bugzilla/show_bug.cgi?id=11588 .\" Darren notes that in the meantime, the patch is shipped with various .\" PREEMPT_RT-enabled Linux systems. .\" .\" Related to the preceding, Darren proposed that somewhere, man-pages .\" should document the following point: .\" .\" While the Linux kernel, since Linux 2.6.31, supports requeueing of .\" priority-inheritance (PI) aware mutexes via the .\" FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI futex operations, .\" the glibc implementation does not yet take full advantage of this. .\" Specifically, the condvar internal data lock remains a non-PI aware .\" mutex, regardless of the type of the pthread_mutex associated with .\" the condvar. This can lead to an unbounded priority inversion on .\" the internal data lock even when associating a PI aware .\" pthread_mutex with a condvar during a pthread_cond*_wait .\" operation. For this reason, it is not recommended to rely on .\" priority inheritance when using pthread condition variables. .\" .\" The problem is that the obvious location for this text is .\" the pthread_cond*wait(3) man page. However, such a man page .\" does not currently exist. .\" .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" أُضيفت \fBFUTEX_WAIT_REQUEUE_PI\fP(2const) و\fBFUTEX_CMP_REQUEUE_PI\fP(2const) لدعم حالة استخدام محددة تمامًا: دعم متغيرات حالة خيوط POSIX المدركة لتوريث الأولويات. الفكرة هي أن هذه العمليات يجب أن تزدوج دائمًا لضمان بقاء مساحة المستخدم والنواة متزامنتين. وبذلك، في عملية \fBFUTEX_WAIT_REQUEUE_PI\fP(2const)، يحدد تطبيق مساحة المستخدم مسبقًا هدف إعادة الصف (requeue) التي تحدث في عملية \fBFUTEX_CMP_REQUEUE_PI\fP(2const). .SH "قيمة الإرجاع" عند الخطأ، تُعاد القيمة \-1، ويُضبط \fIerrno\fP للإشارة إلى الخطأ. .P .\" .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" تعتمد قيمة الإرجاع عند النجاح على العملية. .SH الأخطاء .TP \fBEACCES\fP لا يوجد وصول قراءة إلى ذاكرة كلمة futex. .TP \fBEFAULT\fP لا يشير \fIuaddr\fP إلى عنوان صالح في مساحة المستخدم. .TP \fBEINVAL\fP لا يشير \fIuaddr\fP إلى كائن صالح —أي أن العنوان ليس محاذيًا لأربعة بايتات. .TP \fBEINVAL\fP معطى غير صالح. .TP \fBENOSYS\fP عملية غير صالحة محددة في \fIop\fP. .TP \fBENOSYS\fP .\" .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" حُدد الخيار \fBFUTEX_CLOCK_REALTIME\fP في \fIop\fP، ولكن العملية المرافقة لم تكن \fBFUTEX_WAIT_BITSET\fP(2const)، ولا \fBFUTEX_WAIT_REQUEUE_PI\fP(2const)، ولا \fBFUTEX_LOCK_PI2\fP(2const). .SH المعايير لينكس. .SH التاريخ لينكس 2.6.0. .P دُمج دعم futex الأولي في لينكس 2.5.7 ولكن بدلالات مختلفة عما وُصف أعلاه. قُدم استدعاء نظام بأربعة معطيات مع الدلالات الموضحة في هذه الصفحة في لينكس 2.5.40. أُضيف معطى خامس في لينكس 2.5.70، وأُضيف معطى سادس في لينكس 2.6.7. .SH أمثلة يوضح البرنامج أدناه استخدام الـ futexes في برنامج حيث تستخدم فيه عملية أب وعملية ابن زوجًا من الـ futexes الموجودة داخل تخطيط مجهول مشترك لمزامنة الوصول إلى مورد مشترك: الطرفية. تكتب كل واحدة من العمليتين \fInloops\fP رسالة (معطى في سطر الأوامر قيمته المبدئية 5 إذا حُذف) إلى الطرفية وتوظف بروتوكول مزامنة يضمن تبادلهما في كتابة الرسائل. عند تشغيل هذا البرنامج، نرى مخرجات مثل ما يلي: .P .in +4n .EX $\fB ./futex_demo\fP; Parent (18534) 0 Child (18535) 0 Parent (18534) 1 Child (18535) 1 Parent (18534) 2 Child (18535) 2 Parent (18534) 3 Child (18535) 3 Parent (18534) 4 Child (18535) 4 .EE .in .SS "مصدر البرنامج" .\" SRC BEGIN (futex.c) \& .EX /* futex_demo.c \& الاستخدام: futex_demo [nloops] (المبدئي: 5) \& توضيح استخدام الـ futexes في برنامج حيث يستخدم الأب والابن زوجًا من الـ futexes الموجودة داخل تخطيط مجهول مشترك لـ مزامنة الوصول إلى مورد مشترك: الطرفية. تكتب كل واحدة من العمليتين رسائل بـ \[aq]num\-loops\[aq] إلى الطرفية وتوظف بروتوكول مزامنة يضمن تبادلهما في كتابة الرسائل. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include \& static uint32_t *futex1, *futex2, *iaddr; \& static int futex(uint32_t *uaddr, int op, uint32_t val, const struct timespec *timeout, uint32_t *uaddr2, uint32_t val3) { return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3); } \& /* الاستحواذ على الـ futex الذي يشير إليه \[aq]futexp\[aq]: الانتظار حتى تصبح قيمته 1، ثم ضبط القيمة إلى 0. */ \& static void fwait(uint32_t *futexp) { long s; const uint32_t one = 1; \& /* atomic_compare_exchange_strong(ptr, oldval, newval) ينفذ ذريًا ما يعادل: \& if (*ptr == *oldval) *ptr = newval; \& يعيد true إذا كان الاختبار صحيحًا وحُدث *ptr. */ \& for (;;) { \& /* هل الـ futex متاح؟ */ if (atomic_compare_exchange_strong(futexp, &one, 0)) break; /* نعم */ \& /* الـ futex غير متاح؛ انتظر. */ \& s = futex(futexp, FUTEX_WAIT, 0, NULL, NULL, 0); if (s == \-1 && errno != EAGAIN) err(EXIT_FAILURE, "futex\-FUTEX_WAIT"); } } \& /* تحرير الـ futex الذي يشير إليه \[aq]futexp\[aq]: إذا كانت قيمة الـ futex حاليًا 0، فاضبط قيمته إلى 1 ثم أيقظ أي منتظرين لـ futex، بحيث إذا كان النظير محبوسًا في fwait()، يمكنه المتابعة. */ \& static void fpost(uint32_t *futexp) { long s; const uint32_t zero = 0; \& /* atomic_compare_exchange_strong() شُرحت في التعليقات أعلاه. */ \& if (atomic_compare_exchange_strong(futexp, &zero, 1)) { s = futex(futexp, FUTEX_WAKE, 1, NULL, NULL, 0); if (s == \-1) err(EXIT_FAILURE, "futex\-FUTEX_WAKE"); } } \& int main(int argc, char *argv[]) { pid_t childPid; unsigned int nloops; \& setbuf(stdout, NULL); \& nloops = (argc > 1) ? atoi(argv[1]) : 5; \& /* إنشاء تخطيط مجهول مشترك سيحتوي على الـ futexes. بما أن الـ futexes ستُشارك بين العمليات، فسنستخدم لاحقًا عمليات الـ futex "المشتركة" (أي ليس التي تنتهي بـ "_PRIVATE"). */ \& iaddr = mmap(NULL, sizeof(*iaddr) * 2, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, \-1, 0); if (iaddr == MAP_FAILED) err(EXIT_FAILURE, "mmap"); \& futex1 = &iaddr[0]; futex2 = &iaddr[1]; \& *futex1 = 0; /* الحالة: غير متاح */ *futex2 = 1; /* الحالة: متاح */ \& /* إنشاء عملية ابن ترث التخطيط المجهول المشترك. */ \& childPid = fork(); if (childPid == \-1) err(EXIT_FAILURE, "fork"); \& if (childPid == 0) { /* الابن */ for (unsigned int j = 0; j < nloops; j++) { fwait(futex1); printf("Child (%jd) %u\[rs]n", (intmax_t) getpid(), j); fpost(futex2); } \& exit(EXIT_SUCCESS); } \& /* الأب يصل إلى هنا. */ \& for (unsigned int j = 0; j < nloops; j++) { fwait(futex2); printf("Parent (%jd) %u\[rs]n", (intmax_t) getpid(), j); fpost(futex1); } \& wait(NULL); \& exit(EXIT_SUCCESS); } .EE .\" SRC END .SH "انظر أيضًا" .ad l \fBget_robust_list\fP(2), \fBrestart_syscall\fP(2), \fBpthread_mutexattr_getprotocol\fP(3), \fBfutex\fP(7), \fBsched\fP(7) .P ملفات مصدر النواة التالية: .IP \[bu] 3 \fIDocumentation/locking/pi\-futex.rst\fP .IP \[bu] \fIDocumentation/locking/futex\-requeue\-pi.rst\fP .IP \[bu] \fIDocumentation/locking/rt\-mutex.rst\fP .IP \[bu] \fIDocumentation/locking/rt\-mutex\-design.rst\fP .IP \[bu] \fIDocumentation/robust\-futex\-ABI.rst\fP .P Franke, H., Russell, R., and Kirwood, M., 2002. .br .UR http:\://kernel.org/\:doc/\:ols/\:2002/\:ols2002\-pages\-479\-495.pdf \fIFuss, Futexes and Furwocks: Fast Userlevel Locking in Linux\fP .UE (من وقائع ندوة أوتاوا للينكس 2002). .P Hart, D., 2009. .UR http:\://lwn.net/\:Articles/\:360699/ \fIA futex overview and update\fP .UE . .P Hart, D.\& و Guniguntala, D., 2009. .UR http\://lwn.net/\:images/\:conf/\:rtlws11/\:papers/\:proc/\:p10.pdf \fIRequeue\-PI: جعل glibc Condvars مدركة لـ PI\fP .UE (من وقائع ورشة عمل لينكس للوقت الحقيقي 2009). .P Drepper, U., 2011. .UR http\://www.akkadia.org/\:drepper/\:futex.pdf \fIالفوتكسات خادعة\fP .UE . .P مكتبة أمثلة فوتكس، .UR https\://mirrors.kernel.org/\:pub/\:linux/\:kernel/\:people/\:rusty/ futex\-*.tar.bz2 .UE . .\" .\" FIXME(Torvald) We should probably refer to the glibc code here, in .\" particular the glibc-internal futex wrapper functions that are .\" WIP, and the generic pthread_mutex_t and perhaps condvar .\" implementations. .PP .SH ترجمة تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي . .PP هذه الترجمة هي وثيقة مجانية؛ راجع .UR https://www.gnu.org/licenses/gpl-3.0.html رخصة جنو العامة الإصدار 3 .UE أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات. .PP إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: .MT kde-l10n-ar@kde.org .ME .