/* * Copyright (c) 2011 Ludovic Courtes * * 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. */ /* * Make sure `GC_INIT()` can be called from threads other than the * initial thread. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifndef GC_THREADS # define GC_THREADS #endif /* Do not redirect thread creation and join calls. */ #define GC_NO_THREAD_REDIRECTS 1 #include "gc.h" #ifdef GC_PTHREADS # include #else # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN 1 # endif # define NOSERVICE # include #endif /* !GC_PTHREADS */ #include #include #define CHECK_OUT_OF_MEMORY(p) \ do { \ if (NULL == (p)) { \ fprintf(stderr, "Out of memory\n"); \ exit(69); \ } \ } while (0) #ifdef GC_PTHREADS static void * thread(void *arg) #else static DWORD WINAPI thread(LPVOID arg) #endif { GC_INIT(); CHECK_OUT_OF_MEMORY(GC_MALLOC(123)); CHECK_OUT_OF_MEMORY(GC_MALLOC(12345)); #ifdef GC_PTHREADS return arg; #else return (DWORD)(GC_uintptr_t)arg; #endif } #include "private/gcconfig.h" int main(void) { #ifdef GC_PTHREADS int err; pthread_t t; # ifdef LINT2 /* Explicitly initialize t to some value. */ t = pthread_self(); # endif #else HANDLE t; DWORD thread_id; #endif #if !(defined(ANY_MSWIN) || defined(BEOS) \ || (defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)) \ || ((defined(FREEBSD) || defined(LINUX) || defined(NETBSD) \ || defined(HOST_ANDROID)) \ && !defined(NO_PTHREAD_ATTR_GET_NP) \ && !defined(NO_PTHREAD_GETATTR_NP)) \ || (defined(SOLARIS) && !defined(_STRICT_STDC)) \ || ((!defined(SPECIFIC_MAIN_STACKBOTTOM) || defined(HEURISTIC1)) \ && !defined(STACKBOTTOM))) /* `GC_INIT()` must be called from main thread only. */ GC_INIT(); #endif /* Linking fails if no thread support. */ (void)GC_get_suspend_signal(); if (GC_get_find_leak()) printf("This test program is not designed for leak detection mode\n"); #ifdef GC_PTHREADS err = pthread_create(&t, NULL, thread, NULL); if (err != 0) { fprintf(stderr, "Thread #0 creation failed, errno= %d\n", err); return 1; } err = pthread_join(t, NULL); if (err != 0) { fprintf(stderr, "Thread #0 join failed, errno= %d\n", err); return 1; } #else t = CreateThread(NULL, 0, thread, 0, 0, &thread_id); if (t == NULL) { fprintf(stderr, "Thread #0 creation failed, errcode= %d\n", (int)GetLastError()); return 1; } if (WaitForSingleObject(t, INFINITE) != WAIT_OBJECT_0) { fprintf(stderr, "Thread #0 join failed, errcode= %d\n", (int)GetLastError()); CloseHandle(t); return 1; } CloseHandle(t); #endif printf("SUCCEEDED\n"); return 0; }