diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/tests/test_interprocess.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/source/tests/test_interprocess.c b/source/tests/test_interprocess.c new file mode 100644 index 0000000..df2a375 --- /dev/null +++ b/source/tests/test_interprocess.c @@ -0,0 +1,124 @@ +#ifdef _WIN32 +int main() { + return 0; +} +#else +# include "../kit/threads.h" + +# include <stdio.h> +# include <string.h> +# include <sys/mman.h> +# include <sys/stat.h> +# include <fcntl.h> +# include <unistd.h> + +# define NAME "/kit_test_interprocess" + +enum { STATE_INIT, STATE_READY, STATE_DONE }; + +enum { SIZE = 64 }; + +int run_writer() { + int f = shm_open(NAME, O_RDWR | O_CREAT, 0660); + + if (f == -1) { + printf("%s: shm_open failed.\n", __FUNCTION__); + return 1; + } + + if (ftruncate(f, SIZE) == -1) { + printf("%s: ftruncate failed.\n", __FUNCTION__); + fflush(stdout); + return 1; + } + + void *p = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, f, + 0); + + if (p == MAP_FAILED) { + printf("%s: mmap failed.\n", __FUNCTION__); + fflush(stdout); + return 1; + } + + unsigned char *bytes = (unsigned char *) p; + + bytes[0] = STATE_INIT; + for (int i = 1; i < SIZE; i++) bytes[i] = i; + bytes[0] = STATE_READY; + + while (bytes[0] != STATE_DONE) thrd_yield(); + + shm_unlink(NAME); + + return 0; +} + +int run_reader() { + int f = -1; + + while (f == -1) { + f = shm_open(NAME, O_RDWR, 0); + thrd_yield(); + } + + void *p = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, f, + 0); + + if (p == MAP_FAILED) { + printf("%s: mmap failed.\n", __FUNCTION__); + fflush(stdout); + return 1; + } + + unsigned char *bytes = (unsigned char *) p; + + while (bytes[0] != STATE_READY) thrd_yield(); + + int status = 0; + + for (int i = 1; i < SIZE; i++) + if (bytes[i] != i) { + printf("%s: wrong byte %d\n", __FUNCTION__, i); + fflush(stdout); + status = 1; + } + + bytes[0] = STATE_DONE; + + return status; +} + +int main(int argc, char **argv) { + if (argc != 2) { + printf("Wrong number of command line arguments %d\n", argc); + return 1; + } + + int status = 0; + + struct timespec t0; + timespec_get(&t0, TIME_UTC); + + if (strcmp(argv[1], "writer") == 0) + status = run_writer(); + else if (strcmp(argv[1], "reader") == 0) + status = run_reader(); + else { + printf("Invalid command line argument \"%s\"\n", argv[1]); + return 1; + } + + struct timespec t1; + timespec_get(&t1, TIME_UTC); + + long long sec = t1.tv_sec - t0.tv_sec; + long long nsec = t1.tv_nsec - t0.tv_nsec; + + printf("%s: done in %.2lf msec\n", argv[1], + (sec * 1000000000 + nsec) * 0.000001); + fflush(stdout); + + return status; +} +#endif |