এটি কি সি ++ অ্যাটমিকিন্ট বাস্তবায়ন সঠিক?


9

জায়গা: আমি এমন একটি এআরএম এমবেডেড (প্রায় খালি ধাতব) পরিবেশের সাথে কাজ করছি যেখানে আমার সি ++ 11 (সহ std::atomic<int>) উপলব্ধ নেই, সুতরাং দয়া করে " কেবলমাত্র স্ট্যান্ডার্ড সি ++ ব্যবহার করুনstd::atomic<int> " এর মতো উত্তরগুলি এড়িয়ে চলুন : আমি পারছি না

এটি কি এটমিক্যান্টের এআরএম বাস্তবায়ন সঠিক? ( ধরুন এআরএম আর্কিটেকচারটি এআরএমভি 7-এ )

আপনি কিছু সিঙ্ক্রোনাইজেশন সমস্যা দেখতে পাচ্ছেন? এটি volatileপ্রয়োজনীয় / দরকারী?

// File: atomic_int.h

#ifndef ATOMIC_INT_H_
#define ATOMIC_INT_H_

#include <stdint.h>

class AtomicInt
{
public:
    AtomicInt(int32_t init = 0) : atom(init) { }
    ~AtomicInt() {}

    int32_t add(int32_t value); // Implement 'add' method in platform-specific file

    int32_t sub(int32_t value) { return add(-value); }
    int32_t inc(void)          { return add(1);      }
    int32_t dec(void)          { return add(-1);     }

private:
    volatile int32_t atom;
};

#endif
// File: arm/atomic_int.cpp

#include "atomic_int.h"

int32_t AtomicInt::add(int32_t value)
{
    int32_t res, prev, tmp;

    asm volatile(

    "try:    ldrex   %1, [%3]\n"     // prev = atom;
    "        add     %0, %1, %4\n"   // res = prev + value;
    "        strex   %2, %0, [%3]\n" // tmp = outcome(atom = res); // may fail
    "        teq     %2, #0\n"       // if (tmp)
    "        bne     try"            //     goto try; /* add failed: someone else modified atom -> retry */

    : "=&r" (res), "=&r" (prev), "=&r" (tmp), "+mo" (atom)  // output (atom is both in-out)
    : "r" (value)                                           // input
    : "cc");                                                // clobbers (condition code register [CPSR] changed)

    return prev; // safe return (local variable cannot be changed by other execution contexts)
}

এছাড়াও, আমি কিছু কোড পুনরায় ব্যবহারের চেষ্টা করছি, সে কারণেই আমি প্ল্যাটফর্ম-নির্দিষ্ট কোড (অভ্যন্তরীণ add()পদ্ধতি arm/atomic_int.cpp) প্রয়োগ করতে কেবল একটি প্রাথমিক ফাংশনকে পৃথক করেছিলাম ।

কি atomic_int.hসত্যিই পোর্টেবল যেমন বিভিন্ন প্ল্যাটফর্মের / আর্কিটেকচারের / কম্পাইলার জুড়ে যায়? এই পদ্ধতির কি সম্ভব ? ( সম্ভবপরতার সাথে আমি প্রতিটি প্ল্যাটফর্মের পক্ষে কেবলমাত্র add()পদ্ধতিটি প্রয়োগ করে পারমাণবিকতার গ্যারান্টি দেওয়া সম্ভব ))

এখানে একই এআরএম জিসিসি 8.3.1 একই ফাংশনটির বাস্তবায়ন রয়েছে। স্পষ্টতই, একমাত্র আসল পার্থক্য হ'ল dmbআগে এবং পরে উপস্থিতি । তারা কি সত্যিই আমার ক্ষেত্রে প্রয়োজন? কেন? আমার AtomicInt(ব্যতীত dmb) ব্যর্থ হয়েছে এমন কোনও উদাহরণ কি আপনার আছে ?

আপডেট: স্থির বাস্তবায়ন, get()পারমাণবিকতা এবং প্রান্তিককরণ সমস্যা সমাধানের জন্য সরানো পদ্ধতি। এখন add()স্ট্যান্ডার্ডের মতো আচরণ করে fetchAndAdd()


