[Gc] GC + Windows Mobile + Threads

Zeyi Lee biosli at hotmail.com
Fri Jul 31 04:10:44 PDT 2009


Dear All:

I hope you are well. 

I downloaded the latest GC from CVS to build a GC lib running under Windows 
Mobile 5.0 ARM. To see if it supports threads, I made following modifications:

 

Index: D:/KaiTone/WinCE/libGCWinCE/libgc/include/private/gcconfig.h

===================================================================

--- D:/KaiTone/WinCE/libGCWinCE/libgc/include/private/gcconfig.h    (revision 
4357)

+++ D:/KaiTone/WinCE/libGCWinCE/libgc/include/private/gcconfig.h    (working 
copy)

@@ -2203,7 +2203,7 @@

 # if defined(GC_GNU_THREADS) && !defined(HURD)

    --> inconsistent configuration

 # endif

-# if defined(GC_WIN32_THREADS) && !defined(MSWIN32) && !defined(CYGWIN32)

+# if defined(GC_WIN32_THREADS) && !defined(MSWINCE) && !defined(MSWIN32) && !
defined(CYGWIN32)

    --> inconsistent configuration

 # endif

 

Then, I got errors listed below:

1>.\source\win32_threads.c(255) : error C4013: 'AO_nop_full' undefined; 
assuming extern returning int

1>.\source\win32_threads.c(256) : error C4013: 'AO_load' undefined; assuming 
extern returning int

1>.\source\win32_threads.c(258) : error C4013: 'AO_store' undefined; assuming 
extern returning int

1>.\source\win32_threads.c(479) : error C4013: 'AO_load_acquire' undefined; 
assuming extern returning int

1>.\source\win32_threads.c(538) : error C4013: 'AO_store_release' undefined; 
assuming extern returning int

I think these errors caused by atomic_ops lib which I didn't use. Instead, I 
built gc like a static library so I commented them.

 

Index: D:/KaiTone/WinCE/libGCWinCE/libgc/source/win32_threads.c

===================================================================

--- D:/KaiTone/WinCE/libGCWinCE/libgc/source/win32_threads.c    (revision 4643)

+++ D:/KaiTone/WinCE/libGCWinCE/libgc/source/win32_threads.c    (working copy)

@@ -249,18 +249,19 @@

 /* since GC_attached_thread was explicitly reset.      */

 GC_bool GC_started_thread_while_stopped(void)

 {

-  AO_t result;

+   return FALSE;

+  //AO_t result;

 

-  if (GC_win32_dll_threads) {

-    AO_nop_full(); /* Prior heap reads need to complete earlier. */

-    result = AO_load(&GC_attached_thread);

-    if (result) {

-      AO_store(&GC_attached_thread, FALSE);

-    }

-    return ((GC_bool)result);

-  } else {

-    return FALSE;

-  }

+  //if (GC_win32_dll_threads) {

+  //  AO_nop_full();   /* Prior heap reads need to complete earlier. */

+  //  result = AO_load(&GC_attached_thread);

+  //  if (result) {

+  //    AO_store(&GC_attached_thread, FALSE);

+  //  }

+  //  return ((GC_bool)result);

+  //} else {

+  //  return FALSE;

+  //}

 }

 

 /* Thread table used if GC_win32_dll_threads is set.   */

@@ -432,15 +433,17 @@

 # endif

   if (me -> stack_base == NULL) 

       ABORT("Bad stack base in GC_register_my_thread_inner");

