diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-12-22 18:52:10 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-12-22 18:55:38 +0100 |
| commit | 8e4090902540da8c6e8fa640a0fc325c29c3efcb (patch) | |
| tree | 42af582b4a6b448bc34329346046c67f07f26984 /executor/common_linux.h | |
| parent | 26cd53f078db858a6ccca338e13e7f4d1d291c22 (diff) | |
pkg/csource: mimic the way syscalls are scheduled in executor
Currently csource uses completely different, simpler way of scheduling
syscalls onto threads (thread per call with random sleeps).
Mimic the way calls are scheduled in executor.
Fixes #312
Diffstat (limited to 'executor/common_linux.h')
| -rw-r--r-- | executor/common_linux.h | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/executor/common_linux.h b/executor/common_linux.h index fc60e3a70..421486ed5 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -11,6 +11,7 @@ #include <sys/syscall.h> #include <unistd.h> #if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE) +#include <linux/futex.h> #include <pthread.h> #include <stdlib.h> #endif @@ -1045,3 +1046,66 @@ void loop() } #endif #endif + +#if defined(SYZ_THREADED) +struct thread_t { + int created, running, call; + pthread_t th; +}; + +static struct thread_t threads[16]; +static void execute_call(int call); +static int running; +#if defined(SYZ_COLLIDE) +static int collide; +#endif + +static void* thr(void* arg) +{ + struct thread_t* th = (struct thread_t*)arg; + for (;;) { + while (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) + syscall(SYS_futex, &th->running, FUTEX_WAIT, 0, 0); + execute_call(th->call); + __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); + __atomic_store_n(&th->running, 0, __ATOMIC_RELEASE); + syscall(SYS_futex, &th->running, FUTEX_WAKE); + } + return 0; +} + +static void execute(int num_calls) +{ + int call, thread; + running = 0; + for (call = 0; call < num_calls; call++) { + for (thread = 0; thread < sizeof(threads) / sizeof(threads[0]); thread++) { + struct thread_t* th = &threads[thread]; + if (!th->created) { + th->created = 1; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 128 << 10); + pthread_create(&th->th, &attr, thr, th); + } + if (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) { + th->call = call; + __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); + __atomic_store_n(&th->running, 1, __ATOMIC_RELEASE); + syscall(SYS_futex, &th->running, FUTEX_WAKE); +#if defined(SYZ_COLLIDE) + if (collide && call % 2) + break; +#endif + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 20 * 1000 * 1000; + syscall(SYS_futex, &th->running, FUTEX_WAIT, 1, &ts); + if (running) + usleep((call == num_calls - 1) ? 10000 : 1000); + break; + } + } + } +} +#endif |
