Normalne zmienne globalne nie są na procesor. Zmienne automatyczne są na stosie, a różne procesory używają innego stosu, więc naturalnie otrzymują oddzielne zmienne.
Przypuszczam, że odnosisz się do infrastruktury zmiennych na procesor Linuxa.
Większość magii jest tutaj (asm-generic/percpu.h
):
extern unsigned long __per_cpu_offset[NR_CPUS];
#define per_cpu_offset(x) (__per_cpu_offset[x])
/* Separate out the type, so (int[3], foo) works. */
#define DEFINE_PER_CPU(type, name) \
__attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
/* var is in discarded region: offset to particular copy we want */
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
#define __get_cpu_var(var) per_cpu(var, smp_processor_id())
Makro RELOC_HIDE(ptr, offset)
prostu przesuwa ptr
przez daną przesunięcie w bajtach (niezależnie od rodzaju wskaźnika).
Co robi?
- Definiując
DEFINE_PER_CPU(int, x)
oznacza liczbę całkowitą __per_cpu_x
tworzony jest w specjalnej sekcji .data.percpu
.
- Po załadowaniu jądra ta sekcja jest ładowana wiele razy - raz na procesor (ta część magii nie znajduje się w powyższym kodzie).
- Tablica
__per_cpu_offset
jest wypełniona odległościami między kopiami. Zakładając użycie 1000 bajtów danych na procesor, __per_cpu_offset[n]
będzie zawierać 1000*n
.
- Symbol
per_cpu__x
zostanie przeniesiony, podczas ładowania, do CPU 0's per_cpu__x
.
__get_cpu_var(x)
, po uruchomieniu na procesorze 3, przetłumaczy się na *RELOC_HIDE(&per_cpu__x, __per_cpu_offset[3])
. Zaczyna się to od CPU 0: x
, dodaje przesunięcie pomiędzy danymi procesora 0 i CPU 3, a ostatecznie usuwa wynikowy wskaźnik.
Dziękuję za Twój ansser, ale wciąż mam pytania, nowe do smp, więc bez obrazy dla twojego pomysłu. Po pierwsze, pomyślałem, że ten sam proces powinien mieć ten sam stos, tutaj jest definicja wątku w POSIX "... a zmienne automatyczne, są dostępne dla wszystkich wątków w tym samym procesie.". Zmienna automatyczna jest współdzielona przez wątki. Różne procesory mogą mieć inny rejestr segmentu stosu, ale zawartość powinna być taka sama. Po drugie, czy możemy powiedzieć, że możemy uzyskać dostęp do innej zmiennej procesora, jeśli chcemy, po prostu wycofać offset uzyskany przez percpu? – dspjm
Gdy dwa wątki wywołują funkcję 'foo', która ma automatyczną zmienną' x', istnieją dwa stosy i dwa wystąpienia 'x'. Każdy ma inny adres, a oba wątki mogą uzyskać dostęp do obu, jeśli mają adres. W przypadku zmiennych per-cpu Linuksa 'per_cpu (var, cpu)' umożliwia dostęp do zmiennych cpu. – ugoren
W jaki sposób sekcja .data.percpu określa, czy zmienna percpu jest zadeklarowana na stosie lub sterty? – user31986