Skip to content

[DRAFT] Add interrupt handling #878

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 39 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
3e38acf
Initial commit
hernan-poncedeleon Sep 29, 2023
3ff12e7
Some tests
hernan-poncedeleon Sep 29, 2023
a1b4054
Use fences instead of GenericVisibleEvent
hernan-poncedeleon Sep 29, 2023
d2a0b71
Tag thread create and start events
hernan-poncedeleon Sep 29, 2023
779cd35
Add test cases
hernan-poncedeleon Sep 29, 2023
e3db364
Add harmless racy access annotation
hernan-poncedeleon Sep 29, 2023
4b48618
Merge branch 'refs/heads/development' into mergeBranch
ThomasHaas Mar 21, 2025
d7a97e2
added interrupts models and fixed tests
ThomasHaas Mar 21, 2025
aac60ec
Changed assert to __VERIFIER_assert in vmm interrupts test (not yet i…
ThomasHaas Mar 25, 2025
35f58f7
Updated remaining interrupt tests (mainly LKMM) to use __VERIFIER_assert
ThomasHaas Mar 26, 2025
c63350e
Added new interrupts cat models that use explicit interrupt points (WIP)
ThomasHaas Mar 26, 2025
e90aeb5
Added CallEvent interface
ThomasHaas Mar 31, 2025
47c48ce
- Added DynamicThreadCreate (pthread_create compiles to this one)
ThomasHaas Apr 1, 2025
744fb33
Added DynamicThreadJoin (pthread_join compiles to this).
ThomasHaas Apr 1, 2025
ed794a1
Added UniqueIdGenerator to generalize Function.dummyCount.
ThomasHaas Apr 1, 2025
f4156a0
Added ThreadReturn event (pthread_exit and top-level returns compiled…
ThomasHaas Apr 1, 2025
8583041
- Fixed encoding of AggregateType and ArrayType variables
ThomasHaas Apr 1, 2025
abd149b
Cleanup
ThomasHaas Apr 2, 2025
5e74cfc
Fixed errors
ThomasHaas Apr 2, 2025
2cb7c87
Fix error in NaiveDevirtualisation
ThomasHaas Apr 2, 2025
4020b3e
Merge branch 'refs/heads/better_threading' into interrupt_wip
ThomasHaas Apr 3, 2025
5167df7
Added Thread.Type
ThomasHaas Apr 3, 2025
54c17ca
Connect IH control-flow to IT control-flow.
ThomasHaas Apr 3, 2025
b87e32d
Update interrupts-defs.cat to handle nested IHs
ThomasHaas Apr 3, 2025
e071de3
Add new Termination tests for interrupts
ThomasHaas Apr 3, 2025
0a3a912
Add missing InterruptAnalysis class
ThomasHaas Apr 3, 2025
bb167b3
WIP: Visible non-termination events
ThomasHaas Apr 9, 2025
9f845a4
WIP: Added new interrupt models that handle multiple IHs per thread
ThomasHaas Apr 11, 2025
958aacc
Better interrupt models + new test benchmarks (no unit tests yet)
ThomasHaas Apr 14, 2025
f73edcf
Merge branch 'refs/heads/development' into merge
ThomasHaas Apr 14, 2025
678a0b1
Fixup after Merge
ThomasHaas Apr 14, 2025
174096b
Better handling of control flow of different IHs of the same thread
ThomasHaas Apr 14, 2025
54b1617
Merge branch 'refs/heads/development' into merge
ThomasHaas May 8, 2025
2c297f4
Fixup
ThomasHaas May 8, 2025
c6cfded
Remove outdated benchmarks
ThomasHaas May 8, 2025
21a2799
Remove Fence-tag from Nontermination marker
ThomasHaas May 8, 2025
adb1907
Added comments about expected results of interrupt tests.
ThomasHaas May 9, 2025
bcb60b4
Merge branch 'refs/heads/development' into interrupt_new
ThomasHaas May 14, 2025
ae948c6
Merge branch 'refs/heads/development' into interrupt_new
ThomasHaas May 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions benchmarks/interrupts/assert_assume_race_v1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdlib.h>
#include <stdatomic.h>
#include <pthread.h>
#include <assert.h>
#include <dat3m.h>

// Test case: Racing assume and assert.
// Expected: PASS, IH will not terminate on assert failure, main-thread performs assume.

void *handler(void *arg)
{
// assert(0); // FAIL (assert failure terminates both IH and IT before assume executes)
__VERIFIER_assert(0); // PASS (assert failure does not terminate IH nor IT, therefore assume will execute)
return NULL;
}

int main()
{
__VERIFIER_register_interrupt_handler(handler);

__VERIFIER_assume(0);

return 0;
}
24 changes: 24 additions & 0 deletions benchmarks/interrupts/assert_assume_race_v2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdlib.h>
#include <stdatomic.h>
#include <pthread.h>
#include <assert.h>
#include <dat3m.h>

// Test case: Racing assume and assert.
// Expected: FAIL, IH may interrupt before assume, fail its assertion and therefore terminate the program.

void *handler(void *arg)
{
assert(0); // FAIL (assert failure terminates both IH and IT before assume executes)
// __VERIFIER_assert(0); // PASS (assert failure does not terminate IH nor IT, therefore assume will execute)
return NULL;
}

int main()
{
__VERIFIER_register_interrupt_handler(handler);

__VERIFIER_assume(0);

return 0;
}
51 changes: 51 additions & 0 deletions benchmarks/interrupts/c11_detour.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <stdlib.h>
#include <stdatomic.h>
#include <pthread.h>
#include <assert.h>
#include <dat3m.h>

// Expected: PASS

atomic_int x, y;
int a, b;

pthread_t h;
void *handler(void *arg)
{
atomic_store_explicit(&y, 3, memory_order_seq_cst);
return NULL;
}

void *thread_1(void *arg)
{
__VERIFIER_make_interrupt_handler();
pthread_create(&h, NULL, handler, NULL);

atomic_store_explicit(&x, 1, memory_order_relaxed);
a = atomic_load_explicit(&y, memory_order_relaxed);

pthread_join(h, 0);

return NULL;
}

void *thread_2(void *arg)
{
b = atomic_load_explicit(&x, memory_order_relaxed);
atomic_store_explicit(&y, 2, memory_order_release);
return NULL;
}

int main()
{
pthread_t t1, t2;

pthread_create(&t1, 0, thread_1, NULL);
pthread_create(&t2, 0, thread_2, NULL);
pthread_join(t1, 0);
pthread_join(t2, 0);

__VERIFIER_assert(!(b == 1 && a == 3 && y == 3));

return 0;
}
53 changes: 53 additions & 0 deletions benchmarks/interrupts/c11_detour_disable.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <stdlib.h>
#include <stdatomic.h>
#include <pthread.h>
#include <assert.h>
#include <dat3m.h>

// Expected: FAIL

atomic_int x, y;
int a, b;

pthread_t h;
void *handler(void *arg)
{
atomic_store_explicit(&y, 3, memory_order_seq_cst);
return NULL;
}

void *thread_1(void *arg)
{
__VERIFIER_make_interrupt_handler();
pthread_create(&h, NULL, handler, NULL);

__VERIFIER_disable_irq();
atomic_store_explicit(&x, 1, memory_order_relaxed);
a = atomic_load_explicit(&y, memory_order_relaxed);
__VERIFIER_enable_irq();

pthread_join(h, 0);

return NULL;
}

void *thread_2(void *arg)
{
b = atomic_load_explicit(&x, memory_order_relaxed);
atomic_store_explicit(&y, 2, memory_order_release);
return NULL;
}

int main()
{
pthread_t t1, t2;

pthread_create(&t1, 0, thread_1, NULL);
pthread_create(&t2, 0, thread_2, NULL);
pthread_join(t1, 0);
pthread_join(t2, 0);

__VERIFIER_assert(!(b == 1 && a == 3 && y == 3));

return 0;
}
53 changes: 53 additions & 0 deletions benchmarks/interrupts/c11_detour_disable_release.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <stdlib.h>
#include <stdatomic.h>
#include <pthread.h>
#include <assert.h>
#include <dat3m.h>

// Expected: FAIL

atomic_int x, y;
int a, b;

pthread_t h;
void *handler(void *arg)
{
atomic_store_explicit(&y, 3, memory_order_seq_cst);
return NULL;
}

void *thread_1(void *arg)
{
__VERIFIER_make_interrupt_handler();
pthread_create(&h, NULL, handler, NULL);

__VERIFIER_disable_irq();
atomic_store_explicit(&x, 1, memory_order_release);
a = atomic_load_explicit(&y, memory_order_relaxed);
__VERIFIER_enable_irq();

pthread_join(h, 0);

return NULL;
}

void *thread_2(void *arg)
{
b = atomic_load_explicit(&x, memory_order_relaxed);
atomic_store_explicit(&y, 2, memory_order_release);
return NULL;
}

int main()
{
pthread_t t1, t2;

pthread_create(&t1, 0, thread_1, NULL);
pthread_create(&t2, 0, thread_2, NULL);
pthread_join(t1, 0);
pthread_join(t2, 0);

__VERIFIER_assert(!(b == 1 && a == 3 && y == 3));

return 0;
}
49 changes: 49 additions & 0 deletions benchmarks/interrupts/c11_oota.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include <stdlib.h>
#include <stdatomic.h>
#include <pthread.h>
#include <assert.h>
#include <dat3m.h>

// Expected: PASS

atomic_int x, y, z;

pthread_t h;
void *handler(void *arg)
{
atomic_store_explicit(&z, 3, memory_order_relaxed);
__VERIFIER_assert(atomic_load_explicit(&y, memory_order_relaxed) == 0);
return NULL;
}

void *thread_1(void *arg)
{
__VERIFIER_make_interrupt_handler();
pthread_create(&h, NULL, handler, NULL);

if(atomic_load_explicit(&x, memory_order_relaxed) == 1) {
atomic_store_explicit(&y, 2, memory_order_relaxed);
}

pthread_join(h, 0);

return NULL;
}

void *thread_2(void *arg)
{
if(atomic_load_explicit(&z, memory_order_relaxed) == 3) {
atomic_store_explicit(&x, 1, memory_order_relaxed);
}
return NULL;
}

int main()
{
pthread_t t1, t2;

pthread_create(&t1, 0, thread_1, NULL);
pthread_create(&t2, 0, thread_2, NULL);

return 0;
}
65 changes: 65 additions & 0 deletions benchmarks/interrupts/c11_weak_model.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <stdlib.h>
#include <stdbool.h>
#include <stdatomic.h>
#include <pthread.h>
#include <assert.h>
#include <dat3m.h>

// Expected: ???

atomic_int x, y, a1, a2, b1, b2;
int r1, r2, t1, u1, t2, u2;

pthread_t h;
void *handler(void *arg)
{
r1 = atomic_load_explicit(&x, memory_order_relaxed);
atomic_thread_fence(memory_order_seq_cst);
r2 = atomic_load_explicit(&y, memory_order_relaxed);
return NULL;
}

void *thread_1(void *arg)
{
__VERIFIER_make_interrupt_handler();
pthread_create(&h, NULL, handler, NULL);

atomic_store_explicit(&b1, 1, memory_order_relaxed);
atomic_store_explicit(&x, 1, memory_order_relaxed);
atomic_store_explicit(&a1, 1, memory_order_relaxed);
atomic_store_explicit(&b2, 1, memory_order_relaxed);
atomic_store_explicit(&y, 1, memory_order_relaxed);
atomic_store_explicit(&a2, 1, memory_order_relaxed);

pthread_join(h, 0);

return NULL;
}

void *thread_2(void *arg)
{
t1 = atomic_load_explicit(&a1, memory_order_relaxed);
u1 = atomic_load_explicit(&b1, memory_order_relaxed);
atomic_thread_fence(memory_order_seq_cst);
t2 = atomic_load_explicit(&a2, memory_order_relaxed);
u2 = atomic_load_explicit(&b2, memory_order_relaxed);
return NULL;
}

int main()
{
pthread_t thread1, thread2;

pthread_create(&thread1, 0, thread_1, NULL);
pthread_create(&thread2, 0, thread_2, NULL);
pthread_join(thread1, 0);
pthread_join(thread2, 0);

bool reorder_bx = (t1 == 1 && t2 == 0);
bool reorder_ya = (u1 == 1 && u2 == 0);
if (r1 == 1 && r2 == 0) {
__VERIFIER_assert(! reorder_bx || ! reorder_ya);
}

return 0;
}
52 changes: 52 additions & 0 deletions benchmarks/interrupts/c11_with_barrier.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <stdlib.h>
#include <stdatomic.h>
#include <pthread.h>
#include <assert.h>
#include <dat3m.h>

/*
This test shows how interrupt handlers are spawned
Expected: PASS
*/

struct A { volatile int a; volatile int b; }; // Without "volatile" the compiler removes our assertions.
struct A as[10];
int cnt = 0;

pthread_t h;
void *handler(void *arg)
{
int tindex = ((intptr_t) arg);
int i = cnt++;
__VERIFIER_make_cb();
as[i].a = tindex;
as[i].b = tindex;
__VERIFIER_assert(as[i].a == as[i].b);

return NULL;
}

void *run(void *arg)
{
__VERIFIER_make_interrupt_handler(); // Buggy without this marker
pthread_create(&h, NULL, handler, 0);

int tindex = ((intptr_t) arg);
int i = cnt++;
__VERIFIER_make_cb();
as[i].a = tindex;
as[i].b = tindex;
__VERIFIER_assert(as[i].a == as[i].b);

pthread_join(h, NULL);

return NULL;
}

int main()
{
pthread_t t;
pthread_create(&t, NULL, run, (void *)1);

return 0;
}
Loading