aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSergiusz Bazanski <q3k@q3k.org>2018-07-20 18:34:59 +0100
committerSergiusz Bazanski <q3k@q3k.org>2018-07-20 18:34:59 +0100
commit0311a27a53922783363ab607ca8f3832980990c6 (patch)
tree9cb3555b233b6224d946a263dceb1ebff6569d80 /common
parent5d0dbe9db961f6dbd2494bd8ab730d8926d01626 (diff)
downloadnextpnr-0311a27a53922783363ab607ca8f3832980990c6.tar.gz
nextpnr-0311a27a53922783363ab607ca8f3832980990c6.tar.bz2
nextpnr-0311a27a53922783363ab607ca8f3832980990c6.zip
Use UI lock for yielding
Diffstat (limited to 'common')
-rw-r--r--common/nextpnr.h32
-rw-r--r--common/placer1.cc6
-rw-r--r--common/router1.cc12
3 files changed, 38 insertions, 12 deletions
diff --git a/common/nextpnr.h b/common/nextpnr.h
index d42d3446..8b8299bc 100644
--- a/common/nextpnr.h
+++ b/common/nextpnr.h
@@ -318,6 +318,11 @@ struct BaseCtx
std::mutex mutex;
pthread_t mutex_owner;
+ // Lock to be taken by UI when wanting to access context - the yield()
+ // method will lock/unlock it when its' released the main mutex to make
+ // sure the UI is not starved.
+ std::mutex ui_mutex;
+
// ID String database.
mutable std::unordered_map<std::string, int> *idstring_str_to_idx;
mutable std::vector<const std::string *> *idstring_idx_to_str;
@@ -353,12 +358,31 @@ struct BaseCtx
mutex.unlock();
}
- // TODO(q3k): get rid of this hack
+ // Must be called by the UI before rendering data. This lock will be
+ // prioritized when processing code calls yield().
+ void lock_ui(void)
+ {
+ ui_mutex.lock();
+ mutex.lock();
+ }
+
+ void unlock_ui(void)
+ {
+ mutex.unlock();
+ ui_mutex.unlock();
+ }
+
+ // Yield to UI by unlocking the main mutex, flashing the UI mutex and
+ // relocking the main mutex. Call this when you're performing a
+ // long-standing action while holding a lock to let the UI show
+ // visualization updates.
+ // Must be called with the main lock taken.
void yield(void)
{
- for (int i = 0; i < 10; i++) {
- pthread_yield();
- }
+ unlock();
+ ui_mutex.lock();
+ ui_mutex.unlock();
+ lock();
}
IdString id(const std::string &s) const { return IdString(this, s); }
diff --git a/common/placer1.cc b/common/placer1.cc
index c8ba71a4..025c7c15 100644
--- a/common/placer1.cc
+++ b/common/placer1.cc
@@ -156,8 +156,6 @@ class SAPlacer
// Main simulated annealing loop
for (int iter = 1;; iter++) {
- ctx->yield();
- ctx->lock();
n_move = n_accept = 0;
improved = false;
@@ -242,7 +240,9 @@ class SAPlacer
metrics[net.first] = wl;
curr_metric += wl;
}
- ctx->unlock();
+
+ // Let the UI show visualization updates.
+ ctx->yield();
}
// Final post-pacement validitiy check
ctx->lock();
diff --git a/common/router1.cc b/common/router1.cc
index 3a0aa19b..3e4416df 100644
--- a/common/router1.cc
+++ b/common/router1.cc
@@ -495,8 +495,6 @@ bool router1(Context *ctx)
#endif
return false;
}
- ctx->yield();
- ctx->lock();
iterCnt++;
if (ctx->verbose)
@@ -533,9 +531,11 @@ bool router1(Context *ctx)
ripupQueue.insert(net_name);
}
- if ((ctx->verbose || iterCnt == 1) && !printNets && (netCnt % 100 == 0))
+ if ((ctx->verbose || iterCnt == 1) && !printNets && (netCnt % 100 == 0)) {
log_info(" processed %d nets. (%d routed, %d failed)\n", netCnt, netCnt - int(ripupQueue.size()),
int(ripupQueue.size()));
+ ctx->yield();
+ }
}
int normalRouteCnt = netCnt - int(ripupQueue.size());
@@ -596,8 +596,10 @@ bool router1(Context *ctx)
ripCnt += router.rippedNets.size();
- if ((ctx->verbose || iterCnt == 1) && !printNets && (netCnt % 100 == 0))
+ if ((ctx->verbose || iterCnt == 1) && !printNets && (netCnt % 100 == 0)) {
log_info(" routed %d nets, ripped %d nets.\n", netCnt, ripCnt);
+ ctx->yield();
+ }
}
if ((ctx->verbose || iterCnt == 1) && (netCnt % 100 != 0))
@@ -626,7 +628,7 @@ bool router1(Context *ctx)
if (iterCnt == 8 || iterCnt == 16 || iterCnt == 32 || iterCnt == 64 || iterCnt == 128)
ripup_penalty += ctx->getRipupDelayPenalty();
- ctx->unlock();
+ ctx->yield();
}
log_info("routing complete after %d iterations.\n", iterCnt);