nsprpub/pr/tests/foreign.c

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial