Luca Dariz, le jeu. 28 déc. 2023 20:43:00 +0100, a ecrit: > --- > tests/test-threads.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 88 insertions(+) > create mode 100644 tests/test-threads.c > > diff --git a/tests/test-threads.c b/tests/test-threads.c > new file mode 100644 > index 00000000..659aaf3b > --- /dev/null > +++ b/tests/test-threads.c > @@ -0,0 +1,88 @@ > + > +#include <stdint.h> > +#include <mach/machine/thread_status.h> > + > +#include <syscalls.h> > +#include <testlib.h> > + > +#include <mach.user.h> > + > +void sleeping_thread(void* arg) > +{ > + printf("starting thread %d\n", arg); > + for (int i=0; i<100; i++) > + msleep(50); // maybe we could just yield
Yielding wouldn't give you control on how much time is spent. > + printf("stopping thread %d\n", arg); > + int err = thread_terminate(mach_thread_self()); > + ASSERT_RET(err, "thread_terminate"); > +} > + > +void test_many(void) > +{ > + int err; > + for (long tid=0; tid<10; tid++) > + { > + test_thread_start(mach_task_self(), sleeping_thread, (void*)tid); > + } > + // TODO: wait for thread end notifications > + msleep(6000); > +} > + > +#ifdef __x86_64__ > +void test_fsgs_base_thread(void* tid) > +{ > + int err; > +#if defined(__SEG_FS) && defined(__SEG_GS) > + long __seg_fs *fs_ptr; > + long __seg_gs *gs_ptr; > + long fs_value; > + long gs_value; > + > + struct i386_fsgs_base_state state; > + state.fs_base = (unsigned long)&fs_value; > + state.gs_base = (unsigned long)&gs_value; > + err = thread_set_state(mach_thread_self(), i386_FSGS_BASE_STATE, > + (thread_state_t) &state, > i386_FSGS_BASE_STATE_COUNT); > + ASSERT_RET(err, "thread_set_state"); > + > + fs_value = 0x100 + (long)tid; > + gs_value = 0x200 + (long)tid; > + > + msleep(50); // allow the others to set their segment base > + > + fs_ptr = 0; > + gs_ptr = 0; > + long rdvalue = *fs_ptr; > + printf("FS expected %lx read %lx\n", fs_value, rdvalue); > + ASSERT(fs_value == rdvalue, "FS base error\n"); > + rdvalue = *gs_ptr; > + printf("GS expected %lx read %lx\n", gs_value, rdvalue); > + ASSERT(gs_value == rdvalue, "GS base error\n"); > +#else > +#error " missing __SEG_FS and __SEG_GS" > +#endif > + > + err = thread_terminate(mach_thread_self()); > + ASSERT_RET(err, "thread_terminate"); > +} > +#endif > + > +void test_fsgs_base(void) > +{ > +#ifdef __x86_64__ > + int err; > + for (long tid=0; tid<10; tid++) > + { > + test_thread_start(mach_task_self(), test_fsgs_base_thread, (void*)tid); > + } > + msleep(1000); // TODO: wait for threads > +#endif > +} > + > + > +int main(int argc, char *argv[], int envc, char *envp[]) > +{ > + test_fsgs_base(); > + test_many(); > + return 0; > +} > -- > 2.39.2