Merge 60f5026ae4 into a7502173d3
This commit is contained in:
commit
9e607e5c04
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue