1 module during.tests.thread; 2 3 import during; 4 import during.tests.base; 5 6 import core.stdc.stdio; 7 import core.sys.posix.pthread; 8 9 import std.algorithm : filter; 10 import std.range : drop, empty; 11 12 // setup io_uring from multiple threads at once 13 @("setup") 14 unittest 15 { 16 enum NUM_THREADS = 4; 17 ThreadInfo[NUM_THREADS] threads; 18 19 // start threads 20 foreach (i; 0..NUM_THREADS) 21 { 22 threads[i].num = i; 23 auto ret = pthread_create(&threads[i].tid, null, &doTest, &threads[i]); 24 assert(ret == 0, "pthread_create()"); 25 } 26 27 // join threads 28 foreach (i; 0..NUM_THREADS) 29 { 30 auto ret = pthread_join(threads[i].tid, cast(void**)null); 31 assert(ret == 0, "pthread_join()"); 32 } 33 34 // check for errors 35 auto errors = threads[].filter!(a => a.err != 0); 36 if (!errors.empty) 37 { 38 version (D_BetterC) errmsg = "failed (check 'ulimit -l')"; 39 else assert(0, "failed (check 'ulimit -l')"); 40 } 41 } 42 43 extern(C) void* doTest(void *arg) 44 { 45 enum RING_SIZE = 32; 46 // printf("%d: start\n", (cast(ThreadInfo*)arg).num); 47 48 Uring io; 49 auto res = io.setup(RING_SIZE); 50 if (res < 0) 51 { 52 // printf("%d: error=%d\n", (cast(ThreadInfo*)arg).num, -res); 53 (cast(ThreadInfo*)arg).err = -res; 54 return null; 55 } 56 57 // simulate some work 58 foreach (_; 0..5) 59 { 60 foreach (i; 0..RING_SIZE) io.putWith!((ref SubmissionEntry e) => e.prepNop()); 61 res = io.submit(RING_SIZE); 62 if (res != RING_SIZE) 63 { 64 // printf("%d: submit error=%d\n", (cast(ThreadInfo*)arg).num, -res); 65 (cast(ThreadInfo*)arg).err = -res; 66 return null; 67 } 68 io.drop(RING_SIZE); 69 } 70 71 // printf("%d: done\n", (cast(ThreadInfo*)arg).num); 72 return null; 73 } 74 75 struct ThreadInfo 76 { 77 pthread_t tid; 78 int num; 79 int err; 80 }