Created
February 23, 2017 10:22
-
-
Save primiano/0936c4740a28a26d22d41fff8abb0e6e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <pthread.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| struct MallocFunctions { | |
| void* malloc_fn; | |
| void* zone; | |
| }; | |
| //#define I_REALLY_WANT_THIS_TO_WORK | |
| inline void MemoryBarrier() { | |
| #if defined(__ARMEL__) || defined(__aarch64__) | |
| __asm__ __volatile__("dmb" : : : "memory"); | |
| #endif | |
| // We don't really need one on x86. | |
| } | |
| #define N 1000000ul | |
| // I am making this volatile so we don't even worry about compiler reorderings. | |
| volatile struct MallocFunctions g_mf[N]; | |
| void* WriterThread(void* _) { | |
| unsigned long i; | |
| for (i = 0; i < N; i++) { | |
| g_mf[i].malloc_fn = (void*)0x4242; | |
| #if defined(I_REALLY_WANT_THIS_TO_WORK) | |
| MemoryBarrier(); | |
| #endif | |
| g_mf[i].zone = (void*)(0x42); | |
| MemoryBarrier(); | |
| // Slack a bit to allow the reader to wrap over us and hit more likely the | |
| // race. | |
| } | |
| return NULL; | |
| } | |
| void* ReaderThread(void* _) { | |
| unsigned long i; | |
| for (i = 0; i < N; i++) { | |
| volatile struct MallocFunctions* mf = &g_mf[i]; | |
| // On CPUs with weaker ordering you really need this or only with the one | |
| // above will fail. | |
| volatile void* zone = mf->zone; | |
| #if defined(I_REALLY_WANT_THIS_TO_WORK) | |
| MemoryBarrier(); | |
| #endif | |
| volatile void* malloc_fn = mf->malloc_fn; | |
| MemoryBarrier(); | |
| if (zone && !malloc_fn) { | |
| printf("FAIL at iteration %lu\n", i); | |
| _exit(1); | |
| } else if (!zone) { | |
| // we outpaced the writer, go back a little bit and repeat. | |
| i = i > 2 ? i - 2 : 0; | |
| } | |
| } | |
| return NULL; | |
| } | |
| int main(int argc, const char* argv[]) { | |
| for(;;) { | |
| pthread_t t_reader, t_writer; | |
| pthread_create(&t_reader, NULL, &ReaderThread, NULL); | |
| pthread_create(&t_writer, NULL, &WriterThread, NULL); | |
| pthread_join(t_reader, NULL); | |
| pthread_join(t_writer, NULL); | |
| printf("Iteration succeded!\n"); | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment