[m-rev.] for review: more efficient parallel mmc --make

Peter Wang novalazy at gmail.com
Thu Jul 30 14:27:24 AEST 2009


On 2009-07-29, Julien Fischer <juliensf at csse.unimelb.edu.au> wrote:
> 
> That looks okay.  Please check that it works (or is at least
> properly disabled) on systems other than Linux before committing.

Good old Mac OS X, never fails to underwhelm.  It supports named POSIX
semaphores but not *unnamed* semaphores.  So I changed the code to use pthread
mutexes instead, and somehow thought that it worked.  Then after committing
it I found out that it doesn't support process-shared pthread mutexes
either (I probably had tested the wrong Mercury compiler).

System V semaphores (different again) *do* work, so I've made it use those on
Darwin.  They also work on Linux, and if they work on Cygwin as well I might
just use them everywhere to reduce the conditional code.  Annoyingly that's
what I had implemented in the first place.

Is there a Cygwin machine I can log into?

Here are the changes since the reviewed patch:

diff --git a/Mmake.common.in b/Mmake.common.in
index aaca235..acd0486 100644
--- a/Mmake.common.in
+++ b/Mmake.common.in
@@ -214,7 +214,7 @@ PERL=@PERL@
 MATH_LIB=@MATH_LIB@
 
 # More libraries to link
-SEMAPHORE_LIBRARY=@SEMAPHORE_LIBRARY@
+THREAD_LIBS=@THREAD_LIBS@
 SOCKET_LIBRARY=@SOCKET_LIBRARY@
 NSL_LIBRARY=@NSL_LIBRARY@
 DL_LIBRARY=@DL_LIBRARY@
diff --git a/compiler/Mmakefile b/compiler/Mmakefile
index 62a0d60..7cc5156 100644
--- a/compiler/Mmakefile
+++ b/compiler/Mmakefile
@@ -68,7 +68,7 @@ MCFLAGS	     += --flags COMP_FLAGS $(CONFIG_OVERRIDE)
 MLOBJS       := ../main.$O \
 		../trace/lib$(EVENTSPEC_LIB_NAME).$A \
 		$(MLOBJS)
-MLLIBS       += $(SEMAPHORE_LIBRARY)
+MLLIBS       += $(THREAD_LIBS)
 ALL_MLLIBS    = $(MLLIBS) $(EXTRA_MLLIBS) $(GCC_BACKEND_LIBS)
 MLFLAGS      += --no-main --shared
 C2INITARGS   += $(MDBCOMP_DIR)/$(MDBCOMP_LIB_NAME).init
