曲径通幽论坛

标题: lfence, sfence, mfence [打印本页]

作者: beyes    时间: 2011-3-19 21:08
标题: lfence, sfence, mfence
lfence, sfence, mfence 三条指令与乱序执行引起的内存屏障有关。所谓的乱序执行指令,是处理器为了提高性能,不按照指令原先顺序执行的一种优化形式。但是乱序也会带来副作用,下面进行一种假设的分析。

比如有以下代码(注意,下面代码在真实环境中也许不会得到因为乱序而引起的内存屏障):
[C++] 纯文本查看 复制代码
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

#define wmb() __asm__ __volatile ("sfence":::)

unsigned int a = 0;
unsigned int b = 1;

pthread_mutex_t lock;

static void* f(void* arg)
{
    unsigned int c,d;
    for(;;){
        c = a;
    //wmb();
    d = b;
        if (c>=d) {
            printf("c=%x    d=%x\n",c,d);
            return NULL;
        }
    }
}

static void* g(void* arg)
{
    for(;;){
    pthread_mutex_lock (&lock);
    b++;
    a++;
    if (b == 0x7fffffff) {
        b = 1;   
        a = 0;
    }
        pthread_mutex_unlock (&lock);
    }
}

int main(int argc, const char* argv[])
{
    pthread_t pid1,pid2;

    pthread_mutex_init (&lock, NULL);

    if (pthread_create(&pid1, 0, f, 0)){
        printf("Create thread1 error\n");
        exit(-1);
    }
    if (pthread_create(&pid2, 0, g, 0)){
        printf("Create thread2 error\n");
        exit(-1);
    }

    while (1)
        sleep(1);

    return 0;
}

上面代码创建了 2 个线程,线程1 在 CPU1 上执行,线程2 在 CPU2 上执行。如果因为超标量(此概念参考:http://www.groad.net/bbs/read.php?tid-3242.html)的关系,在执行过程中,c=a; 和 d=b; 两条语句互换了位置,那么得到的结果也就和预期的相反。所以为了得到正确的结果,这里可以采用专门的汇编指令来完成这个工作,这些指令分别是:lfence, sfence, mfence ,它们的原理都是停止流水线,并保证相关操作按照顺序完成。这些指令的作用如下:

lfence : 当 CPU 遇到 lfence 指令时,停止相关流水线,直到 lfence 之前对内存读取操作的指令全部完成。

sfence : 当 CPU 遇到 sfence 指令时,停止相关流水线,直到 sfence 之前对内存进行写入操作的指令全部完成。

mfence : 当 CPU 遇到 mfence 指令时,停止相关流水线,直到 mfence 之前对内存进行读取和写入操作的指令全部完成。

于是,像上面的代码中,在 c=a; 和 d=b 加入这样的指令,这两条语句的执行就不会乱序了。


SFENCE
Serializes all store (write) operations that occurred prior to the SFENCE instruction in the program instruction stream, but does not affect load operations.

LFENCE
Serializes all load (read) operations that occurred prior to the LFENCE instruction in the program instruction stream, but does not affect store operations.

MFENCE
Serializes all store and load operations that occurred prior to the MFENCE instruction in the program instruction stream.




欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2