編譯錯誤 sync bool compare and swap 4的解決
阿新 • • 發佈:2019-01-13
做大檔案的快速傳輸,需要調查一下bit torrent,下載了opentracker。
在編譯libowfat的過程中,出現錯誤:
t.o: In function `main':
t.c:(.text+0x76): undefined reference to `__sync_bool_compare_and_swap_4'
t.c:(.text+0xa2): undefined reference to `__sync_bool_compare_and_swap_4'
collect2: ld returned 1 exit status
make: *** [t] Error 1
這個函式沒有找到定義,是在t.c中使用的函式。
往上看了幾行,發現丟擲這條錯誤的編譯命令是:
gcc -c t.c -pipe -W -Wall -O2 -fomit-frame-pointer -D_REENTRANT -I.
In file included from t.c:25:
iarray.h:5:2: warning: #warning DO NOT USE THIS YET. It may look thread-safe but it is not!
In file included from t.c:27:
CAS.h: In function ‘compare_and_swap’:
CAS.h:31: warning: no return statement in function returning non-void
CAS.h: In function ‘atomic_add_return’:
CAS.h:61: warning: no return statement in function returning non-void
t.c: In function ‘main’:
t.c:50: warning: unused parameter ‘argc’
t.c:50: warning: unused parameter ‘argv’
gcc -g -o t t.o libowfat.a `cat libsocket` -lpthread
開啟t.c看了一下,發現t.c程式碼很短,只有幾十行,引發錯誤的應該是這個函式呼叫:
printf("%u/n",compare_and_swap(&x,26,17));
printf("%u/n",compare_and_swap(&x,23,17));
用__sync_bool_compare_and_swap_4沒有找到原始碼,在原始碼中搜索了一下:
[[email protected] libowfat]$ grep sync_bool_compare_and_swap *
CAS.h: __sync_bool_compare_and_swap(x,oldval,newval);
Binary file t.o matches
發現它定義在CAS.h檔案中。
CAS.h檔案也非常短,相關的程式碼一下子就能看到:
#if defined(__INTEL_COMPILER) || (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1))
#define USE_BUILTINS
#endif
/* if (*x == oldval) { *x=newval; return 1; } else return 0; */
static inline int compare_and_swap(volatile size_t* x,size_t oldval,size_t newval) {
#ifdef USE_BUILTINS
__sync_bool_compare_and_swap(x,oldval,newval);
#elif defined(__i386__)
char result;
asm volatile ("lock; cmpxchgl %3, %0; setz %1" : "=m"(*x), "=q"(result) : "m" (*x), "r" (newval), "a" (oldval) : "memory");
return result;
#elif defined(__x86_64__)
char result;
asm volatile ("lock; cmpxchgq %3, %0; setz %1" : "=m"(*x), "=q"(result) : "m" (*x), "r" (newval), "a" (oldval) : "memory");
return result;
#else
#error architecture not supported and gcc too old, edit CAS.h
#endif
}
很顯然因為定義了USE_BUILTINS巨集,所以compare_and_swap呼叫的是__sync_bool_compare_and_swap(x,oldval,newval);
把這個巨集去掉,換成__i386__,應該就沒問題了,看一下CAS.h被哪些原始檔引用過。
[
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
CAS.h:#error architecture not supported and gcc too old, edit CAS.h
GNUmakefile: havesigio.h CAS.h
Makefile: iarray.h CAS.h io_internal.h haveepoll.h havekqueue.h havedevpoll.h /
Makefile: havesigio.h CAS.h
t.c:#include "CAS.h"
非常幸運,只有t.c一個檔案引用了這個檔案。所以,可以大膽地修改CAS.h:
static inline int compare_and_swap(volatile size_t* x,size_t oldval,size_t newval) {
#undef USE_BUILTINS
#ifndef __i386__
#define __i386__
#define jcwkyl
#endif
#ifdef USE_BUILTINS
__sync_bool_compare_and_swap(x,oldval,newval);
#elif defined(__i386__)
char result;
asm volatile ("lock; cmpxchgl %3, %0; setz %1" : "=m"(*x), "=q"(result) : "m" (*x), "r" (newval), "a" (oldval) : "memory");
#ifdef jcwkyl
#undef __i386__
#endif
#define USE_BUILTINS
return result;
#elif defined(__x86_64__)
char result;
asm volatile ("lock; cmpxchgq %3, %0; setz %1" : "=m"(*x), "=q"(result) : "m" (*x), "r" (newval), "a" (oldval) : "memory");
return result;
#else
#error architecture not supported and gcc too old, edit CAS.h
#endif
}
高亮部分是新增加的程式碼。這次make沒有出錯了。
隨後opentracker也順利make成功。
google一下,會找到這個錯誤的原因和解決方法,解決方法就是給gcc傳遞-march=i486引數。可參考:
http://stackoverflow.com/questions/2118992/how-do-i-use-gcc-builtin-sync-bool-compare-and-swap-in-g-on-macosx
http://bugs.gentoo.org/show_bug.cgi?id=199904
http://dev.ryzom.com/issues/899
http://www.linuxquestions.org/questions/linux-from-scratch-13/glibc-1st-pass-wont-compile-possibly-i486-related-704580/
...
使用opentracker用bitorrent下載一個檔案:
[[email protected] opentracker]# ./opentracker
用ctorrent製作一個torrent檔案:
[[email protected] Desktop]$ ctorrent -t -u http://10.60.56.90:6969/announce -s test.torrent 10.1.1.14.5976.pdf
Create hash table: 1/1
Create metainfo file test.torrent successful.
[[email protected] Desktop]$ ctorrent -x test.torrent
META INFO
Announce: http://10.60.56.90:6969/announce
Created On: Wed Dec 15 19:32:21 2010
Piece length: 262144
Created with: Enhanced-CTorrent/dnh3.3.2
FILES INFO
<1> 10.1.1.14.5976.pdf [90160]
Total: 0 MB
把這個torrent檔案用ftp下載到一個client端。然後在那個client端下載:
[[email protected] ~]# ctorrent test.torrent
META INFO
Announce: http://10.60.56.90:6969/announce
Created On: Wed Dec 15 19:32:21 2010
Piece length: 262144
Created with: Enhanced-CTorrent/dnh3.3.2
FILES INFO
<1> 10.1.1.14.5976.pdf [90160]
Total: 0 MB
Creating file "10.1.1.14.5976.pdf"
Listening on 0.0.0.0:2706
Press 'h' or '?' for help (display/control client options).
|0/0/1 [0/1/0] 0MB,0MB | 0,0K/s | 0,0KE:0,1
Download complete.
Total time used: 0 minutes.
Seed for others 72 hours
- 0/0/2 [1/1/1] 0MB,0MB | 0,0K/s | 0,0K E:0,3 Connecting
同時在原來的機器上做種:
[[email protected] Desktop]$ ctorrent test.torrent
META INFO
Announce: http://10.60.56.90:6969/announce
Created On: Wed Dec 15 19:32:21 2010
Piece length: 262144
Created with: Enhanced-CTorrent/dnh3.3.2
FILES INFO
<1> 10.1.1.14.5976.pdf [90160]
Total: 0 MB
warn, couldn't set bit field refer file "test.torrent.bf": No such file or directory
This is normal if you are seeding.
Listening on 0.0.0.0:2706
Press 'h' or '?' for help (display/control client options).
Checking completed.
FILES INFO
<1> 10.1.1.14.5976.pdf [90160] 1/1 (100%)
Total: 0 MB
-0/0/1 [1/1/1] 0MB,0MB | 0,0K/s | 0,0K E:0,0Connecting
Seed for others 72 hours
檔案下載成功。
開啟瀏覽器,輸入:
http://10.60.56.90:6969/stats?mode=everything
會檢視到所有torrent檔案,以及上傳下載資訊。
再分享一下我老師大神的人工智慧教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智慧的隊伍中來!https://blog.csdn.net/jiangjunshow