Index: trunk/src/kmk/incdep.c
===================================================================
--- trunk/src/kmk/incdep.c	(revision 1851)
+++ trunk/src/kmk/incdep.c	(revision 1852)
@@ -76,4 +76,9 @@
 #endif
 
+#ifdef __APPLE__
+# include <malloc/malloc.h>
+# define PARSE_IN_WORKER
+#endif
+
 
 /*******************************************************************************
@@ -195,5 +200,5 @@
 /* The handles to the worker threads. */
 #ifdef HAVE_PTHREAD
-static pthread_t incdep_threads[2];
+static pthread_t incdep_threads[1];
 #elif defined (WINDOWS32)
 static HANDLE incdep_threads[2];
@@ -206,4 +211,9 @@
 static int volatile incdep_terminate;
 
+#ifdef __APPLE__
+/* malloc zone for the incdep threads. */
+static malloc_zone_t *incdep_zone;
+#endif
+
 
 /*******************************************************************************
@@ -211,5 +221,59 @@
 *******************************************************************************/
 static void incdep_flush_it (struct floc *);
-static void eval_include_dep_file (struct incdep *, struct floc *, int);
+static void eval_include_dep_file (struct incdep *, struct floc *);
+
+
+/* xmalloc wrapper.
+   For working around multithreaded performance problems found on Darwin,
+   Linux (glibc), and possibly other systems. */
+static void *incdep_xmalloc (struct incdep *cur, size_t size)
+{
+  void *ptr;
+
+#ifdef __APPLE__
+  if (cur && cur->is_worker)
+    {
+      ptr = malloc_zone_malloc (incdep_zone, size);
+      if (!ptr)
+        fatal (NILF, _("virtual memory exhausted"));
+    }
+  else
+    ptr = xmalloc (size);
+#else
+  ptr = xmalloc (size);
+#endif
+
+  (void)cur;
+  return ptr;
+}
+
+/* memset(malloc(sz),'\0',sz) wrapper. */
+static void *incdep_xcalloc (struct incdep *cur, size_t size)
+{
+  void *ptr;
+
+#ifdef __APPLE__
+  if (cur && cur->is_worker)
+    ptr = malloc_zone_calloc (incdep_zone, size, 1);
+  else
+    ptr = calloc (size, 1);
+#else
+  ptr = calloc (size, 1);
+#endif
+  if (!ptr)
+    fatal (NILF, _("virtual memory exhausted"));
+
+  (void)cur;
+  return ptr;
+}
+
+/* free wrapper */
+static void incdep_xfree (struct incdep *cur, void *ptr)
+{
+  /* free() *must* work for the allocation hacks above because
+     of free_dep_chain. */
+  free (ptr);
+  (void)cur;
+}
 
 
@@ -347,5 +411,5 @@
   if (!fstat (fd, &st))
     {
-      cur->file_base = xmalloc (st.st_size + 1);
+      cur->file_base = incdep_xmalloc (cur, st.st_size + 1);
       if (read (fd, cur->file_base, st.st_size) == st.st_size)
         {
@@ -359,5 +423,5 @@
 
       error (f, "%s: read: %s", cur->name, strerror (errno));
-      free (cur->file_base);
+      incdep_xfree (cur, cur->file_base);
     }
   else
@@ -371,5 +435,5 @@
 /* Free the incdep structure. */
 static void
-incdep_free (struct incdep *cur)
+incdep_freeit (struct incdep *cur)
 {
 #ifdef PARSE_IN_WORKER
@@ -379,5 +443,5 @@
 #endif
 
-  free (cur->file_base);
+  incdep_xfree (cur, cur->file_base);
   free (cur);
 }
@@ -408,8 +472,10 @@
 
       incdep_unlock ();
+      cur->is_worker = 1;
       incdep_read_file (cur, NILF);
 #ifdef PARSE_IN_WORKER
-      eval_include_dep_file (cur, NILF, 1 /* is_worker */);
-#endif
+      eval_include_dep_file (cur, NILF);
+#endif
+      cur->is_worker = 0;
       incdep_lock ();
 
@@ -475,4 +541,13 @@
   int tid;
 #endif
+
+  /* heap hacks */
+
+#ifdef __APPLE__
+  incdep_zone = malloc_create_zone (0, 0);
+  if (!incdep_zone)
+    incdep_zone = malloc_default_zone ();
+#endif
+
 
   /* create the mutex and two condition variables / event objects. */
@@ -615,7 +690,7 @@
                                 rec_vis->set,
                                 rec_vis->flocp);
-        free (rec_vis->name);
+        incdep_xfree (cur, rec_vis->name);
         rec_vis = rec_vis->next;
-        free (free_me);
+        incdep_xfree (cur, free_me);
       }
     while (rec_vis);
@@ -638,7 +713,7 @@
                                   rec_vd->flavor,
                                   rec_vd->target_var);
-        free (rec_vd->name);
+        incdep_xfree (cur, rec_vd->name);
         rec_vd = rec_vd->next;
