Rework some of the pthread stuff.

Init/uninit is now separate from portal vising.
The global lock has a better name and is now a rwlock.
Use a separate lock for the stats.
This commit is contained in:
Bill Currie 2013-03-18 14:26:52 +09:00
parent 134381f79b
commit c824e668ed
3 changed files with 63 additions and 29 deletions

View file

@ -39,16 +39,24 @@
#ifdef USE_PTHREADS
#include <pthread.h>
extern pthread_mutex_t *my_mutex;
#define LOCK \
extern pthread_rwlock_t *global_lock;
#define WRLOCK(l) \
do { \
if (options.threads > 1) \
pthread_mutex_lock (my_mutex); \
pthread_rwlock_wrlock (l); \
} while (0)
#define UNLOCK \
#define RDLOCK(l) \
do { \
if (options.threads > 1) \
pthread_rwlock_rdlock (l); \
} while (0)
#define UNLOCK(l) \
do { \
if (options.threads > 1) \
pthread_mutex_unlock (my_mutex); \
pthread_rwlock_unlock (l); \
} while (0)
#else
#define LOCK

View file

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

View file

@ -63,7 +63,9 @@
#define MAX_THREADS 4
#ifdef USE_PTHREADS
pthread_mutex_t *my_mutex;
pthread_attr_t threads_attrib;
pthread_rwlock_t *global_lock;
pthread_rwlock_t *stats_lock;
#endif
bsp_t *bsp;
@ -91,6 +93,37 @@ int *leafcluster; // leaf to cluster mappings as read from .prt file
int *working; // per thread current portal #
static void
InitThreads (void)
{
#ifdef USE_PTHREADS
if (pthread_attr_init (&threads_attrib) == -1)
Sys_Error ("pthread_attr_create failed");
if (pthread_attr_setstacksize (&threads_attrib, 0x100000) == -1)
Sys_Error ("pthread_attr_setstacksize failed");
global_lock = malloc (sizeof (pthread_rwlock_t));
if (pthread_rwlock_init (global_lock, 0))
Sys_Error ("pthread_rwlock_init failed");
stats_lock = malloc (sizeof (pthread_rwlock_t));
if (pthread_rwlock_init (stats_lock, 0))
Sys_Error ("pthread_rwlock_init failed");
#endif
}
static void
EndThreads (void)
{
#ifdef USE_PTHREADS
if (pthread_rwlock_destroy (global_lock) == -1)
Sys_Error ("pthread_rwlock_destroy failed");
free (global_lock);
if (pthread_rwlock_destroy (stats_lock) == -1)
Sys_Error ("pthread_rwlock_destroy failed");
free (stats_lock);
#endif
}
static void
PlaneFromWinding (winding_t *winding, plane_t *plane)
@ -264,7 +297,7 @@ GetNextPortal (void)
int min, j;
portal_t *p, *tp;
LOCK;
WRLOCK (global_lock);
min = 99999;
p = NULL;
@ -281,7 +314,7 @@ GetNextPortal (void)
p->status = stat_selected;
}
UNLOCK;
UNLOCK (global_lock);
return p;
}
@ -292,7 +325,7 @@ UpdateMightsee (cluster_t *source, cluster_t *dest)
int i, clusternum;
portal_t *portal;
LOCK;
WRLOCK (global_lock);
clusternum = dest - clusters;
for (i = 0; i < source->numportals; i++) {
portal = source->portals[i];
@ -304,7 +337,7 @@ UpdateMightsee (cluster_t *source, cluster_t *dest)
stats.mightseeupdate++;
}
}
UNLOCK;
UNLOCK (global_lock);
}
static void
@ -317,7 +350,7 @@ PortalCompleted (threaddata_t *thread, portal_t *completed)
int i, j;
completed->status = stat_done;
LOCK;
WRLOCK (stats_lock);
stats.portaltest += thread->stats.portaltest;
stats.portalpass += thread->stats.portalpass;
stats.portalcheck += thread->stats.portalcheck;
@ -331,7 +364,7 @@ PortalCompleted (threaddata_t *thread, portal_t *completed)
stats.mighttest += thread->stats.mighttest;
stats.vistest += thread->stats.vistest;
stats.mightseeupdate += thread->stats.mightseeupdate;
UNLOCK;
UNLOCK (stats_lock);
memset (&thread->stats, 0, sizeof (thread->stats));
changed = set_new_size_r (&thread->set_pool, portalclusters);
@ -543,24 +576,16 @@ CalcPortalVis (void)
{
pthread_t work_threads[MAX_THREADS + 1];
void *status;
pthread_attr_t attrib;
if (options.threads > 1) {
working = calloc (options.threads, sizeof (int));
my_mutex = malloc (sizeof (*my_mutex));
if (pthread_mutex_init (my_mutex, 0) == -1)
Sys_Error ("pthread_mutex_init failed");
if (pthread_attr_init (&attrib) == -1)
Sys_Error ("pthread_attr_create failed");
if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
Sys_Error ("pthread_attr_setstacksize failed");
for (i = 0; i < options.threads; i++) {
if (pthread_create (&work_threads[i], &attrib, LeafThread,
(void *) (intptr_t) i) == -1)
if (pthread_create (&work_threads[i], &threads_attrib,
LeafThread, (void *) (intptr_t) i) == -1)
Sys_Error ("pthread_create failed");
}
if (pthread_create (&work_threads[i], &attrib, WatchThread,
(void *) (intptr_t) i) == -1)
if (pthread_create (&work_threads[i], &threads_attrib,
WatchThread, (void *) (intptr_t) i) == -1)
Sys_Error ("pthread_create failed");
for (i = 0; i < options.threads; i++) {
@ -570,10 +595,7 @@ CalcPortalVis (void)
if (pthread_join (work_threads[i], &status) == -1)
Sys_Error ("pthread_join failed");
if (pthread_mutex_destroy (my_mutex) == -1)
Sys_Error ("pthread_mutex_destroy failed");
free (working);
free (my_mutex);
} else {
LeafThread (0);
}
@ -975,6 +997,8 @@ main (int argc, char **argv)
dstring_t *portalfile = dstring_new ();
QFile *f;
InitThreads ();
start = Sys_DoubleTime ();
this_program = argv[0];
@ -1035,5 +1059,7 @@ main (int argc, char **argv)
free (portals);
free (clusters);
EndThreads ();
return 0;
}