Fix intmap bug for maps with only one element
[bpt/guile.git] / libguile / threads.c
index f39bcc3..3dc0f40 100644 (file)
@@ -1,6 +1,6 @@
 /* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004,
- *   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
- *   Free Software Foundation, Inc.
+ *   2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013,
+ *   2014 Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -29,9 +29,7 @@
 #include "libguile/_scm.h"
 
 #include <stdlib.h>
-#if HAVE_UNISTD_H
 #include <unistd.h>
-#endif
 #include <stdio.h>
 
 #ifdef HAVE_STRING_H
@@ -63,6 +61,7 @@
 #include "libguile/fluids.h"
 #include "libguile/continuations.h"
 #include "libguile/gc.h"
+#include "libguile/gc-inline.h"
 #include "libguile/init.h"
 #include "libguile/scmsigs.h"
 #include "libguile/strings.h"
@@ -95,6 +94,27 @@ thread_mark (GC_word *addr, struct GC_ms_entry *mark_stack_ptr,
                                       mark_stack_ptr, mark_stack_limit,
                                       NULL);
 
+  /* The pointerless freelists are threaded through their first word,
+     but GC doesn't know to trace them (as they are pointerless), so we
+     need to do that here.  See the comments at the top of libgc's
+     gc_inline.h.  */
+  if (t->pointerless_freelists)
+    {
+      size_t n;
+      for (n = 0; n < SCM_INLINE_GC_FREELIST_COUNT; n++)
+        {
+          void *chain = t->pointerless_freelists[n];
+          if (chain)
+            {
+              /* The first link is already marked by the freelist vector,
+                 so we just have to mark the tail.  */
+              while ((chain = *(void **)chain))
+                mark_stack_ptr = GC_mark_and_push (chain, mark_stack_ptr,
+                                                   mark_stack_limit, NULL);
+            }
+        }
+    }
+
   if (t->vp)
     mark_stack_ptr = scm_i_vm_mark_stack (t->vp, mark_stack_ptr,
                                           mark_stack_limit);
@@ -389,6 +409,8 @@ guilify_self_1 (struct GC_stack_base *base)
   t.mutexes = SCM_EOL;
   t.held_mutex = NULL;
   t.join_queue = SCM_EOL;
+  t.freelists = NULL;
+  t.pointerless_freelists = NULL;
   t.dynamic_state = SCM_BOOL_F;
   t.dynstack.base = NULL;
   t.dynstack.top = NULL;
@@ -459,6 +481,12 @@ guilify_self_2 (SCM parent)
   t->continuation_root = scm_cons (t->handle, SCM_EOL);
   t->continuation_base = t->base;
 
+  {
+    size_t size = SCM_INLINE_GC_FREELIST_COUNT * sizeof (void *);
+    t->freelists = scm_gc_malloc (size, "freelists");
+    t->pointerless_freelists = scm_gc_malloc (size, "atomic freelists");
+  }
+
   if (scm_is_true (parent))
     t->dynamic_state = scm_make_dynamic_state (parent);
   else
@@ -1008,6 +1036,11 @@ SCM_DEFINE (scm_yield, "yield", 0, 0, 0,
 }
 #undef FUNC_NAME
 
+/* Some systems, notably Android, lack 'pthread_cancel'.  Don't provide
+   'cancel-thread' on these systems.  */
+
+#if !SCM_USE_PTHREAD_THREADS || defined HAVE_PTHREAD_CANCEL
+
 SCM_DEFINE (scm_cancel_thread, "cancel-thread", 1, 0, 0,
            (SCM thread),
 "Asynchronously force the target @var{thread} to terminate. @var{thread} "
@@ -1033,6 +1066,8 @@ SCM_DEFINE (scm_cancel_thread, "cancel-thread", 1, 0, 0,
 }
 #undef FUNC_NAME
 
+#endif
+
 SCM_DEFINE (scm_set_thread_cleanup_x, "set-thread-cleanup!", 2, 0, 0,
            (SCM thread, SCM proc),
 "Set the thunk @var{proc} as the cleanup handler for the thread @var{thread}. "
@@ -1749,14 +1784,6 @@ do_std_select (void *args)
   return NULL;
 }
 
-#if !SCM_HAVE_SYS_SELECT_H
-static int scm_std_select (int nfds,
-                           fd_set *readfds,
-                           fd_set *writefds,
-                           fd_set *exceptfds,
-                           struct timeval *timeout);
-#endif
-
 int
 scm_std_select (int nfds,
                fd_set *readfds,