initfromthread.c raw
1 /*
2 * Copyright (c) 2011 Ludovic Courtes
3 *
4 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
6 *
7 * Permission is hereby granted to use or copy this program
8 * for any purpose, provided the above notices are retained on all copies.
9 * Permission to modify the code and to distribute modified code is granted,
10 * provided the above notices are retained, and a notice that the code was
11 * modified is included with the above copyright notice.
12 */
13
14 /*
15 * Make sure `GC_INIT()` can be called from threads other than the
16 * initial thread.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #ifndef GC_THREADS
24 # define GC_THREADS
25 #endif
26
27 /* Do not redirect thread creation and join calls. */
28 #define GC_NO_THREAD_REDIRECTS 1
29
30 #include "gc.h"
31
32 #ifdef GC_PTHREADS
33 # include <pthread.h>
34 #else
35 # ifndef WIN32_LEAN_AND_MEAN
36 # define WIN32_LEAN_AND_MEAN 1
37 # endif
38 # define NOSERVICE
39 # include <windows.h>
40 #endif /* !GC_PTHREADS */
41
42 #include <stdio.h>
43 #include <stdlib.h>
44
45 #define CHECK_OUT_OF_MEMORY(p) \
46 do { \
47 if (NULL == (p)) { \
48 fprintf(stderr, "Out of memory\n"); \
49 exit(69); \
50 } \
51 } while (0)
52
53 #ifdef GC_PTHREADS
54 static void *
55 thread(void *arg)
56 #else
57 static DWORD WINAPI
58 thread(LPVOID arg)
59 #endif
60 {
61 GC_INIT();
62 CHECK_OUT_OF_MEMORY(GC_MALLOC(123));
63 CHECK_OUT_OF_MEMORY(GC_MALLOC(12345));
64 #ifdef GC_PTHREADS
65 return arg;
66 #else
67 return (DWORD)(GC_uintptr_t)arg;
68 #endif
69 }
70
71 #include "private/gcconfig.h"
72
73 int
74 main(void)
75 {
76 #ifdef GC_PTHREADS
77 int err;
78 pthread_t t;
79
80 # ifdef LINT2
81 /* Explicitly initialize t to some value. */
82 t = pthread_self();
83 # endif
84 #else
85 HANDLE t;
86 DWORD thread_id;
87 #endif
88 #if !(defined(ANY_MSWIN) || defined(BEOS) \
89 || (defined(DARWIN) && !defined(NO_PTHREAD_GET_STACKADDR_NP)) \
90 || ((defined(FREEBSD) || defined(LINUX) || defined(NETBSD) \
91 || defined(HOST_ANDROID)) \
92 && !defined(NO_PTHREAD_ATTR_GET_NP) \
93 && !defined(NO_PTHREAD_GETATTR_NP)) \
94 || (defined(SOLARIS) && !defined(_STRICT_STDC)) \
95 || ((!defined(SPECIFIC_MAIN_STACKBOTTOM) || defined(HEURISTIC1)) \
96 && !defined(STACKBOTTOM)))
97 /* `GC_INIT()` must be called from main thread only. */
98 GC_INIT();
99 #endif
100
101 /* Linking fails if no thread support. */
102 (void)GC_get_suspend_signal();
103
104 if (GC_get_find_leak())
105 printf("This test program is not designed for leak detection mode\n");
106 #ifdef GC_PTHREADS
107 err = pthread_create(&t, NULL, thread, NULL);
108 if (err != 0) {
109 fprintf(stderr, "Thread #0 creation failed, errno= %d\n", err);
110 return 1;
111 }
112 err = pthread_join(t, NULL);
113 if (err != 0) {
114 fprintf(stderr, "Thread #0 join failed, errno= %d\n", err);
115 return 1;
116 }
117 #else
118 t = CreateThread(NULL, 0, thread, 0, 0, &thread_id);
119 if (t == NULL) {
120 fprintf(stderr, "Thread #0 creation failed, errcode= %d\n",
121 (int)GetLastError());
122 return 1;
123 }
124 if (WaitForSingleObject(t, INFINITE) != WAIT_OBJECT_0) {
125 fprintf(stderr, "Thread #0 join failed, errcode= %d\n",
126 (int)GetLastError());
127 CloseHandle(t);
128 return 1;
129 }
130 CloseHandle(t);
131 #endif
132 printf("SUCCEEDED\n");
133 return 0;
134 }
135