0

我想知道是否有人看到任何可能导致此代码出现问题的内容。我知道我可以使用其他方法/API 调用来做到这一点,但我正试图为我自己的平台独立奠定基础?/ 跨平台互斥框架。

显然我需要做一些#ifdef 并为 Win32 Sleep() 和 GetCurrentThreadID() 调用定义一些宏......

typedef struct aec {
    unsigned long long lastaudibleframe; /* time stamp of last audible frame */
    unsigned short aiws; /* Average mike input when speaker is playing */
    unsigned short aiwos; /*Average mike input when speaker ISNT playing */
    unsigned long long t_aiws, t_aiwos; /* Internal running total */
    unsigned int c_aiws, c_aiwos; /* Internal counters */
    unsigned long lockthreadid;
    int stlc; /* Same thread lock count */
} AEC;

char lockecho( AEC *ec ) {
    unsigned long tid=0;
    static int inproc=0;
    while (inproc) {
        Sleep(1);
    }
    inproc=1;
    if (!ec) {
        inproc=0;
        return 0;
    }
    tid=GetCurrentThreadId();
    if (ec->lockthreadid==tid) {
        inproc=0;
        ec->stlc++;
        return 1;
    }
    while (ec->lockthreadid!=0) {
        Sleep(1);
    }
    ec->lockthreadid=tid;
    inproc=0;
    return 1;
}

char unlockecho( AEC *ec ) {
    unsigned long tid=0;
    if (!ec)
        return 1;
    tid=GetCurrentThreadId();
    if (tid!=ec->lockthreadid)
        return 0;
    if (tid==ec->lockthreadid) {
        if (ec->stlc>0) {
            ec->stlc--;
        } else {
            ec->lockthreadid=0;
        }
    }
    return 1;
}
4

2 回答 2

3

No it's not, AFAIK you can't implement a mutex with plain C code without some low-level atomic operations (RMW, Test and Set... etc).. In your particular example, consider what happens if a context switch interrupts the first thread before it gets a chance to set inproc, then the second thread will resume and set it to 1 and now both threads "think" they have exclusive access to the struct.. this is just one of many things that could go wrong with your approach.

Also note that even if a thread gets a chance to set inproc, assignment is not guranteed to be atomic (it could be interrupted in the middle of assigning the variable).

于 2013-08-05T06:37:20.713 回答
1

正如mux指出的那样,由于许多竞争条件,您提出的代码是不正确的。您可以使用诸如“比较和设置”之类的原子指令来解决此问题,但无论如何您都需要为每个平台单独定义这些指令。你最好只定义一个高级的“锁定”和“解锁”接口,并使用平台提供的任何东西来实现它们。

于 2013-08-05T06:43:06.347 回答