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
#include <pthread.h>
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

View file

@ -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);

View file

@ -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;
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 (global_lock);
UNLOCK_PORTAL (portal);
}
}
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));