nsprpub/pr/tests/foreign.c

changeset 0
6474c204b198
     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 */

mercurial