From 517bba117346bee9f02e403b5cddfa97a70f244e Mon Sep 17 00:00:00 2001
From: solsta <segorov555@gmail.com>
Date: Tue, 18 Jan 2022 13:48:28 +0000
Subject: [PATCH] Added recovery transaction abort trigger

---
 memval_simple.c | 386 ++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 343 insertions(+), 43 deletions(-)

diff --git a/memval_simple.c b/memval_simple.c
index fdd9743..519e8e1 100644
--- a/memval_simple.c
+++ b/memval_simple.c
@@ -56,16 +56,21 @@
 * This client is a simple implementation of a memory reference tracing tool
 * without instrumentation optimization.
 */
-//#include <criu/criu.h>
+
 #include "dr_api.h"
 #include "drmgr.h"
+
 #include "drutil.h"
+
 #include "drreg.h"
+
 #include "utils.h"
 #include "drx.h"
 #include "drsyms.h"
 #include "drwrap.h"
 
+
+
 #include <libpmemobj/base.h>
 #include <libpmemobj/pool_base.h>
 #include <libpmemobj/types.h>
@@ -74,6 +79,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <signal.h>
+#include <fcntl.h>
 
 //#include <fcntl.h>
 
@@ -114,6 +120,16 @@ wrap_pre_tx_start(void *wrapcxt, OUT void **user_data);
 static void
 wrap_pre_tx_finish(void *wrapcxt, OUT void **user_data);
 
+static void
+wrap_tx_start_criu(void *wrapcxt, OUT void **user_data);
+static void
+wrap_tx_finish_criu(void *wrapcxt, OUT void *user_data);
+
+static void
+wrap_tx_start(void *wrapcxt, OUT void **user_data);
+static void
+wrap_tx_finish(void *wrapcxt, OUT void *user_data);
+
 /* --- */
 //static void initislise(void);
 void create_unique_file_name(char *path_to_pmem);
@@ -128,7 +144,9 @@ bool file_exists(const char *path){
    return access(path, F_OK) != 0;
 }
 struct my_root {
-    long oofset;
+    bool tx_is_running;
+    int recovery_count;
+    long offset;
     char pmem_start[64000000];
 };
 /*
@@ -147,6 +165,13 @@ static const char *desc[] = {
 };
 **/
 
