NOPFunction rename, added ualarm link, added rule of thumb for interval

This commit is contained in:
Lenni Hein 2025-02-25 16:25:01 +01:00
parent 54d3b00d54
commit e214322fc3

View File

@ -71,10 +71,10 @@ Muster: `./src/cache_test.c`
**Jetzt können wir den Cache doch mal als Medium verwenden. Der Sender kann `0` und `1` über den (ausbleibenden) Speicherzugriff kodieren. Der Empfänger interpretiert dann, je nach Zugriffszeit.** **Jetzt können wir den Cache doch mal als Medium verwenden. Der Sender kann `0` und `1` über den (ausbleibenden) Speicherzugriff kodieren. Der Empfänger interpretiert dann, je nach Zugriffszeit.**
`sharedlib.c` sieht so aus: Um zu kommunizieren, müssen sich Sender und Empfänger auf eine physische Adresse einigen, die für Flush+Reload verwendet wird. Dafür nehmen wir am besten eine shared library, die ist schon als `sharedlib.c` bereitgestellt:
```C ```C
void function(void) void myStupidNOPFunction(void)
{ asm volatile ( { asm volatile (
"nop\n\t" "nop\n\t"
"nop\n\t" "nop\n\t"
@ -90,11 +90,13 @@ void function(void)
... ...
``` ```
Die Adresse von `function` kann also zum Flushen und Reloaded verwendet werden. Die Adresse von `myStupidNOPFunction` kann also zum Flushen und Reloaded verwendet werden.
Da immer eine gesamte Cacheline geladen wird, sollte sich nichts anderes in dem selben 64Byte Block befinden. Da immer eine gesamte Cacheline geladen wird, sollte sich nichts anderes in dem selben 64Byte Block befinden.
Die Funktionen `padding_before` und `padding_after` sind beide 64 Byte groß, also eine Cacheline. Die Funktionen `padding_before` und `padding_after` sind beide 64 Byte groß, also eine Cacheline.
Damit kann dann auch gar nichts mehr schief gehen :) Damit kann dann auch gar nichts mehr schief gehen :)
*`MyStupidNOPFunction` ist übrigens genau $256*64\ Byte$ groß. Das wird vielleicht ja noch praktisch ;)*
`sharedlib.c` kann man so kompilieren und linken: `sharedlib.c` kann man so kompilieren und linken:
```bash ```bash
@ -107,13 +109,13 @@ gcc -O0 empfaenger.c lib.c -L. -lsharedlib -o empfaenger
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
``` ```
*(oder einfach `cmake` verwenden)* *(oder einfach `cmake` verwenden :P)*
dann kann man `function` verwenden: dann kann man `function` benutzen:
```C ```C
# in e.g. sender.c # in e.g. sender.c
maccess((void *) function) maccess((void *) myStupidNOPFunction)
... ...
``` ```
##### Tips ##### Tips
@ -121,13 +123,13 @@ maccess((void *) function)
- `taskset` zum kann pinnen der Programme auf einen bestimmten CPU-Kern benutzt werden. Das kann helfen. - `taskset` zum kann pinnen der Programme auf einen bestimmten CPU-Kern benutzt werden. Das kann helfen.
- Verwendet man blockierenden Sleep um zu Takten, z.B. `clock_nanosleep`, dann sollte man unbedingt darauf achten nicht eine Periodendauer zu schlafen, sondern nur bis zum nächsten Zeitabschnitt. Einfacher geht es mit nicht-blockierendem Sleep, z.B. `ualarm`. - Verwendet man blockierenden Sleep um zu Takten, z.B. `clock_nanosleep`, dann sollte man unbedingt darauf achten nicht eine Periodendauer zu schlafen, sondern nur bis zum nächsten Zeitabschnitt. Einfacher geht es mit nicht-blockierendem Sleep, z.B. `ualarm`.
So kann man `ualarm` nutzen, um alle x µs einen `SIGARLM` auszulösen: So kann man `ualarm` [Linux Manual](https://man7.org/linux/man-pages/man3/ualarm.3.html) nutzen, um alle x µs einen `SIGARLM` auszulösen:
```C ```C
int main(void){ int main(void){
... ...
signal(SIGALRM, signal_handler); signal(SIGALRM, signal_handler);
ualarm(sample_interval, sample_interval); ualarm(0, interval);
``` ```
Bei jedem `SIGALRM` Signal wird `signal_handler` ausgeführt: Bei jedem `SIGALRM` Signal wird `signal_handler` ausgeführt:
@ -142,6 +144,7 @@ void signal_handler(int signo) {
- Der Zeitabstand von Flush zu Reload sollte MAXIMIERT werden! Dies ist das Zeitfenster, in welchem der Sender die Adresse(n) zurück in den Cache laden kann. - Der Zeitabstand von Flush zu Reload sollte MAXIMIERT werden! Dies ist das Zeitfenster, in welchem der Sender die Adresse(n) zurück in den Cache laden kann.
- Der Sender kann nicht nur einmal Laden. Das kann man auch mehrfach in einem Zeitfenster machen, um sicher zu gehen, dass die Cacheline auch geladen ist, wenn der Empfänger ausließt. - Der Sender kann nicht nur einmal Laden. Das kann man auch mehrfach in einem Zeitfenster machen, um sicher zu gehen, dass die Cacheline auch geladen ist, wenn der Empfänger ausließt.
- **Richtwert**: 1000µs pro Zyklus haben sich als ganz gut erwiesen (→ 1kHz). Ein zu kurzes Zeitfenster lässt nicht genug Zeit um alle Instruktionen abzuarbeiten, ein zu langes führt zu mehr Noise, falls die Cacheline zwischenzeitlich aus dem Cache verdrängt wird.
### Block 3: Einen String über den Cache als Medium senden ### Block 3: Einen String über den Cache als Medium senden