* Makefile.direct: Document EMPTY_GETENV_RESULTS.
* gcj_mlc.c (GC_clear_stack): Remove declaration.
* malloc.c (GC_clear_stack): Ditto.
* mallocx.c (GC_clear_stack): Ditto.
* typd_mlc.c (GC_clear_stack): Ditto.
* gcj_mlc.c (GENERAL_MALLOC, GENERAL_MALLOC_IOP): Rename to
GENERAL_MALLOC_INNER and GENERAL_MALLOC_INNER_IOP, respectively;
remove "lb" unnecessary cast to word.
* include/private/gc_priv.h (GC_clear_stack): Add declaration.
* include/private/gc_priv.h (GENERAL_MALLOC, GENERAL_MALLOC_IOP):
Move common declaration from typd_mlc.c and malloc.c; remove
unnecessary result and "lb" parameter casts.
* include/private/thread_local_alloc.h: Guard against duplicate
header file inclusion.
* os_dep.c (USE_MUNMAP): Replace "-->" with an error directive for
the case when USE_MMAP is not defined.
* pthread_support.c (GC_is_thread_tsd_valid): New internal
function (only if GC_ASSERTIONS and THREAD_LOCAL_ALLOC); move the
code from thread-local GC_malloc(); add FIXME for the condition.
* win32_threads.c (GC_is_thread_tsd_valid): Ditto.
* thread_local_alloc.c (GC_gcjobjfreelist): Change the type (to
match that of its definition).
* thread_local_alloc.c (GC_destroy_thread_local): Add a cast for
GC_gcjobjfreelist.
* thread_local_alloc.c (GC_lookup_thread, GC_lookup_thread_inner):
Remove unused declaration; don't include pthread.h.
* thread_local_alloc.c (GC_is_thread_tsd_valid): New declaration
(only if GC_ASSERTIONS).
* thread_local_alloc.c (GC_malloc): Use GC_is_thread_tsd_valid()
instead of GC_lookup_thread().
* win32_threads.c (GC_lookup_thread_inner): Define as STATIC.
* win32_threads.c (UNPROTECT): Rename to UNPROTECT_THREAD (to have
id different from that in os_dep.c).
+2009-09-26 Ivan Maidanski <ivmai@mail.ru>
+
+ * Makefile.direct: Document EMPTY_GETENV_RESULTS.
+ * gcj_mlc.c (GC_clear_stack): Remove declaration.
+ * malloc.c (GC_clear_stack): Ditto.
+ * mallocx.c (GC_clear_stack): Ditto.
+ * typd_mlc.c (GC_clear_stack): Ditto.
+ * gcj_mlc.c (GENERAL_MALLOC, GENERAL_MALLOC_IOP): Rename to
+ GENERAL_MALLOC_INNER and GENERAL_MALLOC_INNER_IOP, respectively;
+ remove "lb" unnecessary cast to word.
+ * include/private/gc_priv.h (GC_clear_stack): Add declaration.
+ * include/private/gc_priv.h (GENERAL_MALLOC, GENERAL_MALLOC_IOP):
+ Move common declaration from typd_mlc.c and malloc.c; remove
+ unnecessary result and "lb" parameter casts.
+ * include/private/thread_local_alloc.h: Guard against duplicate
+ header file inclusion.
+ * os_dep.c (USE_MUNMAP): Replace "-->" with an error directive for
+ the case when USE_MMAP is not defined.
+ * pthread_support.c (GC_is_thread_tsd_valid): New internal
+ function (only if GC_ASSERTIONS and THREAD_LOCAL_ALLOC); move the
+ code from thread-local GC_malloc(); add FIXME for the condition.
+ * win32_threads.c (GC_is_thread_tsd_valid): Ditto.
+ * thread_local_alloc.c (GC_gcjobjfreelist): Change the type (to
+ match that of its definition).
+ * thread_local_alloc.c (GC_destroy_thread_local): Add a cast for
+ GC_gcjobjfreelist.
+ * thread_local_alloc.c (GC_lookup_thread, GC_lookup_thread_inner):
+ Remove unused declaration; don't include pthread.h.
+ * thread_local_alloc.c (GC_is_thread_tsd_valid): New declaration
+ (only if GC_ASSERTIONS).
+ * thread_local_alloc.c (GC_malloc): Use GC_is_thread_tsd_valid()
+ instead of GC_lookup_thread().
+ * win32_threads.c (GC_lookup_thread_inner): Define as STATIC.
+ * win32_threads.c (UNPROTECT): Rename to UNPROTECT_THREAD (to have
+ id different from that in os_dep.c).
+
2009-09-26 Ivan Maidanski <ivmai@mail.ru>
* allchblk.c (GC_enough_large_bytes_left): Replace "inline static"
# I don't know of a reason to disable this, except possibly if the
# resulting process runs as a privileged user. (This is on by default for
# WinCE.)
+# -DEMPTY_GETENV_RESULTS Define to workaround a reputed Wine bug in getenv
+# (getenv() may return an empty string instead of NULL for a missing entry).
# -DUSE_GLOBAL_ALLOC. Win32 only. Use GlobalAlloc instead of
# VirtualAlloc to allocate the heap. May be needed to work around
# a Windows NT/2000 issue. Incompatible with USE_MUNMAP.
UNLOCK();
}
-void * GC_clear_stack(void *);
+#define GENERAL_MALLOC_INNER(lb,k) \
+ GC_clear_stack(GC_generic_malloc_inner(lb, k))
-#define GENERAL_MALLOC(lb,k) \
- GC_clear_stack(GC_generic_malloc_inner((word)lb, k))
-
-#define GENERAL_MALLOC_IOP(lb,k) \
+#define GENERAL_MALLOC_INNER_IOP(lb,k) \
GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
/* We need a mechanism to release the lock and invoke finalizers. */
op = *opp;
if(EXPECT(op == 0, 0)) {
maybe_finalize();
- op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
+ op = (ptr_t)GENERAL_MALLOC_INNER((word)lb, GC_gcj_kind);
if (0 == op) {
GC_oom_func oom_fn = GC_oom_fn;
UNLOCK();
} else {
LOCK();
maybe_finalize();
- op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
+ op = (ptr_t)GENERAL_MALLOC_INNER((word)lb, GC_gcj_kind);
if (0 == op) {
GC_oom_func oom_fn = GC_oom_fn;
UNLOCK();
LOCK();
if( (op = *opp) == 0 ) {
maybe_finalize();
- op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
+ op = (ptr_t)GENERAL_MALLOC_INNER_IOP(lb, GC_gcj_kind);
if (0 == op) {
GC_oom_func oom_fn = GC_oom_fn;
UNLOCK();
} else {
LOCK();
maybe_finalize();
- op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
+ op = (ptr_t)GENERAL_MALLOC_INNER_IOP(lb, GC_gcj_kind);
if (0 == op) {
GC_oom_func oom_fn = GC_oom_fn;
UNLOCK();
/* free list nonempty, and return its */
/* head. Sz is in granules. */
+void * GC_clear_stack(void *); /* in misc.c, behaves like identity. */
+
+/* We make the GC_clear_stack() call a tail one, hoping to get more of */
+/* the stack. */
+#define GENERAL_MALLOC(lb,k) \
+ GC_clear_stack(GC_generic_malloc(lb, k))
+#define GENERAL_MALLOC_IOP(lb,k) \
+ GC_clear_stack(GC_generic_malloc_ignore_off_page(lb, k))
+
/* Allocation routines that bypass the thread local cache. */
/* Used internally. */
#ifdef THREAD_LOCAL_ALLOC
/* implementation also exports GC_malloc and friends, which */
/* are declared in gc.h. */
+#ifndef GC_THREAD_LOCAL_ALLOC_H
+#define GC_THREAD_LOCAL_ALLOC_H
+
#include "private/gc_priv.h"
#if defined(THREAD_LOCAL_ALLOC)
/* if necessary. */
#endif /* THREAD_LOCAL_ALLOC */
+
+#endif /* GC_THREAD_LOCAL_ALLOC_H */
# include <errno.h>
#endif
-extern void * GC_clear_stack(void *); /* in misc.c, behaves like identity */
void GC_extend_size_map(size_t); /* in misc.c. */
/* Allocate reclaim list for kind: */
}
}
-
-#define GENERAL_MALLOC(lb,k) \
- GC_clear_stack(GC_generic_malloc(lb, k))
-/* We make the GC_clear_stack_call a tail call, hoping to get more of */
-/* the stack. */
-
/* Allocate lb bytes of atomic (pointerfree) data */
#ifdef THREAD_LOCAL_ALLOC
void * GC_core_malloc_atomic(size_t lb)
#include <stdio.h>
#include "private/gc_priv.h"
-void * GC_clear_stack(void *); /* in misc.c, behaves like identity */
-
/* Some externally visible but unadvertised variables to allow access to */
/* free lists from inlined allocators without including gc_priv.h */
/* or introducing dependencies on internal data structure layouts. */
#if defined(MMAP_SUPPORTED) || defined(ADD_HEAP_GUARD_PAGES)
# if defined(USE_MUNMAP) && !defined(USE_MMAP)
- --> USE_MUNMAP requires USE_MMAP
+# error "invalid config - USE_MUNMAP requires USE_MMAP"
# endif
# include <sys/types.h>
# include <sys/mman.h>
return &me->finalizer_nested;
}
+#if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC)
+ /* This is called from thread-local GC_malloc(). */
+ GC_bool GC_is_thread_tsd_valid(void *tsd)
+ {
+ char *me;
+ LOCK();
+ me = (char *)GC_lookup_thread(pthread_self());
+ UNLOCK();
+ /* FIXME: We can check tsd more correctly (since now we have access */
+ /* to the right declarations). This old algorithm (moved from */
+ /* thread_local_alloc.c) checks only that it's close. */
+ return((char *)tsd > me && (char *)tsd < me + 1000);
+ }
+#endif
+
#ifdef HANDLE_FORK
/* Remove all entries from the GC_threads table, except the */
/* one for the current thread. We need to do this in the child */
}
#ifdef GC_GCJ_SUPPORT
- extern void ** GC_gcjobjfreelist;
+ extern ptr_t * GC_gcjobjfreelist;
#endif
/* We hold the allocator lock. */
return_freelists(p -> ptrfree_freelists, GC_aobjfreelist);
return_freelists(p -> normal_freelists, GC_objfreelist);
# ifdef GC_GCJ_SUPPORT
- return_freelists(p -> gcj_freelists, GC_gcjobjfreelist);
+ return_freelists(p -> gcj_freelists, (void **)GC_gcjobjfreelist);
# endif
}
-#if defined(GC_ASSERTIONS) && defined(GC_PTHREADS) && !defined(CYGWIN32) \
- && !defined(GC_WIN32_PTHREADS)
-# include <pthread.h>
- extern char * GC_lookup_thread(pthread_t id);
-#endif
-
-#if defined(GC_ASSERTIONS) && defined(GC_WIN32_THREADS)
- void * /*GC_thread*/ GC_lookup_thread_inner(unsigned /*DWORD*/ thread_id);
+#ifdef GC_ASSERTIONS
+ /* Defined in pthread_support.c or win32_threads.c. */
+ GC_bool GC_is_thread_tsd_valid(void *tsd);
#endif
GC_API void * GC_CALL GC_malloc(size_t bytes)
}
# endif
GC_ASSERT(GC_is_initialized);
-# ifdef GC_ASSERTIONS
- /* We can't check tsd correctly, since we don't have access to */
- /* the right declarations. But we can check that it's close. */
- LOCK();
- {
-# if defined(GC_WIN32_THREADS)
- char * me = (char *)GC_lookup_thread_inner(GetCurrentThreadId());
-# else
- char * me = GC_lookup_thread(pthread_self());
-# endif
- GC_ASSERT((char *)tsd > me && (char *)tsd < me + 1000);
- }
- UNLOCK();
-# endif
+
+ GC_ASSERT(GC_is_thread_tsd_valid(tsd));
+
tiny_fl = ((GC_tlfs)tsd) -> normal_freelists;
GC_FAST_MALLOC_GRANS(result, granules, tiny_fl, DIRECT_GRANULES,
NORMAL, GC_core_malloc(bytes), obj_link(result)=0);
}
}
-void * GC_clear_stack(void *);
-
-#define GENERAL_MALLOC(lb,k) \
- (void *)GC_clear_stack(GC_generic_malloc((word)lb, k))
-
-#define GENERAL_MALLOC_IOP(lb,k) \
- (void *)GC_clear_stack(GC_generic_malloc_ignore_off_page(lb, k))
-
GC_API void * GC_CALL GC_malloc_explicitly_typed(size_t lb, GC_descr d)
{
ptr_t op;
/* This version assumes that either GC_win32_dll_threads is set, or */
/* 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)
+STATIC GC_thread GC_lookup_thread_inner(DWORD thread_id)
{
# ifndef GC_NO_DLLMAIN
if (GC_win32_dll_threads) {
return &me->finalizer_nested;
}
+#if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC)
+ /* This is called from thread-local GC_malloc(). */
+ GC_bool GC_is_thread_tsd_valid(void *tsd)
+ {
+ char *me;
+ LOCK();
+ me = (char *)GC_lookup_thread_inner(GetCurrentThreadId());
+ UNLOCK();
+ /* FIXME: We can check tsd more correctly (since now we have access */
+ /* to the right declarations). This old algorithm (moved from */
+ /* thread_local_alloc.c) checks only that it's close. */
+ return((char *)tsd > me && (char *)tsd < me + 1000);
+ }
+#endif
+
/* Make sure thread descriptor t is not protected by the VDB */
/* implementation. */
/* Used to prevent write faults when the world is (partially) stopped, */
/* since it may have been stopped with a system lock held, and that */
/* lock may be required for fault handling. */
#if defined(MPROTECT_VDB)
-# define UNPROTECT(t) \
+# define UNPROTECT_THREAD(t) \
if (GC_dirty_maintained && !GC_win32_dll_threads && \
t != &first_thread) { \
GC_ASSERT(SMALL_OBJ(GC_size(t))); \
GC_remove_protection(HBLKPTR(t), 1, FALSE); \
}
#else
-# define UNPROTECT(t)
+# define UNPROTECT_THREAD(t)
#endif
/* If a thread has been joined, but we have not yet */
/* appears there's a race here. */
DWORD exitCode;
# endif
- UNPROTECT(t);
+ UNPROTECT_THREAD(t);
# ifndef MSWINCE
if (GetExitCodeThread(t -> handle, &exitCode) &&
exitCode != STILL_ACTIVE) {
# if defined(MPROTECT_VDB)
/* Acquire the spin lock we use to update dirty bits. */
/* Threads shouldn't get stopped holding it. But we may */
- /* acquire and release it in the UNPROTECT call. */
+ /* acquire and release it in the UNPROTECT_THREAD call. */
while (AO_test_and_set_acquire(&GC_fault_handler_lock) == AO_TS_SET) {
/* empty */
}
&& t -> id != thread_id) {
if (ResumeThread(THREAD_HANDLE(t)) == (DWORD)-1)
ABORT("ResumeThread failed");
- UNPROTECT(t);
+ UNPROTECT_THREAD(t);
t -> suspended = FALSE;
}
}
if (thread -> last_stack_min == ADDR_LIMIT) {
stack_min = GC_get_stack_min(activation_frame != NULL ?
(ptr_t)activation_frame : thread -> stack_base);
- UNPROTECT(thread);
+ UNPROTECT_THREAD(thread);
thread -> last_stack_min = stack_min;
} else {
/* First, adjust the latest known minimum stack address if we */
/* are inside GC_call_with_gc_active(). */
if (activation_frame != NULL &&
thread -> last_stack_min > (ptr_t)activation_frame) {
- UNPROTECT(thread);
+ UNPROTECT_THREAD(thread);
thread -> last_stack_min = (ptr_t)activation_frame;
}
stack_min = GC_get_stack_min(thread -> stack_base);
}
# endif
- UNPROTECT(thread);
+ UNPROTECT_THREAD(thread);
thread -> last_stack_min = stack_min;
}
}
/* Remember current stack_min value. */
if (thread != NULL) {
- UNPROTECT(thread);
+ UNPROTECT_THREAD(thread);
}
*plast_stack_min = *lo;
}