backout 29799f914cab, Bug 917642 - [Helix] Please update the helix blobs
[gecko.git] / nsprpub / pr / tests / foreign.c
blobd5be90a5f3a4d9d464e033632567931faa296afb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 ** File: foreign.c
8 ** Description: Testing various functions w/ foreign threads
9 **
10 ** We create a thread and get it to call exactly one runtime function.
11 ** The thread is allowed to be created by some other environment that
12 ** NSPR, but it does not announce itself to the runtime prior to calling
13 ** in.
15 ** The goal: try to survive.
16 **
19 #include "prcvar.h"
20 #include "prenv.h"
21 #include "prerror.h"
22 #include "prinit.h"
23 #include "prinrval.h"
24 #include "prio.h"
25 #include "prlock.h"
26 #include "prlog.h"
27 #include "prmem.h"
28 #include "prthread.h"
29 #include "prtypes.h"
30 #include "prprf.h"
31 #include "plgetopt.h"
33 #include <stdio.h>
34 #include <stdlib.h>
36 static enum {
37 thread_nspr, thread_pthread, thread_sproc, thread_win32
38 } thread_provider;
40 typedef void (*StartFn)(void*);
41 typedef struct StartObject
43 StartFn start;
44 void *arg;
45 } StartObject;
47 static PRFileDesc *output;
49 static int _debug_on = 0;
51 #define DEFAULT_THREAD_COUNT 10
53 #define DPRINTF(arg) if (_debug_on) PR_fprintf arg
55 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
56 #include <pthread.h>
57 #include "md/_pth.h"
58 static void *pthread_start(void *arg)
60 StartFn start = ((StartObject*)arg)->start;
61 void *data = ((StartObject*)arg)->arg;
62 PR_Free(arg);
63 start(data);
64 return NULL;
65 } /* pthread_start */
66 #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
68 #if defined(IRIX) && !defined(_PR_PTHREADS)
69 #include <sys/types.h>
70 #include <sys/prctl.h>
71 static void sproc_start(void *arg, PRSize size)
73 StartObject *so = (StartObject*)arg;
74 StartFn start = so->start;
75 void *data = so->arg;
76 PR_Free(so);
77 start(data);
78 } /* sproc_start */
79 #endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
81 #if defined(WIN32)
82 #if defined(WINCE)
83 #include <windows.h>
84 #endif
85 #include <process.h> /* for _beginthreadex() */
87 static PRUintn __stdcall windows_start(void *arg)
89 StartObject *so = (StartObject*)arg;
90 StartFn start = so->start;
91 void *data = so->arg;
92 PR_Free(so);
93 start(data);
94 return 0;
95 } /* windows_start */
96 #endif /* defined(WIN32) */
98 static PRStatus NSPRPUB_TESTS_CreateThread(StartFn start, void *arg)
100 PRStatus rv;
102 switch (thread_provider)
104 case thread_nspr:
106 PRThread *thread = PR_CreateThread(
107 PR_USER_THREAD, start, arg,
108 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
109 PR_UNJOINABLE_THREAD, 0);
110 rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS;
112 break;
113 case thread_pthread:
114 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
116 int rv;
117 pthread_t id;
118 pthread_attr_t tattr;
119 StartObject *start_object;
120 start_object = PR_NEW(StartObject);
121 PR_ASSERT(NULL != start_object);
122 start_object->start = start;
123 start_object->arg = arg;
125 rv = _PT_PTHREAD_ATTR_INIT(&tattr);
126 PR_ASSERT(0 == rv);
128 rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
129 PR_ASSERT(0 == rv);
131 rv = pthread_attr_setstacksize(&tattr, 64 * 1024);
132 PR_ASSERT(0 == rv);
134 rv = _PT_PTHREAD_CREATE(&id, tattr, pthread_start, start_object);
135 (void)_PT_PTHREAD_ATTR_DESTROY(&tattr);
136 return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
138 #else
139 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
140 rv = PR_FAILURE;
141 break;
142 #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
144 case thread_sproc:
145 #if defined(IRIX) && !defined(_PR_PTHREADS)
147 PRInt32 pid;
148 StartObject *start_object;
149 start_object = PR_NEW(StartObject);
150 PR_ASSERT(NULL != start_object);
151 start_object->start = start;
152 start_object->arg = arg;
153 pid = sprocsp(
154 sproc_start, PR_SALL, start_object, NULL, 64 * 1024);
155 rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE;
157 #else
158 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
159 rv = PR_FAILURE;
160 #endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
161 break;
162 case thread_win32:
163 #if defined(WIN32)
165 void *th;
166 PRUintn id;
167 StartObject *start_object;
168 start_object = PR_NEW(StartObject);
169 PR_ASSERT(NULL != start_object);
170 start_object->start = start;
171 start_object->arg = arg;
172 th = (void*)_beginthreadex(
173 NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */
174 0U, /* DWORD - initial thread stack size, in bytes */
175 windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */
176 start_object, /* LPVOID - argument for new thread */
177 0U, /*DWORD dwCreationFlags - creation flags */
178 &id /* LPDWORD - pointer to returned thread identifier */ );
180 rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS;
182 #else
183 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
184 rv = PR_FAILURE;
185 #endif
186 break;
187 default:
188 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
189 rv = PR_FAILURE;
191 return rv;
192 } /* NSPRPUB_TESTS_CreateThread */
194 static void PR_CALLBACK lazyEntry(void *arg)
196 PR_ASSERT(NULL == arg);
197 } /* lazyEntry */
200 static void OneShot(void *arg)
202 PRUintn pdkey;
203 PRLock *lock;
204 PRFileDesc *fd;
205 PRDir *dir;
206 PRFileDesc *pair[2];
207 PRIntn test = (PRIntn)arg;
209 for (test = 0; test < 12; ++test) {
211 switch (test)
213 case 0:
214 lock = PR_NewLock();
215 DPRINTF((output,"Thread[0x%x] called PR_NewLock\n",
216 PR_GetCurrentThread()));
217 PR_DestroyLock(lock);
218 break;
220 case 1:
221 (void)PR_SecondsToInterval(1);
222 DPRINTF((output,"Thread[0x%x] called PR_SecondsToInterval\n",
223 PR_GetCurrentThread()));
224 break;
226 case 2: (void)PR_CreateThread(
227 PR_USER_THREAD, lazyEntry, NULL, PR_PRIORITY_NORMAL,
228 PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0);
229 DPRINTF((output,"Thread[0x%x] called PR_CreateThread\n",
230 PR_GetCurrentThread()));
231 break;
233 case 3:
234 fd = PR_Open("foreign.tmp", PR_CREATE_FILE | PR_RDWR, 0666);
235 DPRINTF((output,"Thread[0x%x] called PR_Open\n",
236 PR_GetCurrentThread()));
237 PR_Close(fd);
238 break;
240 case 4:
241 fd = PR_NewUDPSocket();
242 DPRINTF((output,"Thread[0x%x] called PR_NewUDPSocket\n",
243 PR_GetCurrentThread()));
244 PR_Close(fd);
245 break;
247 case 5:
248 fd = PR_NewTCPSocket();
249 DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocket\n",
250 PR_GetCurrentThread()));
251 PR_Close(fd);
252 break;
254 case 6:
255 #ifdef SYMBIAN
256 #define TEMP_DIR "c:\\data\\"
257 #else
258 #define TEMP_DIR "/tmp/"
259 #endif
260 dir = PR_OpenDir(TEMP_DIR);
261 DPRINTF((output,"Thread[0x%x] called PR_OpenDir\n",
262 PR_GetCurrentThread()));
263 PR_CloseDir(dir);
264 break;
266 case 7:
267 (void)PR_NewThreadPrivateIndex(&pdkey, NULL);
268 DPRINTF((output,"Thread[0x%x] called PR_NewThreadPrivateIndex\n",
269 PR_GetCurrentThread()));
270 break;
272 case 8:
273 (void)PR_GetEnv("PATH");
274 DPRINTF((output,"Thread[0x%x] called PR_GetEnv\n",
275 PR_GetCurrentThread()));
276 break;
278 case 9:
279 (void)PR_NewTCPSocketPair(pair);
280 DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocketPair\n",
281 PR_GetCurrentThread()));
282 PR_Close(pair[0]);
283 PR_Close(pair[1]);
284 break;
286 case 10:
287 PR_SetConcurrency(2);
288 DPRINTF((output,"Thread[0x%x] called PR_SetConcurrency\n",
289 PR_GetCurrentThread()));
290 break;
292 case 11:
293 PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_HIGH);
294 DPRINTF((output,"Thread[0x%x] called PR_SetThreadPriority\n",
295 PR_GetCurrentThread()));
296 break;
298 default:
299 break;
300 } /* switch() */
302 } /* OneShot */
304 int main(int argc, char **argv)
306 PRStatus rv;
307 PRInt32 thread_cnt = DEFAULT_THREAD_COUNT;
308 PLOptStatus os;
309 PLOptState *opt = PL_CreateOptState(argc, argv, "dt:");
311 #if defined(WIN32)
312 thread_provider = thread_win32;
313 #elif defined(_PR_PTHREADS)
314 thread_provider = thread_pthread;
315 #elif defined(IRIX)
316 thread_provider = thread_sproc;
317 #else
318 thread_provider = thread_nspr;
319 #endif
322 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
324 if (PL_OPT_BAD == os) continue;
325 switch (opt->option)
327 case 'd': /* debug mode */
328 _debug_on = 1;
329 break;
330 case 't': /* thread count */
331 thread_cnt = atoi(opt->value);
332 break;
333 default:
334 break;
337 PL_DestroyOptState(opt);
339 PR_SetConcurrency(2);
341 output = PR_GetSpecialFD(PR_StandardOutput);
343 while (thread_cnt-- > 0)
345 rv = NSPRPUB_TESTS_CreateThread(OneShot, (void*)thread_cnt);
346 PR_ASSERT(PR_SUCCESS == rv);
347 PR_Sleep(PR_MillisecondsToInterval(5));
349 PR_Sleep(PR_SecondsToInterval(3));
350 return (PR_SUCCESS == PR_Cleanup()) ? 0 : 1;
351 } /* main */
353 /* foreign.c */