x86, arm, GCC 및 icc에서 작동하는 Linux에서 원자적인 작업을 수행하는 방법은 무엇입니까?
모든 최신 OS는 오늘날 다음과 같은 원자적인 조작을 제공합니다.
- 에 、
Interlocked*
- 에는 FreeB가 있습니다.SD★★★
<machine/atomic.h>
- 에는 Solaris가 .
<atomic.h>
- 에는 Mac OS X가 탑재되어 있습니다.
<libkern/OSAtomic.h>
Linux에도 비슷한 게 있나요?
- x86, x86_64, arm 등 Linux 지원 플랫폼 대부분에서 동작해야 합니다.
- 적어도 GCC와 인텔 컴파일러에서 동작하려면 이 파일이 필요합니다.
- glib이나 qt와 같은 3rd par 라이브러리를 사용할 필요가 없습니다.
- C++로 동작하려면 필요합니다(C는 필요 없습니다).
문제:
- 빌트인 GCC
__sync_*
는 모든 플랫폼(ARM)에서 지원되지 않으며 인텔 컴파일러에서도 지원되지 않습니다. - AFAIK
<asm/atomic.h>
사용자 공간에서 사용해서는 안 되고 전혀 사용하지도 못했습니다.컴파일러에서도 할 수 잘 모르겠습니다.
좋은 의견이라도 있나?
이 많이 건, 그 중 몇하고 있습니다.__sync*
과 (ARM)의 어느 는 실현 .asm/atomic.h
.
GCC(ICC는 gcc 어셈블리를 지원)를 위해 이를 수행하는 인라인 어셈블리 라이브러리가 있을 수 있습니다.
편집:
add 조작 전용의 극히 부분적인 솔루션이 있습니다(아토믹카운터를 실장할 수 있지만, CAS 를 필요로 하는 락 프리 구조는 실장할 수 없습니다).
「 」를 사용하고 libstc++
( 사용libstdc++
)을 사용하면, 「」를 사용할 수 .__gnu_cxx::__exchange_and_add
되어 있는 것<ext/atomicity.h>
★★★★★★★★★★★★★★★★★」<bits/atomicity.h>
버전에 따라 컴파일러 버전에 따라 다릅니다.
다만, CAS를 서포트하고 있는 것을 보고 싶습니다.
프로젝트에서는 다음을 사용하고 있습니다.
http://packages.debian.org/source/sid/libatomic-ops
CAS 등의 간단한 조작을 원한다면 커널에서 arch 고유의 실장을 사용하고 autotools/cmake를 사용하여 user-space에서 arch 체크를 하면 되지 않을까요?라이선스에 관한 한 커널은 GPL이지만 이러한 작업을 위한 인라인 어셈블리가 인텔/AMD에 의해 제공되는 것이지 커널에 라이선스가 있는 것은 아니라고 생각합니다.커널 소스에서 쉽게 접근할 수 있는 형태로 되어 있을 뿐입니다.
C&C++의 최신 표준(2011년 이후)은 현재 원자 연산을 규정하고 있다.
- C11:
stdatomic.h
- C++11:
std::atomic
단, 플랫폼 또는 컴파일러는 이러한 새로운 헤더 및 기능을 지원하지 않을 수 있습니다.
젠장, GCC 원형을 제안하려고 했는데, 네가 금지라고 했잖아. :-)
저는 '하다', '하다', '하다', '하다', '하다', '하다', '하다', '하다', '하다', '하다', '하다', '', '하다', '하다', '하다', '하다', '하다', '하다',#ifdef
인라인 asm에 관심을 가지고 코드업 하는 아키텍처/패키지 조합별로 대응합니다. 아마 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★__GNUC__
수 합니다. GCC는 GCC를 더 생각하기 에 GCC의 프리미티브를 사용할 수 있습니다.이것들을 사용하는 것이 훨씬 더 적절하다고 생각되기 때문입니다. :-)
중복되는 부분이 많아 정확성을 검증하는 것은 어려울 수 있지만, 많은 프로젝트에서 이렇게 하고 있는 것 같아서 좋은 결과를 얻었습니다.
는 GCC를잊지 asm volatile
는 "크러버"로 되어 있습니다."memory"
★★★★★★★★★★★★★★★★★」"cc"
등등.
Boost(침입적이지 않은 라이선스를 가진 Boost) 및 기타 프레임워크는 타깃 플랫폼에서 지원되는 한 이미 휴대용 원자 카운터를 제공합니다.
서드파티 라이브러리는 우리에게 좋다.또, 회사에서 이상한 이유로 사용을 금지하고 있는 경우에서도, (라이선스에 의해서 사용이 허가되고 있는 한) 원하는 것을 실장하는 방법을 확인할 수 있습니다.
나는 최근에 그런 것을 시행했고 당신과 같은 어려움에 직면했다.저의 솔루션은 기본적으로 다음과 같습니다.
- 기능 매크로를 사용하여 gcc 빌트인을 검출하려고 합니다.
- , '어울리지 마세요', '어울리지 마세요', '어울리지 마세요' 같은 하세요.
cmpxch
__asm__
(ARM) 한 하세요.sizeof(int)
. - 합니다.
inline
여기에서는 ARM 원자 동작을 지원하기 위한 GCC용 패치가 있습니다.인텔에서는 도움이 되지 않지만 코드를 조사할 수 있습니다.구식 ARM 아키텍처에 대한 최신 커널 지원이 있습니다.새로운 아키텍처에는 명령어가 포함되어 있기 때문에 동작하는 것을 구축할 수 있습니다.
http://gcc.gnu.org/ml/gcc-patches/2011-07/msg00050.html
__sync*
GCC가 인텔 컴파일러에서 이러한 빌트인을 채택했기 때문에 인텔 컴파일러에서 확실히 지원되고 있습니다.이 페이지의 첫 번째 단락을 읽으세요.또, 인텔®C++ 컴파일러 Linux*판 내장 레퍼런스(198 페이지)도 참조해 주세요.2006년에 나온 것으로, 빌트인이라고 하는 것이 기재되어 있습니다.
ARM의 서포트에 대해서입니다만, 낡은 ARM CPU의 경우, 유저 스페이스에서는 할 수 없지만, 커널 스페이스에서는 할 수 있습니다(동작중의 인터럽트를 무효로 하는 것으로), 지금까지 서포트되고 있다고 하는 것을 어딘가에서 읽은 적이 있습니다.
2011-10-08년도의 이 PHP 버그에 따르면__sync_*
에만 실패하다
- Linux 이외의 것을 사용하는 PA-RISC
- SPARCv7 이하
- GCC 포함 ARM 4.3 미만
- ARMv5 이하(Linux 이외 사용시)
- MIPS1
따라서 GCC > 4.3(및 현재 4.7)에서는 ARMv6 이후로는 문제가 없습니다.Linux용 컴파일만 하면 ARMv5에 문제가 없습니다.
Debian/Ubuntu 추천으로...
sudo apt-get install libatomic-ops-dev
예: http://www.hpl.hp.com/research/linux/atomic_ops/example.php4
GCC 및 ICC 호환
인텔 스레드 빌딩 블록(TBB)과 비교하여 atomic< T >를 사용하면 libatomic-ops-dev는 2배 이상 빨라집니다.(인텔 컴파일러)
Ubuntu i7 생산자/소비자 스레드에서의 테스트(TBB의 경우 1.2초에 비해 0.5초에 링 버퍼 접속에 1000만 int를 배관)
또, 사용하기 쉽다.
휘발성 AO_t 헤드;
AO_fetch_and_add1(&head);
자세한 내용은 kernel_user_helpers를 참조하십시오.txt 또는 entry-arm.c를 검색하여__kuser_cmpxchg
다른 ARM Linux 버전의 코멘트에서 볼 수 있듯이
kuser_cmpxchg
위치: 0xffff0fc0 레퍼런스 프로토타입: int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr); 입력: r0 = oldvalr1 = newvalr2 = ptrlr = 반송 주소 출력: r0 = 성공 코드(0 또는 0 이외)C 플래그 = r0 == 0이면 설정, r0 != 0이면 삭제 클로버 레지스터: r3, ip, 플래그 정의: *ptr이 oldval과 동일한 경우에만 newval을 *ptr에 아토믹하게 저장합니다. *ptr이 변경된 경우 0을 반환하고, 교환이 이루어지지 않은 경우 0이 아닌 값을 반환합니다. *ptr이 조립을 허용하도록 변경된 경우에도 C 플래그가 설정됩니다.콜 코드의 최적화. 사용 예:
typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
int atomic_add(volatile int *ptr, int val)
{
int old, new;
do {
old = *ptr;
new = old + val;
} while(__kuser_cmpxchg(old, new, ptr));
return new;
}
주의:
- 이 루틴에는 이미 필요에 따라 메모리 장벽이 포함되어 있습니다.
- __kuser_syslog_version >= 2(커널 버전 2.6.12부터)인 경우에만 유효합니다.
이것은 Linux with ARMv3에서 사용하는 것으로,swp
원시적인이를 지원하지 않으려면 매우 오래된 ARM이 있어야 합니다.데이터 중단 또는 인터럽트만이 스핀을 실패시킬 수 있으므로 커널은 이 주소 ~0xffff0fc0을 모니터링하여 사용자 공간을 수행합니다. PC
데이터 중단 또는 인터럽트가 발생했을 때 수정됩니다.ARMv5 이하를 지원하는 모든 사용자 공간 라이브러리가 이 기능을 사용합니다.
예를 들어 QtConcurrent는 이를 사용합니다.
언급URL : https://stackoverflow.com/questions/2287451/how-to-perform-atomic-operations-on-linux-that-work-on-x86-arm-gcc-and-icc
'programing' 카테고리의 다른 글
jQuery를 사용하여 쿠키를 설정/해제하려면 어떻게 해야 합니까? (0) | 2022.10.05 |
---|---|
MySQL IN 조건 제한 (0) | 2022.10.05 |
마리아 삭제 방법다중 소스 복제를 위해 DB가 지정한 Connection_name (0) | 2022.10.05 |
MySQL을 사용하여 뉴스 테이블에서 지난 6개월을 선택하는 방법 (0) | 2022.10.05 |
MySQL Sum() 여러 열 (0) | 2022.10.05 |