আমি সি 11 স্ট্যান্ডার্ডের 5.1.2.4 বিভাগের সাথে বিশেষত মুক্তি / অর্জনের শব্দার্থবিজ্ঞানের সাথে লড়াই করছি। আমি নোট করেছি যে https://preshing.com/20120913/acquire-and-release-semantics/ (অন্যদের মধ্যে) বলেছেন যে:
... রিলিজ শব্দার্থবিজ্ঞান প্রোগ্রাম ক্রমে এর আগে যে কোনও পড়া বা লেখার ক্রিয়াকলাপের সাথে রাইটিং-রিলিজের মেমরি পুনঃক্রম করতে বাধা দেয়।
সুতরাং, নিম্নলিখিতগুলির জন্য:
typedef struct test_struct
{
_Atomic(bool) ready ;
int v1 ;
int v2 ;
} test_struct_t ;
extern void
test_init(test_struct_t* ts, int v1, int v2)
{
ts->v1 = v1 ;
ts->v2 = v2 ;
atomic_store_explicit(&ts->ready, false, memory_order_release) ;
}
extern int
test_thread_1(test_struct_t* ts, int v2)
{
int v1 ;
while (atomic_load_explicit(&ts->ready, memory_order_acquire)) ;
ts->v2 = v2 ; // expect read to happen before store/release
v1 = ts->v1 ; // expect write to happen before store/release
atomic_store_explicit(&ts->ready, true, memory_order_release) ;
return v1 ;
}
extern int
test_thread_2(test_struct_t* ts, int v1)
{
int v2 ;
while (!atomic_load_explicit(&ts->ready, memory_order_acquire)) ;
ts->v1 = v1 ;
v2 = ts->v2 ; // expect write to happen after store/release in thread "1"
atomic_store_explicit(&ts->ready, false, memory_order_release) ;
return v2 ;
}
যেখানে এগুলি কার্যকর করা হয়:
> in the "main" thread: test_struct_t ts ;
> test_init(&ts, 1, 2) ;
> start thread "2" which does: r2 = test_thread_2(&ts, 3) ;
> start thread "1" which does: r1 = test_thread_1(&ts, 4) ;
সুতরাং, আমি থ্রেড "1" এর কাছে r1 == 1 এবং থ্রেড "2" এর কাছে r2 = 4 থাকব expect
আমি এটি আশা করব কারণ (5.1.2.4 বিভাগের 16 এবং 18 অনুচ্ছেদের পরে):
- সমস্ত (পারমাণবিক নয়) পড়া এবং লেখাগুলি "পূর্বে ধারাবাহিক" এবং সুতরাং "1" থ্রেডে পরমাণু রচনা / প্রকাশের আগে "ঘটে যায়",
- যা "আন্ত-থ্রেড-ঘটে" এর আগে "2" থ্রেডে পারমাণবিক পাঠ / অর্জন করে (যখন এটি 'সত্য' পড়ে),
- যা পরবর্তীতে "পূর্বে ক্রমযুক্ত" এবং সুতরাং (পরমাণু নয়) পড়া এবং লেখার (থ্রেড "2") এর আগে "ঘটে যায়"।
তবে এটি পুরোপুরি সম্ভব যে আমি মান বুঝতে ব্যর্থ হয়েছি।
আমি পর্যবেক্ষণ করেছি যে x86_64 এর জন্য উত্পন্ন কোডটিতে অন্তর্ভুক্ত রয়েছে:
test_thread_1:
movzbl (%rdi),%eax -- atomic_load_explicit(&ts->ready, memory_order_acquire)
test $0x1,%al
jne <test_thread_1> -- while is true
mov %esi,0x8(%rdi) -- (W1) ts->v2 = v2
mov 0x4(%rdi),%eax -- (R1) v1 = ts->v1
movb $0x1,(%rdi) -- (X1) atomic_store_explicit(&ts->ready, true, memory_order_release)
retq
test_thread_2:
movzbl (%rdi),%eax -- atomic_load_explicit(&ts->ready, memory_order_acquire)
test $0x1,%al
je <test_thread_2> -- while is false
mov %esi,0x4(%rdi) -- (W2) ts->v1 = v1
mov 0x8(%rdi),%eax -- (R2) v2 = ts->v2
movb $0x0,(%rdi) -- (X2) atomic_store_explicit(&ts->ready, false, memory_order_release)
retq
এবং সরবরাহ করা হয়েছে যে আর 1 এবং এক্স 1 ক্রমে ঘটে, এটি আমার প্রত্যাশার ফলাফল দেয়।
তবে x86_64 সম্পর্কে আমার বোধগম্যতা হ'ল পাঠগুলি অন্য পাঠকের সাথে ক্রম ঘটে এবং লেখাগুলি অন্য লেখকের সাথে ক্রম ঘটে, তবে পড়া এবং লেখাগুলি একে অপরের সাথে ক্রমে না ঘটে। যা বোঝায় যে এক্স 1 এর পক্ষে আর 1 এর আগে হওয়া সম্ভব, এবং এমনকি এক্স 1, এক্স 2, ডাব্লু 2, আর 1 এর ক্রমটি ঘটে - আমি বিশ্বাস করি। [এটি মারাত্মকভাবে অসম্ভব বলে মনে হচ্ছে, তবে আর 1 যদি কিছু ক্যাশে ইস্যু করে থাকে তবে?]
দয়া করে: আমি কি বুঝতে পারছি না?
আমি লক্ষ করুন যে, যদি আমি লোড / দোকান পরিবর্তন ts->ready
করতে memory_order_seq_cst
, দোকানে জন্য উত্পন্ন কোড হল:
xchg %cl,(%rdi)
যা আমার x86_64 বোঝার সাথে সামঞ্জস্যপূর্ণ এবং আমি প্রত্যাশিত ফলাফল দেব।
8.2.3.3 Stores Are Not Reordered With Earlier Loads
। সুতরাং আপনার সংকলক আপনার কোডটি সঠিকভাবে অনুবাদ করছে (কত আশ্চর্যজনক) যেমন আপনার কোডটি কার্যকরভাবে পুরোপুরি অনুক্রমিক এবং একই সাথে আকর্ষণীয় কিছুই ঘটে না।