[英]Why does the page fault not cause the thread to finish its execution later?
我有下面的代碼,我故意在file.c
中的一個線程中創建頁面錯誤
util.c
#include "util.h"
// to use as a fence() instruction
extern inline __attribute__((always_inline))
CYCLES rdtscp(void) {
CYCLES cycles;
asm volatile ("rdtscp" : "=a" (cycles));
return cycles;
}
// initialize address
void init_ram_address(char* FILE_NAME){
char *filename = FILE_NAME;
int fd = open(filename, O_RDWR);
if(fd == -1) {
printf("Could not open file .\n");
exit(0);
}
void *file_address = mmap(NULL, DEFAULT_FILE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, 0);
ram_address = (int *) file_address;
}
// initialize address
void init_disk_address(char* FILE_NAME){
char *filename = FILE_NAME;
int fd = open(filename, O_RDWR);
if(fd == -1) {
printf("Could not open file .\n");
exit(0);
}
void *file_address = mmap(NULL, DEFAULT_FILE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
disk_address = (int *) file_address;
}
file.c
#include "util.h"
void *f1();
void *f2();
pthread_barrier_t barrier;
pthread_mutex_t mutex;
int main(int argc, char **argv)
{
pthread_t t1, t2;
// in ram
init_ram_address(RAM_FILE_NAME);
// in disk
init_disk_address(DISK_FILE_NAME);
pthread_create(&t1, NULL, &f1, NULL);
pthread_create(&t2, NULL, &f2, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}
void *f1()
{
rdtscp();
int load = *(ram_address);
rdtscp();
printf("Expecting this to be run first.\n");
}
void *f2()
{
rdtscp();
int load = *(disk_address);
rdtscp();
printf("Expecting this to be run second.\n");
}
我在上面的代碼中使用rdtscp()
來進行隔離(以確保僅在加載操作完成后才執行打印語句)。
由於t2
將導致頁面錯誤,我希望t1
先完成其打印語句的執行。
為了在同一個內核上運行兩個線程,我運行taskset -c 10./file
。
我看到t2
在t1
之前打印它的語句。 這可能是什么原因?
我認為您期望t2
的int load = *(disk_address);
導致上下文切換到t1
,並且由於您將所有內容都固定到同一個 CPU 內核,這將使t1
有時間贏得爭奪stdout
的鎖定。
軟頁面錯誤不需要上下文切換,只需使用頁面緩存中的文件頁面更新頁表。 盡管映射由磁盤文件支持,而不是匿名 memory 或只是寫時復制技巧,但如果該文件最近已被讀取或寫入,它將在頁面緩存中很熱並且不需要 I/O(這將使硬頁錯誤)。
也許在測試運行之前嘗試驅逐磁盤緩存,比如使用echo 3 | sudo tee /proc/sys/vm/drop_caches
echo 3 | sudo tee /proc/sys/vm/drop_caches
如果這是 Linux,那么在沒有MAP_POPULATE
的情況下訪問 mmap 區域將是一個硬頁面錯誤(需要 I/O)。
(請參閱 * https://unix.stackexchange.com/questions/17936/setting-proc-sys-vm-drop-caches-to-clear-cache*;如果是最近sync
的話,至少在磁盤文件上同步寫的,以確保它的頁面是干凈的並且能夠被驅逐,也就是丟棄。)
您沒有顯示ram_address
或disk_address
的聲明。 如果它不是volatile int *disk_address
之類的指向volatile
的指針,則可以在編譯時優化負載。 對像int load
這樣的非轉義本地變量的寫入不必尊重"memory"
破壞者,因為沒有其他東西可以引用它們。
如果您在沒有優化或其他東西的情況下進行編譯,那么即使沒有volatile
,負載仍然會發生。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.