曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 12901|回复: 0
打印 上一主题 下一主题

lfence, sfence, mfence

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2011-3-19 21:08:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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.
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-4-29 05:59 , Processed in 0.061995 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表