From de59b17efb67056de9a5182dbbeed27aed68117c Mon Sep 17 00:00:00 2001 From: Tomas Mudrunka Date: Fri, 2 Jul 2021 17:51:00 +0200 Subject: [PATCH] Exclusive mode seems to work without deadlocks --- c/pthread_extra/pthread_pause.c | 35 +++++++++++++++++++---------- c/pthread_extra/pthread_user_data.c | 7 ++++-- c/pthread_extra/test_pause.c | 8 ++++--- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/c/pthread_extra/pthread_pause.c b/c/pthread_extra/pthread_pause.c index a9ce5dc..24521af 100644 --- a/c/pthread_extra/pthread_pause.c +++ b/c/pthread_extra/pthread_pause.c @@ -47,8 +47,10 @@ void pthread_pause_handler(const int signal, siginfo_t *info, void *ptr) { } void pthread_pause_enable() { + pthread_pause_init(); //Make sure semaphore is init'd + //Add thread to internal registry - //pthread_user_data_internal(pthread_self()); + pthread_user_data_internal(pthread_self()); //Nesting signals too deep is not good for stack //You can get runtime stats using following command: @@ -56,8 +58,6 @@ void pthread_pause_enable() { //struct rlimit sigq = {.rlim_cur = 32, .rlim_max=32}; //setrlimit(RLIMIT_SIGPENDING, &sigq); - pthread_pause_init(); //Make sure semaphore is init'd - //Prepare signal mask sigset_t sigset; sigemptyset(&sigset); @@ -78,11 +78,11 @@ void pthread_pause_enable() { } void pthread_pause_disable() { - //Add thread to internal registry - //pthread_user_data_internal(pthread_self()); - pthread_pause_init(); //Make sure semaphore is init'd + //Add thread to internal registry + pthread_user_data_internal(pthread_self()); + //Block signal sigset_t sigset; sigemptyset(&sigset); @@ -109,6 +109,8 @@ int pthread_pause_reschedule(pthread_t thread) { int pthread_pause_reschedule(pthread_t thread) { //Decide if the thread should run and signal it + pthread_user_data_lock(); + //Wait for semaphore which means signal queue is empty pthread_pause_init(); //Make sure semaphore is init'd sem_wait(&pthread_pause_sem); @@ -116,17 +118,16 @@ int pthread_pause_reschedule(pthread_t thread) { //Only call this if you already acquired pthread_pause_sem semaphore!!!! //Otherwise call pthread_pause_reschedule() - pthread_user_data_lock(); //Check if thread has running flag int run = (pthread_user_data_internal(thread)->running); //Check if privileged (single thread) mode is active - if((pthread_pause_holder != PTHREAD_XNULL) && !pthread_equal(pthread_pause_holder, thread)) { + if(!pthread_equal(pthread_pause_holder, PTHREAD_XNULL) && !pthread_equal(pthread_pause_holder, thread)) { run = 0; } - pthread_user_data_unlock(); //Send signal to initiate pause handler (keep trying while SigQueue is full) //while(pthread_kill(thread, PTHREAD_XSIG_STOP) == EAGAIN) usleep(1000); + //printf("Sched %lu = %d (self: %lu, lck: %lu)\n", thread, run, pthread_self(), pthread_pause_holder); while(pthread_sigqueue(thread, PTHREAD_XSIG_STOP, (const union sigval){.sival_int=run} ) == EAGAIN) usleep(1000); @@ -134,6 +135,7 @@ int pthread_pause_reschedule(pthread_t thread) { //Wait for signal to be delivered sem_wait(&pthread_pause_sem); sem_post(&pthread_pause_sem); + pthread_user_data_unlock(); return 0; } @@ -162,20 +164,29 @@ int pthread_unpause(pthread_t thread) { return 0; } +///Enter exclusive mode by pausing everyone else int pthread_pause_all() { + //printf("Pause ALL\n"); pthread_user_data_lock(); - if(pthread_pause_holder!=PTHREAD_XNULL) assert(pthread_equal(pthread_pause_holder, pthread_self())); + //printf("Pause ALL+\n"); + //printf("Pause %p == %p\n", (void *)pthread_pause_holder, (void *)pthread_self()); + if(!pthread_equal(pthread_pause_holder,PTHREAD_XNULL)) assert(pthread_equal(pthread_pause_holder, pthread_self())); pthread_pause_holder = pthread_self(); pthread_user_data_internal_iterate(&pthread_pause_reschedule, NULL); + //printf("Pause ALL!\n"); pthread_user_data_unlock(); return 0; } +///Leave exclusive mode by unpausing everyone else int pthread_unpause_all() { + //printf("UnPause ALL\n"); pthread_user_data_lock(); - if(pthread_pause_holder!=PTHREAD_XNULL) assert(pthread_equal(pthread_pause_holder, pthread_self())); + //printf("UnPause ALL+\n"); + if(!pthread_equal(pthread_pause_holder,PTHREAD_XNULL)) assert(pthread_equal(pthread_pause_holder, pthread_self())); pthread_pause_holder = PTHREAD_XNULL; pthread_user_data_internal_iterate(&pthread_pause_reschedule, NULL); + //printf("UnPause ALL!\n"); pthread_user_data_unlock(); return 0; } @@ -194,7 +205,7 @@ void *pthread_extra_thread_wrapper(void *arg) { free(arg); //Register new thread to user data structure - pthread_user_data_internal(pthread_self()); + pthread_user_data_internal(pthread_self()); //Perhaps already done in pthread_extra_yield()?? //TODO: user_data should do this automaticaly? pthread_cleanup_push(pthread_user_data_cleanup, (void *)pthread_self()); diff --git a/c/pthread_extra/pthread_user_data.c b/c/pthread_extra/pthread_user_data.c index cf97a65..74ae114 100644 --- a/c/pthread_extra/pthread_user_data.c +++ b/c/pthread_extra/pthread_user_data.c @@ -1,5 +1,6 @@ #define __PTHREAD_EXTRA_INTERNAL +//#include #include #include #include @@ -10,13 +11,13 @@ pthread_user_data_internal_t pthread_user_data[PTHREAD_XTHREADS_MAX+1] = {{.tid= pthread_mutex_t pthread_user_data_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; int pthread_user_data_lock() { - pthread_pause_disable(); + //pthread_pause_disable(); return pthread_mutex_lock(&pthread_user_data_mutex); } int pthread_user_data_unlock() { pthread_mutex_unlock(&pthread_user_data_mutex); - pthread_pause_enable(); + //pthread_pause_enable(); return 0; } @@ -36,6 +37,8 @@ pthread_user_data_internal_t* pthread_user_data_internal(pthread_t thread) { if(pthread_equal(pthread_user_data[i].tid, PTHREAD_XNULL)) { pthread_user_data[i+1].tid = PTHREAD_XNULL; pthread_user_data[i].tid = thread; + pthread_user_data[i].running = 1; //NEW THREADS ARE RUNNING UNLESS PAUSED! + //printf("ADDED %lu = %lu\n", pthread_user_data[i].tid, thread); break; } if(pthread_equal(pthread_user_data[i].tid, thread)) break; diff --git a/c/pthread_extra/test_pause.c b/c/pthread_extra/test_pause.c index 439c6d8..b99c388 100644 --- a/c/pthread_extra/test_pause.c +++ b/c/pthread_extra/test_pause.c @@ -13,10 +13,10 @@ void *thread_test(void *arg) { //pthread_pause_enable(); while(1) { pthread_nsleep(0, 1000*1000*300); - //pthread_pause_all(); - pthread_pause(main_thread); + pthread_pause_all(); printf("Running%s!\n", (char *)arg); - //pthread_unpause_all(); + pthread_unpause_all(); + pthread_pause(main_thread); pthread_unpause(main_thread); } } @@ -65,9 +65,11 @@ int main() { printf("SWITCH MAIN ONLY:\n"); pthread_pause_all(); + //printf("\n"); pthread_sleep(1); printf("SWITCH MAIN A+B:\n"); pthread_unpause_all(); + //printf("\n"); pthread_sleep(1); } -- 2.30.2