volatileসি ++ এর কীওয়ার্ডের অর্থ ভেরিয়েবলের মাধ্যমে অনুকূলিতকরণ করবেন না। সুতরাং get()পদ্ধতি এটি থেকে উপকৃত হয়। যদিও, সাধারণভাবে, অস্থির সি ++ এ অবসন্ন হতে চলেছে। যদি আপনার সিস্টেমটি অন্তর্নির্মিত 32-বিট ডেটা সিঙ্ক্রোনাইজ করতে না পারে, তবে আপনার কাছে খুব পরিমাণে স্পিনলক - মিউটেক্সগুলি ব্যবহার করা ছাড়া বিকল্প নেই।
ALX23z

আপনি আর্ম আর্কিটেকচারের কোন সংস্করণ ব্যবহার করছেন? armv -7?
মাইক ভ্যান ডাইক

1
এটি প্রশ্নের সমাধান করে না, তবে ধারাবাহিকভাবে দুটি আন্ডারস্কোর ( __ATOMIC_INT_H_) নাম এবং মূল নাম সহ একটি আন্ডারস্কোর দিয়ে শুরু হওয়া নামগুলি প্রয়োগের মাধ্যমে ব্যবহারের জন্য সংরক্ষিত। এগুলি আপনার কোডে ব্যবহার করবেন না।
পিট বেকার

সদস্যের নামটি atomicসম্ভবত বিভ্রান্তি এড়াতে সবচেয়ে বেশি ব্যবহৃত হয় না std::atomic, যদিও আপনি যে কোনও ক্ষেত্রে কেবল এটি ব্যবহার করবেন না কেন তা প্রশ্ন করে।
ক্লিফোর্ড

এআরএম আর্কিটেকচার যুক্ত হয়েছে, নামকরণ __ATOMIC_INT_H_শনাক্তকারী।
28 এ আলতো চাপ দিন

উত্তর:


2

আপনি যদি ব্যবহার করেন তবে পারমাণবিক মেমোরি অ্যাক্সেসের জন্য লেগ্যাসি বিল্ট-ইন ফাংশনগুলিgcc ব্যবহার করতে পারেন :__sync

void add(int volatile& a, int value) {
    __sync_fetch_and_add(&a, value);
}

উত্পন্ন :

add(int volatile&, int):
.L2:
        ldxr    w2, [x0]
        add     w2, w2, w1
        stlxr   w3, w2, [x0]
        cbnz    w3, .L2
        dmb     ish
        ret

দুর্ভাগ্যক্রমে আমি ব্যবহার করছি না gcc, এবং কোনও অবস্থাতেই আমি প্রয়োগটি কোনও নির্দিষ্ট সংকলককে আবদ্ধ করতে চাই না। আপনার ইঙ্গিতটির জন্য যাইহোক ধন্যবাদ, কমপক্ষে এটি আমাকে বলেছে যে আমার এআরএম add()অংশটি সঠিক হওয়া উচিত। মধ্যে পার্থক্য কি ldxrএবং ldrex?
আলতো চাপ দিন

এটি 32-বিট সংস্করণের একের চেয়ে ARM8 (eg64bit)।
মার্কো

আমি লক্ষ্য আর্কিটেকচার: লিঙ্কটি নির্দিষ্ট করে সংশ্লিষ্ট কোডটি পেতে সক্ষম হয়েছি । দেখে মনে হচ্ছে জিসিসি আসলে / লুপের dmbআগে এবং পরে রাখে । ldrexstrex
14:46

2
আমি মনে করি এটি ভাল পদ্ধতির তবে এটিকে সংকলককে স্বাধীন করতে কেবল গডবোল্ট.আরজেজ / ডাব্লুবি 8আরএক্সডব্লিউ টাইপ করুন আপনি যে সিসিএস বিল্টিনগুলি ব্যবহার করতে চান তাতে ফাংশনটিতে যান এবং সংশ্লিষ্ট সমাবেশের আউটপুট অনুলিপি করেন। মার্চ প্যারামিটারটি এআরএমের নির্দিষ্ট সংস্করণের সাথে মেলাতে ভুলবেন না।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.