From: weiyu <weiyuluo1232@gmail.com> Date: Tue, 15 Sep 2020 01:17:04 +0000 (-0700) Subject: Try to catch data races for memcpy X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=92661595546bc783908d3795fd53265988565e02;p=c11tester.git Try to catch data races for memcpy --- diff --git a/clockvector.cc b/clockvector.cc index 9820b8f9..ba5d1f4b 100644 --- a/clockvector.cc +++ b/clockvector.cc @@ -24,7 +24,7 @@ ClockVector::ClockVector(ClockVector *parent, const ModelAction *act) clock = (modelclock_t *)snapshot_calloc(num_threads, sizeof(int)); if (parent) - std::memcpy(clock, parent->clock, parent->num_threads * sizeof(modelclock_t)); + real_memcpy(clock, parent->clock, parent->num_threads * sizeof(modelclock_t)); if (act != NULL) clock[id_to_int(act->get_tid())] = act->get_seq_number(); diff --git a/datarace.cc b/datarace.cc index 9c403668..13aa4655 100644 --- a/datarace.cc +++ b/datarace.cc @@ -575,8 +575,8 @@ struct DataRace * fullRaceCheckRead(thread_id_t thread, const void *location, ui int newCapacity = copytoindex * 2; thread_id_t *newthread = (thread_id_t *)snapshot_malloc(sizeof(thread_id_t) * newCapacity); modelclock_t *newreadClock = (modelclock_t *)snapshot_malloc(sizeof(modelclock_t) * newCapacity); - std::memcpy(newthread, record->thread, copytoindex * sizeof(thread_id_t)); - std::memcpy(newreadClock, record->readClock, copytoindex * sizeof(modelclock_t)); + real_memcpy(newthread, record->thread, copytoindex * sizeof(thread_id_t)); + real_memcpy(newreadClock, record->readClock, copytoindex * sizeof(modelclock_t)); snapshot_free(record->readClock); snapshot_free(record->thread); record->readClock = newreadClock; diff --git a/main.cc b/main.cc index b0931f75..36055107 100644 --- a/main.cc +++ b/main.cc @@ -114,7 +114,7 @@ void parse_options(struct model_params *params) { } argc++; //first parameter is executable name char optcpy[index + 1]; - memcpy(optcpy, options, index+1); + real_memcpy(optcpy, options, index+1); char * argv[argc + 1]; argv[0] = NULL; argv[1] = optcpy; diff --git a/model.cc b/model.cc index 4b2143dc..450aac5a 100644 --- a/model.cc +++ b/model.cc @@ -21,6 +21,7 @@ #include "plugins.h" ModelChecker *model = NULL; +int inside_model = 0; void placeholder(void *) { ASSERT(0); @@ -80,6 +81,7 @@ ModelChecker::ModelChecker() : "Copyright (c) 2013 and 2019 Regents of the University of California. All rights reserved.\n" "Distributed under the GPLv2\n" "Written by Weiyu Luo, Brian Norris, and Brian Demsky\n\n"); + init_memory_ops(); memset(&stats,0,sizeof(struct execution_stats)); init_thread = new Thread(execution->get_next_id(), (thrd_t *) model_malloc(sizeof(thrd_t)), &placeholder, NULL, NULL); #ifdef TLS @@ -353,7 +355,7 @@ void ModelChecker::startRunExecution(Thread *old) { Thread *thr = getNextThread(old); if (thr != nullptr) { scheduler->set_current_thread(thr); - + inside_model = 0; if (Thread::swap(old, thr) < 0) { perror("swap threads"); exit(EXIT_FAILURE); @@ -452,6 +454,8 @@ uint64_t ModelChecker::switch_thread(ModelAction *act) delete act; return 0; } + inside_model = 1; + DBG(); Thread *old = thread_current(); old->set_state(THREAD_READY); diff --git a/model.h b/model.h index e35457e1..331ea18a 100644 --- a/model.h +++ b/model.h @@ -104,6 +104,7 @@ private: void print_stats() const; }; +extern int inside_model; extern ModelChecker *model; void parse_options(struct model_params *params); void install_trace_analyses(ModelExecution *execution); diff --git a/mymemory.cc b/mymemory.cc index dd22909c..e82f8d2e 100644 --- a/mymemory.cc +++ b/mymemory.cc @@ -110,3 +110,69 @@ void Thread_free(void *ptr) { snapshot_free(ptr); } + +void * (*volatile real_memcpy)(void * dst, const void *src, size_t n) = NULL; +void * (*volatile real_memmove)(void * dst, const void *src, size_t len) = NULL; +void (*volatile real_bzero)(void * dst, size_t len) = NULL; +void * (*volatile real_memset)(void * dst, int c, size_t len) = NULL; + +void init_memory_ops() +{ + if (!real_memcpy) { + real_memcpy = (void * (*)(void * dst, const void *src, size_t n)) 1; + real_memcpy = (void * (*)(void * dst, const void *src, size_t n))dlsym(RTLD_NEXT, "memcpy"); + } + if (!real_memmove) { + real_memmove = (void * (*)(void * dst, const void *src, size_t n)) 1; + real_memmove = (void * (*)(void * dst, const void *src, size_t n))dlsym(RTLD_NEXT, "memmove"); + } + if (!real_memset) { + real_memset = (void * (*)(void * dst, int c, size_t n)) 1; + real_memset = (void * (*)(void * dst, int c, size_t n))dlsym(RTLD_NEXT, "memset"); + } + if (!real_bzero) { + real_bzero = (void (*)(void * dst, size_t len)) 1; + real_bzero = (void (*)(void * dst, size_t len))dlsym(RTLD_NEXT, "bzero"); + } +} + +void * memcpy(void * dst, const void * src, size_t n) { + if (false && model && !inside_model) { + thread_id_t tid = thread_current_id(); + if (((uintptr_t)src&7) == 0 && ((uintptr_t)dst&7) == 0 && (n&7) == 0) { + for (uint i = 0; i < (n>>3); i++) { + raceCheckRead64(tid, (void *)(((char *)src) + i)); + ((volatile uint64_t *)dst)[i] = ((uint64_t *)src)[i]; + raceCheckWrite64(tid, (void *)(((char *)src) + i)); + } + } else if (((uintptr_t)src&3) == 0 && ((uintptr_t)dst&3) == 0 && (n&3) == 0) { + for (uint i = 0; i < (n>>2); i++) { + raceCheckRead32(tid, (void *)(((char *)src) + i)); + ((volatile uint32_t *)dst)[i] = ((uint32_t *)src)[i]; + raceCheckWrite32(tid, (void *)(((char *)src) + i)); + } + } else if (((uintptr_t)src&1) == 0 && ((uintptr_t)dst&1) == 0 && (n&1) == 0) { + for (uint i = 0; i < (n>>1); i++) { + raceCheckRead16(tid, (void *)(((char *)src) + i)); + ((volatile uint16_t *)dst)[i] = ((uint16_t *)src)[i]; + raceCheckWrite16(tid, (void *)(((char *)src) + i)); + } + } else { + for(uint i=0;i<n;i++) { + raceCheckRead8(tid, (void *)(((char *)src) + i)); + ((volatile char *)dst)[i] = ((char *)src)[i]; + raceCheckWrite8(tid, (void *)(((char *)src) + i)); + } + } + } else { + if (((uintptr_t)real_memcpy) < 2) { + for(uint i=0;i<n;i++) { + ((volatile char *)dst)[i] = ((char *)src)[i]; + } + return dst; + } + + return real_memcpy(dst, src, n); + } + return dst; +} diff --git a/mymemory.h b/mymemory.h index 6fb2992b..88d92dca 100644 --- a/mymemory.h +++ b/mymemory.h @@ -63,6 +63,8 @@ extern mspace sStaticSpace; void * Thread_malloc(size_t size); void Thread_free(void *ptr); +void init_memory_ops(); + /** @brief Provides a non-snapshotting allocator for use in STL classes. * * The code was adapted from a code example from the book The C++ @@ -260,6 +262,11 @@ extern mspace create_mspace(size_t capacity, int locked); extern mspace model_snapshot_space; +extern void * (*volatile real_memcpy)(void * dst, const void *src, size_t n); +extern void * (*volatile real_memmove)(void * dst, const void *src, size_t len); +extern void (*volatile real_bzero)(void * dst, size_t len); +extern void * (*volatile real_memset)(void * dst, int c, size_t len); + #ifdef __cplusplus }; /* end of extern "C" */ #endif diff --git a/schedule.cc b/schedule.cc index f55c7b0d..74ecf406 100644 --- a/schedule.cc +++ b/schedule.cc @@ -59,7 +59,7 @@ void Scheduler::set_enabled(Thread *t, enabled_type_t enabled_status) { enabled_type_t *new_enabled = (enabled_type_t *)snapshot_malloc(sizeof(enabled_type_t) * (threadid + 1)); memset(&new_enabled[enabled_len], 0, (threadid + 1 - enabled_len) * sizeof(enabled_type_t)); if (enabled != NULL) { - memcpy(new_enabled, enabled, enabled_len * sizeof(enabled_type_t)); + real_memcpy(new_enabled, enabled, enabled_len * sizeof(enabled_type_t)); snapshot_free(enabled); } enabled = new_enabled; diff --git a/stl-model.h b/stl-model.h index 611520fc..53e41206 100644 --- a/stl-model.h +++ b/stl-model.h @@ -369,7 +369,7 @@ public: _size(_capacity), capacity(_capacity), array((type *) model_malloc(sizeof(type) * _capacity)) { - memcpy(array, _array, capacity * sizeof(type)); + real_memcpy(array, _array, capacity * sizeof(type)); } void pop_back() { _size--; @@ -474,7 +474,7 @@ public: _size(_capacity), capacity(_capacity), array((type *) snapshot_malloc(sizeof(type) * _capacity)) { - memcpy(array, _array, capacity * sizeof(type)); + real_memcpy(array, _array, capacity * sizeof(type)); } void pop_back() { _size--;