(x | y) - y এগুলি কেন কেবল x বা এমনকি be x | হতে পারে না 0`


47

আমি একটি কার্নেল কোড পড়া হয়, এবং এক জায়গায় আমি ভিতরে একটি অভিব্যক্তি দেখা করেছি ifমত বিবৃতি

if (value == (SPINLOCK_SHARED | 1) - 1) {
         ............
}

যেখানে SPINLOCK_SHARED = 0x80000000পূর্বনির্ধারিত ধ্রুবক।

আমি ভাবছি কেন আমাদের প্রয়োজন (SPINLOCK_SHARED | 1) - 1- ধরণের রূপান্তর উদ্দেশ্যে? অভিব্যক্তিটির ফলাফল 80000000-- 0x80000000 এর সমান হবে, তাই না? তবুও, কেন ORing 1 এবং 1 টি বিয়োগ করে?

এমন কিছু অনুভব করুন যেন আমি কিছু পেতে মিস করছি ..


3
# নির্ধারিত স্পিনলোক_SHARED 0x80000000
রাগা__ এম

1
আমার সন্দেহ আছে এর কোন কারণ নেই। সম্ভবত একটি অনুলিপি-পেস্ট জিনিস। আপনি ঠিক কোথায় এটি পেয়েছেন তা যুক্ত করতে পারেন (কোন কার্নেলের কোন সংস্করণ, কোন ফাইল, ইত্যাদি)।
Sander De Dycker


2
একই উত্স কোড ফাইলটিতেও রয়েছে if (atomic_cmpset_int(&spin->counta, SPINLOCK_SHARED|0, 1))
এরিক পোস্টপিসিল

2
তারপরে আমি মনে করি এটি লেখককে কেন জিজ্ঞাসা করা দরকার কেন এটি পরিবর্তন করা হয়েছিল।
ফানিডম্যান

উত্তর:


1

এটি কেবল স্বচ্ছতার জন্য সেভাবে করা হয়েছিল, এটিই কেবল। এটি কারণ পারমাণবিক_ফ্যাচড্যাড_িন্ট () উদাহরণস্বরূপ সায়স / স্পিনলক ২ এইচ) পিআরআইআরটি সংযোজন / বিয়োগফলকে প্রদান করে এবং এই মানটি _ স্পিন_লক_কন্টেস্টেড () এ পাস করা হয়েছে

নোট করুন যে সি সংকলক সমস্ত ধ্রুবক এক্সপ্রেশনগুলি সম্পূর্ণ প্রাক-গণনা করে। প্রকৃতপক্ষে, সংকলক এমনকি শর্তগুলির ভিত্তিতে ইনলাইনড কোডটি অনুকূলিত করতে পারে যা শর্তগুলির ভিত্তিতে পাস-ইন পদ্ধতি আর্গুমেন্টগুলি ব্যবহার করে যখন প্রক্রিয়াগুলি সেই যুক্তিতে স্থির হয় ants এই কারণেই লকজম্যাগার () ইনলাইন সিস্টেমে / লক। এইচ এর একটি কেস স্টেটমেন্ট আছে .... কারণ সেই পুরো কেস স্টেটমেন্টটি অপ্টিমাইজ হবে এবং উপযুক্ত ফাংশনে সরাসরি ডাকা হবে into

এছাড়াও, এই সমস্ত লকিং ফাংশনগুলিতে পারমাণবিক ওপেনের ওভারহেড দুটি বা তিনটি মাত্রার মাত্রার দ্বারা অন্যান্য সমস্ত গণনাগুলি বামন করে।

-মথি


এই উত্তরটি লেখকের !!!
রাগা__এম

31

কোডটি পাওয়া গেছে _spin_lock_contested, যা _spin_lock_quickঅন্য কেউ লকটি পাওয়ার চেষ্টা করার সময় থেকে কল করা হয়েছিল:

count = atomic_fetchadd_int(&spin->counta, 1);
if (__predict_false(count != 0)) {
    _spin_lock_contested(spin, ident, count);
}

যদি কোনও প্রতিযোগিতা না থাকে, তবে count(পূর্ববর্তী মান) হওয়া উচিত 0, তবে তা নয়। এই countমান প্যারামিটার হিসাবে পাস করা হয়েছে _spin_lock_contestedযেমন valueপ্যারামিটার। এই valueতারপর পরীক্ষা করা হয় ifওপি থেকে:

/*
 * WARNING! Caller has already incremented the lock.  We must
 *      increment the count value (from the inline's fetch-add)
 *      to match.
 *
 * Handle the degenerate case where the spinlock is flagged SHARED
 * with only our reference.  We can convert it to EXCLUSIVE.
 */
if (value == (SPINLOCK_SHARED | 1) - 1) {
    if (atomic_cmpset_int(&spin->counta, SPINLOCK_SHARED | 1, 1))
        return;
}

valueএটি পূর্বের মানটি বিবেচনায় রেখে এবং এরপরেরটি spin->countaইতিমধ্যে 1 দ্বারা বাড়ানো হয়েছে, আমরা spin->countaসমান হওয়ার প্রত্যাশা করব value + 1(যদি না এর মধ্যে কিছু পরিবর্তন হয়)।

সুতরাং, spin->counta == SPINLOCK_SHARED | 1(এর পূর্বশর্তটি atomic_cmpset_int) কিনা তা যাচাইয়ের সাথে মিলছে কিনা তা যাচাই করা হচ্ছে value + 1 == SPINLOCK_SHARED | 1, যা value == (SPINLOCK_SHARED | 1) - 1আবার লিখতে পারে (ইতিমধ্যে যদি কিছু পরিবর্তন না হয়ে থাকে)।

আবার value == (SPINLOCK_SHARED | 1) - 1যেমন লিখতে পারা যায় value == SPINLOCK_SHARED, তেমনি রেখে দেওয়া হয়েছে, তুলনার উদ্দেশ্যটি স্পষ্ট করার জন্য (যেমন পরীক্ষার মানের সাথে বর্ধিত পূর্ববর্তী মানটির তুলনা করা)।

বা iow। উত্তরটি প্রদর্শিত হবে: স্পষ্টতা এবং কোডের ধারাবাহিকতার জন্য।


আপনার প্রতিক্রিয়াটির জন্য ধন্যবাদ, (SPINLOCK_SHARED | 1) - 1অংশ ব্যতীত সমস্ত কিছুই বোধগম্য এবং value == SPINLOCK_SHAREDএটি আমার চিন্তাভাবনাও, কারণ আমরা আগের মানটি ভাগ করে নেওয়া হয়েছে কিনা তা যাচাই করে দেখছি if হ্যাঁ, লকটি একচেটিয়াতে পরিণত করুন .........
রাগা_এম

1
@ রাগা__ এম: চেকের উদ্দেশ্যটি (যা এর মধ্যে এমন কোনও মান হওয়া উচিত যা এর মধ্যে কিছু পরিবর্তন হয়নি) সমান ifকিনা তা পরীক্ষা করা । আপনি যদি চেকটি লিখেন তবে এই উদ্দেশ্যটি পরিষ্কার নয়, এবং চেকটির অর্থ কী তা বোঝা অনেক কঠিন হবে be উভয় এবং সুস্পষ্টভাবে চেক মধ্যে রাখা ইচ্ছাকৃত। value + 1spin->countaSPINLOCK_SHARED | 1ifvalue == SPINLOCK_SHAREDSPINLOCK_SHARED | 1- 1if
Sander De Dycker

তবে এটি আসলে বিভ্রান্তির সৃষ্টি করছে।
রাগা__এম

না কেন if (value + 1 == (SPINLOCK_SHARED | 1) )?
পাবলো এইচ

ভাল .... এটি কেবল value & SPINLOCK_SHAREDযা বেশি পাঠযোগ্য could
রাগা__ এম

10

আমি মনে করি লক্ষ্যটি সম্ভবত সর্বনিম্ন তাৎপর্যপূর্ণ কিছুটিকে অগ্রাহ্য করা:

  • যদি স্পিনলোক_সেইআরএইডিড বাইনারিতে প্রকাশ করা হয় তবে এটি এক্সএক্সএক্সএক্স -> ফলাফল xxx0
  • যদি স্পিনলোক_এসএইআরএইডি = এক্সএক্সএক্সএক্স 1 -> ফলাফলটিও xxx0 হয় 0

একটি বিট মাস্ক এক্সপ্রেশন ব্যবহার সম্ভবত পরিষ্কার হতে হবে?


8
কোডটি সেটাই করে, তবে প্রশ্নটি হল আপনি কেন এমন সংজ্ঞায়িত ধ্রুবকটির জন্য এমন করবেন যাতে কমপক্ষে উল্লেখযোগ্য বিট সেট নেই?
Sander De Dycker

4
লিনাক্স কার্নেল কারণ স্যান্ডারডিডাইকার?
লন্ডিন

9
@ লন্ডিন লিনাক্স কার্নেলটি বোধগম্য কোডিং অনুশীলন থেকে ছাড় নয়। পুরোপুরি বিপরীত.
কিউস - মনিকো

2
@ কিউস আপনি যদি তাই বলেন। আমি কোডটি না দেখে এবং কার্নেল কোডিং শৈলী নথিটি না পড়া পর্যন্ত আমি লিনাক্সের একটি বড় অনুরাগী ছিলাম। আজকাল আমি লিনাক্স কম্পিউটারগুলিতে 10 মিটার সুরক্ষা দূরত্ব রাখি।
লন্ডিন

2
@ কিউস নাহ আমি বরং এর উত্স কোডের ভিত্তিতে এটি বিচার করছি ...
লন্ডিন

4

প্রভাবে

(SPINLOCK_SHARED | 1) - 1

ফলাফলের নিম্ন-অর্ডার বিটটি তুলনা করার আগেই সাফ হয়ে গেছে তা নিশ্চিত করা value। আমি সম্মত হই যে এটি বরং অর্থহীন বলে মনে হচ্ছে তবে আপাতদৃষ্টিতে নিম্ন-অর্ডার বিটের একটি নির্দিষ্ট ব্যবহার বা অর্থ রয়েছে যা এই কোডটিতে আপাত নয়, এবং আমি মনে করি আমাদের ধরে নিতে হবে যে দেবগণের এটি করার উপযুক্ত কারণ ছিল। একটি আকর্ষণীয় প্রশ্ন হবে - | 1) -1আপনি কি দেখছেন কোডবেস জুড়ে একই প্যাটার্নটি ( ) ব্যবহার করা হচ্ছে?


2

এটি কিছুটা মাস্ক লেখার একটি অস্পষ্ট উপায়। রিডেবল সংস্করণ: value == (SPINLOCK_SHARED & ~1u)


5
হ্যাঁ, তবে কেন । ওপি জিজ্ঞাসা করছে যে যদি SPINLOCK_SHAREDজানা ধ্রুবক হয় তবে কেন এটি হবে । যদি তারা কেবল SPINLOCK_SHAREDকোনও মুখোশটিতে উপস্থিত থাকার জন্য পরীক্ষা করে থাকে তবে কেন নয় if (value & SPINLOCK_SHARED)?
কিউস - মনিকি

4
value == (SPINLOCK_SHARED & ~1u)সমতুল্য নয় কারণ value == (SPINLOCK_SHARED | 1) - 1এর ধরণের SPINLOCK_SHAREDচেয়ে বৃহত্তর হলেও কাজ করে unsigned
এরিক পোস্টপিসিল

4
সত্য, আমি নিশ্চিত যে & ~1uএটি কোন পরিষ্কার। আমি & 0xFFFFFFFEআমার উত্তরে পরামর্শ দেওয়ার কথা ভেবেছিলাম কিন্তু বুঝতে পেরেছিলাম যে এটিও স্পষ্ট নয়। যদিও আপনার পরামর্শটি ব্রিভটির সুবিধা রয়েছে have :-)
বব জার্ভিস - মনিকা

6
@ লন্ডিন: আমরা জানি না যে এটি হবে 0x80000000। ওপি জানিয়েছেন যে এটি সংজ্ঞায়িত হয়েছে #define SPINLOCK_SHARED 0x80000000তবে এটি ভিতরে থাকতে পারে #if…#endifএবং অন্য পরিস্থিতিতে একটি আলাদা সংজ্ঞা ব্যবহৃত হতে পারে বা সংজ্ঞাটি সম্পাদিত হয় বা কোডটি অন্য শিরোলেখগুলির সাথে সংকলিত হলেও এই কোডটির লেখক এটি কাজ করার ইচ্ছা পোষণ করতে পারে that এটি আলাদাভাবে সংজ্ঞায়িত করুন নির্বিশেষে, কোডের দুটি টুকরা নিজের দ্বারা সমতুল্য নয়।
এরিক পোস্টপিসিল

2
@ বব জার্ভিস-রিইনস্টেটমোনিকা এটি এমন লোকদের কাছে অনেক বেশি স্পষ্ট যারা প্রতিদিন বিটওয়াইজ অপারেটরদের সাথে কাজ করেন। নিয়মিত গাণিতিকের সাথে বিটওয়াইসের মিশ্রণ বিভ্রান্তিকর।
লন্ডিন

0

বেশিরভাগ এরকম বেশ কয়েকটি অতিরিক্ত কেস পরিচালনা করার জন্য করা হয়। উদাহরণস্বরূপ, এই ক্ষেত্রে, আমরা বলি যে SPINLOCK_SHARED1 হতে পারে না:

int SPINLOCK_SHARED = 0x01

int res = (SPINLOCK_SHARED | 1) - 1 // 0

2
এটি বোধগম্য হবে তবে, যদিও এটি প্রশ্ন থেকে আসলে পরিষ্কার নয়, মনে হচ্ছে SPINLOCK_SHAREDএটি একটি সংজ্ঞায়িত ধ্রুবক এবং পরীক্ষিত পরিবর্তনশীল value। এক্ষেত্রে মিস্টি থেকে যায়।
রবার্তো ক্যাবনি

আপনার জবাবের জন্য ধন্যবাদ, তবে আমি মনে করি মূল ক্ষেত্রে SPINLOCK_SHARED 0x01 নয়, আপনি | 1) - 1অংশটি রেখেছিলেন , যখন স্পিনলোক_শারাইডের 0x80000000কী প্রভাব থাকবে | 1) - 1?
রাগা__ এম

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