diff --git a/compiler/make.util.m b/compiler/make.util.m
index bc883d0..5c29bee 100644
--- a/compiler/make.util.m
+++ b/compiler/make.util.m
@@ -520,16 +520,29 @@ typedef struct MC_JobCtl MC_JobCtl;
 
 :- pragma foreign_decl("C", local,
 "
-#if defined(MR_HAVE_SEMAPHORE_H) && defined(MR_HAVE_SYS_MMAN_H)
-  #include <semaphore.h>
+#ifdef MR_HAVE_SYS_MMAN_H
   #include <sys/mman.h>
 
   /* Just in case. */
   #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
     #define MAP_ANONYMOUS MAP_ANON
   #endif
+#endif
+
+#ifdef MAP_ANONYMOUS
+  /*
+  ** Darwin 5.x doesn't implement unnamed POSIX semaphores nor process-shared
+  ** POSIX mutexes; the functions fail when you try to create them.
+  ** System V semaphores do work however.
+  */
+  #if !defined(__APPLE__) && defined(MR_HAVE_PTHREAD_H)
+    #include <pthread.h>
+
+    #define MC_HAVE_JOBCTL_IPC 1
+  #elif defined(MR_HAVE_SYS_SEM_H)
+    #include <sys/sem.h>
 
-  #ifdef MAP_ANONYMOUS
+    #define MC_USE_SYSV_SEMAPHORE 1
     #define MC_HAVE_JOBCTL_IPC 1
   #endif
 #endif
@@ -548,10 +561,14 @@ enum MC_TaskStatus {
 /* This structure is placed in shared memory. */
 struct MC_JobCtl {
     /* Static data. */
-    sem_t           jc_sem;
     MR_Integer      jc_total_tasks;
 
-    /* Dynamic data, protected with a semaphore. */
+    /* Dynamic data.  The mutex protects the rest. */
+  #ifdef MC_USE_SYSV_SEMAPHORE
+    int             jc_semid;
+  #else
+    pthread_mutex_t jc_mutex;
+  #endif
     MR_bool         jc_abort;
     MC_TaskStatus   jc_tasks[MR_VARIABLE_SIZED];
 };
@@ -572,29 +589,66 @@ static void         MC_unlock_job_ctl(MC_JobCtl *job_ctl);
 static MC_JobCtl *
 MC_create_job_ctl(MR_Integer total_tasks)
 {
-    sem_t       sem;
-    int         shmid;
-    MC_JobCtl   *job_ctl;
-    MR_Integer  i;
-
-    shmid = -1;
+    size_t              size;
+    MC_JobCtl           *job_ctl;
+    MR_Integer          i;
 
-    /* Create semaphore. */
-    if (sem_init(&sem, 1, 1) != 0) {
-        perror(""MC_create_job_ctl: sem_init"");
-        return NULL;
-    }
+    size = MC_JOB_CTL_SIZE(total_tasks);
 
     /* Create the shared memory segment. */
-    job_ctl = mmap(NULL, MC_JOB_CTL_SIZE(total_tasks), PROT_READ | PROT_WRITE,
+    job_ctl = mmap(NULL, size, PROT_READ | PROT_WRITE,
         MAP_ANONYMOUS | MAP_SHARED, -1, 0);
     if (job_ctl == (void *) -1) {
         perror(""MC_create_job_ctl: mmap"");
-        sem_destroy(&sem);
         return NULL;
     }
 
-    job_ctl->jc_sem = sem;
+#ifdef MC_USE_SYSV_SEMAPHORE
+    {
+        struct sembuf sb;
+
+        job_ctl->jc_semid = semget(IPC_PRIVATE, 1, 0600);
+        if (job_ctl->jc_semid == -1) {
+            perror(""MC_create_sem: semget"");
+            munmap(job_ctl, size);
+            return NULL;
+        }
+
+        sb.sem_num = 0;
+        sb.sem_op = 1;
+        sb.sem_flg = 0;
+        if (semop(job_ctl->jc_semid, &sb, 1) == -1) {
+            perror(""MC_create_sem: semop"");
+            semctl(job_ctl->jc_semid, 0, IPC_RMID);
+            munmap(job_ctl, size);
+            return NULL;
+        }
+    }
+#else
+    {
+        pthread_mutexattr_t mutex_attr;
+
+        pthread_mutexattr_init(&mutex_attr);
+        if (pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED)
+            != 0)
+        {
+            perror(""MC_create_job_ctl: pthread_mutexattr_setpshared"");
+            pthread_mutexattr_destroy(&mutex_attr);
+            munmap(job_ctl, size);
+            return NULL;
+        }
+
+        if (pthread_mutex_init(&job_ctl->jc_mutex, &mutex_attr) != 0) {
+            perror(""MC_create_job_ctl: sem_init"");
+            pthread_mutexattr_destroy(&mutex_attr);
+            munmap(job_ctl, size);
+            return NULL;
+        }
+
+        pthread_mutexattr_destroy(&mutex_attr);
+    }
+#endif
+
     job_ctl->jc_total_tasks = total_tasks;
     job_ctl->jc_abort = MR_FALSE;
     for (i = 0; i < total_tasks; i++) {
@@ -607,13 +661,35 @@ MC_create_job_ctl(MR_Integer total_tasks)
 static void
 MC_lock_job_ctl(MC_JobCtl *job_ctl)
 {
-    sem_wait(&job_ctl->jc_sem);
+#ifdef MC_USE_SYSV_SEMAPHORE
+    struct sembuf sb;
+
+    sb.sem_num = 0;
+    sb.sem_op = -1;
+    sb.sem_flg = 0;
+    if (semop(job_ctl->jc_semid, &sb, 1) == -1) {
+        perror(""MC_lock_job_ctl: semop"");
+    }
+#else
+    pthread_mutex_lock(&job_ctl->jc_mutex);
+#endif
 }
 
 static void
 MC_unlock_job_ctl(MC_JobCtl *job_ctl)
 {
-    sem_post(&job_ctl->jc_sem);
+#ifdef MC_USE_SYSV_SEMAPHORE
+    struct sembuf sb;
+
+    sb.sem_num = 0;
+    sb.sem_op = 1;
+    sb.sem_flg = 0;
+    if (semop(job_ctl->jc_semid, &sb, 1) == -1) {
+        perror(""MC_unlock_job_ctl: semop"");
+    }
+#else
+    pthread_mutex_unlock(&job_ctl->jc_mutex);
+#endif
 }
 
 #endif /* MC_HAVE_JOBCTL_IPC */
@@ -638,8 +714,6 @@ have_job_ctl_ipc :-
 #endif
 ").
 
-    % The job control structure should really be unique that's too annoying.
-    %
 :- pred create_job_ctl(int::in, maybe(job_ctl)::out, io::di, io::uo) is det.
 
 :- pragma foreign_proc("C",
@@ -670,7 +744,12 @@ have_job_ctl_ipc :-
         may_not_duplicate],
 "
 #ifdef MC_HAVE_JOBCTL_IPC
-    sem_destroy(&JobCtl->jc_sem);
+  #ifdef MC_USE_SYSV_SEMAPHORE
+    semctl(JobCtl->jc_semid, 0, IPC_RMID);
+  #else
+    pthread_mutex_destroy(&JobCtl->jc_mutex);
+  #endif
+
     munmap(JobCtl, MC_JOB_CTL_SIZE(JobCtl->jc_total_tasks));
 #endif
     IO = IO0;
diff --git a/configure.in b/configure.in
index b18d87e..d05fcef 100644
--- a/configure.in
+++ b/configure.in
@@ -1096,7 +1096,7 @@ MERCURY_CHECK_FOR_HEADERS( \
         asm/sigcontext.h sys/param.h sys/time.h sys/times.h \
         sys/types.h sys/stat.h fcntl.h termios.h sys/ioctl.h \
         sys/stropts.h windows.h dirent.h getopt.h malloc.h \
-        semaphore.h pthread.h time.h spawn.h fenv.h sys/mman.h)
+        semaphore.h pthread.h time.h spawn.h fenv.h sys/mman.h sys/sem.h)
 
 if test "$MR_HAVE_GETOPT_H" = 1; then
     GETOPT_H_AVAILABLE=yes
@@ -4379,15 +4379,6 @@ MERCURY_CHECK_FOR_IEEE_FUNC(isinff)
 
 #-----------------------------------------------------------------------------#
 #
-# Check whether POSIX semaphores requires -lrt
-#
-
-AC_CHECK_LIB(rt, sem_init, SEMAPHORE_LIBRARY=-lrt, SEMAPHORE_LIBRARY="")
-
-AC_SUBST(SEMAPHORE_LIBRARY)
-
-#-----------------------------------------------------------------------------#
-#
 # Check whether sockets work (we need them for the external debugger)
 #
 
diff --git a/runtime/mercury_conf.h.in b/runtime/mercury_conf.h.in
index 987e84c..99fee3d 100644
--- a/runtime/mercury_conf.h.in
+++ b/runtime/mercury_conf.h.in
@@ -135,6 +135,7 @@
 ** 	MR_HAVE_SPAWN_H		we have <spawn.h>
 **	MR_HAVE_FENV_H		we have <fenv.h>
 **	MR_HAVE_SYS_MMAN_H	we have <sys/mman.h>
+**	MR_HAVE_SYS_SEM_H 	we have <sys/sem.h>
 */
 #undef	MR_HAVE_SYS_SIGINFO_H
 #undef	MR_HAVE_SYS_SIGNAL_H
@@ -163,6 +164,7 @@
 #undef	MR_HAVE_SPAWN_H
 #undef	MR_HAVE_FENV_H
 #undef	MR_HAVE_SYS_MMAN_H
+#undef	MR_HAVE_SYS_SEM_H
 
 /*
 ** MR_HAVE_POSIX_TIMES is defined if we have the POSIX

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list