+bool verbose = true;
+void print_with_log_level(const char str[50]){
+    if(verbose){
+        printf("%s \n", str);
+    }
+}
+
 static void
 log_stages(PMEMobjpool *pop_local, enum pobj_tx_stage stage, void *arg)
 {
@@ -165,9 +190,15 @@ module_load_event(void *drcontext, const module_data_t *mod, bool loaded)
 
     if (drsym_lookup_symbol(mod->full_path, func_name, &offs, DRSYM_DEMANGLE) == DRSYM_SUCCESS) {
         orig = offs + mod->start;
-        dr_printf("function \"%s\" is found..\n", func_name);
+        if(verbose) {
+            dr_printf("function \"%s\" is found..\n", func_name);
+        }
         bool wrapped = drwrap_wrap(orig, wrap_pre_tx_start, NULL);
-        if (wrapped) { dr_printf("function \"%s\" is wrapped..\n", func_name); }
+        if (wrapped) {
+            if(verbose){
+            dr_printf("function \"%s\" is wrapped..\n", func_name);
+            }
+        }
     }
 
     func_name = "sm_op_end";
@@ -175,10 +206,52 @@ module_load_event(void *drcontext, const module_data_t *mod, bool loaded)
 
     if (drsym_lookup_symbol(mod->full_path, func_name, &offs, DRSYM_DEMANGLE) == DRSYM_SUCCESS) {
         orig = offs + mod->start;
-        dr_printf("function \"%s\" is found..\n", func_name);
+        if(verbose) {
+            dr_printf("function \"%s\" is found..\n", func_name);
+        }
         bool wrapped = drwrap_wrap(orig, wrap_pre_tx_finish, NULL);
-        if (wrapped) { dr_printf("function \"%s\" is wrapped..\n", func_name); }
+        if (wrapped) {
+            if(verbose){ dr_printf("function \"%s\" is wrapped..\n", func_name);
+            }
+        }
+    }
+
+    func_name = "state_machine_loop";
+
+
+    if (drsym_lookup_symbol(mod->full_path, func_name, &offs, DRSYM_DEMANGLE) == DRSYM_SUCCESS) {
+        orig = offs + mod->start;
+        if(verbose) {
+            dr_printf("function \"%s\" is found..\n", func_name);
+        }
+        bool wrapped = drwrap_wrap(orig, wrap_tx_start, wrap_tx_finish);
+        if (wrapped) {
+            if(verbose){
+            dr_printf("function \"%s\" is wrapped..\n", func_name);
+            }
+        }
     }
+
+
+    /////
+    /* change pre and post  */
+    func_name = "setup_criu";
+
+
+    if (drsym_lookup_symbol(mod->full_path, func_name, &offs, DRSYM_DEMANGLE) == DRSYM_SUCCESS) {
+        orig = offs + mod->start;
+        if(verbose) {
+            dr_printf("function \"%s\" is found..\n", func_name);
+        }
+        bool wrapped = drwrap_wrap(orig, wrap_tx_start_criu, wrap_tx_finish_criu);
+        if (wrapped) {
+            if(verbose){
+                dr_printf("function \"%s\" is wrapped..\n", func_name);
+            }
+        }
+    }
+
+     //////
     /* This methos is called multiple times, but we only need to open the file once */
     if(!file_was_created) {
         file_was_created = true;
@@ -213,14 +286,17 @@ module_load_event(void *drcontext, const module_data_t *mod, bool loaded)
            drwrap_wrap(towrap2, wrap_pre2, wrap_post2);
 #ifdef SHOW_RESULTS
        if (ok) {
-           dr_fprintf(STDERR, "<wrapped " MALLOC_ROUTINE_NAME " @" PFX "\n", towrap);
-           dr_fprintf(STDERR,   "%ld %ld \n", (long)getpid(), (long)getppid());
+           if(verbose) {
+               dr_fprintf(STDERR, "<wrapped " MALLOC_ROUTINE_NAME " @" PFX "\n", towrap);
+               dr_fprintf(STDERR, "%ld %ld \n", (long)getpid(), (long)getppid());
+           }
        } else {
-
-           dr_fprintf(STDERR,
-                      "<FAILED to wrap " MALLOC_ROUTINE_NAME " @" PFX
-                      ": already wrapped?\n",
-                      towrap);
+           if(verbose) {
+               dr_fprintf(STDERR,
+                          "<FAILED to wrap " MALLOC_ROUTINE_NAME " @" PFX
+                          ": already wrapped?\n",
+                          towrap);
+           }
        }
 #endif
    }
@@ -229,36 +305,207 @@ module_load_event(void *drcontext, const module_data_t *mod, bool loaded)
 static bool tx_active = false;
 static void
 wrap_pre_tx_start(void *wrapcxt, OUT void **user_data){
-    perror("Starting a new transaction \n");
+    if(verbose) {
+        //perror("Starting a new transaction \n");
+    }
+    // No idea how i can use it
+    enum pobj_tx_stage tx_stage =  pmemobj_tx_stage();
+    printf("TX stage before init: %u\n", tx_stage);
+
+    /*
+    if(rootp->tx_is_running){
+        perror("Failure recovery mode\n");
+        //pmemobj_tx_end();
+        perror("Recovery is complete!\n");
+    }
+     */
+    //pmemobj_tx_abort(0);
+    //pmemobj_tx_end();
+    /*
+    if(rootp->tx_is_running){
+        perror("Transaction was not supposed to be active at this moment!\n");
+        perror("Aborting!\n");
+        pmemobj_tx_abort(1);
+    }
+    printf("Initializing transaction\n");
+*/
+    //if(rootp->tx_is_running){
+        //perror("Transaction was not supposed to be active at this moment!\n");
+        //perror("Recovering!\n");
+        /* Need to reinitialize here */
+        //
+    /*
+        perror("Closing old pool connector\n");
+        pmemobj_close(pop);
+        perror("Initialising a new pool!\n");
+        //initialize(128000000);
+
+
+        char *path_to_pmem = calloc(200, 1);
+        create_unique_file_name(path_to_pmem);
+        if ((pop = pmemobj_open(path_to_pmem, POBJ_LAYOUT_NAME(list))) == NULL) {
+                perror("failed to open pool\n");
+        }
+
+        if(verbose) {
+            printf("Pool is provisioned!\n");
+        }
+        root = pmemobj_root(pop, sizeof(struct my_root));
+        rootp = pmemobj_direct(root);
+
+        if(verbose) {
+            printf("Setting up initial values.\n");
+        }
+        printf("Offset is: %lu\n", rootp->offset);
+        //rootp->offset = 0;
+        rootp->tx_is_running = false;
+        rootp->recovery_count = 0;
+        //long *t = &rootp->oofset;
+        //t = 0;
+        //uintptr_t *start = (uintptr_t *)rootp->pmem_start;
+        //uintptr_t *current = (uintptr_t *)rootp->next_available_slot;
+        //rootp->next_available_slot = rootp->pmem_start;
+        //rootp->next_available_slot = start;
+        if(verbose) {
+            printf("Setting is done!\n");
+        }
+        //exit(1);
+        //return;
+        //
+    //}
+     */
     pmemobj_tx_begin(pop, NULL, TX_PARAM_CB, log_stages, NULL,
                      TX_PARAM_NONE);
-
+    perror("Transaction started!");
+    tx_stage =  pmemobj_tx_stage();
+    printf("TX stage: %u\n", tx_stage);
+    rootp->tx_is_running = true;
+    pmemobj_flush(pop, &rootp->tx_is_running,10);
     tx_active = true;
+    printf("Wrap pre tx is finished\n");
 }
 static void
 wrap_pre_tx_finish(void *wrapcxt, OUT void **user_data){
-    perror("Commiting transaction! \n");
+    if(verbose) {
+        perror("Commiting transaction! \n");
+    }
     pmemobj_tx_commit();
     pmemobj_tx_end();
+    rootp->tx_is_running = false;
     tx_active = false;
 }
 
+
+/**
+ * These 2 a very hacky and the idea here is that
+ * if criu snapshot is taken in the middle of a transaction
+ * it will be recovered with transactional information being
+ * stored on the stack. This stack variable would point
+ * to the position of the undo log and hence we can trigger
+ * an abort of a transaction, which has not commited.
+ *
+ */
+int counter = 0;
+static void
+wrap_tx_start_criu(void *wrapcxt, OUT void **user_data){
+    if(counter == 0){
+        /* Try starting and ending a transaction to clear an undo log */
+        //enum pobj_tx_stage tx_stage;
+        pmemobj_tx_begin(pop, NULL, TX_PARAM_CB, log_stages, NULL,
+                         TX_PARAM_NONE);
+        //setup_criu();
+        //tx_stage =  pmemobj_tx_stage();
+        //printf("TX stage : %u\n", tx_stage);
+        //pmemobj_tx_abort(-1);
+        //pmemobj_tx_end();
+
+        counter++;
+    }
+}
+
+static void
+wrap_tx_finish_criu(void *wrapcxt, OUT void *user_data){
+    enum pobj_tx_stage tx_stage;
+    tx_stage =  pmemobj_tx_stage();
+    printf("TX stage : %u\n", tx_stage);
+    perror("Aborting idle transaction! \n");
+    pmemobj_tx_abort(0);
+    pmemobj_tx_end();
+}
+
+static void
+wrap_tx_start(void *wrapcxt, OUT void **user_data){
+    printf("TX stage: %d\n", pmemobj_tx_stage());
+    if(pmemobj_tx_stage() > 0){
+        //if(verbose) {
+        printf("Commiting transaction!\n");
+        //}
+        pmemobj_tx_commit();
+        pmemobj_tx_end();
+        tx_active = false;
+    }
+    perror("17/01/2021");
+       // if(verbose) {
+            perror("Starting a new transaction \n");
+            /* Reinitialise here? */
+            if(pop == NULL){
+                printf("Pop was null!\n");
+            }
+            printf("Pop was not null!\n");
+            //printf("REINITIALIZING\n");
+            //if(condition){
+                //initialize(128000000);
+            //}
+            perror("Starting a new transaction \n");
+
+
+       // }
+        pmemobj_tx_begin(pop, NULL, TX_PARAM_CB, log_stages, NULL, TX_PARAM_NONE);
+
+        printf("Transaction started!\n");
+        tx_active = true;
+
+}
+static void
+wrap_tx_finish(void *wrapcxt, OUT void *user_data){
+    if(verbose) {
+        perror("Commiting transaction! \n");
+    }
+    perror("Does this ever get executed?\n");
+    pmemobj_tx_commit();
+    pmemobj_tx_end();
+    tx_active = false;
+}
+int number_of_times_mmap_called = 0;
+long total_mmaped = 0;
 static void
 wrap_pre(void *wrapcxt, OUT void **user_data)
 {
     /* 0 for malloc, 1 for mmap */
    size_t sz = (size_t)drwrap_get_arg(wrapcxt, IF_WINDOWS_ELSE(2, 1));
-   printf("MMAP size: %zu \n", sz);
+   if(verbose){
+       printf("MMAP size: %zu \n", sz);
+       total_mmaped = total_mmaped + sz;
+       printf("Total mmaped: %lu \n", total_mmaped);
+       number_of_times_mmap_called++;
+       printf("mamp called %d times\n", number_of_times_mmap_called);
+   }
+
+
    *user_data = (void *)sz;
 }
-
+int number_of_times_munmap_called = 0;
 static void
 wrap_pre2(void *wrapcxt, OUT void **user_data)
 {
     /* Need to match this with PMEMoid or file and release */
     //void *addr = (void *)(size_t)drwrap_get_arg(wrapcxt, 1);
     //munmap()
-    perror("munmap called");
+    if(verbose) {
+        perror("munmap called");
+        number_of_times_munmap_called++;
+        printf("number_of_times_munmap_called: %d\n", number_of_times_munmap_called);
+    }
 }
 
 static void
@@ -271,6 +518,8 @@ wrap_post2(void *wrapcxt, void *user_data)
 /**
  *
  */
+bool refresh_only = false;
+
 static struct my_root *rootp;
 void initialize(size_t requested_pool_size){
 
@@ -278,7 +527,9 @@ void initialize(size_t requested_pool_size){
     char *path_to_pmem = calloc(200, 1);
     create_unique_file_name(path_to_pmem);
     size_t pool_size = requested_pool_size;
-    printf("Requested pool size: %zu MB\n", pool_size/1000000);
+    if(verbose) {
+        printf("Requested pool size: %zu MB\n", pool_size / 1000000);
+    }
     if(pool_size < PMEMOBJ_MIN_POOL){
         pool_size = PMEMOBJ_MIN_POOL;
     }
@@ -293,26 +544,44 @@ void initialize(size_t requested_pool_size){
             perror("failed to open pool\n");
         }
     }
-    printf("Pool is provisioned!\n");
-    //root = pmemobj_root(pop, sizeof(struct my_root));
-    //rootp = pmemobj_direct(root);
-    printf("Setting up initial values.\n");
-    //rootp->oofset = 0;
+    if(verbose) {
+        printf("Pool is provisioned!\n");
+    }
+    root = pmemobj_root(pop, sizeof(struct my_root));
+    rootp = pmemobj_direct(root);
+
+    //PMEMoid pmeMoid = pmemoi
+
+    if(refresh_only){
+        pmemobj_close(pop);
+        printf("Only running to refresh the file\n");
+        exit(1);
+    }
+
+    if(verbose) {
+        printf("Setting up initial values.\n");
+    }
+    rootp->offset = 0;
+    rootp->tx_is_running = false;
+    rootp->recovery_count = 0;
     //long *t = &rootp->oofset;
     //t = 0;
     //uintptr_t *start = (uintptr_t *)rootp->pmem_start;
     //uintptr_t *current = (uintptr_t *)rootp->next_available_slot;
     //rootp->next_available_slot = rootp->pmem_start;
     //rootp->next_available_slot = start;
-    printf("Setting is done!\n");
+    if(verbose) {
+        printf("Setting is done!\n");
+    }
 }
 
 /* Needs to be inside a transaction, otherwise this space is wasted */
-static long offset = 0;
+//static long offset = 0;
 void *allocate_space_on_pmem(size_t size){
     /* Case if pmem is free */
-    printf("start\n");
-
+    if(verbose) {
+        printf("start\n");
+    }
     root = pmemobj_root(pop, sizeof(struct my_root));
     rootp = pmemobj_direct(root);
 
@@ -320,18 +589,28 @@ void *allocate_space_on_pmem(size_t size){
     //memcpy(t, &rootp->oofset, sizeof (long));
     //printf("Managed to read value! %lu\n", *t);
     void *currently_available_slot;
-    if(offset == 0){
-        printf("Pmem is empty\n");
-        offset = size+10000;
-        printf("ADDR: %p \n", rootp->pmem_start);
+    if(rootp->offset == 0){
+        if(verbose) {
+            printf("Pmem is empty\n");
+        }
+        rootp->offset = size+10000;
+        if(verbose) {
+            printf("ADDR: %p \n", rootp->pmem_start);
+        }
         return rootp->pmem_start;
     } else{
         /* Case if there is a reserved region on pmem */
-        printf("Pmem is used\n");
-        currently_available_slot = rootp->pmem_start + offset+10000;
-        printf("ADDR: %p \n", currently_available_slot);
-        offset = offset + size+10000;
-        printf("end\n");
+        if(verbose) {
+            printf("Pmem is used\n");
+        }
+        currently_available_slot = rootp->pmem_start + rootp->offset+10000;
+        if(verbose) {
+            printf("ADDR: %p \n", currently_available_slot);
+        }
+        rootp->offset = rootp->offset + size+10000;
+        if(verbose) {
+            printf("end\n");
+        }
     }
 
     return currently_available_slot;
@@ -353,13 +632,20 @@ wrap_post(void *wrapcxt, void *user_data)
 
    //drwrap_set_retval(wrapcxt, rootp->this_is_on_pmem);
    //drwrap_set_retval(wrapcxt, create_and_map_persistent_memory_pool());
-   printf("Allocating space \n");
+   if(verbose) {
+       printf("Allocating space \n");
+   }
    if(!initialized){
        //initialize(128000000);
        //initialized = true;
    }
    void *ptr = allocate_space_on_pmem(sz);
-   printf("Space was allocated\n");
+   if(verbose) {
+       printf("Space was allocated\n");
+   }
+   void *ret_ptr = drwrap_get_retval(wrapcxt);
+   printf("Original return value: %p is replaced with pmem: %p\n", ret_ptr, ptr);
+
    drwrap_set_retval(wrapcxt, ptr);
    //}
 #endif
@@ -471,7 +757,7 @@ static void catch_mem_ref(uintptr_t *addr, uintptr_t *pc, uint size){
 
    /* Check if this operation is updating persistent memory */
    if(addr >= start && addr <=finish && tx_active == true){
-       perror("Adding to transaction \n");
+       //print_with_log_level("Adding to transaction");
        pmemobj_tx_add_range_direct(addr, 64);
        /* Uncoment to text crash consistency */
 
@@ -883,18 +1169,32 @@ static void *create_and_map_persistent_memory_pool(){
 /* End */
 
 void sig_handler(int signum){
-    printf("Handling signal \n");
+    //if(verbose) {
+        printf("Handling signal \n");
+    //}
     pmemobj_tx_abort(-1);
     exit(1);
 }
 
+
+
 DR_EXPORT void
 dr_client_main(client_id_t id, int argc, const char *argv[])
 {
+    if(argc>1){
+        if(strcmp(argv[1], "refresh_file_only") == 0){
+            refresh_only = true;
+        }
+    }
     /* */
+    //printf("ARG 1: %s \n", argv[1]);
+    //if(strcmp(argv[1], "verbose") == 0){
+    //    verbose = true;
+    //}
     //initialize(64000000);
     /* Handles cases for both programs */
-    signal(SIGUSR1,sig_handler);
+    //signal(SIGUSR1,sig_handler);
+    //signal(SIGINT, sig_handler);
 
    drreg_options_t ops = { sizeof(ops), 4 /*max slots needed*/, false };
    dr_set_client_name("DynamoRIO Sample Client 'memval'", "http://dynamorio.org/issues");
-- 
GitLab