Use a per-portal rwlock for portal updates.

This should make qfvis scale a little better with cpu count.
This commit is contained in:
Bill Currie 2013-03-18 15:03:11 +09:00
parent c824e668ed
commit cb096c601d
3 changed files with 26 additions and 10 deletions

View file

@ -40,6 +40,7 @@
#ifdef USE_PTHREADS #ifdef USE_PTHREADS
#include <pthread.h> #include <pthread.h>
extern pthread_rwlock_t *global_lock; extern pthread_rwlock_t *global_lock;
extern pthread_rwlock_t *portal_locks;
#define WRLOCK(l) \ #define WRLOCK(l) \
do { \ do { \
@ -58,6 +59,11 @@ extern pthread_rwlock_t *global_lock;
if (options.threads > 1) \ if (options.threads > 1) \
pthread_rwlock_unlock (l); \ pthread_rwlock_unlock (l); \
} while (0) } 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 #else
#define LOCK #define LOCK
#define UNLOCK #define UNLOCK

View file

@ -459,11 +459,11 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack)
void void
PortalFlow (threaddata_t *data, portal_t *portal) PortalFlow (threaddata_t *data, portal_t *portal)
{ {
WRLOCK (global_lock); WRLOCK_PORTAL (portal);
if (portal->status != stat_selected) if (portal->status != stat_selected)
Sys_Error ("PortalFlow: reflowed"); Sys_Error ("PortalFlow: reflowed");
portal->status = stat_working; portal->status = stat_working;
UNLOCK (global_lock); UNLOCK_PORTAL (portal);
portal->visbits = set_new_size_r (&data->set_pool, portalclusters); portal->visbits = set_new_size_r (&data->set_pool, portalclusters);

View file

@ -65,6 +65,7 @@
#ifdef USE_PTHREADS #ifdef USE_PTHREADS
pthread_attr_t threads_attrib; pthread_attr_t threads_attrib;
pthread_rwlock_t *global_lock; pthread_rwlock_t *global_lock;
pthread_rwlock_t *portal_locks;
pthread_rwlock_t *stats_lock; pthread_rwlock_t *stats_lock;
#endif #endif
@ -310,8 +311,10 @@ GetNextPortal (void)
} }
if (p) { if (p) {
WRLOCK_PORTAL (p);
portal_count++; portal_count++;
p->status = stat_selected; p->status = stat_selected;
UNLOCK_PORTAL (p);
} }
UNLOCK (global_lock); UNLOCK (global_lock);
@ -325,19 +328,19 @@ UpdateMightsee (cluster_t *source, cluster_t *dest)
int i, clusternum; int i, clusternum;
portal_t *portal; portal_t *portal;
WRLOCK (global_lock);
clusternum = dest - clusters; clusternum = dest - clusters;
for (i = 0; i < source->numportals; i++) { for (i = 0; i < source->numportals; i++) {
portal = source->portals[i]; portal = source->portals[i];
if (portal->status != stat_none) WRLOCK_PORTAL (portal);
continue; if (portal->status == stat_none) {
if (set_is_member (portal->mightsee, clusternum)) { if (set_is_member (portal->mightsee, clusternum)) {
set_remove (portal->mightsee, clusternum); set_remove (portal->mightsee, clusternum);
portal->nummightsee--; portal->nummightsee--;
stats.mightseeupdate++; stats.mightseeupdate++;
} }
} }
UNLOCK (global_lock); UNLOCK_PORTAL (portal);
}
} }
static void static void
@ -888,6 +891,13 @@ LoadPortals (char *name)
// each file portal is split into two memory portals, one for each // each file portal is split into two memory portals, one for each
// direction // direction
portals = calloc (2 * numportals, sizeof (portal_t)); 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)); clusters = calloc (portalclusters, sizeof (cluster_t));