-  if (GC_win32_dll_threads) {

-    if (GC_please_stop) {

-      AO_store(&GC_attached_thread, TRUE);

-      AO_nop_full();  /* Later updates must become visible after this. */

-    }

-    /* We'd like to wait here, but can't, since waiting in DllMain     */

-    /* provokes deadlocks.                     */

-    /* Thus we force marking to be restarted instead.          */

-  } else {

+  //if (GC_win32_dll_threads) {

+  //  if (GC_please_stop) {

+  //    AO_store(&GC_attached_thread, TRUE);

+  //    AO_nop_full();  /* Later updates must become visible after this.   */

+  //  }

+  //  /* We'd like to wait here, but can't, since waiting in DllMain   */

+  //  /* provokes deadlocks.                       */

+  //  /* Thus we force marking to be restarted instead.            */

+  //} 

+  //else 

+  {

     GC_ASSERT(!GC_please_stop);

   /* Otherwise both we and the thread stopping code would be  */

   /* holding the allocation lock.                 */

@@ -471,21 +474,23 @@

 /* we hold the allocator lock.                     */

 /* Also used (for assertion checking only) from thread_local_alloc.c.  */

 GC_thread GC_lookup_thread_inner(DWORD thread_id) {

-  if (GC_win32_dll_threads) {

-    int i;

-    LONG my_max = GC_get_max_thread_index();

-    for (i = 0;

-       i <= my_max &&

-       (!AO_load_acquire(&(dll_thread_table[i].in_use))

-   || dll_thread_table[i].id != thread_id);

-       /* Must still be in_use, since nobody else can store our thread_id. */

-       i++) {}

-    if (i > my_max) {

-      return 0;

-    } else {

-      return (GC_thread)(dll_thread_table + i);

-    }

-  } else {

+ // if (GC_win32_dll_threads) {

+ //   int i;

+ //   LONG my_max = GC_get_max_thread_index();

+ //   for (i = 0;

+ //      i <= my_max &&

+ //      (!AO_load_acquire(&(dll_thread_table[i].in_use))

+   //|| dll_thread_table[i].id != thread_id);

+ //      /* Must still be in_use, since nobody else can store our thread_id. 
*/

+ //      i++) {}

+ //   if (i > my_max) {

+ //     return 0;

+ //   } else {

+ //     return (GC_thread)(dll_thread_table + i);

+ //   }

+ // } 

+ // else 

+  {

     word hv = ((word)thread_id) % THREAD_TABLE_SZ;

     register GC_thread p = GC_threads[hv];

     

@@ -522,21 +527,23 @@

 STATIC void GC_delete_gc_thread(GC_vthread gc_id)

 {

   CloseHandle(gc_id->handle);

-  if (GC_win32_dll_threads) {

-    /* This is intended to be lock-free.               */

-    /* It is either called synchronously from the thread being deleted,    */

-    /* or by the joining thread.                   */

-    /* In this branch asynchronous changes to *gc_id are possible. */

-    gc_id -> stack_base = 0;

-    gc_id -> id = 0;

-#   ifdef CYGWIN32

-      gc_id -> pthread_id = 0;

-#   endif /* CYGWIN32 */

-#   ifdef GC_WIN32_PTHREADS

-      gc_id -> pthread_id.p = NULL;

-#   endif /* GC_WIN32_PTHREADS */

-    AO_store_release(&(gc_id->in_use), FALSE);

-  } else {

+//  if (GC_win32_dll_threads) {

+//    /* This is intended to be lock-free.             */

+//    /* It is either called synchronously from the thread being deleted,  */

+//    /* or by the joining thread.                 */

+//    /* In this branch asynchronous changes to *gc_id are possible.   */

+//    gc_id -> stack_base = 0;

+//    gc_id -> id = 0;

+//#   ifdef CYGWIN32

+//      gc_id -> pthread_id = 0;

+//#   endif /* CYGWIN32 */

+//#   ifdef GC_WIN32_PTHREADS

+//      gc_id -> pthread_id.p = NULL;

+//#   endif /* GC_WIN32_PTHREADS */

+//    AO_store_release(&(gc_id->in_use), FALSE);

+//  } 

+//  else 

+  {

     /* Cast away volatile qualifier, since we have lock. */

     GC_thread gc_nvid = (GC_thread)gc_id;

     DWORD id = gc_nvid -> id;

 

I do apologies for my comments on others' codes.

Well, compiling pass. Then I found link issue as below:

2>libgc_smt2005_d.lib(misc.obj) : error LNK2019: unresolved external symbol 
GC_thr_init referenced in function GC_init_inner

2>libgc_smt2005_d.lib(os_dep.obj) : error LNK2019: unresolved external symbol 
backtrace referenced in function GC_save_callers

2>libgc_smt2005_d.lib(os_dep.obj) : error LNK2019: unresolved external symbol 
backtrace_symbols referenced in function GC_print_callers

Since Wins Mobile don't have such function debug as Win32, I turned off the 
save call chain.

 

    Index: D:/KaiTone/WinCE/libGCWinCE/libgc/stdafx.h 

===================================================================

--- D:/KaiTone/WinCE/libGCWinCE/libgc/stdafx.h  (revision 4624)

+++ D:/KaiTone/WinCE/libGCWinCE/libgc/stdafx.h  (working copy)

@@ -15,6 +15,6 @@

 

 #define __STDC__ 1

 

-#define SAVE_CALL_CHAIN

+//#define SAVE_CALL_CHAIN

 

-#define SAVE_CALL_COUNT 8

+//#define SAVE_CALL_COUNT 8

 

 

The last problem is "unresolved external symbol GC_thr_init" ,which I found 
this function in win32_threads.c. but no Wince Version available.  If I 
comment it from GC_init_inner, it will alert:

GC_stop_world() called before GC_thr_init()

C_stop_world() called before GC_thr_init()

       Pls kindly share your thoughts.

 

Thanks and regards,

 

 

GC Beginner 

Zeyi Lee





More information about the Gc mailing list