-        free (free_me);
+        incdep_xfree (cur, free_me);
       }
     while (rec_vd);
@@ -663,5 +738,5 @@
 
         newname = strcache_add (rec_f->filenames->name);
-        free ((char *)rec_f->filenames->name);
+        incdep_xfree (cur, (char *)rec_f->filenames->name);
         rec_f->filenames->name = newname;
 
@@ -677,5 +752,5 @@
 
         rec_f = rec_f->next;
-        free (free_me);
+        incdep_xfree (cur, free_me);
       }
     while (rec_f);
@@ -717,5 +792,5 @@
       /* Duplicate the string. The other recorders knows which arguments
          needs to be added to the string cache later. */
-      char *newstr = xmalloc (len + 1);
+      char *newstr = incdep_xmalloc (cur, len + 1);
       memcpy (newstr, str, len);
       newstr[len] = '\0';
@@ -747,5 +822,5 @@
   else
     {
-      struct incdep_variable_in_set *rec = xmalloc (sizeof (*rec));
+      struct incdep_variable_in_set *rec = incdep_xmalloc (cur, sizeof (*rec));
       rec->name = (char *)name;
       rec->name_length = name_length;
@@ -786,5 +861,5 @@
   else
     {
-      struct incdep_variable_def *rec = xmalloc (sizeof (*rec));
+      struct incdep_variable_def *rec = incdep_xmalloc (cur, sizeof (*rec));
       rec->flocp = flocp;
       rec->name = (char *)name;
@@ -823,5 +898,5 @@
   else
     {
-      struct incdep_recorded_files *rec = xmalloc (sizeof (*rec));
+      struct incdep_recorded_files *rec = incdep_xmalloc (cur, sizeof (*rec));
 
       rec->filenames = filenames;
@@ -866,5 +941,5 @@
    */
 static void
-eval_include_dep_file (struct incdep *curdep, struct floc *f, int is_worker)
+eval_include_dep_file (struct incdep *curdep, struct floc *f)
 {
   unsigned line_no = 1;
@@ -876,5 +951,4 @@
   if (!cur)
     return;
-  curdep->is_worker = is_worker;
 
   /* now parse the file. */
@@ -983,5 +1057,5 @@
 
           /* make a copy of the value, converting \r\n to \n, and define it. */
-          value = xmalloc (value_len + 1);
+          value = incdep_xmalloc (curdep, value_len + 1);
           endp = memchr (value_start, '\r', value_len);
           if (endp)
@@ -1142,5 +1216,5 @@
               /* make a copy of the value, converting \r\n to \n, and define it. */
               value_len = value_end - value_start;
-              value = xmalloc (value_len + 1);
+              value = incdep_xmalloc (curdep, value_len + 1);
               if (!multi_line)
                   memcpy (value, value_start, value_len);
@@ -1213,5 +1287,5 @@
                   break;
                 }
-              filenames = xmalloc (sizeof (struct nameseq));
+              filenames = incdep_xmalloc (curdep, sizeof (struct nameseq));
               memset (filenames, 0, sizeof (*filenames));
               filenames->name = incdep_record_strcache (curdep, cur, endp - cur);
@@ -1253,5 +1327,5 @@
 
                   /* add it to the list. */
-                  *nextdep = dep = alloc_dep ();
+                  *nextdep = dep = incdep_xcalloc (curdep, sizeof (*dep));
                   dep->name = incdep_record_strcache (curdep, cur, endp - cur);
                   dep->includedep = 1;
@@ -1269,9 +1343,6 @@
 
   /* free the file data */
-  if (is_worker)
-    {
-      free (curdep->file_base);
-      curdep->file_base = curdep->file_end = NULL;
-    }
+  incdep_xfree (curdep, curdep->file_base);
+  curdep->file_base = curdep->file_end = NULL;
 }
 
@@ -1296,6 +1367,6 @@
 
           incdep_read_file (cur, f);
-          eval_include_dep_file (cur, f, 0);
-          incdep_free (cur);
+          eval_include_dep_file (cur, f);
+          incdep_freeit (cur);
 
           incdep_lock ();
@@ -1324,7 +1395,7 @@
           incdep_flush_recorded_instructions (cur);
 #else
-          eval_include_dep_file (cur, f, 0);
-#endif
-          incdep_free (cur);
+          eval_include_dep_file (cur, f);
+#endif
+          incdep_freeit (cur);
           cur = next;
         }
@@ -1352,5 +1423,5 @@
   while ((name = find_next_token (&names_iterator, &name_len)) != 0)
     {
-       cur = xmalloc (sizeof (*cur) + name_len);
+       cur = xmalloc (sizeof (*cur) + name_len); /* not incdep_xmalloc here */
        cur->file_base = cur->file_end = NULL;
        memcpy (cur->name, name, name_len);
@@ -1385,5 +1456,6 @@
           struct incdep *next = cur->next;
           incdep_read_file (cur, f);
-          eval_include_dep_file (cur, f, 0); /* eats cur */
+          eval_include_dep_file (cur, f);
+          incdep_freeit (cur);
           cur = next;
         }
