[racket-dev] current-load-extension: expects argument of type <procedure (arity 2)>; given #"([^:]*):(.*)"

From: Nick Sivo (nick at kogir.com)
Date: Tue May 1 19:15:22 EDT 2012

Hi Everyone,

I'm trying to add support for per-thread allocation accounting to aid
in some performance debugging.  I've already instrumented the GC and
can retrieve the statistics via hacks I added to current-memory-use.

I'm running into trouble reverting current-memory-use and instead
adding a primitive: (thread-memory-allocations thread [allocated #f])

In src/thread.c
===========
static Scheme_Object *thread_memory_allocations(int argc,
Scheme_Object *args[]);
GLOBAL_PRIM_W_ARITY("thread-memory-allocations" ,
thread_memory_allocations   , 1, 2, env);
static Scheme_Object *thread_memory_allocations(int argc, Scheme_Object *args[])
{
  Scheme_Thread *thread = NULL;
  intptr_t retval = 0;

  if (!SCHEME_THREADP(args[0]))
    scheme_wrong_type("thread-memory-allocations", "thread", 0, argc, args);

  thread = (Scheme_Thread*) args[0];
  if(argc == 1 || SCHEME_FALSEP(args[1])) {
    retval = thread->total_memory_requested;
  } else {
    retval = thread->total_memory_allocated;
  }

  return scheme_make_integer_value(retval);
}

In src/schinc.h
===========
#define EXPECTED_PRIM_COUNT 1043

When I build I get:
...
<snip>
...
cd gc2; make all
mkdir xsrc
make xsrc/precomp.h
env XFORM_PRECOMP=yes ../racketcgc -cqu ../../../racket/gc2/xform.rkt
--setup . --cpp "gcc -E -I./.. -I../../../racket/gc2/../include
-I/usr/local/lib/libffi-3.0.9/include   -pthread    -DMZ_NO_ICONV"
--keep-lines -o xsrc/precomp.h ../../../racket/gc2/precomp.c
current-load-extension: expects argument of type <procedure (arity
2)>; given #"([^:]*):(.*)"
*** Signal 11

I've scanned through xform.rkt but I'm not able to track down the
origin of that error.  Any ideas?

Thanks,
Nick

A full patch (based on tag v5.2.1) is attached if that helps.
-------------- next part --------------
diff --git a/src/racket/gc2/newgc.c b/src/racket/gc2/newgc.c
index 7370cde..816cf16 100644
--- a/src/racket/gc2/newgc.c
+++ b/src/racket/gc2/newgc.c
@@ -968,6 +975,14 @@ static void *allocate_big(const size_t request_size_bytes, int type)
   else
     addr = malloc_pages(gc, realpagesize, APAGE_SIZE, MMU_ZEROED, MMU_BIG_MED, MMU_PROTECTABLE, &bpage->mmu_src_block);
 
+  {
+    Scheme_Thread *thread = scheme_get_current_thread();
+    if(thread) {
+      thread->total_memory_requested += request_size_bytes;
+      thread->total_memory_allocated += realpagesize;
+    }
+  }
+
   bpage->addr = addr;
   bpage->size = allocate_size;
   bpage->size_class = 2;
@@ -1100,15 +1115,24 @@ static void *allocate_medium(const size_t request_size_bytes, const int type)
 
   {
     NewGC *gc = GC_get_GC();
+    Scheme_Thread *thread = scheme_get_current_thread();
     void *objptr;
 
     gc_if_needed_account_alloc_size(gc, sz);
 
+    if(thread) {
+      thread->total_memory_requested += request_size_bytes;
+    }
+
     objptr = medium_page_realloc_dead_slot(gc, sz, pos, type);
     if (!objptr) {
       mpage *page;
       objhead *info;
 
+      if(thread) {
+        thread->total_memory_allocated += sz;
+      }
+
       page = create_new_medium_page(gc, sz, pos);
       info = (objhead *)PTR(NUM(page->addr) + MED_NEXT_SEARCH_SLOT(page));
 
@@ -1303,6 +1327,14 @@ inline static void *allocate(const size_t request_size, const int type)
     newptr = allocate_slowpath(gc, allocate_size, newptr);
   }
 
+  {
+    Scheme_Thread *thread = scheme_get_current_thread();
+    if(thread) {
+      thread->total_memory_requested += request_size;
+      thread->total_memory_allocated += allocate_size;
+    }
+  }
+
   /* actual Allocation */
   {
     objhead *info = (objhead *)PTR(GC_gen0_alloc_page_ptr);
@@ -1350,6 +1382,14 @@ inline static void *fast_malloc_one_small_tagged(size_t request_size, int dirty)
     info->size = BYTES_MULTIPLE_OF_WORD_TO_WORDS(allocate_size); /* ALIGN_BYTES_SIZE bumbed us up to the next word boundary */
 
     {
+      Scheme_Thread *thread = scheme_get_current_thread();
+      if(thread) {
+        thread->total_memory_requested += request_size;
+        thread->total_memory_allocated += allocate_size;
+      }
+    }
+
+    {
       void * objptr = OBJHEAD_TO_OBJPTR(info);
       ASSERT_VALID_OBJPTR(objptr);
       return objptr;
diff --git a/src/racket/include/scheme.h b/src/racket/include/scheme.h
index e90062c..c57bccc 100644
--- a/src/racket/include/scheme.h
+++ b/src/racket/include/scheme.h
@@ -1130,6 +1130,8 @@ typedef struct Scheme_Thread {
 
   intptr_t accum_process_msec;
   intptr_t current_start_process_msec;
+  intptr_t total_memory_allocated;
+  intptr_t total_memory_requested;
 
   struct Scheme_Thread_Custodian_Hop *mr_hop;
   Scheme_Custodian_Reference *mref;
diff --git a/src/racket/src/schminc.h b/src/racket/src/schminc.h
index 4d377b1..1ed428b 100644
--- a/src/racket/src/schminc.h
+++ b/src/racket/src/schminc.h
@@ -13,7 +13,7 @@
 
 #define USE_COMPILED_STARTUP 1
 
-#define EXPECTED_PRIM_COUNT 1042
+#define EXPECTED_PRIM_COUNT 1043
 #define EXPECTED_UNSAFE_COUNT 78
 #define EXPECTED_FLFXNUM_COUNT 68
 #define EXPECTED_FUTURES_COUNT 11
diff --git a/src/racket/src/thread.c b/src/racket/src/thread.c
index 78a919c..ca74dab 100644
--- a/src/racket/src/thread.c
+++ b/src/racket/src/thread.c
@@ -321,6 +321,7 @@ static Scheme_Object *union_tracking_val(int argc, Scheme_Object *args[]);
 
 static Scheme_Object *collect_garbage(int argc, Scheme_Object *args[]);
 static Scheme_Object *current_memory_use(int argc, Scheme_Object *args[]);
+static Scheme_Object *thread_memory_allocations(int argc, Scheme_Object *args[]);
 
 static Scheme_Object *sch_thread(int argc, Scheme_Object *args[]);
 static Scheme_Object *sch_thread_nokill(int argc, Scheme_Object *args[]);
@@ -558,8 +559,9 @@ void scheme_init_thread(Scheme_Env *env)
   scheme_add_evt_through_sema(scheme_will_executor_type, will_executor_sema, NULL);
 
 
-  GLOBAL_PRIM_W_ARITY("collect-garbage"                       , collect_garbage      , 0, 0, env);
-  GLOBAL_PRIM_W_ARITY("current-memory-use"                    , current_memory_use   , 0, 1, env);
+  GLOBAL_PRIM_W_ARITY("collect-garbage"           , collect_garbage             , 0, 0, env);
+  GLOBAL_PRIM_W_ARITY("current-memory-use"        , current_memory_use          , 0, 1, env);
+  GLOBAL_PRIM_W_ARITY("thread-memory-allocations" , thread_memory_allocations   , 1, 2, env);
 
   GLOBAL_PRIM_W_ARITY("custodian-require-memory"              , custodian_require_mem, 3, 3, env);
   GLOBAL_PRIM_W_ARITY("custodian-limit-memory"                , custodian_limit_mem  , 2, 3, env);
@@ -698,6 +700,24 @@ static Scheme_Object *current_memory_use(int argc, Scheme_Object *args[])
   return scheme_make_integer_value(retval);
 }
 
+static Scheme_Object *thread_memory_allocations(int argc, Scheme_Object *args[])
+{
+  Scheme_Thread *thread = NULL;
+  intptr_t retval = 0;
+
+  if (!SCHEME_THREADP(args[0]))
+    scheme_wrong_type("thread-memory-allocations", "thread", 0, argc, args);
+
+  thread = (Scheme_Thread*) args[0];
+  if(argc == 1 || SCHEME_FALSEP(args[1])) {
+    retval = thread->total_memory_requested;
+  } else {
+    retval = thread->total_memory_allocated;
+  }
+  
+  return scheme_make_integer_value(retval);
+}
+
 
 /*========================================================================*/
 /*                              custodians                                */
@@ -2219,7 +2239,8 @@ static Scheme_Thread *make_thread(Scheme_Config *config,
   process->mref = NULL;
   process->extra_mrefs = NULL;
 
-    
+  process->total_memory_allocated = 0;
+  process->total_memory_requested = 0;
 
   /* A thread points to a lot of stuff, so it's bad to put a finalization
      on it, which is what registering with a custodian does. Instead, we

Posted on the dev mailing list.