Exclusive mode seems to work without deadlocks
authorTomas Mudrunka <tomas@mudrunka.cz>
Fri, 2 Jul 2021 15:51:00 +0000 (17:51 +0200)
committerTomas Mudrunka <tomas@mudrunka.cz>
Fri, 2 Jul 2021 15:51:00 +0000 (17:51 +0200)
c/pthread_extra/pthread_pause.c
c/pthread_extra/pthread_user_data.c
c/pthread_extra/test_pause.c

index a9ce5dce3c487e87613fff24d90c39fe045f5741..24521af71f38741c0e85ea04412f89724f173626 100644 (file)
@@ -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());
index cf97a652f6d1c973aa06f9920c2e0643cb17ae63..74ae1145c46511d7ed34021ee678fae8b1dede94 100644 (file)
@@ -1,5 +1,6 @@
 #define __PTHREAD_EXTRA_INTERNAL
 
+//#include <stdio.h>
 #include <assert.h>
 #include <pthread.h>
 #include <pthread_extra.h>
@@ -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;
index 439c6d8d22de9da53d1807b2b42222e835cb03b3..b99c388c735cc3ac0579fcace9f6cfa815a4df7f 100644 (file)
@@ -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);
        }
 
This page took 0.197814 seconds and 4 git commands to generate.