1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/foreign.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,351 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 +** File: foreign.c 1.11 +** Description: Testing various functions w/ foreign threads 1.12 +** 1.13 +** We create a thread and get it to call exactly one runtime function. 1.14 +** The thread is allowed to be created by some other environment that 1.15 +** NSPR, but it does not announce itself to the runtime prior to calling 1.16 +** in. 1.17 +** 1.18 +** The goal: try to survive. 1.19 +** 1.20 +*/ 1.21 + 1.22 +#include "prcvar.h" 1.23 +#include "prenv.h" 1.24 +#include "prerror.h" 1.25 +#include "prinit.h" 1.26 +#include "prinrval.h" 1.27 +#include "prio.h" 1.28 +#include "prlock.h" 1.29 +#include "prlog.h" 1.30 +#include "prmem.h" 1.31 +#include "prthread.h" 1.32 +#include "prtypes.h" 1.33 +#include "prprf.h" 1.34 +#include "plgetopt.h" 1.35 + 1.36 +#include <stdio.h> 1.37 +#include <stdlib.h> 1.38 + 1.39 +static enum { 1.40 + thread_nspr, thread_pthread, thread_sproc, thread_win32 1.41 +} thread_provider; 1.42 + 1.43 +typedef void (*StartFn)(void*); 1.44 +typedef struct StartObject 1.45 +{ 1.46 + StartFn start; 1.47 + void *arg; 1.48 +} StartObject; 1.49 + 1.50 +static PRFileDesc *output; 1.51 + 1.52 +static int _debug_on = 0; 1.53 + 1.54 +#define DEFAULT_THREAD_COUNT 10 1.55 + 1.56 +#define DPRINTF(arg) if (_debug_on) PR_fprintf arg 1.57 + 1.58 +#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) 1.59 +#include <pthread.h> 1.60 +#include "md/_pth.h" 1.61 +static void *pthread_start(void *arg) 1.62 +{ 1.63 + StartFn start = ((StartObject*)arg)->start; 1.64 + void *data = ((StartObject*)arg)->arg; 1.65 + PR_Free(arg); 1.66 + start(data); 1.67 + return NULL; 1.68 +} /* pthread_start */ 1.69 +#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ 1.70 + 1.71 +#if defined(IRIX) && !defined(_PR_PTHREADS) 1.72 +#include <sys/types.h> 1.73 +#include <sys/prctl.h> 1.74 +static void sproc_start(void *arg, PRSize size) 1.75 +{ 1.76 + StartObject *so = (StartObject*)arg; 1.77 + StartFn start = so->start; 1.78 + void *data = so->arg; 1.79 + PR_Free(so); 1.80 + start(data); 1.81 +} /* sproc_start */ 1.82 +#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */ 1.83 + 1.84 +#if defined(WIN32) 1.85 +#include <windows.h> 1.86 +#include <process.h> /* for _beginthreadex() */ 1.87 + 1.88 +static PRUintn __stdcall windows_start(void *arg) 1.89 +{ 1.90 + StartObject *so = (StartObject*)arg; 1.91 + StartFn start = so->start; 1.92 + void *data = so->arg; 1.93 + PR_Free(so); 1.94 + start(data); 1.95 + return 0; 1.96 +} /* windows_start */ 1.97 +#endif /* defined(WIN32) */ 1.98 + 1.99 +static PRStatus NSPRPUB_TESTS_CreateThread(StartFn start, void *arg) 1.100 +{ 1.101 + PRStatus rv; 1.102 + 1.103 + switch (thread_provider) 1.104 + { 1.105 + case thread_nspr: 1.106 + { 1.107 + PRThread *thread = PR_CreateThread( 1.108 + PR_USER_THREAD, start, arg, 1.109 + PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, 1.110 + PR_UNJOINABLE_THREAD, 0); 1.111 + rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS; 1.112 + } 1.113 + break; 1.114 + case thread_pthread: 1.115 +#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) 1.116 + { 1.117 + int rv; 1.118 + pthread_t id; 1.119 + pthread_attr_t tattr; 1.120 + StartObject *start_object; 1.121 + start_object = PR_NEW(StartObject); 1.122 + PR_ASSERT(NULL != start_object); 1.123 + start_object->start = start; 1.124 + start_object->arg = arg; 1.125 + 1.126 + rv = _PT_PTHREAD_ATTR_INIT(&tattr); 1.127 + PR_ASSERT(0 == rv); 1.128 + 1.129 + rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 1.130 + PR_ASSERT(0 == rv); 1.131 + 1.132 + rv = pthread_attr_setstacksize(&tattr, 64 * 1024); 1.133 + PR_ASSERT(0 == rv); 1.134 + 1.135 + rv = _PT_PTHREAD_CREATE(&id, tattr, pthread_start, start_object); 1.136 + (void)_PT_PTHREAD_ATTR_DESTROY(&tattr); 1.137 + return (0 == rv) ? PR_SUCCESS : PR_FAILURE; 1.138 + } 1.139 +#else 1.140 + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 1.141 + rv = PR_FAILURE; 1.142 + break; 1.143 +#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ 1.144 + 1.145 + case thread_sproc: 1.146 +#if defined(IRIX) && !defined(_PR_PTHREADS) 1.147 + { 1.148 + PRInt32 pid; 1.149 + StartObject *start_object; 1.150 + start_object = PR_NEW(StartObject); 1.151 + PR_ASSERT(NULL != start_object); 1.152 + start_object->start = start; 1.153 + start_object->arg = arg; 1.154 + pid = sprocsp( 1.155 + sproc_start, PR_SALL, start_object, NULL, 64 * 1024); 1.156 + rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE; 1.157 + } 1.158 +#else 1.159 + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 1.160 + rv = PR_FAILURE; 1.161 +#endif /* defined(IRIX) && !defined(_PR_PTHREADS) */ 1.162 + break; 1.163 + case thread_win32: 1.164 +#if defined(WIN32) 1.165 + { 1.166 + void *th; 1.167 + PRUintn id; 1.168 + StartObject *start_object; 1.169 + start_object = PR_NEW(StartObject); 1.170 + PR_ASSERT(NULL != start_object); 1.171 + start_object->start = start; 1.172 + start_object->arg = arg; 1.173 + th = (void*)_beginthreadex( 1.174 + NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */ 1.175 + 0U, /* DWORD - initial thread stack size, in bytes */ 1.176 + windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */ 1.177 + start_object, /* LPVOID - argument for new thread */ 1.178 + STACK_SIZE_PARAM_IS_A_RESERVATION, /*DWORD dwCreationFlags - creation flags */ 1.179 + &id /* LPDWORD - pointer to returned thread identifier */ ); 1.180 + 1.181 + rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS; 1.182 + } 1.183 +#else 1.184 + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 1.185 + rv = PR_FAILURE; 1.186 +#endif 1.187 + break; 1.188 + default: 1.189 + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 1.190 + rv = PR_FAILURE; 1.191 + } 1.192 + return rv; 1.193 +} /* NSPRPUB_TESTS_CreateThread */ 1.194 + 1.195 +static void PR_CALLBACK lazyEntry(void *arg) 1.196 +{ 1.197 + PR_ASSERT(NULL == arg); 1.198 +} /* lazyEntry */ 1.199 + 1.200 + 1.201 +static void OneShot(void *arg) 1.202 +{ 1.203 + PRUintn pdkey; 1.204 + PRLock *lock; 1.205 + PRFileDesc *fd; 1.206 + PRDir *dir; 1.207 + PRFileDesc *pair[2]; 1.208 + PRIntn test = (PRIntn)arg; 1.209 + 1.210 + for (test = 0; test < 12; ++test) { 1.211 + 1.212 + switch (test) 1.213 + { 1.214 + case 0: 1.215 + lock = PR_NewLock(); 1.216 + DPRINTF((output,"Thread[0x%x] called PR_NewLock\n", 1.217 + PR_GetCurrentThread())); 1.218 + PR_DestroyLock(lock); 1.219 + break; 1.220 + 1.221 + case 1: 1.222 + (void)PR_SecondsToInterval(1); 1.223 + DPRINTF((output,"Thread[0x%x] called PR_SecondsToInterval\n", 1.224 + PR_GetCurrentThread())); 1.225 + break; 1.226 + 1.227 + case 2: (void)PR_CreateThread( 1.228 + PR_USER_THREAD, lazyEntry, NULL, PR_PRIORITY_NORMAL, 1.229 + PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); 1.230 + DPRINTF((output,"Thread[0x%x] called PR_CreateThread\n", 1.231 + PR_GetCurrentThread())); 1.232 + break; 1.233 + 1.234 + case 3: 1.235 + fd = PR_Open("foreign.tmp", PR_CREATE_FILE | PR_RDWR, 0666); 1.236 + DPRINTF((output,"Thread[0x%x] called PR_Open\n", 1.237 + PR_GetCurrentThread())); 1.238 + PR_Close(fd); 1.239 + break; 1.240 + 1.241 + case 4: 1.242 + fd = PR_NewUDPSocket(); 1.243 + DPRINTF((output,"Thread[0x%x] called PR_NewUDPSocket\n", 1.244 + PR_GetCurrentThread())); 1.245 + PR_Close(fd); 1.246 + break; 1.247 + 1.248 + case 5: 1.249 + fd = PR_NewTCPSocket(); 1.250 + DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocket\n", 1.251 + PR_GetCurrentThread())); 1.252 + PR_Close(fd); 1.253 + break; 1.254 + 1.255 + case 6: 1.256 +#ifdef SYMBIAN 1.257 +#define TEMP_DIR "c:\\data\\" 1.258 +#else 1.259 +#define TEMP_DIR "/tmp/" 1.260 +#endif 1.261 + dir = PR_OpenDir(TEMP_DIR); 1.262 + DPRINTF((output,"Thread[0x%x] called PR_OpenDir\n", 1.263 + PR_GetCurrentThread())); 1.264 + PR_CloseDir(dir); 1.265 + break; 1.266 + 1.267 + case 7: 1.268 + (void)PR_NewThreadPrivateIndex(&pdkey, NULL); 1.269 + DPRINTF((output,"Thread[0x%x] called PR_NewThreadPrivateIndex\n", 1.270 + PR_GetCurrentThread())); 1.271 + break; 1.272 + 1.273 + case 8: 1.274 + (void)PR_GetEnv("PATH"); 1.275 + DPRINTF((output,"Thread[0x%x] called PR_GetEnv\n", 1.276 + PR_GetCurrentThread())); 1.277 + break; 1.278 + 1.279 + case 9: 1.280 + (void)PR_NewTCPSocketPair(pair); 1.281 + DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocketPair\n", 1.282 + PR_GetCurrentThread())); 1.283 + PR_Close(pair[0]); 1.284 + PR_Close(pair[1]); 1.285 + break; 1.286 + 1.287 + case 10: 1.288 + PR_SetConcurrency(2); 1.289 + DPRINTF((output,"Thread[0x%x] called PR_SetConcurrency\n", 1.290 + PR_GetCurrentThread())); 1.291 + break; 1.292 + 1.293 + case 11: 1.294 + PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_HIGH); 1.295 + DPRINTF((output,"Thread[0x%x] called PR_SetThreadPriority\n", 1.296 + PR_GetCurrentThread())); 1.297 + break; 1.298 + 1.299 + default: 1.300 + break; 1.301 + } /* switch() */ 1.302 + } 1.303 +} /* OneShot */ 1.304 + 1.305 +int main(int argc, char **argv) 1.306 +{ 1.307 + PRStatus rv; 1.308 + PRInt32 thread_cnt = DEFAULT_THREAD_COUNT; 1.309 + PLOptStatus os; 1.310 + PLOptState *opt = PL_CreateOptState(argc, argv, "dt:"); 1.311 + 1.312 +#if defined(WIN32) 1.313 + thread_provider = thread_win32; 1.314 +#elif defined(_PR_PTHREADS) 1.315 + thread_provider = thread_pthread; 1.316 +#elif defined(IRIX) 1.317 + thread_provider = thread_sproc; 1.318 +#else 1.319 + thread_provider = thread_nspr; 1.320 +#endif 1.321 + 1.322 + 1.323 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.324 + { 1.325 + if (PL_OPT_BAD == os) continue; 1.326 + switch (opt->option) 1.327 + { 1.328 + case 'd': /* debug mode */ 1.329 + _debug_on = 1; 1.330 + break; 1.331 + case 't': /* thread count */ 1.332 + thread_cnt = atoi(opt->value); 1.333 + break; 1.334 + default: 1.335 + break; 1.336 + } 1.337 + } 1.338 + PL_DestroyOptState(opt); 1.339 + 1.340 + PR_SetConcurrency(2); 1.341 + 1.342 + output = PR_GetSpecialFD(PR_StandardOutput); 1.343 + 1.344 + while (thread_cnt-- > 0) 1.345 + { 1.346 + rv = NSPRPUB_TESTS_CreateThread(OneShot, (void*)thread_cnt); 1.347 + PR_ASSERT(PR_SUCCESS == rv); 1.348 + PR_Sleep(PR_MillisecondsToInterval(5)); 1.349 + } 1.350 + PR_Sleep(PR_SecondsToInterval(3)); 1.351 + return (PR_SUCCESS == PR_Cleanup()) ? 0 : 1; 1.352 +} /* main */ 1.353 + 1.354 +/* foreign.c */