ইন্টেল x86 ন্যূনতম চলমানযোগ্য খোলামেলা উদাহরণ
সমস্ত প্রয়োজনীয় বয়লারপ্লেট সহ চলমান বেয়ার ধাতব উদাহরণ । সমস্ত প্রধান অংশ নীচে আচ্ছাদিত করা হয়।
উবুন্টু 15.10 কিউএমইউ 2.3.0 এবং লেনোভো থিংকপ্যাড টি 400 আসল হার্ডওয়্যার অতিথির পরীক্ষিত ।
ইন্টেল ম্যানুয়াল ভলিউম 3 সিস্টেম প্রোগ্রামিং নির্দেশিকা - 325384-056US সেপ্টেম্বর 2015 অধ্যায়গুলির 8, 9 ও 10 কভার জন্য SMP।
সারণী 8-1। "ব্রডকাস্ট INIT-SIPI-SIPI সিকোয়েন্স এবং চয়েস অফ টাইমআউটস" এর একটি উদাহরণ রয়েছে যা মূলত স্রেফ কাজ করে:
MOV ESI, ICR_LOW ; Load address of ICR low dword into ESI.
MOV EAX, 000C4500H ; Load ICR encoding for broadcast INIT IPI
; to all APs into EAX.
MOV [ESI], EAX ; Broadcast INIT IPI to all APs
; 10-millisecond delay loop.
MOV EAX, 000C46XXH ; Load ICR encoding for broadcast SIPI IP
; to all APs into EAX, where xx is the vector computed in step 10.
MOV [ESI], EAX ; Broadcast SIPI IPI to all APs
; 200-microsecond delay loop
MOV [ESI], EAX ; Broadcast second SIPI IPI to all APs
; Waits for the timer interrupt until the timer expires
এই কোডটিতে:
বেশিরভাগ অপারেটিং সিস্টেমগুলি operations অপারেশনগুলিকে বেশিরভাগ রিং 3 (ব্যবহারকারী প্রোগ্রাম) থেকে অসম্ভব করে তুলবে।
এটির সাথে নিখরচায় খেলতে আপনার নিজের কার্নেলটি লিখতে হবে: একটি ইউজারল্যান্ড লিনাক্স প্রোগ্রাম কাজ করবে না।
প্রথমে, একটি একক প্রসেসর চালিত হয়, যার নাম বুটস্ট্র্যাপ প্রসেসর (বিএসপি)।
এটি অবশ্যই ইন্টার প্রসেসর ইন্ট্রিপ্টস (আইপিআই) নামে বিশেষ বিঘ্নের মাধ্যমে অন্যদের (অ্যাপ্লিকেশন প্রসেসর (এপি)) জাগ্রত করতে হবে ।
সেগুলি বাধাগুলি বিঘ্নিত কমান্ড রেজিস্টারের (আইসিআর) মাধ্যমে অ্যাডভান্সড প্রোগ্রামেবল ইন্টারফেট কন্ট্রোলার (এপিআইসি) প্রোগ্রামিংয়ের মাধ্যমে করা যেতে পারে
আইসিআর এর ফর্ম্যাটটি এখানে নথিভুক্ত করা হয়েছে: 10.6 "ইন্টারপ্রেসেসর ইস্যু করা হচ্ছে"
আমরা আইসিআর-কে লেখার সাথে সাথে আইপিআই ঘটে।
ICR_LOW 8.4.4 "এমপি সূচনা উদাহরণ" হিসাবে সংজ্ঞায়িত করা হয়েছে:
ICR_LOW EQU 0FEE00300H
ম্যাজিক মান 0FEE00300
হ'ল আইসিআর এর মেমরি ঠিকানা, টেবিল 10-1 "স্থানীয় এপিক রেজিস্টার ঠিকানা মানচিত্র" তে নথিভুক্ত রয়েছে
সহজতম পদ্ধতিটি উদাহরণটিতে ব্যবহৃত হয়: এটি ব্রডকাস্ট আইপিআই প্রেরণের জন্য আইসিআর সেট আপ করে যা বর্তমান ব্যতীত অন্য সমস্ত প্রসেসরের কাছে সরবরাহ করা হয়।
তবে এটিও সম্ভব, এবং কারও দ্বারা সুপারিশ করা হয়েছে , এসিপিআই টেবিল বা ইন্টেলের এমপি কনফিগারেশন টেবিলের মতো বিআইওএস দ্বারা বিশেষ ডেটা স্ট্রাকচার সেটআপের মাধ্যমে প্রসেসর সম্পর্কে তথ্য পেতে এবং কেবল আপনার একে একে জাগ্রত করা।
XX
মধ্যে 000C46XXH
এনকোড প্রথম নির্দেশ যে প্রসেসর যেমন চালানো হবে ঠিকানা:
CS = XX * 0x100
IP = 0
মনে রাখবেন যে সিএস দ্বারা ঠিকানাগুলি গুণিত করে0x10
, তাই প্রথম নির্দেশিকার আসল মেমরি ঠিকানাটি হ'ল:
XX * 0x1000
সুতরাং উদাহরণস্বরূপ XX == 1
, প্রসেসর শুরু হবে 0x1000
।
তারপরে আমাদের অবশ্যই তা নিশ্চিত করতে হবে যে সেই মেমরি লোকেশনে 16-বিট রিয়েল মোড কোড চালানো হবে, যেমন:
cld
mov $init_len, %ecx
mov $init, %esi
mov 0x1000, %edi
rep movsb
.code16
init:
xor %ax, %ax
mov %ax, %ds
/* Do stuff. */
hlt
.equ init_len, . - init
লিঙ্কার স্ক্রিপ্ট ব্যবহার করা অন্য সম্ভাবনা।
বিলম্বের লুপগুলি কাজ করার জন্য একটি বিরক্তিকর অংশ: সুনির্দিষ্টভাবে ঘুমানোর কোনও দুর্দান্ত সহজ উপায় নেই।
সম্ভাব্য পদ্ধতিগুলির মধ্যে রয়েছে:
- পিআইটি (আমার উদাহরণে ব্যবহৃত)
- HPET
- উপরের সাথে ব্যস্ত লুপের সময়টি ক্যালিব্রেট করুন এবং পরিবর্তে এটি ব্যবহার করুন
সম্পর্কিত: কীভাবে স্ক্রিনে একটি নম্বর প্রদর্শিত হবে এবং ডস x86 সমাবেশের সাথে এক সেকেন্ডের জন্য ঘুমাবে?
আমি মনে করি প্রাথমিক প্রসেসরের এটির জন্য সুরক্ষিত মোডে থাকা দরকার কারণ আমরা ঠিকানায় লিখি 0FEE00300H
যা 16-বিটের জন্য খুব বেশি
প্রসেসরের মধ্যে যোগাযোগের জন্য, আমরা প্রধান প্রক্রিয়াটিতে একটি স্পিনলক ব্যবহার করতে পারি এবং দ্বিতীয় কোর থেকে লকটি সংশোধন করতে পারি।
আমাদের নিশ্চিত করা উচিত যে স্মৃতি লিখনের কাজটি সম্পন্ন হয়েছে, উদাহরণস্বরূপ wbinvd
।
প্রসেসরের মধ্যে ভাগ করা রাষ্ট্র
৮..1.১ "লজিকাল প্রসেসরের রাজ্য" বলেছেন:
নিম্নলিখিত বৈশিষ্ট্যগুলি ইন্টেল 64 বা আইএ -32 প্রসেসরের ইনটেল হাইপার-থ্রেডিং প্রযুক্তি সমর্থনকারী লজিকাল প্রসেসরের আর্কিটেকচারাল স্টেটের অংশ। বৈশিষ্ট্যগুলি তিনটি গ্রুপে বিভক্ত করা যেতে পারে:
- প্রতিটি লজিকাল প্রসেসরের জন্য নকল
- একটি শারীরিক প্রসেসরে লজিকাল প্রসেসর দ্বারা ভাগ করা
- ভাগ করা বা সদৃশ, বাস্তবায়নের উপর নির্ভর করে
প্রতিটি লজিকাল প্রসেসরের জন্য নিম্নলিখিত বৈশিষ্ট্যগুলি সদৃশ করা হয়েছে:
- সাধারণ উদ্দেশ্যে নিবন্ধগুলি (EAX, EBX, ECX, EDX, ESI, EDI, ESP, এবং EBP)
- বিভাগের নিবন্ধগুলি (সিএস, ডিএস, এসএস, ইএস, এফএস এবং জিএস)
- EFLAGS এবং EIP রেজিস্টার। নোট করুন যে প্রতিটি লজিকাল প্রসেসরের জন্য সিএস এবং ইআইপি / আরআইপি নিবন্ধগুলি লজিকাল প্রসেসরের দ্বারা চালিত থ্রেডের জন্য নির্দেশ প্রবাহকে নির্দেশ করে।
- x87 এফপিইউ নিবন্ধগুলি (এসটি 7 এর মাধ্যমে এসটি 0, স্থিতি শব্দ, নিয়ন্ত্রণ শব্দ, ট্যাগ শব্দ, ডেটা অপারেন্ড পয়েন্টার এবং নির্দেশ পয়েন্টার)
- এমএমএক্স নিবন্ধগুলি (এমএম 7 এর মাধ্যমে এমএম0)
- এক্সএমএম রেজিস্টার (এক্সএমএম 7 এর মাধ্যমে এক্সএমএম 0) এবং এমএক্সসিএসআর রেজিস্টার
- নিয়ন্ত্রণ রেজিস্টার এবং সিস্টেম টেবিল পয়েন্টার রেজিস্টার (জিডিটিআর, এলডিডিআর, আইডিটিআর, টাস্ক রেজিস্টার)
- ডিবাগ নিবন্ধগুলি (ডিআর 0, ডিআর 1, ডিআর 2, ডিআর 3, ডিআর 6, ডিআর 7) এবং ডিবাগ নিয়ন্ত্রণ এমএসআরগুলি
- মেশিন চেক গ্লোবাল স্ট্যাটাস (IA32_MCG_STATUS) এবং মেশিন চেক ক্ষমতা (IA32_MCG_CAP) এমএসআর
- তাপীয় ঘড়ি মোডুলেশন এবং এসিপিআই পাওয়ার পরিচালনা নিয়ন্ত্রণ এমএসআরগুলি
- টাইম স্ট্যাম্প কাউন্টার এমএসআর
- পৃষ্ঠা অ্যাট্রিবিউট টেবিল (পিএটি) সহ অন্যান্য এমএসআর বেশিরভাগ রেজিস্টার। নীচে ব্যতিক্রম দেখুন।
- স্থানীয় এপিক রেজিস্ট্রেশন করে।
- অতিরিক্ত সাধারণ উদ্দেশ্যে নিবন্ধগুলি (আর 8-আর 15), এক্সএমএম রেজিস্টারগুলি (এক্সএমএম 8-এক্সএমএম 15), কন্ট্রোল রেজিস্টার, আইএএ 32_ ইফার ইনটেল 64 প্রসেসরের উপর।
নিম্নলিখিত বৈশিষ্ট্যগুলি লজিকাল প্রসেসর দ্বারা ভাগ করা হয়েছে:
- মেমরি ধরণের রেঞ্জ রেজিস্টার (এমটিআরআর)
নিম্নলিখিত বৈশিষ্ট্যগুলি ভাগ করা বা সদৃশ কিনা তা বাস্তবায়ন-নির্দিষ্ট:
- IA32_MISC_ENABLE MSR (MSR ঠিকানা 1A0H)
- মেশিন চেক আর্কিটেকচার (এমসিএ) এমএসআরগুলি (IA32_MCG_STATUS এবং IA32_MCG_CAP এমএসআর ব্যতীত)
- পারফরম্যান্স মনিটরিং কন্ট্রোল এবং এমএসআরদের কাউন্টারে
ক্যাশে ভাগ করে নেওয়ার বিষয়ে আলোচনা করা হয়েছে:
ইন্টেল হাইপারথ্রেডগুলির পৃথক কোরের চেয়ে ক্যাশে এবং পাইপলাইন ভাগ করে নেওয়া রয়েছে: https://superuser.com
লিনাক্স কার্নেল ৪.২
মূল সূচনা কর্মটি মনে হচ্ছে arch/x86/kernel/smpboot.c
।
এআরএম ন্যূনতম চলমানযোগ্য খোলামেলা উদাহরণ
এখানে আমি কিউইএমইউর জন্য একটি ন্যূনতম চলমানযোগ্য এআরএমভি 8 আরচ 64 উদাহরণ সরবরাহ করি:
.global mystart
mystart:
/* Reset spinlock. */
mov x0, #0
ldr x1, =spinlock
str x0, [x1]
/* Read cpu id into x1.
* TODO: cores beyond 4th?
* Mnemonic: Main Processor ID Register
*/
mrs x1, mpidr_el1
ands x1, x1, 3
beq cpu0_only
cpu1_only:
/* Only CPU 1 reaches this point and sets the spinlock. */
mov x0, 1
ldr x1, =spinlock
str x0, [x1]
/* Ensure that CPU 0 sees the write right now.
* Optional, but could save some useless CPU 1 loops.
*/
dmb sy
/* Wake up CPU 0 if it is sleeping on wfe.
* Optional, but could save power on a real system.
*/
sev
cpu1_sleep_forever:
/* Hint CPU 1 to enter low power mode.
* Optional, but could save power on a real system.
*/
wfe
b cpu1_sleep_forever
cpu0_only:
/* Only CPU 0 reaches this point. */
/* Wake up CPU 1 from initial sleep!
* See:https://github.com/cirosantilli/linux-kernel-module-cheat#psci
*/
/* PCSI function identifier: CPU_ON. */
ldr w0, =0xc4000003
/* Argument 1: target_cpu */
mov x1, 1
/* Argument 2: entry_point_address */
ldr x2, =cpu1_only
/* Argument 3: context_id */
mov x3, 0
/* Unused hvc args: the Linux kernel zeroes them,
* but I don't think it is required.
*/
hvc 0
spinlock_start:
ldr x0, spinlock
/* Hint CPU 0 to enter low power mode. */
wfe
cbz x0, spinlock_start
/* Semihost exit. */
mov x1, 0x26
movk x1, 2, lsl 16
str x1, [sp, 0]
mov x0, 0
str x0, [sp, 8]
mov x1, sp
mov w0, 0x18
hlt 0xf000
spinlock:
.skip 8
গিটহাব উজানের দিকে ।
একত্রিত হয়ে চালান:
aarch64-linux-gnu-gcc \
-mcpu=cortex-a57 \
-nostdlib \
-nostartfiles \
-Wl,--section-start=.text=0x40000000 \
-Wl,-N \
-o aarch64.elf \
-T link.ld \
aarch64.S \
;
qemu-system-aarch64 \
-machine virt \
-cpu cortex-a57 \
-d in_asm \
-kernel aarch64.elf \
-nographic \
-semihosting \
-smp 2 \
;
এই উদাহরণস্বরূপ, আমরা একটি স্পিনলক লুপে সিপিইউ 0 রেখেছি এবং এটি কেবল সিপিইউ 1 দিয়ে স্পিনলক প্রকাশ করে।
স্পিনলকের পরে, সিপিইউ 0 তারপর একটি সেমিহোস্ট প্রস্থান কল করে যা কিউইএমইউকে প্রস্থান করে।
আপনি যদি মাত্র একটি সিপিইউ দিয়ে কিউইএমইউ শুরু করেন -smp 1
তবে সিমুলেশনটি স্পিনলকের উপর চিরতরে স্তব্ধ।
সিপিইউ 1 পিএসসিআই ইন্টারফেসের সাথে জেগে উঠেছে, আরও বিশদ এখানে: এআরএম: স্টার্ট / ওয়াকআপ / অন্যান্য সিপিইউ কোর / এপিগুলি আনুন এবং এক্সিকিউশন শুরুর ঠিকানাটি পাস করবেন?
মূল প্রজেক্টের সংস্করণ এছাড়াও যাতে আপনি কর্মক্ষমতা বৈশিষ্ট্য সঙ্গে পাশাপাশি পরীক্ষা করতে পারেন, এটা gem5 কাজ করতে একটি কয়েক tweaks হয়েছে।
আমি এটি সত্যিকারের হার্ডওয়্যারে পরীক্ষা করে দেখিনি, সুতরাং আমি নিশ্চিত না যে এটি কতটা পোর্টেবল। নিম্নলিখিত রাস্পবেরি পাই গ্রন্থাগারটি আগ্রহী হতে পারে:
এই দস্তাবেজটি এআরএম সিঙ্ক্রোনাইজেশন প্রিমিটিভের ব্যবহার করে কিছু দিক নির্দেশনা যা আপনি পরে একাধিক কোর সঙ্গে মজা কিছু করার ব্যবহার করতে পারেন প্রদান করে: http://infocenter.arm.com/help/topic/com.arm.doc.dht0008a/DHT0008A_arm_synchronization_primitives.pdf
উবুন্টু 18.10, জিসিসি 8.2.0, বিন্টিলস 2.31.1, কিউইএমইউ 2.12.0 এ পরীক্ষিত।
আরও সুবিধাজনক প্রোগ্রামযোগ্যতার জন্য পরবর্তী পদক্ষেপ
পূর্ববর্তী উদাহরণগুলি মাধ্যমিক সিপিইউ জেগে থাকে এবং উত্সর্গীকৃত নির্দেশাবলীর সাথে বেসিক মেমরি সিঙ্ক্রোনাইজেশন করে, যা একটি ভাল শুরু।
তবে মাল্টিকোর সিস্টেমগুলিকে প্রোগ্রাম করা সহজ করার জন্য, যেমন পসিক্সের মতো pthreads
, আপনাকে নিম্নলিখিত আরও জড়িত বিষয়ের মধ্যে যেতে হবে:
সেটআপ বাধা দেয় এবং একটি টাইমার চালিত করে যা নিয়মিত সিদ্ধান্ত নেয় যে কোন থ্রেডটি এখন চলবে। এটি প্রিম্পিটিভ মাল্টিথ্রেডিং হিসাবে পরিচিত ।
এই জাতীয় সিস্টেমে থ্রেড রেজিস্টারগুলি শুরু এবং বন্ধ হওয়ার সাথে সাথে সংরক্ষণ এবং পুনরুদ্ধার করা দরকার।
অ-প্রাকিমিটিভ মাল্টিটাস্কিং সিস্টেম থাকাও সম্ভব, তবে সেগুলির জন্য আপনার কোডটি পরিবর্তন করার প্রয়োজন হতে পারে যাতে প্রতিটি থ্রেড ফলন দেয় (যেমন একটি pthread_yield
প্রয়োগের সাথে), এবং কাজের চাপ ভারসাম্য বজায় রাখা আরও শক্ত হয়ে যায়।
এখানে কয়েকটি সরলবস্তু খালি ধাতব টাইমার উদাহরণ রয়েছে:
স্মৃতি বিরোধের সাথে ডিল করুন। উল্লেখযোগ্যভাবে, আপনি সি বা অন্যান্য উচ্চ স্তরের ভাষায় কোড করতে চাইলে প্রতিটি থ্রেডের একটি অনন্য স্ট্যাকের প্রয়োজন হবে ।
আপনি কেবল থ্রেডগুলিকে একটি সর্বাধিক স্ট্যাক আকারের জন্য সীমাবদ্ধ করতে পারেন তবে এর সাথে মোকাবিলা করার সর্বোত্তম উপায় হল পেজিং সহ যা দক্ষ "সীমাহীন আকার" স্ট্যাকের অনুমতি দেয়।
এখানে একটি নিষ্পাপ আড়ম্বরপূর্ণ খালি উদাহরণ রয়েছে যা স্ট্যাকটি আরও গভীরভাবে বাড়লে আপ ফুঁকবে
লিনাক্স কার্নেল বা অন্য কোনও অপারেটিং সিস্টেম ব্যবহার করার জন্য এটি কয়েকটি ভাল কারণ :-)
ইউজারল্যান্ড মেমরি সিঙ্ক্রোনাইজেশন আদিম
থ্রেড স্টার্ট / স্টপ / ম্যানেজমেন্ট সাধারণত ইউজারল্যান্ড স্কোপ ছাড়িয়ে গেলেও আপনি সম্ভাব্য বেশি ব্যয়বহুল সিস্টেম কল ছাড়াই মেমরি অ্যাক্সেসগুলিকে সিঙ্ক্রোনাইজ করতে ইউজারল্যান্ড থ্রেড থেকে সমাবেশ নির্দেশাবলী ব্যবহার করতে পারেন instructions
আপনার অবশ্যই এমন লাইব্রেরিগুলি পছন্দ করা উচিত যা এই নিম্ন স্তরের আদিমগুলিকে পোর্টেবল মোড়ানো থাকে। সি ++ স্ট্যান্ডার্ড নিজে <mutex>
এবং <atomic>
হেডারগুলিতে এবং বিশেষত এর সাথে দুর্দান্ত অগ্রগতি করেছে std::memory_order
। আমি নিশ্চিত না যে এটি সমস্ত সম্ভাব্য মেমরি শব্দার্থকগুলি অর্জনযোগ্যকে কভার করে কিনা তবে এটি সম্ভবত might
আরও সূক্ষ্ম শব্দার্থবিজ্ঞান লক ফ্রি ডেটা স্ট্রাকচারের প্রসঙ্গে বিশেষভাবে প্রাসঙ্গিক , যা নির্দিষ্ট ক্ষেত্রে পারফরম্যান্স সুবিধা দিতে পারে। এগুলি বাস্তবায়নের জন্য, আপনাকে বিভিন্ন ধরণের মেমোরি বাধা সম্পর্কে সম্ভবত কিছুটা শিখতে হবে: https://preshing.com/20120710/mmory- Barিয়ার-are- Like-source-control-operation/
বুস্ট উদাহরণস্বরূপ এখানে কিছু লক ফ্রি কনটেইনার বাস্তবায়ন রয়েছে: https://www.boost.org/doc/libs/1_63_0/doc/html/ockfree.html
এই জাতীয় ব্যবহারকারী নির্দেশাবলী লিনাক্স futex
সিস্টেম কল প্রয়োগ করার জন্য ব্যবহার করা হয় , যা লিনাক্সের অন্যতম প্রধান সিঙ্ক্রোনাইজেশন আদিম। man futex
4.15 পঠিত:
Futex () সিস্টেম কলটি নির্দিষ্ট শর্তটি সত্য না হওয়া পর্যন্ত অপেক্ষা করার জন্য একটি পদ্ধতি সরবরাহ করে। এটি সাধারণত ভাগ করা-মেমরি সিঙ্ক্রোনাইজেশনের প্রসঙ্গে ব্লকিং কনস্ট্রাক্ট হিসাবে ব্যবহৃত হয়। ফিউটেক্সগুলি ব্যবহার করার সময়, সিংক্রোনাইজেশনের বেশিরভাগ ক্রিয়াকলাপ ব্যবহারকারীর জায়গায় সঞ্চালিত হয়। কোনও ইউজার-স্পেস প্রোগ্রাম কেবল তখনই ফিউটেক্স () সিস্টেম কল নিয়োগ করে যখন শর্তটি সত্য না হওয়া পর্যন্ত প্রোগ্রামটিকে দীর্ঘ সময়ের জন্য ব্লক করতে হবে। অন্যান্য ফুটেক্স () অপারেশনগুলি কোনও বিশেষ শর্তের জন্য অপেক্ষা করা কোনও প্রক্রিয়া বা থ্রেড জাগ্রত করতে ব্যবহার করা যেতে পারে।
সিস্কেল নামের অর্থ নিজেই "ফাস্ট ইউজারস্পেস XXX"।
এখানে ইনলাইন অ্যাসেমব্লির সাথে একটি ন্যূনতম অপ্রয়োজনীয় সি ++ x86_64 / আড়াল 64৪ উদাহরণ রয়েছে যা মূলত মজাদার জন্য এই জাতীয় নির্দেশের প্রাথমিক ব্যবহার চিত্রিত করে:
main.cpp
#include <atomic>
#include <cassert>
#include <iostream>
#include <thread>
#include <vector>
std::atomic_ulong my_atomic_ulong(0);
unsigned long my_non_atomic_ulong = 0;
#if defined(__x86_64__) || defined(__aarch64__)
unsigned long my_arch_atomic_ulong = 0;
unsigned long my_arch_non_atomic_ulong = 0;
#endif
size_t niters;
void threadMain() {
for (size_t i = 0; i < niters; ++i) {
my_atomic_ulong++;
my_non_atomic_ulong++;
#if defined(__x86_64__)
__asm__ __volatile__ (
"incq %0;"
: "+m" (my_arch_non_atomic_ulong)
:
:
);
// https://github.com/cirosantilli/linux-kernel-module-cheat#x86-lock-prefix
__asm__ __volatile__ (
"lock;"
"incq %0;"
: "+m" (my_arch_atomic_ulong)
:
:
);
#elif defined(__aarch64__)
__asm__ __volatile__ (
"add %0, %0, 1;"
: "+r" (my_arch_non_atomic_ulong)
:
:
);
// https://github.com/cirosantilli/linux-kernel-module-cheat#arm-lse
__asm__ __volatile__ (
"ldadd %[inc], xzr, [%[addr]];"
: "=m" (my_arch_atomic_ulong)
: [inc] "r" (1),
[addr] "r" (&my_arch_atomic_ulong)
:
);
#endif
}
}
int main(int argc, char **argv) {
size_t nthreads;
if (argc > 1) {
nthreads = std::stoull(argv[1], NULL, 0);
} else {
nthreads = 2;
}
if (argc > 2) {
niters = std::stoull(argv[2], NULL, 0);
} else {
niters = 10000;
}
std::vector<std::thread> threads(nthreads);
for (size_t i = 0; i < nthreads; ++i)
threads[i] = std::thread(threadMain);
for (size_t i = 0; i < nthreads; ++i)
threads[i].join();
assert(my_atomic_ulong.load() == nthreads * niters);
// We can also use the atomics direclty through `operator T` conversion.
assert(my_atomic_ulong == my_atomic_ulong.load());
std::cout << "my_non_atomic_ulong " << my_non_atomic_ulong << std::endl;
#if defined(__x86_64__) || defined(__aarch64__)
assert(my_arch_atomic_ulong == nthreads * niters);
std::cout << "my_arch_non_atomic_ulong " << my_arch_non_atomic_ulong << std::endl;
#endif
}
গিটহাব উজানের দিকে ।
সম্ভাব্য আউটপুট:
my_non_atomic_ulong 15264
my_arch_non_atomic_ulong 15267
এ থেকে আমরা দেখতে পাই যে x86 এলওএকেকে উপসর্গ / আড়াল 64৪ LDADD
নির্দেশনাই সংযোজনটিকে পারমাণবিক করে তুলেছে: এটি ছাড়া আমাদের অনেকগুলি অ্যাডের রেসের শর্ত রয়েছে এবং শেষে মোট গণনাটি সিঙ্ক্রোনাইজড 20000 এর চেয়ে কম is
আরো দেখুন:
উবুন্টু 19.04 amd64 এবং QEMU aarch64 ব্যবহারকারী মোডের সাথে পরীক্ষিত।