programing

x86, arm, GCC 및 icc에서 작동하는 Linux에서 원자적인 작업을 수행하는 방법은 무엇입니까?

coolbiz 2022. 10. 5. 23:07
반응형

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년 이후)은 현재 원자 연산을 규정하고 있다.

단, 플랫폼 또는 컴파일러는 이러한 새로운 헤더 및 기능을 지원하지 않을 수 있습니다.

젠장, 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

반응형