缓存刷新和冷缓存

时间:2016-12-22 06:14:21

标签: c caching x86-64

以下代码出现在其中一个内核邮件列表中。我目前无法引用它,因为该消息尚未发布到任何内核存档(mail-archive.com,marc.info或spinics.net):

static void clflush(void)
{
    extern char const _init, _fini;
    char const *p = &_init;

    while (p < &_fini) {
        asm("clflush %0" : : "m" (*p));
        p += 64;
    }
}

这里是消息中函数的描述:

  • 在每次偶数编号迭代之前,我刷新了I-cache 从_init到_fini的所有内容(即所有非库代码)。 这种冷缓存案例将在内核中发生。

我不太清楚_init_fini的诀窍是怎么回事。

基于_init_fini(以及两者之间的函数指针)的循环的目的是什么?为什么没有使用缓存大小和关联性的简单指针?

这是邮件中提供的完整代码。该代码尝试将提出的算法(SipHash)与特定状态(冷)中的缓存进行基准测试,以避免可能的偏差测量。

static void clflush(void)
{
        extern char const _init, _fini;
        char const *p = &_init;

        while (p < &_fini) {
                asm("clflush %0" : : "m" (*p));
                p += 64;
        }
}

typedef uint32_t cycles_t;
static cycles_t get_cycles(void)
{
        uint32_t eax, edx;
        asm volatile("rdtsc" : "=a" (eax), "=d" (edx));
        return eax;
}

static int benchmark(void)
{
        cycles_t start, finish;
        int i;
        u32 seq_number = 0;
        __be32 saddr6[4] = { 1, 4, 182, 393 }, daddr6[4] = { 9192, 18288, 2222222, 0xffffff10 };
        __be32 saddr4 = 28888, daddr4 = 182112;
        __be16 sport = 22, dport = 41992;
        u32 tsoff;
        cycles_t result[4];

        printf("seq num benchmark\n");

        for (i = 0; i < 10; i++) {
                if ((i & 1) == 0)
                        clflush();

                start = get_cycles();
                seq_number += secure_tcpv6_sequence_number_md5(saddr6, daddr6, sport, dport, &tsoff);
                finish = get_cycles();
                result[0] = finish - start;

                start = get_cycles();
                seq_number += secure_tcp_sequence_number_md5(saddr4, daddr4, sport, dport, &tsoff);
                finish = get_cycles();
                result[1] = finish - start;

                start = get_cycles();
                seq_number += secure_tcpv6_sequence_number(saddr6, daddr6, sport, dport, &tsoff);
                finish = get_cycles();
                result[2] = finish - start;

                start = get_cycles();
                seq_number += secure_tcp_sequence_number(saddr4, daddr4, sport, dport, &tsoff);
                finish = get_cycles();
                result[3] = finish - start;

                printf("* Iteration %d results:\n", i);
                printf("secure_tcpv6_sequence_number_md5# cycles: %u\n", result[0]);
                printf("secure_tcp_sequence_number_md5# cycles: %u\n", result[1]);
                printf("secure_tcpv6_sequence_number_siphash# cycles: %u\n", result[2]);
                printf("secure_tcp_sequence_number_siphash# cycles: %u\n", result[3]);
                printf("benchmark result: %u\n", seq_number);
        }

        printf("benchmark result: %u\n", seq_number);
        return 0;
}
//device_initcall(benchmark);

int
main(void)
{
        memset(net_secret, 0xff, sizeof net_secret);
        memset(net_secret_md5, 0xff, sizeof net_secret_md5);
        return benchmark();

}

0 个答案:

没有答案