NOPFunction rename, added ualarm link, added rule of thumb for interval
This commit is contained in:
parent
54d3b00d54
commit
e214322fc3
19
README.md
19
README.md
@ -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.**
|
||||
|
||||
`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
|
||||
void function(void)
|
||||
void myStupidNOPFunction(void)
|
||||
{ asm volatile (
|
||||
"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.
|
||||
Die Funktionen `padding_before` und `padding_after` sind beide 64 Byte groß, also eine Cacheline.
|
||||
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:
|
||||
|
||||
```bash
|
||||
@ -107,13 +109,13 @@ gcc -O0 empfaenger.c lib.c -L. -lsharedlib -o empfaenger
|
||||
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
|
||||
# in e.g. sender.c
|
||||
maccess((void *) function)
|
||||
maccess((void *) myStupidNOPFunction)
|
||||
...
|
||||
```
|
||||
##### Tips
|
||||
@ -121,13 +123,13 @@ maccess((void *) function)
|
||||
- `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`.
|
||||
|
||||
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
|
||||
int main(void){
|
||||
...
|
||||
signal(SIGALRM, signal_handler);
|
||||
ualarm(sample_interval, sample_interval);
|
||||
ualarm(0, interval);
|
||||
```
|
||||
|
||||
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 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
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user