+2011-03-27 Ivan Maidanski <ivmai@mail.ru>
+
+ * dbg_mlc.c (GC_debug_strdup, GC_debug_free): Output a portability
+ warning if the argument is NULL and GC is in leaks detection mode.
+ * dbg_mlc.c (GC_debug_strndup, GC_debug_wcsdup): New public
+ function definition.
+ * malloc.c (GC_strndup, GC_wcsdup, strndup): Ditto.
+ * mallocx.c (GC_posix_memalign): Ditto.
+ * malloc.c (strdup): Fix string size value; rename "len" to "lb".
+ * mallocx.c: Include errno.h unless WinCE (otherwise include
+ windows.h for Win32 error constants).
+ * win32_threads.c: Define WIN32_LEAN_AND_MEAN and NOSERVICE before
+ windows.h inclusion.
+ * misc.c (GC_init): Register at-exit callback if GC_find_leak
+ (even if GC_FIND_LEAK macro is unset).
+ * pthread_stop_world.c (NACL_STORE_REGS,
+ __nacl_suspend_thread_if_needed, GC_nacl_initialize_gc_thread):
+ Use BCOPY() instead of memcpy().
+ * pthread_support.c (GC_init_real_syms): Ditto.
+ * doc/README: Update year in copyright.
+ * include/gc.h: Ditto.
+ * doc/README.macros (GC_DEBUG_REPLACEMENT, GC_REQUIRE_WCSDUP):
+ Document new macro.
+ * doc/README.macros (REDIRECT_MALLOC): Update documentation.
+ * include/gc.h (GC_strndup, GC_posix_memalign, GC_debug_strndup):
+ New API function prototype.
+ * include/gc.h (GC_MALLOC, GC_REALLOC): Redirect to
+ GC_debug_malloc/realloc_replacement() if GC_DEBUG_REPLACEMENT.
+ * include/gc.h (GC_STRDUP): Remove redundant parentheses.
+ * include/leak_detector.h (realloc, strdup): Ditto.
+ * include/gc.h (GC_STRNDUP): New API macro.
+ * include/gc.h (GC_NEW, GC_NEW_ATOMIC, GC_NEW_STUBBORN,
+ GC_NEW_UNCOLLECTABLE): Add missing parentheses.
+ * include/gc.h (GC_wcsdup, GC_debug_wcsdup): New API function
+ prototype (only if GC_REQUIRE_WCSDUP).
+ * include/gc.h (GC_WCSDUP): New API macro (only if
+ GC_REQUIRE_WCSDUP).
+ * include/leak_detector.h: Add copyright header; add usage
+ comment; include stdlib.h and string.h after gc.h (unless
+ GC_DONT_INCLUDE_STDLIB).
+ * include/leak_detector.h (malloc, calloc, free, realloc):
+ Undefine symbol before its redefinition.
+ * include/leak_detector.h (strndup, memalign, posix_memalign):
+ Redefine to the corresponding GC function.
+ * include/leak_detector.h (wcsdup): Redefine to GC_WCSDUP (only
+ if GC_REQUIRE_WCSDUP).
+ * include/leak_detector.h (CHECK_LEAKS): Add comment; don't define
+ the macro if already defined.
+
2011-03-22 Ivan Maidanski <ivmai@mail.ru>
* misc.c (GC_abort): Use _exit() (instead of DebugBreak) on Win32 when
GC_API char * GC_CALL GC_debug_strdup(const char *str, GC_EXTRA_PARAMS)
{
- char *copy;
- size_t lb;
- if (str == NULL) return NULL;
- lb = strlen(str) + 1;
- copy = GC_debug_malloc_atomic(lb, OPT_RA s, i);
+ char *copy;
+ size_t lb;
+ if (str == NULL) {
+ if (GC_find_leak)
+ WARN("strdup(NULL) behavior is undefined\n", 0);
+ return NULL;
+ }
+ lb = strlen(str) + 1;
+ copy = GC_debug_malloc_atomic(lb, OPT_RA s, i);
+ if (copy == NULL) {
+# ifndef MSWINCE
+ errno = ENOMEM;
+# endif
+ return NULL;
+ }
+# ifndef MSWINCE
+ strcpy(copy, str);
+# else
+ /* strcpy() is deprecated in WinCE */
+ memcpy(copy, str, lb);
+# endif
+ return copy;
+}
+
+GC_API char * GC_CALL GC_debug_strndup(const char *str, size_t size,
+ GC_EXTRA_PARAMS)
+{
+ char *copy;
+ size_t len = strlen(str); /* str is expected to be non-NULL */
+ if (len > size)
+ len = size;
+ copy = GC_debug_malloc_atomic(len + 1, OPT_RA s, i);
+ if (copy == NULL) {
+# ifndef MSWINCE
+ errno = ENOMEM;
+# endif
+ return NULL;
+ }
+ BCOPY(str, copy, len);
+ copy[len] = '\0';
+ return copy;
+}
+
+#ifdef GC_REQUIRE_WCSDUP
+# include <wchar.h> /* for wcslen() */
+
+ GC_API wchar_t * GC_CALL GC_debug_wcsdup(const wchar_t *str, GC_EXTRA_PARAMS)
+ {
+ size_t lb = (wcslen(str) + 1) * sizeof(wchar_t);
+ wchar_t *copy = GC_debug_malloc_atomic(lb, OPT_RA s, i);
if (copy == NULL) {
# ifndef MSWINCE
errno = ENOMEM;
# endif
return NULL;
}
-# ifndef MSWINCE
- strcpy(copy, str);
-# else
- /* strcpy() is deprecated in WinCE */
- memcpy(copy, str, lb);
-# endif
+ BCOPY(str, copy, lb);
return copy;
-}
+ }
+#endif /* GC_REQUIRE_WCSDUP */
GC_API void * GC_CALL GC_debug_malloc_uncollectable(size_t lb,
GC_EXTRA_PARAMS)
ptr_t clobbered;
# endif
- if (0 == p) return;
+ if (0 == p) {
+ if (GC_find_leak)
+ WARN("free(NULL) is non-portable\n", 0);
+ return;
+ }
base = GC_base(p);
if (base == 0) {
GC_err_printf("Attempt to free invalid pointer %p\n", p);
Copyright (c) 1988, 1989 Hans-J. Boehm, Alan J. Demers
Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
-Copyright (c) 1999-2005 Hewlett-Packard Development Company, L.P.
+Copyright (c) 1999-2011 by Hewlett-Packard Development Company.
The file linux_threads.c is also
Copyright (c) 1998 by Fergus Henderson. All rights reserved.
GC_DEBUG Tested by gc.h. Causes all-upper-case macros to
expand to calls to debug versions of collector routines.
+GC_DEBUG_REPLACEMENT Tested by gc.h. Causes GC_MALLOC/REALLOC() to be
+ defined as GC_debug_malloc/realloc_replacement().
+
GC_NO_THREAD_REDIRECTS Tested by gc.h. Prevents redirection of thread
creation routines etc. to GC_ versions. Requires the
programmer to explicitly handle thread registration.
dynamic libraries are used, but the collector is in a static
library. Tested by gc_config_macros.h.
+GC_REQUIRE_WCSDUP Force GC to export GC_wcsdup() (the Unicode version
+ of GC_strdup); could be useful in the leak-finding mode.
+
These define arguments influence the collector configuration:
FIND_LEAK causes GC_find_leak to be initially set.
REDIRECT_MALLOC=<X> Causes malloc to be defined as alias for X.
Unless the following macros are defined, realloc is also redirected
to GC_realloc, and free is redirected to GC_free.
- Calloc and strdup are redefined in terms of the new malloc. X should
+ Calloc and str[n]dup are redefined in terms of the new malloc. X should
be either GC_malloc or GC_malloc_uncollectable, or
GC_debug_malloc_replacement. (The latter invokes GC_debug_malloc
with dummy source location information, but still results in
* Copyright 1996-1999 by Silicon Graphics. All rights reserved.
* Copyright 1999 by Hewlett-Packard Company. All rights reserved.
* Copyright (C) 2007 Free Software Foundation, Inc
- * Copyright (c) 2000-2010 by Hewlett-Packard Development Company.
+ * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.
*
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
GC_API void * GC_CALL GC_malloc_atomic(size_t /* size_in_bytes */)
GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1);
GC_API char * GC_CALL GC_strdup(const char *) GC_ATTR_MALLOC;
+GC_API char * GC_CALL GC_strndup(const char *, size_t) GC_ATTR_MALLOC;
GC_API void * GC_CALL GC_malloc_uncollectable(size_t /* size_in_bytes */)
GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1);
GC_API void * GC_CALL GC_malloc_stubborn(size_t /* size_in_bytes */)
/* GC_memalign() is not well tested. */
GC_API void * GC_CALL GC_memalign(size_t /* align */, size_t /* lb */)
GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(2);
+GC_API int GC_CALL GC_posix_memalign(void ** /* memptr */, size_t /* align */,
+ size_t /* lb */);
/* The following is only defined if the library has been suitably */
/* compiled: */
GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1);
GC_API char * GC_CALL GC_debug_strdup(const char *,
GC_EXTRA_PARAMS) GC_ATTR_MALLOC;
+GC_API char * GC_CALL GC_debug_strndup(const char *, size_t,
+ GC_EXTRA_PARAMS) GC_ATTR_MALLOC;
GC_API void * GC_CALL GC_debug_malloc_uncollectable(
size_t /* size_in_bytes */, GC_EXTRA_PARAMS)
GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1);
size_t /* size_in_bytes */)
/* 'realloc' attr */ GC_ATTR_ALLOC_SIZE(2);
-#ifdef GC_DEBUG
+#ifdef GC_DEBUG_REPLACEMENT
+# define GC_MALLOC(sz) GC_debug_malloc_replacement(sz)
+# define GC_REALLOC(old, sz) GC_debug_realloc_replacement(old, sz)
+#elif defined(GC_DEBUG)
# define GC_MALLOC(sz) GC_debug_malloc(sz, GC_EXTRAS)
+# define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS)
+#else
+# define GC_MALLOC(sz) GC_malloc(sz)
+# define GC_REALLOC(old, sz) GC_realloc(old, sz)
+#endif /* !GC_DEBUG_REPLACEMENT && !GC_DEBUG */
+
+#ifdef GC_DEBUG
# define GC_MALLOC_ATOMIC(sz) GC_debug_malloc_atomic(sz, GC_EXTRAS)
-# define GC_STRDUP(s) GC_debug_strdup((s), GC_EXTRAS)
+# define GC_STRDUP(s) GC_debug_strdup(s, GC_EXTRAS)
+# define GC_STRNDUP(s, sz) GC_debug_strndup(s, sz, GC_EXTRAS)
# define GC_MALLOC_UNCOLLECTABLE(sz) \
GC_debug_malloc_uncollectable(sz, GC_EXTRAS)
# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
GC_debug_malloc_ignore_off_page(sz, GC_EXTRAS)
# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
GC_debug_malloc_atomic_ignore_off_page(sz, GC_EXTRAS)
-# define GC_REALLOC(old, sz) GC_debug_realloc(old, sz, GC_EXTRAS)
# define GC_FREE(p) GC_debug_free(p)
# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
GC_debug_register_finalizer(p, f, d, of, od)
GC_general_register_disappearing_link(link, GC_base(obj))
# define GC_REGISTER_DISPLACEMENT(n) GC_debug_register_displacement(n)
#else
-# define GC_MALLOC(sz) GC_malloc(sz)
# define GC_MALLOC_ATOMIC(sz) GC_malloc_atomic(sz)
# define GC_STRDUP(s) GC_strdup(s)
+# define GC_STRNDUP(s, sz) GC_strndup(s, sz)
# define GC_MALLOC_UNCOLLECTABLE(sz) GC_malloc_uncollectable(sz)
# define GC_MALLOC_IGNORE_OFF_PAGE(sz) \
GC_malloc_ignore_off_page(sz)
# define GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(sz) \
GC_malloc_atomic_ignore_off_page(sz)
-# define GC_REALLOC(old, sz) GC_realloc(old, sz)
# define GC_FREE(p) GC_free(p)
# define GC_REGISTER_FINALIZER(p, f, d, of, od) \
GC_register_finalizer(p, f, d, of, od)
# define GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj) \
GC_general_register_disappearing_link(link, obj)
# define GC_REGISTER_DISPLACEMENT(n) GC_register_displacement(n)
-#endif
+#endif /* !GC_DEBUG */
/* The following are included because they are often convenient, and */
/* reduce the chance for a misspecified size argument. But calls may */
/* expand to something syntactically incorrect if t is a complicated */
/* type expression. */
-#define GC_NEW(t) (t *)GC_MALLOC(sizeof (t))
-#define GC_NEW_ATOMIC(t) (t *)GC_MALLOC_ATOMIC(sizeof (t))
-#define GC_NEW_STUBBORN(t) (t *)GC_MALLOC_STUBBORN(sizeof (t))
-#define GC_NEW_UNCOLLECTABLE(t) (t *)GC_MALLOC_UNCOLLECTABLE(sizeof (t))
+#define GC_NEW(t) ((t*)GC_MALLOC(sizeof(t)))
+#define GC_NEW_ATOMIC(t) ((t*)GC_MALLOC_ATOMIC(sizeof(t)))
+#define GC_NEW_STUBBORN(t) ((t*)GC_MALLOC_STUBBORN(sizeof(t)))
+#define GC_NEW_UNCOLLECTABLE(t) ((t*)GC_MALLOC_UNCOLLECTABLE(sizeof(t)))
+
+#ifdef GC_REQUIRE_WCSDUP
+ /* This might be unavailable on some targets (or not needed). */
+ /* wchar_t should be defined in stddef.h */
+ GC_API wchar_t * GC_CALL GC_wcsdup(const wchar_t *) GC_ATTR_MALLOC;
+ GC_API wchar_t * GC_CALL GC_debug_wcsdup(const wchar_t *,
+ GC_EXTRA_PARAMS) GC_ATTR_MALLOC;
+# ifdef GC_DEBUG
+# define GC_WCSDUP(s) GC_debug_wcsdup(s, GC_EXTRAS)
+# else
+# define GC_WCSDUP(s) GC_wcsdup(s)
+# endif
+#endif /* GC_REQUIRE_WCSDUP */
/* Finalization. Some of these primitives are grossly unsafe. */
/* The idea is to make them both cheap, and sufficient to build */
-#define GC_DEBUG
+/*
+ * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.
+ * All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#ifndef GC_LEAK_DETECTOR_H
+#define GC_LEAK_DETECTOR_H
+
+/* Include leak_detector.h (eg., via GCC --include directive) */
+/* to turn BoehmGC into a Leak Detector. */
+
+#ifndef GC_DEBUG
+# define GC_DEBUG
+#endif
#include "gc.h"
+
+#ifndef GC_DONT_INCLUDE_STDLIB
+ /* We ensure stdlib.h and string.h are included before */
+ /* redirecting malloc() and the accompanying functions. */
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#undef malloc
#define malloc(n) GC_MALLOC(n)
+#undef calloc
#define calloc(m,n) GC_MALLOC((m)*(n))
+#undef free
#define free(p) GC_FREE(p)
-#define realloc(p,n) GC_REALLOC((p),(n))
+#undef realloc
+#define realloc(p,n) GC_REALLOC(p,n)
+
#undef strdup
-#define strdup(s) GC_STRDUP((s))
-#define CHECK_LEAKS() GC_gcollect()
+#define strdup(s) GC_STRDUP(s)
+#undef strndup
+#define strndup(s,n) GC_STRNDUP(s,n)
+
+#ifdef GC_REQUIRE_WCSDUP
+ /* The collector should be built with GC_REQUIRE_WCSDUP */
+ /* defined as well to redirect wcsdup(). */
+# include <wchar.h>
+# undef wcsdup
+# define wcsdup(s) GC_WCSDUP(s)
+#endif
+
+#undef memalign
+#define memalign(a,n) GC_memalign(a,n)
+#undef posix_memalign
+#define posix_memalign(p,a,n) GC_posix_memalign(p,a,n)
+
+#ifndef CHECK_LEAKS
+# define CHECK_LEAKS() GC_gcollect()
+ /* Note 1: CHECK_LEAKS does not have GC prefix (preserved for */
+ /* backward compatibility). */
+ /* Note 2: GC_gcollect() is also called automatically in the */
+ /* leak-finding mode at program exit. */
+#endif
+
+#endif /* GC_LEAK_DETECTOR_H */
return copy;
}
+GC_API char * GC_CALL GC_strndup(const char *str, size_t size)
+{
+ char *copy;
+ size_t len = strlen(str); /* str is expected to be non-NULL */
+ if (len > size)
+ len = size;
+ copy = GC_malloc_atomic(len + 1);
+ if (copy == NULL) {
+# ifndef MSWINCE
+ errno = ENOMEM;
+# endif
+ return NULL;
+ }
+ BCOPY(str, copy, len);
+ copy[len] = '\0';
+ return copy;
+}
+
+#ifdef GC_REQUIRE_WCSDUP
+# include <wchar.h> /* for wcslen() */
+
+ GC_API wchar_t * GC_CALL GC_wcsdup(const wchar_t *str)
+ {
+ size_t lb = (wcslen(str) + 1) * sizeof(wchar_t);
+ wchar_t *copy = GC_malloc_atomic(lb);
+ if (copy == NULL) {
+# ifndef MSWINCE
+ errno = ENOMEM;
+# endif
+ return NULL;
+ }
+ BCOPY(str, copy, lb);
+ return copy;
+ }
+#endif /* GC_REQUIRE_WCSDUP */
+
/* Allocate lb bytes of composite (pointerful) data */
#ifdef THREAD_LOCAL_ALLOC
GC_INNER void * GC_core_malloc(size_t lb)
# include <string.h>
char *strdup(const char *s)
{
- size_t len = strlen(s) + 1;
- char * result = ((char *)REDIRECT_MALLOC(len+1));
+ size_t lb = strlen(s) + 1;
+ char *result = (char *)REDIRECT_MALLOC(lb);
if (result == 0) {
errno = ENOMEM;
return 0;
}
- BCOPY(s, result, len+1);
+ BCOPY(s, result, lb);
return result;
}
#endif /* !defined(strdup) */
/* and thus the right thing will happen even without overriding it. */
/* This seems to be true on most Linux systems. */
+#ifndef strndup
+ /* This is similar to strdup(). */
+# include <string.h>
+ char *strndup(const char *str, size_t size)
+ {
+ char *copy;
+ size_t len = strlen(str);
+ if (len > size)
+ len = size;
+ copy = (char *)REDIRECT_MALLOC(len + 1);
+ if (copy == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ BCOPY(str, copy, len);
+ copy[len] = '\0';
+ return copy;
+ }
+#endif /* !strndup */
+
#undef GC_debug_malloc_replacement
# endif /* REDIRECT_MALLOC */
#include <stdio.h>
+#ifdef MSWINCE
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+# endif
+# define NOSERVICE
+# include <windows.h>
+#else
+# include <errno.h>
+#endif
+
/* 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. */
return result;
}
+/* This one exists largerly to redirect posix_memalign for leaks finding. */
+GC_API int GC_CALL GC_posix_memalign(void **memptr, size_t align, size_t lb)
+{
+ /* Check alignment properly. */
+ if (((align - 1) & align) != 0 || align < sizeof(void *)) {
+# ifdef MSWINCE
+ return ERROR_INVALID_PARAMETER;
+# else
+ return EINVAL;
+# endif
+ }
+
+ if ((*memptr = GC_memalign(align, lb)) == NULL) {
+# ifdef MSWINCE
+ return ERROR_NOT_ENOUGH_MEMORY;
+# else
+ return ENOMEM;
+# endif
+ }
+ return 0;
+}
+
#ifdef ATOMIC_UNCOLLECTABLE
/* Allocate lb bytes of pointerfree, untraced, uncollectable data */
/* This is normally roughly equivalent to the system malloc. */
# endif
if (0 != GETENV("GC_FIND_LEAK")) {
GC_find_leak = 1;
- atexit(GC_exit_check);
}
if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) {
GC_all_interior_pointers = 1;
}
# endif
+ if (GC_find_leak) {
+ /* This is to give us at least one chance to detect leaks. */
+ /* This may report some very benign leaks, but ... */
+ atexit(GC_exit_check);
+ }
+
/* The rest of this again assumes we don't really hold */
/* the allocation lock. */
# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
__asm__ __volatile__ ("push %r15"); \
__asm__ __volatile__ ("mov %%esp, %0" \
: "=m" (GC_nacl_gc_thread_self->stop_info.stack_ptr)); \
- memcpy(GC_nacl_gc_thread_self->stop_info.reg_storage, \
- GC_nacl_gc_thread_self->stop_info.stack_ptr, \
- NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t)); \
+ BCOPY(GC_nacl_gc_thread_self->stop_info.stack_ptr, \
+ GC_nacl_gc_thread_self->stop_info.reg_storage, \
+ NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t)); \
__asm__ __volatile__ ("naclasp $48, %r15"); \
} while (0)
# elif defined(__i386__)
__asm__ __volatile__ ("push %edi"); \
__asm__ __volatile__ ("mov %%esp, %0" \
: "=m" (GC_nacl_gc_thread_self->stop_info.stack_ptr)); \
- memcpy(GC_nacl_gc_thread_self->stop_info.reg_storage, \
- GC_nacl_gc_thread_self->stop_info.stack_ptr, \
- NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));\
+ BCOPY(GC_nacl_gc_thread_self->stop_info.stack_ptr, \
+ GC_nacl_gc_thread_self->stop_info.reg_storage, \
+ NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));\
__asm__ __volatile__ ("add $16, %esp"); \
} while (0)
# else
GC_nacl_thread_parked[GC_nacl_thread_idx] = 0;
/* Clear out the reg storage for next suspend. */
- memset(GC_nacl_gc_thread_self->stop_info.reg_storage, 0,
- NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));
+ BZERO(GC_nacl_gc_thread_self->stop_info.reg_storage,
+ NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));
}
}
int i;
pthread_mutex_lock(&GC_nacl_thread_alloc_lock);
if (!GC_nacl_thread_parking_inited) {
- memset(GC_nacl_thread_parked, 0, sizeof(GC_nacl_thread_parked));
- memset(GC_nacl_thread_used, 0, sizeof(GC_nacl_thread_used));
+ BZERO(GC_nacl_thread_parked, sizeof(GC_nacl_thread_parked));
+ BZERO(GC_nacl_thread_used, sizeof(GC_nacl_thread_used));
GC_nacl_thread_parking_inited = TRUE;
}
GC_ASSERT(GC_nacl_num_gc_threads <= MAX_NACL_GC_THREADS);
if (NULL == dl_handle) {
while (isdigit(libpthread_name[len-1])) --len;
if (libpthread_name[len-1] == '.') --len;
- memcpy(namebuf, libpthread_name, len);
+ BCOPY(libpthread_name, namebuf, len);
namebuf[len] = '\0';
dl_handle = dlopen(namebuf, RTLD_LAZY);
}
#if defined(GC_WIN32_THREADS)
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+#endif
+#define NOSERVICE
#include <windows.h>
#ifdef THREAD_LOCAL_ALLOC