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/. */
8 ** Description: Testing various functions w/ foreign threads
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
15 ** The goal: try to survive.
37 thread_nspr
, thread_pthread
, thread_sproc
, thread_win32
40 typedef void (*StartFn
)(void*);
41 typedef struct 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)
58 static void *pthread_start(void *arg
)
60 StartFn start
= ((StartObject
*)arg
)->start
;
61 void *data
= ((StartObject
*)arg
)->arg
;
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
;
79 #endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
85 #include <process.h> /* for _beginthreadex() */
87 static PRUintn __stdcall
windows_start(void *arg
)
89 StartObject
*so
= (StartObject
*)arg
;
90 StartFn start
= so
->start
;
96 #endif /* defined(WIN32) */
98 static PRStatus
NSPRPUB_TESTS_CreateThread(StartFn start
, void *arg
)
102 switch (thread_provider
)
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
;
114 #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
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
);
128 rv
= pthread_attr_setdetachstate(&tattr
, PTHREAD_CREATE_DETACHED
);
131 rv
= pthread_attr_setstacksize(&tattr
, 64 * 1024);
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
;
139 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
142 #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
145 #if defined(IRIX) && !defined(_PR_PTHREADS)
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
;
154 sproc_start
, PR_SALL
, start_object
, NULL
, 64 * 1024);
155 rv
= (0 < pid
) ? PR_SUCCESS
: PR_FAILURE
;
158 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
160 #endif /* defined(IRIX) && !defined(_PR_PTHREADS) */
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
;
183 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
188 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
192 } /* NSPRPUB_TESTS_CreateThread */
194 static void PR_CALLBACK
lazyEntry(void *arg
)
196 PR_ASSERT(NULL
== arg
);
200 static void OneShot(void *arg
)
207 PRIntn test
= (PRIntn
)arg
;
209 for (test
= 0; test
< 12; ++test
) {
215 DPRINTF((output
,"Thread[0x%x] called PR_NewLock\n",
216 PR_GetCurrentThread()));
217 PR_DestroyLock(lock
);
221 (void)PR_SecondsToInterval(1);
222 DPRINTF((output
,"Thread[0x%x] called PR_SecondsToInterval\n",
223 PR_GetCurrentThread()));
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()));
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()));
241 fd
= PR_NewUDPSocket();
242 DPRINTF((output
,"Thread[0x%x] called PR_NewUDPSocket\n",
243 PR_GetCurrentThread()));
248 fd
= PR_NewTCPSocket();
249 DPRINTF((output
,"Thread[0x%x] called PR_NewTCPSocket\n",
250 PR_GetCurrentThread()));
256 #define TEMP_DIR "c:\\data\\"
258 #define TEMP_DIR "/tmp/"
260 dir
= PR_OpenDir(TEMP_DIR
);
261 DPRINTF((output
,"Thread[0x%x] called PR_OpenDir\n",
262 PR_GetCurrentThread()));
267 (void)PR_NewThreadPrivateIndex(&pdkey
, NULL
);
268 DPRINTF((output
,"Thread[0x%x] called PR_NewThreadPrivateIndex\n",
269 PR_GetCurrentThread()));
273 (void)PR_GetEnv("PATH");
274 DPRINTF((output
,"Thread[0x%x] called PR_GetEnv\n",
275 PR_GetCurrentThread()));
279 (void)PR_NewTCPSocketPair(pair
);
280 DPRINTF((output
,"Thread[0x%x] called PR_NewTCPSocketPair\n",
281 PR_GetCurrentThread()));
287 PR_SetConcurrency(2);
288 DPRINTF((output
,"Thread[0x%x] called PR_SetConcurrency\n",
289 PR_GetCurrentThread()));
293 PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_HIGH
);
294 DPRINTF((output
,"Thread[0x%x] called PR_SetThreadPriority\n",
295 PR_GetCurrentThread()));
304 int main(int argc
, char **argv
)
307 PRInt32 thread_cnt
= DEFAULT_THREAD_COUNT
;
309 PLOptState
*opt
= PL_CreateOptState(argc
, argv
, "dt:");
312 thread_provider
= thread_win32
;
313 #elif defined(_PR_PTHREADS)
314 thread_provider
= thread_pthread
;
316 thread_provider
= thread_sproc
;
318 thread_provider
= thread_nspr
;
322 while (PL_OPT_EOL
!= (os
= PL_GetNextOpt(opt
)))
324 if (PL_OPT_BAD
== os
) continue;
327 case 'd': /* debug mode */
330 case 't': /* thread count */
331 thread_cnt
= atoi(opt
->value
);
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;