Hallo,
Ik heb problemen met het compileren van:
__sync_bool_compare_and_swap(); voor ARMv7-a (Cortex A8).
Om te kijken waar het probleem zit heb ik eerst een simpele applicatie gemaakt om te kijken of ik daarmee het probleem kan vinden.
-> Hieronder volgt de code van dit programma inclusief makefile. Deze werkt en cross compileert ook voor ARM.
-> Vervolgens de situatie waarin het niet werkt.
Werkende situatie:
Test applicatie:
Makefile:
Code van de "LockFree.h" welke ik uit een intern ontwikkelde library gebruik:
Dit bovenstaande voorbeeld compileert prima voor zowel de x86 als ARMv7-a.
Niet werkende situatie::
Het probleem is echter wanneer ik deze CAS functie toepas in een lock-free queue. Om deze generiek te maken voor verschillende datatypes maak ik gebruik van templates. Hiervoor is een structure gedefinieerd die de pointers naar de nodes in de queue bijhoud:
En de node:
De compare and swap pas ik hierbij toe op de pointer_t structures:
Voor x86 compileert dit prima, echter wanneer ik dit voor ARMv7-a compileer, laat hij de compare and swap naar
Dit levert op dat hij de referenties naar deze functie niet kan vinden:
Gezien de arm architecture 32 bits is, heb ik ook het vermoeden dat een 8 bytes CAS niet bestaat. De vraag hierbij dus:
-> Waarom wordt deze CAS naar een LONG data type gemapped.
-> Is er een methode om hem te forceren naar een _4 variant (__sync_bool_compare_and_swap_4() hardcoden heb ik al geprobeerd, dan compileert hij wel, maar gaat het bij de executie fout).
Ik heb problemen met het compileren van:
__sync_bool_compare_and_swap(); voor ARMv7-a (Cortex A8).
Om te kijken waar het probleem zit heb ik eerst een simpele applicatie gemaakt om te kijken of ik daarmee het probleem kan vinden.
-> Hieronder volgt de code van dit programma inclusief makefile. Deze werkt en cross compileert ook voor ARM.
-> Vervolgens de situatie waarin het niet werkt.
Werkende situatie:
Test applicatie:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| #include <stdlib.h>
#include <stdio.h>
#include "utility/LockFree.h"
int main(int argc, char* argv[])
{
long target = 3;
// Simple compare and swap scenario test:
// Read value to temp, generate update value, perform a compare and swap.
int temp = target;
int newVal = 8;
printf("Current target value: %li\n", target);
if (LUNA::Utility::CAS(&target, temp, newVal))
{
printf("Successfull compare and swap: %li\n", target);
}
else
{
printf("Unsuccessfull compare and swap: %li\n", target);
}
return 0;
} |
Makefile:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| SOURCE_DIR=.
BUILD_DIR=build
LUNA_ROOT_DIR=/home/janjaap/workspace-cpp/LUNA/LUNA
SOURCE_FILES=$(SOURCE_DIR)/test.cpp
OBJECT_FILES=$(patsubst %.cpp,%.o,$(SOURCE_FILES))
ifeq ($(target),ARM)
CROSS_COMPILE=arm-linux-gnueabi-
LUNA_INCLUDE_DIR=$(LUNA_ROOT_DIR)/build_dir/target-arm-linux_v7-a/root-linux-arm-v7/include
LUNA_LINK_DIR=$(LUNA_ROOT_DIR)/build_dir/luna/target-arm-linux_v7-a
else
CROSS_COMPILE=
LUNA_INCLUDE_DIR=$(LUNA_ROOT_DIR)/staging_dir/target-i386-linux/include
LUNA_LINK_DIR=$(LUNA_ROOT_DIR)/build_dir/luna/target-i386-linux
endif
LDFLAGS=-L$(LUNA_LINK_DIR)
CPPFLAGS=-I$(LUNA_INCLUDE_DIR) -Wall
LIBS=-lLUNA -pthread -lrt
CC=$(CROSS_COMPILE)g++
LD=$(CROSS_COMPILE)g++
RM=rm -f
all: test
test: $(OBJECT_FILES)
$(LD) $(LDFLAGS) $^ $(LIBS) -o $@
.cpp.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
clean:
$(RM) $(OBJECT_FILES) test |
Code van de "LockFree.h" welke ik uit een intern ontwikkelde library gebruik:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| #pragma once
#include "utility/LUNATypes.h"
#include <stdlib.h>
namespace LUNA
{
namespace Utility
{
template<typename PTRType, typename DataType>
inline bool CAS(PTRType *ptr, DataType prev, DataType update)
{
return __sync_bool_compare_and_swap(ptr, prev, update);
}
}
} |
Dit bovenstaande voorbeeld compileert prima voor zowel de x86 als ARMv7-a.
Niet werkende situatie::
Het probleem is echter wanneer ik deze CAS functie toepas in een lock-free queue. Om deze generiek te maken voor verschillende datatypes maak ik gebruik van templates. Hiervoor is een structure gedefinieerd die de pointers naar de nodes in de queue bijhoud:
code:
1
2
3
4
5
6
7
| template<typename ItemType>
union pointer_t
{
DWORD dword;
WORD words[2];
struct node_t<ItemType>* ptrs[2];
}; |
En de node:
code:
1
2
3
4
5
6
| template<typename ItemType>
struct node_t
{
volatile pointer_t<ItemType> next;
ItemType value;
}; |
De compare and swap pas ik hierbij toe op de pointer_t structures:
code:
1
| if (LUNA::Utility::CAS(&(nextPtr->dword), next.dword, make_tuple(relPtr, next.words[COUNT] + 1).dword)) |
Voor x86 compileert dit prima, echter wanneer ik dit voor ARMv7-a compileer, laat hij de compare and swap naar
code:
verwijzen.1
| __sync_bool_compare_and_swap_8 |
Dit levert op dat hij de referenties naar deze functie niet kan vinden:
code:
1
2
3
| >(unsigned long long volatile*, unsigned long long, unsigned long long)]+0x30): undefined reference to `__sync_bool_compare_and_swap_8' build/target-arm-linux_v7-a/obj/sharedMemTest.o: In function `bool LUNA::Utility::CAS<unsigned long long, unsigned long long>(unsigned long long*, unsigned long long, unsigned long long)': sharedMemTest.cpp:(.text._ZN4LUNA7Utility3CASIyyEEbPT_T0_S4_[bool LUNA::Utility::CAS<unsigned long long, unsigned long long>(unsigned long long*, unsigned long long, unsigned long long)]+0x30): undefined reference to `__sync_bool_compare_and_swap_8' |
Gezien de arm architecture 32 bits is, heb ik ook het vermoeden dat een 8 bytes CAS niet bestaat. De vraag hierbij dus:
-> Waarom wordt deze CAS naar een LONG data type gemapped.
-> Is er een methode om hem te forceren naar een _4 variant (__sync_bool_compare_and_swap_4() hardcoden heb ik al geprobeerd, dan compileert hij wel, maar gaat het bij de executie fout).