This commit is contained in:
Gianluca Martino 2025-10-29 22:36:49 +01:00 committed by GitHub
commit 9e607e5c04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 34 additions and 37 deletions

View File

@ -467,7 +467,6 @@ static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
static void *close_dumpfile(void) static void *close_dumpfile(void)
{ {
vcd_work_terminate();
lxt2_wr_close(dump_file); lxt2_wr_close(dump_file);
dump_file = NULL; dump_file = NULL;
return NULL; return NULL;

View File

@ -21,10 +21,13 @@
# include <map> # include <map>
# include <set> # include <set>
# include <string> # include <string>
# include <pthread.h>
# include <cstdlib> # include <cstdlib>
# include <cstdint>
# include <cstring> # include <cstring>
# include <cassert> # include <cassert>
# include <thread>
# include <mutex>
# include <condition_variable>
/* /*
Nexus Id cache Nexus Id cache
@ -83,7 +86,7 @@ extern "C" void vcd_scope_names_delete(void)
vcd_scope_names_set.clear(); vcd_scope_names_set.clear();
} }
static pthread_t work_thread; static std::thread work_thread;
static const unsigned WORK_QUEUE_SIZE = 128*1024; static const unsigned WORK_QUEUE_SIZE = 128*1024;
static const unsigned WORK_QUEUE_BATCH_MIN = 4*1024; static const unsigned WORK_QUEUE_BATCH_MIN = 4*1024;
@ -93,10 +96,10 @@ static struct vcd_work_item_s work_queue[WORK_QUEUE_SIZE];
static volatile unsigned work_queue_next = 0; static volatile unsigned work_queue_next = 0;
static volatile unsigned work_queue_fill = 0; static volatile unsigned work_queue_fill = 0;
static pthread_mutex_t work_queue_mutex = PTHREAD_MUTEX_INITIALIZER; static std::mutex work_queue_mutex;
static pthread_cond_t work_queue_is_empty_sig = PTHREAD_COND_INITIALIZER; static std::condition_variable work_queue_is_empty_sig;
static pthread_cond_t work_queue_notempty_sig = PTHREAD_COND_INITIALIZER; static std::condition_variable work_queue_notempty_sig;
static pthread_cond_t work_queue_minfree_sig = PTHREAD_COND_INITIALIZER; static std::condition_variable work_queue_minfree_sig;
extern "C" struct vcd_work_item_s* vcd_work_thread_peek(void) extern "C" struct vcd_work_item_s* vcd_work_thread_peek(void)
@ -107,10 +110,8 @@ extern "C" struct vcd_work_item_s* vcd_work_thread_peek(void)
// one item that I can peek at. I only need to lock if I must // one item that I can peek at. I only need to lock if I must
// wait for the work_queue_fill to become non-zero. // wait for the work_queue_fill to become non-zero.
if (work_queue_fill == 0) { if (work_queue_fill == 0) {
pthread_mutex_lock(&work_queue_mutex); std::unique_lock<std::mutex> lock(work_queue_mutex);
while (work_queue_fill == 0) work_queue_notempty_sig.wait(lock, []{ return work_queue_fill != 0; });
pthread_cond_wait(&work_queue_notempty_sig, &work_queue_mutex);
pthread_mutex_unlock(&work_queue_mutex);
} }
return work_queue + work_queue_next; return work_queue + work_queue_next;
@ -118,7 +119,7 @@ extern "C" struct vcd_work_item_s* vcd_work_thread_peek(void)
extern "C" void vcd_work_thread_pop(void) extern "C" void vcd_work_thread_pop(void)
{ {
pthread_mutex_lock(&work_queue_mutex); std::lock_guard<std::mutex> lock(work_queue_mutex);
unsigned use_fill = work_queue_fill - 1; unsigned use_fill = work_queue_fill - 1;
work_queue_fill = use_fill; work_queue_fill = use_fill;
@ -136,11 +137,10 @@ extern "C" void vcd_work_thread_pop(void)
work_queue_next = use_next; work_queue_next = use_next;
if (use_fill == WORK_QUEUE_SIZE-WORK_QUEUE_BATCH_MIN) if (use_fill == WORK_QUEUE_SIZE-WORK_QUEUE_BATCH_MIN)
pthread_cond_signal(&work_queue_minfree_sig); work_queue_minfree_sig.notify_one();
else if (use_fill == 0) else if (use_fill == 0)
pthread_cond_signal(&work_queue_is_empty_sig); work_queue_is_empty_sig.notify_one();
pthread_mutex_unlock(&work_queue_mutex);
} }
/* /*
@ -157,20 +157,21 @@ static unsigned current_batch_base = 0;
extern "C" void vcd_work_start( void* (*fun) (void*), void*arg ) extern "C" void vcd_work_start( void* (*fun) (void*), void*arg )
{ {
pthread_create(&work_thread, 0, fun, arg); work_thread = std::thread(fun, arg);
} }
static struct vcd_work_item_s* grab_item(void) static struct vcd_work_item_s* grab_item(void)
{ {
if (current_batch_alloc == 0) { if (current_batch_alloc == 0) {
pthread_mutex_lock(&work_queue_mutex); {
while ((WORK_QUEUE_SIZE-work_queue_fill) < WORK_QUEUE_BATCH_MIN) std::unique_lock<std::mutex> lock(work_queue_mutex);
pthread_cond_wait(&work_queue_minfree_sig, &work_queue_mutex); work_queue_minfree_sig.wait(lock, [] {
return (WORK_QUEUE_SIZE - work_queue_fill) >= WORK_QUEUE_BATCH_MIN;
});
current_batch_base = work_queue_next + work_queue_fill; current_batch_base = work_queue_next + work_queue_fill;
current_batch_alloc = WORK_QUEUE_SIZE - work_queue_fill; current_batch_alloc = WORK_QUEUE_SIZE - work_queue_fill;
}
pthread_mutex_unlock(&work_queue_mutex);
if (current_batch_base >= WORK_QUEUE_SIZE) if (current_batch_base >= WORK_QUEUE_SIZE)
current_batch_base -= WORK_QUEUE_SIZE; current_batch_base -= WORK_QUEUE_SIZE;
@ -193,7 +194,7 @@ static struct vcd_work_item_s* grab_item(void)
static void end_batch(void) static void end_batch(void)
{ {
pthread_mutex_lock(&work_queue_mutex); std::lock_guard<std::mutex> lock(work_queue_mutex);
unsigned use_fill = work_queue_fill; unsigned use_fill = work_queue_fill;
bool was_empty_flag = (use_fill==0) && (current_batch_cnt > 0); bool was_empty_flag = (use_fill==0) && (current_batch_cnt > 0);
@ -205,9 +206,8 @@ static void end_batch(void)
current_batch_cnt = 0; current_batch_cnt = 0;
if (was_empty_flag) if (was_empty_flag)
pthread_cond_signal(&work_queue_notempty_sig); work_queue_notempty_sig.notify_one();
pthread_mutex_unlock(&work_queue_mutex);
} }
static inline void unlock_item(bool flush_batch =false) static inline void unlock_item(bool flush_batch =false)
@ -223,10 +223,8 @@ extern "C" void vcd_work_sync(void)
end_batch(); end_batch();
if (work_queue_fill > 0) { if (work_queue_fill > 0) {
pthread_mutex_lock(&work_queue_mutex); std::unique_lock<std::mutex> lock(work_queue_mutex);
while (work_queue_fill > 0) work_queue_is_empty_sig.wait(lock, []{ return work_queue_fill == 0; });
pthread_cond_wait(&work_queue_is_empty_sig, &work_queue_mutex);
pthread_mutex_unlock(&work_queue_mutex);
} }
} }
@ -281,5 +279,5 @@ extern "C" void vcd_work_terminate(void)
struct vcd_work_item_s*cell = grab_item(); struct vcd_work_item_s*cell = grab_item();
cell->type = WT_TERMINATE; cell->type = WT_TERMINATE;
unlock_item(true); unlock_item(true);
pthread_join(work_thread, 0); work_thread.join();
} }