كيفية معرفة ما إذا برمجيا متغيرين على نفس كومة؟ (في نظام التشغيل Windows)

StackOverflow https://stackoverflow.com/questions/1743511

سؤال

وأنا في الموضوع. لدي عنوان. وهذا العنوان من متغير في نفس كومة أنني أستخدم؟

static int *address;

void A()
{
    int x;
    atomic::CAS(address, 0, &x); // ie address = &x
    // ...
}

void B()
{
   int y;
   int * addr = atomic::read(address); // ie addr = address
   if (addr && on_same_stack(&y, addr))
   {
      // B() called from A()
   }
   else
   {
      // B() called from different thread than A()
   }
}

وأحتاج لتنفيذ on_same_stack(addr1, addr2). وأنا أعلم أن كومة (ق) على ويندوز تنمو حسب الحاجة، ولكن أعلم أيضا أن هناك حدودا لنمو، وأن (في التصحيح على الأقل) هناك كود التحقق كومة تجاوز على كل مكالمة وظيفة. لذلك اعتقد انه يمكن القيام به.

والآن، وأعرف أيضا أن أتمكن / يجب أن تستخدم معرفات موضوع، وما إلى ذلك ولكن أنا أحاول لتنفيذ بعض صعبة قفل خالية من الترميز هنا، وأنا لم يكن لديك حقا غرفة لتخزين معرفات موضوع، فقط مؤشر واحد. (أنا على أمل لتجنب CMPXCH16). يرجى الثقة لي أنني إلى حد ما أعرف ما أفعله: -)

وهذا هو لويندوز فقط في الوقت الراهن. ولكن أكثر المحمولة كلما كان ذلك أفضل. (NT / XP / 7 / CE؟)

وP.S. ويسمى هذا الموقع "ستاكوفيرفلوو" لذلك يجب أن يكون المكان المناسب أن نسأل، أليس كذلك؟ : -)

وتحرير: مضيفا السياق، لأن الجميع يسأل. أنا تنفيذ call_once العرف على غرار pthread_once أو boost.threads call_once. أنا محاولة للتحقق من العودية. أنا <م> جدا محدودة مع ما لدي للعمل مع. لا أستطيع إضافة معلمات وظيفة. لا أستطيع وضع افتراضات بشأن ما تبقى من البرنامج يقوم به، مثل مقدار TLS أنها تستخدم بالفعل. وما يمكنني سوى رمز داخل بلدي وظيفة واحدة، وعدم إجراء أية تغييرات أو افتراضات حول أي شيء خارج ذلك.

وشكرا لأسئلتك / إجابات.

هل كانت مفيدة؟

المحلول

وماذا عن شيء مجنون مثل (غير مجربة):

declspec(__thread) void* stackBottom;

void Thread1Routine(void* arg)
{
  volatile int bottom;
  stackBottom = &bottom;

  ... (do stuff which ends up calling on_same_stack()) ...
}


bool on_same_stack(void* p)
{
  volatile int top;
  return ((LONG_PTR)p >= (LONG_PTR)&top) && ((LONG_PTR)p <= (LONG_PTR)stackBottom);
}

و(تحرير لإزالة النظري السجل المستندة إلى ARG القضايا التي تمر)

نصائح أخرى

Win32 والموضوع معلومات بلوك

وهذه الأمثلة استخدام الخيط الرئيسي ولكن في الواقع يجب أن يعمل على في أي موضوع.

مثال رقم 1:

#include <iostream>
#include <windows.h>
#include <winnt.h>
#include <intrin.h>

inline size_t get_thread_top_stack_size()
{
    NT_TIB *s = (NT_TIB*)getTib();
    return (size_t)s->StackBase ;
}

int global_var;

int main () 
{
    size_t sp_value = 0; 
    _asm { mov [sp_value], esp } 
    size_t thread_top_stack = get_thread_top_stack_size();

    int my_local_var;
    size_t my_local_var_addr = (size_t)&my_local_var;
    if (my_local_var_addr  < thread_top_stack && my_local_var_addr > sp_value  ) {
        std::cout << "Yes, on the thread stack";
    } else {
        std::cout << "No, not on the thread stack";
    }

    size_t my_global_var_addr = (size_t)&global_var;
    if (my_global_var_addr < thread_top_stack && my_global_var_addr> sp_value  ) {
        std::cout << "Yes, on the thread stack";
    } else {
        std::cout << "No, not on the thread stack";
    }
    return 0;
}

مثال رقم 2:

#include <windows.h>
#include <winnt.h>
#include <intrin.h>

inline NT_TIB* getTib()
{
    return (NT_TIB*)__readfsdword( 0x18 );
}

inline bool is_var_on_the_thread_stack(void* ptr)
{
    NT_TIB *nt_tib = getTib();
    return (nt_tib->StackBase >= ptr) &&  (nt_tib->StackLimit <= ptr );
}

int my_global_var;

int main () 
{
    int my_thread_var;
    if (is_var_on_the_thread_stack(&my_thread_var)) {
        std::cout << "Yes, on the thread stack" << std::endl;
    } else {
        std::cout << "No, not on the thread stack" << std::endl;
    }
    if (is_var_on_the_thread_stack(&my_global_var)) {
        std::cout << "Yes, on the thread stack" << std::endl;
    } else {
        std::cout << "No, not on the thread stack" << std::endl;
    }
    return 0;
}

ومن B() called from A() تعليقك، لا يمكن لك مجرد تمرير حجة لB() وتعيينها إلى قيمة محددة عند استدعائه من A() ؟؟ (مع قيمة الوسيطة الافتراضية، التي لا تتطلب تغييرا كبيرا)

وعينة ليست كاملة جدا، حتى هنا هو صنع محاولة أخرى على A LOT من الافتراضات حول مشكلتك ... ماذا عن:

void A()
{
    B_lockfree();
}

void B()
{
    // acquire a lock here
    B_lockfree();
    // release your lock here
}

void B_lockfree()
{
    // do whatever you want here
}

و(حسنا، أستطيع أن أفكر في الكثير من الطرق، ولكن من دون معرفة الصورة الكبيرة، فإنها قد تكون كلها خاطئة تماما ...)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top