void ClosingService::ShutdownInternal() { { mozilla::MonitorAutoLock mon(mMonitor); mShutdown = true; // If it is waiting on the empty queue, wake it up. if (mQueue.Length() == 0) { mon.Notify(); } } if (mThread) { PR_JoinThread(mThread); mThread = nullptr; } }
int main(PRIntn argc, const char **argv) { PRThread *thread; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); #ifndef XP_MAC if (argc > 1) { if (!PR_SetLogFile(argv[1])) { Error("Access: Cannot create log file"); goto exit; } } #else SetupMacPrintfLog("logger.log"); #endif /* Start logging something here */ PR_LogPrint("%s logging into %s\n", argv[0], argv[1]); PR_LogPrint("%s creating new thread\n", argv[0]); /* ** Now change buffering. */ PR_SetLogBuffering( 65500 ); thread = PR_CreateThread( PR_USER_THREAD, forked, (void*)argv[0], PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_LogPrint("%s joining thread\n", argv[0]); UserLogStuff(); PR_JoinThread(thread); PR_LogFlush(); return 0; exit: return -1; }
PR_IMPLEMENT(PRStatus) PR_DestroyAlarm(PRAlarm *alarm) { PRStatus rv; PR_Lock(alarm->lock); alarm->state = alarm_inactive; rv = PR_NotifyCondVar(alarm->cond); PR_Unlock(alarm->lock); if (rv == PR_SUCCESS) rv = PR_JoinThread(alarm->notifier); if (rv == PR_SUCCESS) { PR_DestroyCondVar(alarm->cond); PR_DestroyLock(alarm->lock); PR_DELETE(alarm); } return rv; } /* PR_DestroyAlarm */
int main(int argc, char **argv) { PRThread *thread; PRIntervalTime start, end; PRUint32 elapsed_ms; lock1 = PR_NewLock(); PR_ASSERT(NULL != lock1); cv1 = PR_NewCondVar(lock1); PR_ASSERT(NULL != cv1); lock2 = PR_NewLock(); PR_ASSERT(NULL != lock2); cv2 = PR_NewCondVar(lock2); PR_ASSERT(NULL != cv2); start = PR_IntervalNow(); thread = PR_CreateThread( PR_USER_THREAD, ThreadFunc, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_ASSERT(NULL != thread); PR_Lock(lock2); PR_WaitCondVar(cv2, PR_MillisecondsToInterval(LONG_TIMEOUT)); PR_Unlock(lock2); PR_JoinThread(thread); end = PR_IntervalNow(); elapsed_ms = PR_IntervalToMilliseconds((PRIntervalTime)(end - start)); /* Allow 100ms imprecision */ if (elapsed_ms < LONG_TIMEOUT - 100 || elapsed_ms > LONG_TIMEOUT + 100) { printf("Elapsed time should be %u ms but is %u ms\n", LONG_TIMEOUT, elapsed_ms); printf("FAIL\n"); exit(1); } printf("Elapsed time: %u ms, expected time: %u ms\n", LONG_TIMEOUT, elapsed_ms); printf("PASS\n"); return 0; }
static PRUint32 ContentiousMonitor(PRUint32 loops) { PRStatus status; PRThread *thread = NULL; MonitorContentious_t * contention; PRIntervalTime rv, overhead, timein = PR_IntervalNow(); contention = PR_NEWZAP(MonitorContentious_t); contention->loops = loops; contention->overhead = 0; contention->ml = PR_NewMonitor(); contention->interval = contention_interval; thread = PR_CreateThread( PR_USER_THREAD, MonitorContender, contention, PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_ASSERT(thread != NULL); overhead = PR_IntervalNow() - timein; while (contention->loops-- > 0) { PR_EnterMonitor(contention->ml); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml); contention->contentious+= 1; contention->overhead += contention->interval; PR_Sleep(contention->interval); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml); PR_ExitMonitor(contention->ml); } timein = PR_IntervalNow(); status = PR_JoinThread(thread); PR_DestroyMonitor(contention->ml); overhead += (PR_IntervalNow() - timein); rv = overhead + contention->overhead; if (verbosity) PR_fprintf( std_err, "Access ratio: %u to %u\n", contention->contentious, contention->contender); PR_Free(contention); return rv; } /* ContentiousMonitor */
int main(int argc, const char **argv) { if (argc != 3) usage(argv[0]); try { WikiDumpParser parser(argv[1], argv[2]); PRThread *runner = 0; { MonitorBlock sync(&parser); runner = PR_CreateThread(PR_USER_THREAD, myThreadStart, &parser, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); sync.wait(); } size_t ticksPerSecond = PR_TicksPerSecond(); float progress; do { progress = parser.getProgress(); std::cout << progress << std::endl; PR_Sleep(1 * ticksPerSecond); } while (progress > 0 && progress < 1); PR_JoinThread(runner); if (progress == -1) { std::cerr << parser.errMsg() << std::endl; return 1; } //parser.parse(); } catch (std::exception &e) { std::cerr << "error: " << e.what() << std::endl; } catch (...) { std::cerr << "error: ..." << std::endl; } return 0; }
main() { int index; PRThread *a[THREADS]; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 5); PR_STDIO_INIT(); for (index=0; index<THREADS; index++) { a[index] = PR_CreateThread(PR_USER_THREAD, threadmain, (void *)index, PR_PRIORITY_NORMAL, index%2?PR_LOCAL_THREAD:PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); } for(index=0; index<THREADS; index++) PR_JoinThread(a[index]); printf("main dying\n"); }
static PRIntervalTime ConditionNotify(PRUint32 loops) { PRThread *thread; NotifyData notifyData; PRIntervalTime timein, overhead; timein = PR_IntervalNow(); notifyData.counter = loops; notifyData.ml = PR_NewLock(); notifyData.child = PR_NewCondVar(notifyData.ml); notifyData.parent = PR_NewCondVar(notifyData.ml); thread = PR_CreateThread( PR_USER_THREAD, Notifier, ¬ifyData, PR_GetThreadPriority(PR_GetCurrentThread()), thread_scope, PR_JOINABLE_THREAD, 0); overhead = PR_IntervalNow() - timein; /* elapsed so far */ PR_Lock(notifyData.ml); while (notifyData.counter > 0) { notifyData.pending = PR_TRUE; PR_NotifyCondVar(notifyData.child); while (notifyData.pending) PR_WaitCondVar(notifyData.parent, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(notifyData.ml); timein = PR_IntervalNow(); (void)PR_JoinThread(thread); PR_DestroyCondVar(notifyData.child); PR_DestroyCondVar(notifyData.parent); PR_DestroyLock(notifyData.ml); overhead += (PR_IntervalNow() - timein); /* more overhead */ return overhead; } /* ConditionNotify */
nsresult IPC_Disconnect() { // Must disconnect on same thread used to connect! PR_ASSERT(gMainThread == PR_GetCurrentThread()); if (!gConnState || !gConnThread) return NS_ERROR_NOT_INITIALIZED; PR_Lock(gConnState->lock); gConnState->shutdown = PR_TRUE; PR_SetPollableEvent(gConnState->fds[POLL].fd); PR_Unlock(gConnState->lock); PR_JoinThread(gConnThread); ConnDestroy(gConnState); gConnState = NULL; gConnThread = NULL; return NS_OK; }
Resolver :: Resolver(PRIntervalTime timeout) { curlookups = namelookups = addrlookups = 0; ar_vc = 0; ok = PR_FALSE; ar_default_workerthread_timeout = timeout; memset(&ar_reinfo, 0, sizeof(ar_reinfo)); dnslock = PR_NewLock(); initcvar = PR_NewCondVar(dnslock); awake = PR_FALSE; afd = NULL; // then create a DNS manager background thread PRThread* ar_worker = PR_CreateThread(PR_SYSTEM_THREAD, run, this, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); if (ar_worker) { wait(); if (!ok) { PR_JoinThread(ar_worker); } } }
void nsPluginInstance::shut(void) { DBG("nsPluginInstance::shut\n"); DBG("Acquiring playerLock mutex for shutdown.\n"); PR_Lock(playerLock); _shutdown = TRUE; DBG("Releasing playerLock mutex for shutdown.\n"); PR_Unlock(playerLock); if (_thread) { DBG("Waiting for thread to terminate.\n"); PR_JoinThread(_thread); _thread = NULL; } // subclass it back //SubclassWindow(_window, _oldWndProc); _initialized = FALSE; }
// // Should only stop if we are through with the module. // CancelWait has the side effect of losing all the keys and // current operations on the module!. (See the comment in // SECMOD_CancelWait for why this is so..). // void SmartCardMonitoringThread::Stop() { SECStatus rv; rv = SECMOD_CancelWait(mModule); if (rv != SECSuccess) { // we didn't wake up the Wait, so don't try to join the thread // otherwise we will hang forever... return; } // confused about the memory model here? NSPR owns the memory for // threads. non-joinable threads are freed when the thread dies. // joinable threads are freed after the call to PR_JoinThread. // That means if SECMOD_CancelWait fails, we'll leak the mThread // structure. this is considered preferable to hanging (which is // what will happen if we try to join a thread that blocked). if (mThread) { PR_JoinThread(mThread); mThread = 0; } }
void joinWithUnjoinable(void) { PRThread *thread; /* create the unjoinable thread */ thread = PR_CreateThread(PR_USER_THREAD, unjoinable, 0, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (!thread) { if (debug_mode) printf("\tcannot create unjoinable thread\n"); else Test_Result(FAIL); return; } if (PR_JoinThread(thread) == PR_SUCCESS) { if (debug_mode) printf("\tsuccessfully joined with unjoinable thread?!\n"); else Test_Result(FAIL); return; } else { if (debug_mode) printf("\tcannot join with unjoinable thread, as expected\n"); if (PR_GetError() != PR_INVALID_ARGUMENT_ERROR) { if (debug_mode) printf("\tWrong error code\n"); else Test_Result(FAIL); return; } } if (PR_Interrupt(thread) == PR_FAILURE) { if (debug_mode) printf("\tcannot interrupt unjoinable thread\n"); else Test_Result(FAIL); return; } else { if (debug_mode) printf("\tinterrupted unjoinable thread\n"); } }
SECStatus reap_threads(GlobalThreadMgr *threadMGR) { perThread * slot; int i; if (!threadMGR->threadLock) return SECSuccess; PR_Lock(threadMGR->threadLock); while (threadMGR->numRunning > 0) { PR_WaitCondVar(threadMGR->threadEndQ, PR_INTERVAL_NO_TIMEOUT); for (i = 0; i < threadMGR->numUsed; ++i) { slot = &threadMGR->threads[i]; if (slot->running == rs_zombie) { /* Handle cleanup of thread here. */ /* Now make sure the thread has ended OK. */ PR_JoinThread(slot->prThread); slot->running = rs_idle; --threadMGR->numRunning; /* notify the thread launcher. */ PR_NotifyCondVar(threadMGR->threadStartQ); } } } /* Safety Sam sez: make sure count is right. */ for (i = 0; i < threadMGR->numUsed; ++i) { slot = &threadMGR->threads[i]; if (slot->running != rs_idle) { fprintf(stderr, "Thread in slot %d is in state %d!\n", i, slot->running); } } PR_Unlock(threadMGR->threadLock); return SECSuccess; }
nsresult DOMStorageDBThread::Shutdown() { if (!mThread) { return NS_ERROR_NOT_INITIALIZED; } Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_SHUTDOWN_DATABASE_MS> timer; { MonitorAutoLock monitor(mThreadObserver->GetMonitor()); // After we stop, no other operations can be accepted mFlushImmediately = true; mStopIOThread = true; monitor.Notify(); } PR_JoinThread(mThread); mThread = nullptr; return mStatus; }
void Shutdown() { if (GeckoProcessType_Default != XRE_GetProcessType()) return; MOZ_ASSERT(gMonitor, "Hang monitor not started"); { // Scope the lock we're going to delete later MonitorAutoLock lock(*gMonitor); gShutdown = true; lock.Notify(); } // thread creation could theoretically fail if (gThread) { PR_JoinThread(gThread); gThread = NULL; } delete gMonitor; gMonitor = NULL; }
XPGetDocStatus XpuWaitForPrintFileChild( void *handle ) { MyPrintFileData *mpfd = (MyPrintFileData *)handle; void *res; XPGetDocStatus status; /* Flush data a last time to make sure we send all data to Xprt and that * the Xlib internal hooks have called a last time */ XFlush(mpfd->parent_pdpy); #ifdef XPU_USE_NSPR if( PR_JoinThread(mpfd->prthread) != PR_SUCCESS ) perror("XpuWaitForPrintFileChild: PR_JoinThread() failure"); /* fixme(later): use NSPR error handling calls... */ #else if( XPU_TRACE(pthread_join(mpfd->tid, &res)) != 0 ) perror("XpuWaitForPrintFileChild: pthread_join() failure"); #endif status = mpfd->status; free(handle); XPU_DEBUG_ONLY(PrintXPGetDocStatus(status)); return(status); }
void CondVarTestSUU(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; exitcount=0; tcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index<arg; ) { CreateTestThread(&list[index], index, sharedlock, sharedcvar, count, PR_INTERVAL_NO_TIMEOUT, &tcount, exitlock, exitcvar, &exitcount, PR_TRUE, PR_LOCAL_THREAD); index++; DPRINTF(("CondVarTestSUU: created thread 0x%lx\n",list[index].thread)); } for (loops = 0; loops < count; loops++) { /* Notify the threads */ for(index=0; index<(arg); index++) { PR_Lock(list[index].lock); (*list[index].tcount)++; PR_NotifyCondVar(list[index].cvar); PR_Unlock(list[index].lock); DPRINTF(("PrivateCondVarThread: thread 0x%lx notified cvar = 0x%lx\n", PR_GetCurrentThread(), list[index].cvar)); } /* Wait for threads to finish */ PR_Lock(exitlock); while(exitcount < arg) PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); PR_ASSERT(exitcount >= arg); exitcount -= arg; PR_Unlock(exitlock); } /* Join all the threads */ for(index=0; index<(arg); index++) PR_JoinThread(list[index].thread); PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DestroyCondVar(exitcvar); PR_DestroyLock(exitlock); PR_DELETE(list); }
/*********************************************************************** ** PRIVATE FUNCTION: main ** DESCRIPTION: ** Hammer on the file I/O system ** INPUTS: The usual argc and argv ** argv[0] - program name (not used) ** argv[1] - the number of times to execute the major loop ** argv[2] - the number of threads to toss into the batch ** argv[3] - the clipping number applied to randoms ** default values: loops = 2, threads = 10, limit = 57 ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** Creates, accesses and deletes lots of files ** RESTRICTIONS: ** (Currently) must have file create permission in "/usr/tmp". ** MEMORY: NA ** ALGORITHM: ** 1) Fork a "Thread()" ** 2) Wait for 'interleave' seconds ** 3) For [0..'threads') repeat [1..2] ** 4) Mark all objects to stop ** 5) Collect the threads, accumulating the results ** 6) For [0..'loops') repeat [1..5] ** 7) Print accumulated results and exit ** ** Characteristic output (from IRIX) ** Random File: Using loops = 2, threads = 10, limit = 57 ** Random File: [min [avg] max] writes/sec average ***********************************************************************/ int main (int argc, char *argv[]) { PRLock *ml; PRUint32 id = 0; int active, poll; PRIntervalTime interleave; PRIntervalTime duration = 0; int limit = 0, loops = 0, threads = 0, times; PRUint32 writes, writesMin = 0x7fffffff, writesTot = 0, durationTot = 0, writesMax = 0; const char *where[] = {"okay", "open", "close", "delete", "write", "seek"}; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:t:i:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'G': /* global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'd': /* debug mode */ debug_mode = 1; break; case 'l': /* limiting number */ limit = atoi(opt->value); break; case 't': /* number of threads */ threads = atoi(opt->value); break; case 'i': /* iteration counter */ loops = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); interleave = PR_SecondsToInterval(10); #ifdef XP_MAC SetupMacPrintfLog("ranfile.log"); debug_mode = 1; #endif ml = PR_NewLock(); cv = PR_NewCondVar(ml); if (loops == 0) loops = DEFAULT_LOOPS; if (limit == 0) limit = DEFAULT_LIMIT; if (threads == 0) threads = DEFAULT_THREADS; if (debug_mode) printf( "%s: Using loops = %d, threads = %d, limit = %d and %s threads\n", programName, loops, threads, limit, (thread_scope == PR_LOCAL_THREAD) ? "LOCAL" : "GLOBAL"); for (times = 0; times < loops; ++times) { if (debug_mode) printf("%s: Setting concurrency level to %d\n", programName, times + 1); PR_SetConcurrency(times + 1); for (active = 0; active < threads; active++) { hammer[active].ml = ml; hammer[active].cv = cv; hammer[active].id = id++; hammer[active].writes = 0; hammer[active].action = sg_go; hammer[active].problem = sg_okay; hammer[active].limit = (Random() % limit) + 1; hammer[active].timein = PR_IntervalNow(); hammer[active].thread = PR_CreateThread( PR_USER_THREAD, Thread, &hammer[active], PR_GetThreadPriority(PR_GetCurrentThread()), thread_scope, PR_JOINABLE_THREAD, 0); PR_Lock(ml); PR_WaitCondVar(cv, interleave); /* start new ones slowly */ PR_Unlock(ml); } /* * The last thread started has had the opportunity to run for * 'interleave' seconds. Now gather them all back in. */ PR_Lock(ml); for (poll = 0; poll < threads; poll++) { if (hammer[poll].action == sg_go) /* don't overwrite done */ hammer[poll].action = sg_stop; /* ask him to stop */ } PR_Unlock(ml); while (active > 0) { for (poll = 0; poll < threads; poll++) { PR_Lock(ml); while (hammer[poll].action < sg_done) PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(ml); active -= 1; /* this is another one down */ (void)PR_JoinThread(hammer[poll].thread); hammer[poll].thread = NULL; if (hammer[poll].problem == sg_okay) { duration = PR_IntervalToMilliseconds( PR_IntervalNow() - hammer[poll].timein); writes = hammer[poll].writes * 1000 / duration; if (writes < writesMin) writesMin = writes; if (writes > writesMax) writesMax = writes; writesTot += hammer[poll].writes; durationTot += duration; } else if (debug_mode) printf( "%s: test failed %s after %ld seconds\n", programName, where[hammer[poll].problem], duration); else failed_already=1; } } } if (debug_mode) printf( "%s: [%ld [%ld] %ld] writes/sec average\n", programName, writesMin, writesTot * 1000 / durationTot, writesMax); PR_DestroyCondVar(cv); PR_DestroyLock(ml); if (failed_already) { printf("FAIL\n"); return 1; } else { printf("PASS\n"); return 0; } } /* main */
void CondVarTestPUU(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; PRInt32 *tcount, *saved_tcount; exitcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index<arg; ) { list[index].lock = PR_NewLock(); list[index].cvar = PR_NewCondVar(list[index].lock); CreateTestThread(&list[index], index, list[index].lock, list[index].cvar, count, PR_INTERVAL_NO_TIMEOUT, tcount, exitlock, exitcvar, &exitcount, PR_FALSE, PR_LOCAL_THREAD); DPRINTF(("CondVarTestPUU: created thread 0x%lx\n",list[index].thread)); index++; tcount++; } for (loops = 0; loops < count; loops++) { /* Notify the threads */ for(index=0; index<(arg); index++) { PR_Lock(list[index].lock); (*list[index].tcount)++; PR_NotifyCondVar(list[index].cvar); PR_Unlock(list[index].lock); } PR_Lock(exitlock); /* Wait for threads to finish */ while(exitcount < arg) { DPRINTF(("CondVarTestPUU: thread 0x%lx waiting on exitcvar = 0x%lx cnt = %ld\n", PR_GetCurrentThread(), exitcvar, exitcount)); PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); } PR_ASSERT(exitcount >= arg); exitcount -= arg; PR_Unlock(exitlock); } /* Join all the threads */ for(index=0; index<(arg); index++) { DPRINTF(("CondVarTestPUU: joining thread 0x%lx\n",list[index].thread)); PR_JoinThread(list[index].thread); if (list[index].internal) { PR_Lock(list[index].lock); PR_DestroyCondVar(list[index].cvar); PR_Unlock(list[index].lock); PR_DestroyLock(list[index].lock); } } PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DestroyCondVar(exitcvar); PR_DestroyLock(exitlock); PR_DELETE(list); PR_DELETE(saved_tcount); }
void CondVarMixedTest(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; PRInt32 *ptcount; exitcount=0; tcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index<arg*4; ) { CreateTestThread(&list[index], index, sharedlock, sharedcvar, count, PR_MillisecondsToInterval(50), &tcount, exitlock, exitcvar, &exitcount, PR_TRUE, PR_LOCAL_THREAD); index++; CreateTestThread(&list[index], index, sharedlock, sharedcvar, count, PR_MillisecondsToInterval(50), &tcount, exitlock, exitcvar, &exitcount, PR_TRUE, PR_GLOBAL_THREAD); index++; list[index].lock = PR_NewLock(); list[index].cvar = PR_NewCondVar(list[index].lock); CreateTestThread(&list[index], index, list[index].lock, list[index].cvar, count, PR_MillisecondsToInterval(50), ptcount, exitlock, exitcvar, &exitcount, PR_FALSE, PR_LOCAL_THREAD); index++; ptcount++; list[index].lock = PR_NewLock(); list[index].cvar = PR_NewCondVar(list[index].lock); CreateTestThread(&list[index], index, list[index].lock, list[index].cvar, count, PR_MillisecondsToInterval(50), ptcount, exitlock, exitcvar, &exitcount, PR_FALSE, PR_GLOBAL_THREAD); index++; ptcount++; } /* Notify every 3rd thread */ for (loops = 0; loops < count; loops++) { /* Notify the threads */ for(index=0; index<(arg*4); index+=3) { PR_Lock(list[index].lock); *list[index].tcount++; PR_NotifyCondVar(list[index].cvar); PR_Unlock(list[index].lock); } /* Wait for threads to finish */ PR_Lock(exitlock); while(exitcount < arg*4) PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); PR_ASSERT(exitcount >= arg*4); exitcount -= arg*4; PR_Unlock(exitlock); } /* Join all the threads */ for(index=0; index<(arg*4); index++) { PR_JoinThread(list[index].thread); if (list[index].internal) { PR_Lock(list[index].lock); PR_DestroyCondVar(list[index].cvar); PR_Unlock(list[index].lock); PR_DestroyLock(list[index].lock); } } PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DELETE(list); }
PRIntn main(PRIntn argc, char **argv) { PRStatus rv; PRIntn mits; PLOptStatus os; PRFileDesc *client, *service; PRFileDesc *client_stack, *service_stack; PRNetAddr any_address; const char *server_name = NULL; const PRIOMethods *stubMethods; PRThread *client_thread, *server_thread; PRThreadScope thread_scope = PR_LOCAL_THREAD; PLOptState *opt = PL_CreateOptState(argc, argv, "dqGC:c:p:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: server_name = opt->value; break; case 'd': /* debug mode */ if (verbosity < noisy) verbosity = ChangeVerbosity(verbosity, 1); break; case 'q': /* debug mode */ if (verbosity > silent) verbosity = ChangeVerbosity(verbosity, -1); break; case 'G': /* use global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'C': /* number of threads waiting */ major_iterations = atoi(opt->value); break; case 'c': /* number of client threads */ minor_iterations = atoi(opt->value); break; case 'p': /* default port */ default_port = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); PR_STDIO_INIT(); logFile = PR_GetSpecialFD(PR_StandardError); identity = PR_GetUniqueIdentity("Dummy"); stubMethods = PR_GetDefaultIOMethods(); /* ** The protocol we're going to implement is one where in order to initiate ** a send, the sender must first solicit permission. Therefore, every ** send is really a send - receive - send sequence. */ myMethods = *stubMethods; /* first get the entire batch */ myMethods.recv = MyRecv; /* then override the ones we care about */ myMethods.send = MySend; /* then override the ones we care about */ if (NULL == server_name) rv = PR_InitializeNetAddr( PR_IpAddrLoopback, default_port, &server_address); else { rv = PR_StringToNetAddr(server_name, &server_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_InitializeNetAddr( PR_IpAddrNull, default_port, &server_address); } PR_ASSERT(PR_SUCCESS == rv); /* one type w/o layering */ mits = minor_iterations; while (major_iterations-- > 0) { if (verbosity > silent) PR_fprintf(logFile, "Beginning non-layered test\n"); client = PR_NewTCPSocket(); PR_ASSERT(NULL != client); service = PR_NewTCPSocket(); PR_ASSERT(NULL != service); rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv); minor_iterations = mits; server_thread = PR_CreateThread( PR_USER_THREAD, Server, service, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != server_thread); client_thread = PR_CreateThread( PR_USER_THREAD, Client, client, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != client_thread); rv = PR_JoinThread(client_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(server_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv); if (verbosity > silent) PR_fprintf(logFile, "Ending non-layered test\n"); /* with layering */ if (verbosity > silent) PR_fprintf(logFile, "Beginning layered test\n"); client = PR_NewTCPSocket(); PR_ASSERT(NULL != client); PushLayer(client); service = PR_NewTCPSocket(); PR_ASSERT(NULL != service); PushLayer(service); rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv); minor_iterations = mits; server_thread = PR_CreateThread( PR_USER_THREAD, Server, service, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != server_thread); client_thread = PR_CreateThread( PR_USER_THREAD, Client, client, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != client_thread); rv = PR_JoinThread(client_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(server_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv); /* with layering, using new style stack */ if (verbosity > silent) PR_fprintf(logFile, "Beginning layered test with new style stack\n"); client = PR_NewTCPSocket(); PR_ASSERT(NULL != client); client_stack = PR_CreateIOLayer(client); PushNewLayers(client_stack); service = PR_NewTCPSocket(); PR_ASSERT(NULL != service); service_stack = PR_CreateIOLayer(service); PushNewLayers(service_stack); rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv); minor_iterations = mits; server_thread = PR_CreateThread( PR_USER_THREAD, Server, service_stack, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != server_thread); client_thread = PR_CreateThread( PR_USER_THREAD, Client, client_stack, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != client_thread); rv = PR_JoinThread(client_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(server_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(client_stack); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service_stack); PR_ASSERT(PR_SUCCESS == rv); if (verbosity > silent) PR_fprintf(logFile, "Ending layered test\n"); } return 0; } /* main */
/* Time iter repetitions of operation op. */ SECStatus M_TimeOperation(void (*threadFunc)(void *), op_func opfunc, char *op, void *param1, void *param2, void *param3, int iters, int numThreads, PRLock *lock, CK_SESSION_HANDLE session, int isSign, double *rate) { double dUserTime; int i, total; PRIntervalTime startTime, totalTime; PRThread **threadIDs; ThreadData *threadData; pk11_op_func pk11_op = (pk11_op_func)opfunc; SECStatus rv; /* verify operation works before testing performance */ if (session) { rv = (*pk11_op)(session, param1, param2, param3); } else { rv = (*opfunc)(param1, param2, param3); } if (rv != SECSuccess) { SECU_PrintError("Error:", op); return rv; } /* get Data structures */ threadIDs = (PRThread **)PORT_Alloc(numThreads * sizeof(PRThread *)); threadData = (ThreadData *)PORT_Alloc(numThreads * sizeof(ThreadData)); startTime = PR_Now(); if (numThreads == 1) { for (i = 0; i < iters; i++) { if (session) { rv = (*pk11_op)(session, param1, param2, param3); } else { rv = (*opfunc)(param1, param2, param3); } } total = iters; } else { for (i = 0; i < numThreads; i++) { threadData[i].op = opfunc; threadData[i].p1 = (void *)param1; threadData[i].p2 = (void *)param2; threadData[i].p3 = (void *)param3; threadData[i].iters = iters; threadData[i].lock = lock; threadData[i].isSign = isSign; threadIDs[i] = PR_CreateThread(PR_USER_THREAD, threadFunc, (void *)&threadData[i], PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); } total = 0; for (i = 0; i < numThreads; i++) { PR_JoinThread(threadIDs[i]); /* check the status */ total += threadData[i].count; } PORT_Free(threadIDs); PORT_Free(threadData); } totalTime = PR_Now() - startTime; /* SecondsToInterval seems to be broken here ... */ dUserTime = (double)totalTime / (double)1000000; if (dUserTime) { printf(" %-15s count:%4d sec: %3.2f op/sec: %6.2f\n", op, total, dUserTime, (double)total / dUserTime); if (rate) { *rate = ((double)total) / dUserTime; } } return SECSuccess; }
int test_mutex2(int argc, char *argv[]) { PRThread *consThread, *prodThread, *prodThread2, *prodThread3; int x = 10, y = 20, z = 30; PKIX_UInt32 actualMinorVersion; PKIX_UInt32 j = 0; PKIX_TEST_STD_VARS(); startTests("Mutex and Threads"); PKIX_TEST_EXPECT_NO_ERROR( PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); (void)printf("Attempting to create new mutex...\n"); subTest("Mutex Creation"); PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(&mutex, plContext)); cv = PR_NewCondVar(*(PRLock **)mutex); subTest("Starting consumer thread"); consThread = PR_CreateThread(PR_USER_THREAD, consumer, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); subTest("Starting producer thread 1"); prodThread = PR_CreateThread(PR_USER_THREAD, producer, &x, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); subTest("Starting producer thread 2"); prodThread2 = PR_CreateThread(PR_USER_THREAD, producer, &y, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); subTest("Starting producer thread 3"); prodThread3 = PR_CreateThread(PR_USER_THREAD, producer, &z, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_JoinThread(consThread); (void)PR_DestroyCondVar(cv); PKIX_TEST_DECREF_BC(mutex); /* * Note: we should also be freeing each thread's stack, but we * don't have access to the prodThread->stack variable (since * it is not exported). As a result, we have 120 bytes of memory * leakage. */ PR_Free(prodThread); PR_Free(prodThread2); PR_Free(prodThread3); cleanup: PKIX_Shutdown(plContext); PKIX_TEST_RETURN(); endTests("Mutex and Threads"); return (0); }
void CondVarTest(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; PRInt32 *ptcount, *saved_ptcount; exitcount=0; tcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); saved_ptcount = ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index<arg*4; ) { CreateTestThread(&list[index], index, sharedlock, sharedcvar, count, PR_INTERVAL_NO_TIMEOUT, &tcount, exitlock, exitcvar, &exitcount, PR_TRUE, PR_LOCAL_THREAD); index++; CreateTestThread(&list[index], index, sharedlock, sharedcvar, count, PR_INTERVAL_NO_TIMEOUT, &tcount, exitlock, exitcvar, &exitcount, PR_TRUE, PR_GLOBAL_THREAD); index++; list[index].lock = PR_NewLock(); list[index].cvar = PR_NewCondVar(list[index].lock); CreateTestThread(&list[index], index, list[index].lock, list[index].cvar, count, PR_INTERVAL_NO_TIMEOUT, ptcount, exitlock, exitcvar, &exitcount, PR_FALSE, PR_LOCAL_THREAD); index++; ptcount++; list[index].lock = PR_NewLock(); list[index].cvar = PR_NewCondVar(list[index].lock); CreateTestThread(&list[index], index, list[index].lock, list[index].cvar, count, PR_INTERVAL_NO_TIMEOUT, ptcount, exitlock, exitcvar, &exitcount, PR_FALSE, PR_GLOBAL_THREAD); index++; ptcount++; } for (loops = 0; loops < count; loops++) { /* Notify the threads */ for(index=0; index<(arg*4); index++) { PR_Lock(list[index].lock); (*list[index].tcount)++; PR_NotifyCondVar(list[index].cvar); PR_Unlock(list[index].lock); } #if 0 printf("wait for threads done\n"); #endif /* Wait for threads to finish */ PR_Lock(exitlock); while(exitcount < arg*4) PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); PR_ASSERT(exitcount >= arg*4); exitcount -= arg*4; PR_Unlock(exitlock); #if 0 printf("threads ready\n"); #endif } /* Join all the threads */ for(index=0; index<(arg*4); index++) { PR_JoinThread(list[index].thread); if (list[index].internal) { PR_Lock(list[index].lock); PR_DestroyCondVar(list[index].cvar); PR_Unlock(list[index].lock); PR_DestroyLock(list[index].lock); } } PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DestroyCondVar(exitcvar); PR_DestroyLock(exitlock); PR_DELETE(list); PR_DELETE(saved_ptcount); }
PRIntn main(PRIntn argc, char *argv[]) { PRThread *tJitter; PRThread *tAccept; PRThread *tConnect; PRStatus rv; /* This test if valid for WinNT only! */ #if !defined(WINNT) return 0; #endif { /* ** Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "hdrvj:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug */ debug = 1; msgLevel = PR_LOG_ERROR; break; case 'v': /* verbose mode */ verbose = 1; msgLevel = PR_LOG_DEBUG; break; case 'j': jitter = atoi(opt->value); if ( jitter == 0) jitter = JITTER_DEFAULT; break; case 'r': resume = PR_TRUE; break; case 'h': /* help message */ Help(); break; default: break; } } PL_DestroyOptState(opt); } lm = PR_NewLogModule("Test"); /* Initialize logging */ /* set concurrency */ PR_SetConcurrency( 4 ); /* setup thread synchronization mechanics */ ml = PR_NewLock(); cv = PR_NewCondVar( ml ); /* setup a tcp socket */ memset(&listenAddr, 0, sizeof(listenAddr)); rv = PR_InitializeNetAddr(PR_IpAddrAny, BASE_PORT, &listenAddr); PR_ASSERT( PR_SUCCESS == rv ); listenSock = PR_NewTCPSocket(); PR_ASSERT( listenSock ); rv = PR_Bind( listenSock, &listenAddr); PR_ASSERT( PR_SUCCESS == rv ); rv = PR_Listen( listenSock, 5 ); PR_ASSERT( PR_SUCCESS == rv ); /* open a file for writing, provoke bug */ file1 = PR_Open("xxxTestFile", PR_CREATE_FILE | PR_RDWR, 666); /* create Connect thread */ tConnect = PR_CreateThread( PR_USER_THREAD, ConnectThread, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0 ); PR_ASSERT( tConnect ); /* create jitter off thread */ tJitter = PR_CreateThread( PR_USER_THREAD, JitterThread, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0 ); PR_ASSERT( tJitter ); /* create acceptread thread */ tAccept = PR_CreateThread( PR_USER_THREAD, AcceptThread, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0 ); PR_ASSERT( tAccept ); /* wait for all threads to quit, then terminate gracefully */ PR_JoinThread( tConnect ); PR_JoinThread( tAccept ); PR_JoinThread( tJitter ); PR_Close( listenSock ); PR_DestroyCondVar(cv); PR_DestroyLock(ml); PR_Close( file1 ); PR_Delete( "xxxTestFile"); /* test return and exit */ if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS"); return( (failed_already == PR_TRUE )? 1 : 0 ); } /* main() */
void main(int argc, char** argv) { int index = 0, numThreads, numDead = 0; int ch; SearchThread **threads; while ((ch = getopt(argc, argv, "j:i:h:s:f:p:t:D:w:n:A:bvlyqmcdu")) != EOF) switch (ch) { case 'h': hostname = optarg; break; case 's': suffix = optarg; break; case 'f': filter = optarg; break; case 'i': nameFile = optarg; break; case 'D': bindDN = optarg; break; case 'w': bindPW = optarg; break; case 'A': attrList = optarg; break; case 'p': port = atoi(optarg); break; case 'b': doBind = 1; break; case 'u': noUnBind = 1; break; case 'n': numeric = atoi(optarg); break; case 't': threadCount = atoi(optarg); break; case 'j': sampleInterval = atoi(optarg) * 1000; break; case 'v': verbose = 1; break; case 'q': quiet = 1; break; case 'l': logging = 1; break; case 'y': noDelay = 1; break; case 'm': opType = op_modify; break; case 'd': opType = op_delete; break; case 'c': opType = op_compare; break; case '?': usage(); exit(1); break; default: break; } argc -= optind; argv += optind; PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 0); ntable = nt_new(0); if (nameFile) { if (!nt_load(ntable, nameFile)) { printf("Failed to read name table\n"); exit(1); } } if (attrList) attrToReturn = string_to_list(attrList); /* a "vector" */ threads = (SearchThread **)malloc(threadCount * sizeof(SearchThread *)); while (threadCount--) { SearchThread *st; PRThread *thr; st = st_new(); thr = PR_CreateThread(PR_SYSTEM_THREAD, search_start, (void *)st, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); st_setThread(st, thr, index+1); threads[index++] = st; } numThreads = index; printf("rsearch: %d threads launched.\n\n", numThreads); while (numThreads != numDead) { int x; PR_Sleep(PR_MillisecondsToInterval(sampleInterval)); /* now check for deadies */ for (x = 0; x < numThreads; x++) { if (!st_alive(threads[x])) { int y; PRThread *tid; printf("T%d DEAD.\n", st_getThread(threads[x], &tid)); PR_JoinThread(tid); for (y = x+1; y < numThreads; y++) threads[y-1] = threads[y]; numThreads--; numDead++; x--; } } /* print out stats */ if (!quiet) { PRUint32 total = 0; for (x = 0; x < numThreads; x++) { PRUint32 count, min, max; st_getCountMinMax(threads[x], &count, &min, &max); total += count; printf("T%d min=%4ums, max=%4ums, count = %u\n", st_getThread(threads[x], NULL), min, max, count); } if (numThreads > 1) printf("Average rate = %.2f\n", (double)total/(double)numThreads); } /* watchdogs were reset when we fetched the min/max counters */ } printf("All threads died. (?)\n"); exit(1); }
int main(int argc, char **argv) { PRHostEnt he; PRStatus status; PRIntn next_index; PRUint16 port_number; char netdb_buf[PR_NETDB_BUF_SIZE]; PRNetAddr client_addr, server_addr; PRThread *client_thread, *server_thread; PRIntervalTime delta = PR_MillisecondsToInterval(500); err_out = PR_STDERR; std_out = PR_STDOUT; accept_timeout = PR_SecondsToInterval(2); emu_layer_ident = PR_GetUniqueIdentity("Emulated AcceptRead"); emu_layer_methods = *PR_GetDefaultIOMethods(); emu_layer_methods.acceptread = emu_AcceptRead; if (argc != 2 && argc != 3) port_number = DEFAULT_PORT; else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]); status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr); if (PR_SUCCESS != status) { PL_FPrintError(err_out, "PR_InitializeNetAddr failed"); PR_ProcessExit(1); } if (argc < 3) { status = PR_InitializeNetAddr( PR_IpAddrLoopback, port_number, &client_addr); if (PR_SUCCESS != status) { PL_FPrintError(err_out, "PR_InitializeNetAddr failed"); PR_ProcessExit(1); } } else { status = PR_GetHostByName( argv[1], netdb_buf, sizeof(netdb_buf), &he); if (status == PR_FAILURE) { PL_FPrintError(err_out, "PR_GetHostByName failed"); PR_ProcessExit(1); } next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr); if (next_index == -1) { PL_FPrintError(err_out, "PR_EnumerateHostEnt failed"); PR_ProcessExit(1); } } for ( write_dally = 0; write_dally < accept_timeout + (2 * delta); write_dally += delta) { PR_fprintf( std_out, "Testing w/ write_dally = %d msec\n", PR_IntervalToMilliseconds(write_dally)); server_thread = PR_CreateThread( PR_USER_THREAD, AcceptingThread, &server_addr, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (server_thread == NULL) { PL_FPrintError(err_out, "PR_CreateThread (server) failed"); PR_ProcessExit(1); } PR_Sleep(delta); /* let the server pot thicken */ client_thread = PR_CreateThread( PR_USER_THREAD, ConnectingThread, &client_addr, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (client_thread == NULL) { PL_FPrintError(err_out, "PR_CreateThread (client) failed"); PR_ProcessExit(1); } if (PR_JoinThread(client_thread) == PR_FAILURE) PL_FPrintError(err_out, "PR_JoinThread (client) failed"); if (PR_JoinThread(server_thread) == PR_FAILURE) PL_FPrintError(err_out, "PR_JoinThread (server) failed"); } return 0; }
/* * End recording (called in a thread) */ void MediaRecorder::EndRecordingThread(void *data) { nsresult rv; PRUint32 wr; MediaRecorder *mr = static_cast<MediaRecorder*>(data); if (mr->v_rec) { rv = mr->vState->backend->StopRecording(); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "could not stop video recording" )); return; } } if (mr->a_rec) { rv = mr->aState->backend->Stop(); if (NS_FAILED(rv)) { NS_DispatchToMainThread(new MediaCallback( mr->observer, "error", "could not stop audio recording" )); return; } } /* Wait for encoder to finish */ if (mr->v_rec) { mr->v_stp = PR_TRUE; mr->vState->vPipeOut->Close(); } if (mr->a_rec) { mr->a_stp = PR_TRUE; mr->aState->aPipeOut->Close(); } PR_JoinThread(mr->thread); if (mr->v_rec) { mr->vState->vPipeIn->Close(); th_encode_free(mr->vState->th); /* Video trailer */ if (ogg_stream_flush(&mr->vState->os, &mr->vState->og)) { rv = mr->WriteData( mr->vState->og.header, mr->vState->og.header_len, &wr ); rv = mr->WriteData( mr->vState->og.body, mr->vState->og.body_len, &wr ); } ogg_stream_clear(&mr->vState->os); mr->v_rec = PR_FALSE; } if (mr->a_rec) { mr->aState->aPipeIn->Close(); /* Audio trailer */ vorbis_analysis_wrote(&mr->aState->vd, 0); mr->WriteAudio(); vorbis_block_clear(&mr->aState->vb); vorbis_dsp_clear(&mr->aState->vd); vorbis_comment_clear(&mr->aState->vc); vorbis_info_clear(&mr->aState->vi); ogg_stream_clear(&mr->aState->os); mr->a_rec = PR_FALSE; } /* GG */ mr->pipeStream->Close(); NS_DispatchToMainThread(new MediaCallback( mr->observer, "record-ended", "" )); return; }
int thread_join(thread_t thread) { if (!thread) { return 0; } return PR_JoinThread((PRThread*)thread) == PR_SUCCESS; }