//------------------------------------------------------------------------- // // Create a new thread and run the message pump in there // //------------------------------------------------------------------------- void nsToolkit::CreateUIThread() { PRMonitor *monitor = ::PR_NewMonitor(); PR_EnterMonitor(monitor); ThreadInitInfo *ti = new ThreadInitInfo(); if (ti) { ti->monitor = monitor; ti->toolkit = this; // create a gui thread mGuiThread = PR_CreateThread(PR_SYSTEM_THREAD, RunPump, (void*)ti, PR_PRIORITY_HIGH, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); // wait for the gui thread to start while(gThreadState == PR_FALSE) { PR_Wait(monitor, PR_INTERVAL_NO_TIMEOUT); } } image_info iinfo; int32 cookie = 0; char *leaf = NULL; do { if (get_next_image_info(0, &cookie, &iinfo) == B_OK && strlen(iinfo.name) > 0 && (leaf = strrchr(iinfo.name, '/')) != NULL) { leaf++; mGUIThreadID = find_thread(leaf); } else { mGUIThreadID = find_thread(0); } } while(iinfo.type != B_APP_IMAGE); // at this point the thread is running PR_ExitMonitor(monitor); PR_DestroyMonitor(monitor); }
static void CondWaitContextSwitch(PRThreadScope scope1, PRThreadScope scope2) { PRThread *t1, *t2; CircBuf *cbp; PR_EnterMonitor(mon); alive = 2; cbp = NewCB(); t1 = PR_CreateThread(PR_USER_THREAD, CXReader, cbp, PR_PRIORITY_NORMAL, scope1, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t1); t2 = PR_CreateThread(PR_USER_THREAD, CXWriter, cbp, PR_PRIORITY_NORMAL, scope2, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t2); /* Wait for both of the threads to exit */ while (alive) { PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); } DeleteCB(cbp); PR_ExitMonitor(mon); }
void RunClients(void) { PRInt32 index; numRequests = _iterations; numClients = _clients; clientMonitor = PR_NewMonitor(); for (index=0; index<_clients; index++) { PRThread *clientThread; clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc, NULL, PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); } else if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients); } PR_EnterMonitor(clientMonitor); while(numClients) PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(clientMonitor); }
nsresult Monitor::Wait(PRIntervalTime interval) { AssertCurrentThreadIn(); // save monitor state and reset it to empty PRInt32 savedEntryCount = mEntryCount; CallStack savedAcquisitionContext = GetAcquisitionContext(); BlockingResourceBase* savedChainPrev = mChainPrev; mEntryCount = 0; SetAcquisitionContext(CallStack::kNone); mChainPrev = 0; // give up the monitor until we're back from Wait() nsresult rv = PR_Wait(mMonitor, interval) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE; // restore saved state mEntryCount = savedEntryCount; SetAcquisitionContext(savedAcquisitionContext); mChainPrev = savedChainPrev; return rv; }
//------------------------------------------------------------------------- // // Create a new thread and run the message pump in there // //------------------------------------------------------------------------- void nsToolkit::CreateUIThread() { #ifdef DEBUG printf("TK-CUIT\n"); #endif PRMonitor *monitor = ::PR_NewMonitor(); PR_EnterMonitor(monitor); ThreadInitInfo *ti = new ThreadInitInfo(); if (ti) { ti->monitor = monitor; ti->toolkit = this; // create a gui thread mGuiThread = PR_CreateThread(PR_SYSTEM_THREAD, RunPump, (void*)ti, PR_PRIORITY_HIGH, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); // wait for the gui thread to start while(!gThreadState) { PR_Wait(monitor, PR_INTERVAL_NO_TIMEOUT); } } // at this point the thread is running PR_ExitMonitor(monitor); PR_DestroyMonitor(monitor); }
nsresult ReentrantMonitor::Wait(PRIntervalTime aInterval) { AssertCurrentThreadIn(); // save monitor state and reset it to empty int32_t savedEntryCount = mEntryCount; CallStack savedAcquisitionContext = GetAcquisitionContext(); BlockingResourceBase* savedChainPrev = mChainPrev; mEntryCount = 0; SetAcquisitionContext(CallStack::kNone); mChainPrev = 0; nsresult rv; #ifdef MOZILLA_INTERNAL_API { GeckoProfilerSleepRAII profiler_sleep; #endif //MOZILLA_INTERNAL_API // give up the monitor until we're back from Wait() rv = PR_Wait(mReentrantMonitor, aInterval) == PR_SUCCESS ? NS_OK : NS_ERROR_FAILURE; #ifdef MOZILLA_INTERNAL_API } #endif //MOZILLA_INTERNAL_API // restore saved state mEntryCount = savedEntryCount; SetAcquisitionContext(savedAcquisitionContext); mChainPrev = savedChainPrev; return rv; }
/* ** Stress() ** Flog the hell out of arenas multi-threaded. ** Do NOT pass an individual arena to another thread. ** */ static void Stress( void ) { PRThread *tt; PRIntn i; tMon = PR_NewMonitor(); for ( i = 0 ; i < stressThreads ; i++ ) { PR_EnterMonitor(tMon); tt = PR_CreateThread(PR_USER_THREAD, StressThread, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); threadCount++; PR_ExitMonitor(tMon); } /* Wait for all threads to exit */ PR_EnterMonitor(tMon); while ( threadCount != 0 ) { PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT); } PR_ExitMonitor(tMon); PR_DestroyMonitor(tMon); return; } /* end Stress() */
static void T1Mon(void) { PRStatus rv; PRThread *t2, *t3; PR_fprintf(err, "\n**********************************\n"); PR_fprintf(err, " MONITORS\n"); PR_fprintf(err, "**********************************\n"); sharedM.o1 = PR_NewMonitor(); sharedM.o2 = PR_NewMonitor(); base = PR_IntervalNow(); PR_EnterMonitor(sharedM.o1); LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); rv = PR_Wait(sharedM.o1, PR_SecondsToInterval(3)); if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); else LogNow("T1 wait on o1 failed", rv); PR_ExitMonitor(sharedM.o1); LogNow("T1 creating T2", PR_SUCCESS); t2 = PR_CreateThread( PR_USER_THREAD, T2Mon, &sharedM, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); LogNow("T1 creating T3", PR_SUCCESS); t3 = PR_CreateThread( PR_USER_THREAD, T3Mon, &sharedM, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_EnterMonitor(sharedM.o2); LogNow("T1 waiting forever on o2", PR_SUCCESS); rv = PR_Wait(sharedM.o2, PR_INTERVAL_NO_TIMEOUT); if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); else LogNow("T1 wait on o2 failed", rv); PR_ExitMonitor(sharedM.o2); (void)PR_JoinThread(t2); (void)PR_JoinThread(t3); PR_DestroyMonitor(sharedM.o1); PR_DestroyMonitor(sharedM.o2); } /* T1Mon */
static void WaitMonitorThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) && !defined(WINCE) struct _timeb end_time_tb; #endif PRMonitor *mon; mon = PR_NewMonitor(); if (mon == NULL) { fprintf(stderr, "PR_NewMonitor failed\n"); exit(1); } PR_EnterMonitor(mon); PR_Wait(mon, timeout); PR_ExitMonitor(mon); elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) #if defined(WINCE) elapsed_msecs = GetTickCount() - start_time_tick; #else _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif PR_DestroyMonitor(mon); if (debug_mode) { fprintf(stderr, "wait monitor thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } }
void doReadThread (void* arg) { PRInt32 last; Arg_t *args = (Arg_t*)arg; PRInt32 aWorkDelay = args->a, aWaitDelay = args->b; PR_Sleep(0); while (1) { // -- enter read lock PR_EnterMonitor (gMonitor); if (0 < gWriteWaiting) // give up the monitor to waiting writes { PRIntervalTime fiveSecs = PR_SecondsToInterval(5); gReadWaiting++; if (gReadWaiting > gMaxReadWaits) // stats gMaxReadWaits = gReadWaiting; while (0 < gWriteWaiting) PR_Wait (gMonitor, fiveSecs); gReadWaiting--; } gReading++; gReads++; // stats if (gReading > gMaxReads) // stats gMaxReads = gReading; PR_ExitMonitor (gMonitor); // -- read lock entered last = gCounter; spin (aWorkDelay); PR_ASSERT (gCounter == last); // test invariance // -- exit read lock PR_EnterMonitor (gMonitor); // read unlock gReading--; // if ((0 == gReading) && (0 < gWriteWaiting)) // notify waiting writes (do it anyway to show off the CondWait bug) PR_NotifyAll (gMonitor); PR_ExitMonitor (gMonitor); // -- read lock exited spin (aWaitDelay); } }
static void Level_0_Thread(PRThreadScope scope1, PRThreadScope scope2) { PRThread *thr; PRThread *me = PR_GetCurrentThread(); int n; PRInt32 words; PRWord *registers; alive = 0; mon = PR_NewMonitor(); alive = count; for (n=0; n<count; n++) { thr = PR_CreateThreadGCAble(PR_USER_THREAD, Level_1_Thread, (void *)scope2, PR_PRIORITY_NORMAL, scope1, PR_UNJOINABLE_THREAD, 0); if (!thr) { printf("Could not create thread!\n"); alive--; } printf("Level_0_Thread[0x%lx] created %15s thread 0x%lx\n", PR_GetCurrentThread(), (scope1 == PR_GLOBAL_THREAD) ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD", thr); PR_Sleep(0); } PR_SuspendAll(); PR_EnumerateThreads(print_thread, NULL); registers = PR_GetGCRegisters(me, 1, (int *)&words); if (registers) printf("My Registers: R0 = 0x%x R1 = 0x%x R2 = 0x%x R3 = 0x%x\n", registers[0],registers[1],registers[2],registers[3]); printf("My Stack Pointer = 0x%lx\n", PR_GetSP(me)); PR_ResumeAll(); /* Wait for all threads to exit */ PR_EnterMonitor(mon); while (alive) { PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); } PR_ExitMonitor(mon); PR_DestroyMonitor(mon); }
static void PR_CALLBACK T3Mon(void *arg) { PRStatus rv; MonShared *shared = (MonShared*)arg; PR_EnterMonitor(shared->o2); LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); rv = PR_Wait(shared->o2, PR_SecondsToInterval(5)); if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); else LogNow("T3 wait failed on o2", rv); rv = PR_Notify(shared->o2); LogNow("T3 notify on o2", rv); PR_ExitMonitor(shared->o2); } /* T3Mon */
void doWriteThread (void* arg) { PRInt32 last; Arg_t *args = (Arg_t*)arg; PRInt32 aWorkDelay = args->a, aWaitDelay = args->b; PR_Sleep(0); while (1) { // -- enter write lock PR_EnterMonitor (gMonitor); if (0 < gReading) // wait for read locks to go away { PRIntervalTime fiveSecs = PR_SecondsToInterval(5); gWriteWaiting++; if (gWriteWaiting > gMaxWriteWaits) // stats gMaxWriteWaits = gWriteWaiting; while (0 < gReading) PR_Wait (gMonitor, fiveSecs); gWriteWaiting--; } // -- write lock entered last = gCounter; gCounter++; spin (aWorkDelay); PR_ASSERT (gCounter == (last + 1)); // test invariance // -- exit write lock // if (0 < gReadWaiting) // notify waiting reads (do it anyway to show off the CondWait bug) PR_NotifyAll (gMonitor); PR_ExitMonitor (gMonitor); // -- write lock exited spin (aWaitDelay); } }
static PRInt32 TCP_Socket_Client_Server_Test(void) { int i; PRThread *t; PRThreadScope scope; PRSemaphore *server_sem; Server_Param *sparamp; Client_Param *cparamp; PRMonitor *mon2; PRInt32 datalen; datalen = tcp_mesg_size; thread_count = 0; /* * start the server thread */ sparamp = PR_NEW(Server_Param); if (sparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; return -1; } server_sem = PR_NewSem(0); if (server_sem == NULL) { fprintf(stderr,"prsocket_test: PR_NewSem failed\n"); failed_already=1; return -1; } mon2 = PR_NewMonitor(); if (mon2 == NULL) { fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); failed_already=1; return -1; } PR_EnterMonitor(mon2); sparamp->addr_sem = server_sem; sparamp->exit_mon = mon2; sparamp->exit_counter = &thread_count; sparamp->datalen = datalen; t = PR_CreateThread(PR_USER_THREAD, TCP_Server, (void *)sparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; return -1; } DPRINTF(("Created TCP server = 0x%lx\n", t)); thread_count++; /* * wait till the server address is setup */ PR_WaitSem(server_sem); /* * Now start a bunch of client threads */ cparamp = PR_NEW(Client_Param); if (cparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; return -1; } cparamp->server_addr = tcp_server_addr; cparamp->server_addr.inet.ip = PR_htonl(INADDR_LOOPBACK); cparamp->exit_mon = mon2; cparamp->exit_counter = &thread_count; cparamp->datalen = datalen; for (i = 0; i < num_tcp_clients; i++) { /* * Every other thread is a LOCAL/GLOBAL thread */ if (i & 1) scope = PR_LOCAL_THREAD; else scope = PR_GLOBAL_THREAD; t = PR_CreateThread(PR_USER_THREAD, TCP_Client, (void *) cparamp, PR_PRIORITY_NORMAL, scope, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; return -1; } DPRINTF(("Created TCP client = 0x%lx\n", t)); thread_count++; } /* Wait for server and client threads to exit */ while (thread_count) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("TCP Server - thread_count = %d\n", thread_count)); } PR_ExitMonitor(mon2); printf("%30s","TCP_Socket_Client_Server_Test:"); printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l, num_tcp_clients, num_tcp_connections_per_client); printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":", num_tcp_mesgs_per_connection, tcp_mesg_size); return 0; }
JD_METHOD_(JDBool) CNSAdapter_NSPR::JD_Wait(void* mon, JDUint32 ticks) { return PR_Wait((PRMonitor*)mon, (PRIntervalTime)ticks); }
void RunWriter(void* arg) { PR_SetCurrentThreadName("Shutdown Statistics Writer"); MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(arg); // Shutdown will generally complete before we have a chance to // deallocate. This is not a leak. // Setup destinationPath and tmpFilePath nsCString destinationPath(static_cast<char*>(arg)); nsAutoCString tmpFilePath; tmpFilePath.Append(destinationPath); tmpFilePath.AppendLiteral(".tmp"); // Cleanup any file leftover from a previous run Unused << PR_Delete(tmpFilePath.get()); Unused << PR_Delete(destinationPath.get()); while (true) { // // Check whether we have received data from the main thread. // // We perform the check before waiting on `gWriteReady` as we may // have received data while we were busy writing. // // Also note that gWriteData may have been modified several times // since we last checked. That's ok, we are not losing any important // data (since we keep adding data), and we are not leaking memory // (since the main thread deallocates any data that hasn't been // consumed by the writer thread). // UniquePtr<nsCString> data(gWriteData.exchange(nullptr)); if (!data) { // Data is not available yet. // Wait until the main thread provides it. PR_EnterMonitor(gWriteReady); PR_Wait(gWriteReady, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(gWriteReady); continue; } MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(data.get()); // Shutdown may complete before we have a chance to deallocate. // This is not a leak. // // Write to a temporary file // // In case of any error, we simply give up. Since the data is // hardly critical, we don't want to spend too much effort // salvaging it. // UniquePtr<PRFileDesc, PR_CloseDelete> tmpFileDesc(PR_Open(tmpFilePath.get(), PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE, 00600)); // Shutdown may complete before we have a chance to close the file. // This is not a leak. MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(tmpFileDesc.get()); if (tmpFileDesc == nullptr) { break; } if (PR_Write(tmpFileDesc.get(), data->get(), data->Length()) == -1) { break; } tmpFileDesc.reset(); // // Rename on top of destination file. // // This is not sufficient to guarantee that the destination file // will be written correctly, but, again, we don't care enough // about the data to make more efforts. // if (PR_Rename(tmpFilePath.get(), destinationPath.get()) != PR_SUCCESS) { break; } } }
static PRInt32 TCP_Socket_Client_Server_Test(void) { int i; Client_Param *cparamp; PRMonitor *mon2; PRInt32 datalen; PRInt32 connections = 0; PRThread *thr; datalen = tcp_mesg_size; connections = 0; mon2 = PR_NewMonitor(); if (mon2 == NULL) { fprintf(stderr,"%s: PR_NewMonitor failed\n", program_name); failed_already=1; return -1; } /* * Start client jobs */ cparamp = PR_NEW(Client_Param); if (cparamp == NULL) { fprintf(stderr,"%s: PR_NEW failed\n", program_name); failed_already=1; return -1; } cparamp->server_addr.inet.family = PR_AF_INET; cparamp->server_addr.inet.port = PR_htons(server_port); cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); cparamp->exit_mon = mon2; cparamp->exit_counter = &connections; cparamp->datalen = datalen; for (i = 0; i < num_tcp_clients; i++) { thr = PR_CreateThread(PR_USER_THREAD, TCP_Client, (void *)cparamp, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (NULL == thr) { fprintf(stderr,"%s: PR_CreateThread failed\n", program_name); failed_already=1; return -1; } PR_EnterMonitor(mon2); connections++; PR_ExitMonitor(mon2); DPRINTF(("Created TCP client = 0x%lx\n", thr)); } /* Wait for client jobs to exit */ PR_EnterMonitor(mon2); while (0 != connections) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("Client job count = %d\n", connections)); } PR_ExitMonitor(mon2); printf("%30s","TCP_Socket_Client_Server_Test:"); printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l, num_tcp_clients, num_tcp_connections_per_client); printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":", num_tcp_mesgs_per_connection, tcp_mesg_size); PR_DELETE(cparamp); return 0; }
NS_IMETHODIMP nsDNSService::Resolve(const nsACString &hostname, PRUint32 flags, nsIDNSRecord **result) { // grab reference to global host resolver and IDN service. beware // simultaneous shutdown!! nsRefPtr<nsHostResolver> res; nsCOMPtr<nsIIDNService> idn; { nsAutoLock lock(mLock); res = mResolver; idn = mIDN; } NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE); const nsACString *hostPtr = &hostname; nsresult rv; nsCAutoString hostACE; if (idn && !IsASCII(hostname)) { if (NS_SUCCEEDED(idn->ConvertUTF8toACE(hostname, hostACE))) hostPtr = &hostACE; } // // sync resolve: since the host resolver only works asynchronously, we need // to use a mutex and a condvar to wait for the result. however, since the // result may be in the resolvers cache, we might get called back recursively // on the same thread. so, our mutex needs to be re-entrant. inotherwords, // we need to use a monitor! ;-) // PRMonitor *mon = PR_NewMonitor(); if (!mon) return NS_ERROR_OUT_OF_MEMORY; PR_EnterMonitor(mon); nsDNSSyncRequest syncReq(mon); PRUint16 af = GetAFForLookup(*hostPtr); rv = res->ResolveHost(PromiseFlatCString(*hostPtr).get(), flags, af, &syncReq); if (NS_SUCCEEDED(rv)) { // wait for result while (!syncReq.mDone) PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); if (NS_FAILED(syncReq.mStatus)) rv = syncReq.mStatus; else { NS_ASSERTION(syncReq.mHostRecord, "no host record"); nsDNSRecord *rec = new nsDNSRecord(syncReq.mHostRecord); if (!rec) rv = NS_ERROR_OUT_OF_MEMORY; else NS_ADDREF(*result = rec); } } PR_ExitMonitor(mon); PR_DestroyMonitor(mon); return rv; }
int monitor_join(monitor_t monitor) { PRStatus rv; rv = PR_Wait((PRMonitor*)monitor, PR_INTERVAL_NO_TIMEOUT); return rv == PR_SUCCESS ? 1 : 0; }
static PRInt32 UDP_Socket_Client_Server_Test(void) { int i; PRThread *t; PRSemaphore *server_sem; Server_Param *sparamp; Client_Param *cparamp; PRMonitor *mon2; PRInt32 datalen; PRInt32 udp_connect = 1; datalen = udp_datagram_size; thread_count = 0; /* * start the server thread */ sparamp = PR_NEW(Server_Param); if (sparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; return -1; } server_sem = PR_NewSem(0); if (server_sem == NULL) { fprintf(stderr,"prsocket_test: PR_NewSem failed\n"); failed_already=1; return -1; } mon2 = PR_NewMonitor(); if (mon2 == NULL) { fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); failed_already=1; return -1; } PR_EnterMonitor(mon2); sparamp->addr_sem = server_sem; sparamp->exit_mon = mon2; sparamp->exit_counter = &thread_count; sparamp->datalen = datalen; DPRINTF(("Creating UDP server")); t = PR_CreateThread(PR_USER_THREAD, UDP_Server, (void *)sparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; return -1; } thread_count++; /* * wait till the server address is setup */ PR_WaitSem(server_sem); /* * Now start a bunch of client threads */ for (i = 0; i < num_udp_clients; i++) { cparamp = PR_NEW(Client_Param); if (cparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; return -1; } cparamp->server_addr = udp_server_addr; cparamp->exit_mon = mon2; cparamp->exit_counter = &thread_count; cparamp->datalen = datalen; /* * Cause every other client thread to connect udp sockets */ #ifndef XP_MAC cparamp->udp_connect = udp_connect; #else /* No support for UDP connects on Mac */ cparamp->udp_connect = 0; #endif if (udp_connect) udp_connect = 0; else udp_connect = 1; DPRINTF(("Creating UDP client %d\n", i)); t = PR_CreateThread(PR_USER_THREAD, UDP_Client, (void *) cparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; return -1; } thread_count++; } /* Wait for server and client threads to exit */ while (thread_count) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("UDP Server - thread_count = %d\n", thread_count)); } PR_ExitMonitor(mon2); printf("%30s","UDP_Socket_Client_Server_Test: "); printf("%2ld Server %2ld Clients\n",1l, num_udp_clients); printf("%30s %2ld datagrams_per_client %4ld bytes_per_datagram\n",":", num_udp_datagrams_per_client, udp_datagram_size); return 0; }
static void TCP_Server_Accept(void *arg) { Server_Param *sp = (Server_Param *) arg; PRThreadPool *tp = sp->tp; Serve_Client_Param *scp; PRFileDesc *newsockfd; PRJob *jobp; if ((newsockfd = PR_Accept(sp->iod.socket, &sp->netaddr, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr,"%s: ERROR - PR_Accept failed\n", program_name); failed_already=1; goto exit; } scp = PR_NEW(Serve_Client_Param); if (scp == NULL) { fprintf(stderr,"%s: PR_NEW failed\n", program_name); failed_already=1; goto exit; } /* * Start a Serve_Client job for each incoming connection */ scp->iod.socket = newsockfd; scp->iod.timeout = PR_SecondsToInterval(60); scp->datalen = tcp_mesg_size; scp->exit_mon = sp->exit_mon; scp->job_counterp = sp->job_counterp; scp->tp = sp->tp; PR_EnterMonitor(sp->exit_mon); (*sp->job_counterp)++; PR_ExitMonitor(sp->exit_mon); jobp = PR_QueueJob(tp, Serve_Client, scp, PR_FALSE); PR_ASSERT(NULL != jobp); DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", jobp)); /* * single-threaded update; no lock needed */ sp->conn_counter++; if (sp->conn_counter < (num_tcp_clients * num_tcp_connections_per_client)) { jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp, PR_FALSE); PR_ASSERT(NULL != jobp); return; } jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500), print_stats, sp, PR_FALSE); PR_ASSERT(NULL != jobp); DPRINTF(("TCP_Server: Created print_stats timer job = 0x%lx\n", jobp)); exit: PR_EnterMonitor(sp->exit_mon); /* Wait for server jobs to finish */ while (0 != *sp->job_counterp) { PR_Wait(sp->exit_mon, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("TCP_Server: conn_counter = %d\n", *sp->job_counterp)); } PR_ExitMonitor(sp->exit_mon); if (sp->iod.socket) { PR_Close(sp->iod.socket); } PR_DestroyMonitor(sp->exit_mon); printf("%30s","TCP_Socket_Client_Server_Test:"); printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l, num_tcp_clients, num_tcp_connections_per_client); printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":", num_tcp_mesgs_per_connection, tcp_mesg_size); DPRINTF(("%s: calling PR_ShutdownThreadPool\n", program_name)); PR_ShutdownThreadPool(sp->tp); PR_DELETE(sp); }
/* * Socket_Misc_Test - test miscellaneous functions * */ static PRInt32 Socket_Misc_Test(void) { PRIntn i, rv = 0, bytes, count, len; PRThread *t; PRThreadScope scope; PRSemaphore *server_sem; Server_Param *sparamp; Client_Param *cparamp; PRMonitor *mon2; PRInt32 datalen; /* * We deliberately pick a buffer size that is not a nice multiple * of 1024. */ #define TRANSMITFILE_BUF_SIZE (4 * 1024 - 11) typedef struct { char data[TRANSMITFILE_BUF_SIZE]; } file_buf; file_buf *buf = NULL; /* * create file(s) to be transmitted */ if ((PR_MkDir(TEST_DIR, 0777)) < 0) { printf("prsocket_test failed to create dir %s\n",TEST_DIR); failed_already=1; return -1; } small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777); if (small_file_fd == NULL) { fprintf(stderr,"prsocket_test failed to create/open file %s\n", SMALL_FILE_NAME); failed_already=1; rv = -1; goto done; } buf = PR_NEW(file_buf); if (buf == NULL) { fprintf(stderr,"prsocket_test failed to allocate buffer\n"); failed_already=1; rv = -1; goto done; } /* * fill in random data */ for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) { buf->data[i] = i; } count = 0; do { len = (SMALL_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ? TRANSMITFILE_BUF_SIZE : (SMALL_FILE_SIZE - count); bytes = PR_Write(small_file_fd, buf->data, len); if (bytes <= 0) { fprintf(stderr, "prsocket_test failed to write to file %s\n", SMALL_FILE_NAME); failed_already=1; rv = -1; goto done; } count += bytes; } while (count < SMALL_FILE_SIZE); #ifdef XP_UNIX /* * map the small file; used in checking for data corruption */ small_file_addr = mmap(0, SMALL_FILE_SIZE, PROT_READ, MAP_PRIVATE, small_file_fd->secret->md.osfd, 0); if (small_file_addr == (void *) -1) { fprintf(stderr,"prsocket_test failed to mmap file %s\n", SMALL_FILE_NAME); failed_already=1; rv = -1; goto done; } #endif /* * header for small file */ small_file_header = PR_MALLOC(SMALL_FILE_HEADER_SIZE); if (small_file_header == NULL) { fprintf(stderr,"prsocket_test failed to malloc header file\n"); failed_already=1; rv = -1; goto done; } memset(small_file_header, (int) PR_IntervalNow(), SMALL_FILE_HEADER_SIZE); /* * setup large file */ large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777); if (large_file_fd == NULL) { fprintf(stderr,"prsocket_test failed to create/open file %s\n", LARGE_FILE_NAME); failed_already=1; rv = -1; goto done; } /* * fill in random data */ for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) { buf->data[i] = i; } count = 0; do { len = (LARGE_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ? TRANSMITFILE_BUF_SIZE : (LARGE_FILE_SIZE - count); bytes = PR_Write(large_file_fd, buf->data, len); if (bytes <= 0) { fprintf(stderr, "prsocket_test failed to write to file %s: (%ld, %ld)\n", LARGE_FILE_NAME, PR_GetError(), PR_GetOSError()); failed_already=1; rv = -1; goto done; } count += bytes; } while (count < LARGE_FILE_SIZE); #ifdef XP_UNIX /* * map the large file; used in checking for data corruption */ large_file_addr = mmap(0, LARGE_FILE_SIZE, PROT_READ, MAP_PRIVATE, large_file_fd->secret->md.osfd, 0); if (large_file_addr == (void *) -1) { fprintf(stderr,"prsocket_test failed to mmap file %s\n", LARGE_FILE_NAME); failed_already=1; rv = -1; goto done; } #endif datalen = tcp_mesg_size; thread_count = 0; /* * start the server thread */ sparamp = PR_NEW(Server_Param); if (sparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; rv = -1; goto done; } server_sem = PR_NewSem(0); if (server_sem == NULL) { fprintf(stderr,"prsocket_test: PR_NewSem failed\n"); failed_already=1; rv = -1; goto done; } mon2 = PR_NewMonitor(); if (mon2 == NULL) { fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); failed_already=1; rv = -1; goto done; } PR_EnterMonitor(mon2); sparamp->addr_sem = server_sem; sparamp->exit_mon = mon2; sparamp->exit_counter = &thread_count; sparamp->datalen = datalen; t = PR_CreateThread(PR_USER_THREAD, TransmitFile_Server, (void *)sparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; rv = -1; goto done; } DPRINTF(("Created TCP server = 0x%x\n", t)); thread_count++; /* * wait till the server address is setup */ PR_WaitSem(server_sem); /* * Now start a bunch of client threads */ cparamp = PR_NEW(Client_Param); if (cparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; rv = -1; goto done; } cparamp->server_addr = tcp_server_addr; cparamp->server_addr.inet.ip = PR_htonl(INADDR_LOOPBACK); cparamp->exit_mon = mon2; cparamp->exit_counter = &thread_count; cparamp->datalen = datalen; for (i = 0; i < num_transmitfile_clients; i++) { /* * Every other thread is a LOCAL/GLOBAL thread */ if (i & 1) scope = PR_GLOBAL_THREAD; else scope = PR_LOCAL_THREAD; t = PR_CreateThread(PR_USER_THREAD, TransmitFile_Client, (void *) cparamp, PR_PRIORITY_NORMAL, scope, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); rv = -1; failed_already=1; goto done; } DPRINTF(("Created TransmitFile client = 0x%lx\n", t)); thread_count++; } /* Wait for server and client threads to exit */ while (thread_count) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("Socket_Misc_Test - thread_count = %d\n", thread_count)); } PR_ExitMonitor(mon2); done: if (buf) { PR_DELETE(buf); } #ifdef XP_UNIX munmap(small_file_addr, SMALL_FILE_SIZE); munmap(large_file_addr, LARGE_FILE_SIZE); #endif PR_Close(small_file_fd); PR_Close(large_file_fd); if ((PR_Delete(SMALL_FILE_NAME)) == PR_FAILURE) { fprintf(stderr,"prsocket_test: failed to unlink file %s\n", SMALL_FILE_NAME); failed_already=1; } if ((PR_Delete(LARGE_FILE_NAME)) == PR_FAILURE) { fprintf(stderr,"prsocket_test: failed to unlink file %s\n", LARGE_FILE_NAME); failed_already=1; } if ((PR_RmDir(TEST_DIR)) == PR_FAILURE) { fprintf(stderr,"prsocket_test failed to rmdir %s: (%ld, %ld)\n", TEST_DIR, PR_GetError(), PR_GetOSError()); failed_already=1; } printf("%-29s%s","Socket_Misc_Test",":"); printf("%2d Server %2d Clients\n",1, num_transmitfile_clients); printf("%30s Sizes of Transmitted Files - %4d KB, %2d MB \n",":", SMALL_FILE_SIZE/1024, LARGE_FILE_SIZE/(1024 * 1024)); return rv; }