From cb096c601d69ae83557cf707381c1c5aead04a6c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 18 Mar 2013 15:03:11 +0900 Subject: [PATCH] Use a per-portal rwlock for portal updates. This should make qfvis scale a little better with cpu count. --- tools/qfvis/include/vis.h | 6 ++++++ tools/qfvis/source/flow.c | 4 ++-- tools/qfvis/source/qfvis.c | 26 ++++++++++++++++++-------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 75192b35a..92c304fb5 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -40,6 +40,7 @@ #ifdef USE_PTHREADS #include extern pthread_rwlock_t *global_lock; +extern pthread_rwlock_t *portal_locks; #define WRLOCK(l) \ do { \ @@ -58,6 +59,11 @@ extern pthread_rwlock_t *global_lock; if (options.threads > 1) \ pthread_rwlock_unlock (l); \ } while (0) + +#define WRLOCK_PORTAL(p) WRLOCK (&portal_locks[p - portals]) +#define RDLOCK_PORTAL(p) RDLOCK (&portal_locks[p - portals]) +#define UNLOCK_PORTAL(p) UNLOCK (&portal_locks[p - portals]) + #else #define LOCK #define UNLOCK diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 2885a8e28..84edf205e 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -459,11 +459,11 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) void PortalFlow (threaddata_t *data, portal_t *portal) { - WRLOCK (global_lock); + WRLOCK_PORTAL (portal); if (portal->status != stat_selected) Sys_Error ("PortalFlow: reflowed"); portal->status = stat_working; - UNLOCK (global_lock); + UNLOCK_PORTAL (portal); portal->visbits = set_new_size_r (&data->set_pool, portalclusters); diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 733b597d6..a7e63e640 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -65,6 +65,7 @@ #ifdef USE_PTHREADS pthread_attr_t threads_attrib; pthread_rwlock_t *global_lock; +pthread_rwlock_t *portal_locks; pthread_rwlock_t *stats_lock; #endif @@ -310,8 +311,10 @@ GetNextPortal (void) } if (p) { + WRLOCK_PORTAL (p); portal_count++; p->status = stat_selected; + UNLOCK_PORTAL (p); } UNLOCK (global_lock); @@ -325,19 +328,19 @@ UpdateMightsee (cluster_t *source, cluster_t *dest) int i, clusternum; portal_t *portal; - WRLOCK (global_lock); clusternum = dest - clusters; for (i = 0; i < source->numportals; i++) { portal = source->portals[i]; - if (portal->status != stat_none) - continue; - if (set_is_member (portal->mightsee, clusternum)) { - set_remove (portal->mightsee, clusternum); - portal->nummightsee--; - stats.mightseeupdate++; + WRLOCK_PORTAL (portal); + if (portal->status == stat_none) { + if (set_is_member (portal->mightsee, clusternum)) { + set_remove (portal->mightsee, clusternum); + portal->nummightsee--; + stats.mightseeupdate++; + } } + UNLOCK_PORTAL (portal); } - UNLOCK (global_lock); } static void @@ -888,6 +891,13 @@ LoadPortals (char *name) // each file portal is split into two memory portals, one for each // direction portals = calloc (2 * numportals, sizeof (portal_t)); +#ifdef USE_PTHREADS + portal_locks = calloc (2 * numportals, sizeof (pthread_rwlock_t)); + for (i = 0; i < 2 * numportals; i++) { + if (pthread_rwlock_init (&portal_locks[i], 0)) + Sys_Error ("pthread_rwlock_init failed"); + } +#endif clusters = calloc (portalclusters, sizeof (cluster_t));