/* API: stop stream */ static pj_status_t alsa_stream_stop (pjmedia_aud_stream *s) { struct alsa_stream *stream = (struct alsa_stream*)s; stream->quit = 1; if (stream->pb_thread) { TRACE_((THIS_FILE, "alsa_stream_stop(%u): Waiting for playback to stop.", (unsigned)syscall(SYS_gettid))); pj_thread_join (stream->pb_thread); TRACE_((THIS_FILE, "alsa_stream_stop(%u): playback stopped.", (unsigned)syscall(SYS_gettid))); pj_thread_destroy(stream->pb_thread); stream->pb_thread = NULL; } if (stream->ca_thread) { TRACE_((THIS_FILE, "alsa_stream_stop(%u): Waiting for capture to stop.", (unsigned)syscall(SYS_gettid))); pj_thread_join (stream->ca_thread); TRACE_((THIS_FILE, "alsa_stream_stop(%u): capture stopped.", (unsigned)syscall(SYS_gettid))); pj_thread_destroy(stream->ca_thread); stream->ca_thread = NULL; } return PJ_SUCCESS; }
void stop_stack() { // Terminate the PJSIP threads and the worker threads to exit. We kill // the PJSIP threads first - if we killed the worker threads first the // rx_msg_q will stop getting serviced so could fill up blocking // PJSIP threads, causing a deadlock. // Set the quit flag to signal the PJSIP threads to exit, then wait // for them to exit. quit_flag = PJ_TRUE; for (std::vector<pj_thread_t*>::iterator i = pjsip_threads.begin(); i != pjsip_threads.end(); ++i) { pj_thread_join(*i); } // Now it is safe to signal the worker threads to exit via the queue and to // wait for them to terminate. rx_msg_q.terminate(); for (std::vector<pj_thread_t*>::iterator i = worker_threads.begin(); i != worker_threads.end(); ++i) { pj_thread_join(*i); } }
/* API: stop stream. */ static pj_status_t strm_stop(pjmedia_aud_stream *s) { struct android_aud_stream *stream = (struct android_aud_stream*)s; int i; //We assume that all jni calls are safe ... that's acceptable if(stream->quit_flag == 0){ PJ_LOG(3, (THIS_FILE, "Stopping stream")); }else{ PJ_LOG(2, (THIS_FILE, "Already stopped.... nothing to do here")); return PJ_SUCCESS; } JNIEnv *jni_env = 0; ATTACH_JVM(jni_env); jmethodID method_id; stream->quit_flag = 1; /* if (result != 0) { PJ_LOG(1, (THIS_FILE, "Not able to attach the jvm")); return PJ_ENOMEM; } */ if(stream->record){ //stop recording method_id = jni_env->GetMethodID(stream->record_class, "stop", "()V"); jni_env->CallVoidMethod(stream->record, method_id); if(stream->rec_thread){ pj_thread_join(stream->rec_thread); pj_thread_destroy(stream->rec_thread); stream->rec_thread = NULL; } } if(stream->track){ method_id = jni_env->GetMethodID(stream->track_class,"flush", "()V"); jni_env->CallVoidMethod(stream->track, method_id); method_id = jni_env->GetMethodID(stream->track_class, "stop", "()V"); jni_env->CallVoidMethod(stream->track, method_id); if(stream->play_thread){ pj_thread_join(stream->play_thread); pj_thread_destroy(stream->play_thread); stream->play_thread = NULL; } } PJ_LOG(4,(THIS_FILE, "Stopping Done")); DETACH_JVM(jni_env); return PJ_SUCCESS; }
/* * Destroy the clock. */ PJ_DEF(pj_status_t) pjmedia_clock_destroy(pjmedia_clock *clock) { PJ_ASSERT_RETURN(clock != NULL, PJ_EINVAL); clock->running = PJ_FALSE; clock->quitting = PJ_TRUE; if (clock->thread) { pj_thread_join(clock->thread); pj_thread_destroy(clock->thread); clock->thread = NULL; } if (clock->lock) { pj_lock_destroy(clock->lock); clock->lock = NULL; } if (clock->pool) { pj_pool_t *pool = clock->pool; clock->pool = NULL; pj_pool_release(pool); } return PJ_SUCCESS; }
/* * Destroy SIP */ static void destroy_app() { unsigned i; app.thread_quit = 1; for (i=0; i<app.thread_count; ++i) { if (app.thread[i]) { pj_thread_join(app.thread[i]); pj_thread_destroy(app.thread[i]); app.thread[i] = NULL; } } if (app.sip_endpt) { pjsip_endpt_destroy(app.sip_endpt); app.sip_endpt = NULL; } if (app.pool) { pj_pool_release(app.pool); app.pool = NULL; PJ_LOG(3,(THIS_FILE, "Peak memory size: %uMB", app.cp.peak_used_size / 1000000)); pj_caching_pool_destroy(&app.cp); } /* Shutdown PJLIB */ pj_shutdown(); }
static pj_status_t job_queue_destroy(job_queue *jq) { unsigned i; jq->is_quitting = PJ_TRUE; if (jq->thread) { pj_sem_post(jq->sem); pj_thread_join(jq->thread); pj_thread_destroy(jq->thread); } if (jq->sem) { pj_sem_destroy(jq->sem); jq->sem = NULL; } for (i = 0; i < jq->size; i++) { if (jq->job_sem[i]) { pj_sem_destroy(jq->job_sem[i]); jq->job_sem[i] = NULL; } } if (jq->mutex) { pj_mutex_destroy(jq->mutex); jq->mutex = NULL; } return PJ_SUCCESS; }
/* Utility: display error message and exit application (usually * because of fatal error. */ static void err_exit(const char *title, pj_status_t status) { if (status != PJ_SUCCESS) { icedemo_perror(title, status); } PJ_LOG(3,(THIS_FILE, "Shutting down..")); if (icedemo.icest) pj_ice_strans_destroy(icedemo.icest); pj_thread_sleep(500); icedemo.thread_quit_flag = PJ_TRUE; if (icedemo.thread) { pj_thread_join(icedemo.thread); pj_thread_destroy(icedemo.thread); } if (icedemo.ice_cfg.stun_cfg.ioqueue) pj_ioqueue_destroy(icedemo.ice_cfg.stun_cfg.ioqueue); if (icedemo.ice_cfg.stun_cfg.timer_heap) pj_timer_heap_destroy(icedemo.ice_cfg.stun_cfg.timer_heap); pj_caching_pool_destroy(&icedemo.cp); pj_shutdown(); if (icedemo.log_fhnd) { fclose(icedemo.log_fhnd); icedemo.log_fhnd = NULL; } exit(status != PJ_SUCCESS); }
PJ_DEF(void) pjmedia_event_mgr_destroy(pjmedia_event_mgr *mgr) { if (!mgr) mgr = pjmedia_event_mgr_instance(); PJ_ASSERT_ON_FAIL(mgr != NULL, return); if (mgr->thread) { mgr->is_quitting = PJ_TRUE; pj_sem_post(mgr->sem); pj_thread_join(mgr->thread); } if (mgr->sem) { pj_sem_destroy(mgr->sem); mgr->sem = NULL; } if (mgr->mutex) { pj_mutex_destroy(mgr->mutex); mgr->mutex = NULL; } if (mgr->pool) pj_pool_release(mgr->pool); if (event_manager_instance == mgr) event_manager_instance = NULL; }
/** * Deinitialize media endpoint. */ PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt) { unsigned i; PJ_ASSERT_RETURN(endpt, PJ_EINVAL); endpt->quit_flag = 1; /* Destroy threads */ for (i=0; i<endpt->thread_cnt; ++i) { if (endpt->thread[i]) { pj_thread_join(endpt->thread[i]); pj_thread_destroy(endpt->thread[i]); endpt->thread[i] = NULL; } } /* Destroy internal ioqueue */ if (endpt->ioqueue && endpt->own_ioqueue) { pj_ioqueue_destroy(endpt->ioqueue); endpt->ioqueue = NULL; } endpt->pf = NULL; pjmedia_aud_subsys_shutdown(); pj_pool_release (endpt->pool); return PJ_SUCCESS; }
/* * Destroy stream. */ PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream) { unsigned i; PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); pjmedia_snd_stream_stop(stream); if (stream->thread) { SetEvent(stream->thread_quit_event); pj_thread_join(stream->thread); pj_thread_destroy(stream->thread); stream->thread = NULL; } /* Unprepare the headers and close the play device */ if (stream->play_strm.hWave.Out) { waveOutReset(stream->play_strm.hWave.Out); for (i = 0; i < stream->play_strm.dwMaxBufIdx; ++i) waveOutUnprepareHeader(stream->play_strm.hWave.Out, &(stream->play_strm.WaveHdr[i]), sizeof(WAVEHDR)); waveOutClose(stream->play_strm.hWave.Out); stream->play_strm.hWave.Out = NULL; } /* Close the play event */ if (stream->play_strm.hEvent) { CloseHandle(stream->play_strm.hEvent); stream->play_strm.hEvent = NULL; } /* Unprepare the headers and close the record device */ if (stream->rec_strm.hWave.In) { waveInReset(stream->rec_strm.hWave.In); for (i = 0; i < stream->play_strm.dwMaxBufIdx; ++i) waveInUnprepareHeader(stream->rec_strm.hWave.In, &(stream->rec_strm.WaveHdr[i]), sizeof(WAVEHDR)); waveInClose(stream->rec_strm.hWave.In); stream->rec_strm.hWave.In = NULL; } /* Close the record event */ if (stream->rec_strm.hEvent) { CloseHandle(stream->rec_strm.hEvent); stream->rec_strm.hEvent = NULL; } pj_pool_release(stream->pool); return PJ_SUCCESS; }
PJStunTurn::~PJStunTurn() { worker_quit_ = true; if (nullptr != thread_) { pj_thread_join(thread_); pj_thread_destroy(thread_); } if (ice_cfg_.stun_cfg.ioqueue) pj_ioqueue_destroy(ice_cfg_.stun_cfg.ioqueue); if (ice_cfg_.stun_cfg.timer_heap) pj_timer_heap_destroy(ice_cfg_.stun_cfg.timer_heap); }
/* API: stop stream */ static pj_status_t bb10_stream_stop (pjmedia_aud_stream *s) { struct bb10_stream *stream = (struct bb10_stream*)s; stream->quit = 1; TRACE_((THIS_FILE,"bb10_stream_stop()")); if (stream->pb_thread) { pj_thread_join (stream->pb_thread); pj_thread_destroy(stream->pb_thread); stream->pb_thread = NULL; } if (stream->ca_thread) { pj_thread_join (stream->ca_thread); pj_thread_destroy(stream->ca_thread); stream->ca_thread = NULL; } return PJ_SUCCESS; }
ConnectionPool::~ConnectionPool() { if (_recycler) { // Set the terminated flag to signal the recycler thread to exit. _terminated = true; // Wait for the recycler thread to exit. pj_thread_join(_recycler); } // Quiesce all the connections. quiesce_connections(); }
pj_status_t stop_pjsip_threads() { // Set the quit flag to signal the PJSIP threads to exit, then wait // for them to exit. quit_flag = PJ_TRUE; for (std::vector<pj_thread_t*>::iterator i = pjsip_threads.begin(); i != pjsip_threads.end(); ++i) { pj_thread_join(*i); } pjsip_threads.clear(); return PJ_SUCCESS; }
/* * Stop the clock. */ PJ_DEF(pj_status_t) pjmedia_clock_stop(pjmedia_clock *clock) { PJ_ASSERT_RETURN(clock != NULL, PJ_EINVAL); clock->running = PJ_FALSE; clock->quitting = PJ_TRUE; if (clock->thread) { if (pj_thread_join(clock->thread) == PJ_SUCCESS) { clock->thread = NULL; } else { clock->quitting = PJ_FALSE; } } return PJ_SUCCESS; }
/* Destroy server */ static void destroy_server(void) { if (server->thread) { server->quit = PJ_TRUE; pj_thread_join(server->thread); pj_thread_destroy(server->thread); } if (server->sock) { pj_sock_close(server->sock); } if (server->sess) { pj_stun_session_destroy(server->sess); } pj_pool_release(server->pool); server = NULL; }
/** * Stop and destroy the worker threads of the media endpoint */ PJ_DEF(pj_status_t) pjmedia_endpt_stop_threads(pjmedia_endpt *endpt) { unsigned i; PJ_ASSERT_RETURN(endpt, PJ_EINVAL); endpt->quit_flag = 1; /* Destroy threads */ for (i=0; i<endpt->thread_cnt; ++i) { if (endpt->thread[i]) { pj_thread_join(endpt->thread[i]); pj_thread_destroy(endpt->thread[i]); endpt->thread[i] = NULL; } } return PJ_SUCCESS; }
static void destroy_stack(void) { enum { WAIT_CLEAR = 5000, WAIT_INTERVAL = 500 }; unsigned i; PJ_LOG(3,(THIS_FILE, "Shutting down..")); /* Wait until all clear */ hangup_all(); for (i=0; i<WAIT_CLEAR/WAIT_INTERVAL; ++i) { unsigned j; for (j=0; j<MAX_CALLS; ++j) { call_t *call = &app.call[j]; if (call->inv && call->inv->state <= PJSIP_INV_STATE_CONFIRMED) break; } if (j==MAX_CALLS) return; pj_thread_sleep(WAIT_INTERVAL); } app.quit = PJ_TRUE; if (app.worker_thread) { pj_thread_join(app.worker_thread); app.worker_thread = NULL; } //if (app.med_endpt) //pjmedia_endpt_destroy(app.med_endpt); if (app.sip_endpt) pjsip_endpt_destroy(app.sip_endpt); if (app.pool) pj_pool_release(app.pool); dump_pool_usage(THIS_FILE, &app.cp); pj_caching_pool_destroy(&app.cp); }
static void destroy_client_server(void) { if (client->thread) { client->quit = 1; pj_thread_join(client->thread); pj_thread_destroy(client->thread); } if (client->sess) pj_stun_session_destroy(client->sess); if (client->sock) pj_sock_close(client->sock); if (client->test_complete) pj_sem_destroy(client->test_complete); if (server) destroy_server(); }
/** * Deinitialize media endpoint. */ PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt) { exit_cb *ecb; unsigned i; PJ_ASSERT_RETURN(endpt, PJ_EINVAL); endpt->quit_flag = 1; /* Destroy threads */ for (i=0; i<endpt->thread_cnt; ++i) { if (endpt->thread[i]) { pj_thread_join(endpt->thread[i]); pj_thread_destroy(endpt->thread[i]); endpt->thread[i] = NULL; } } /* Destroy internal ioqueue */ if (endpt->ioqueue && endpt->own_ioqueue) { pj_ioqueue_destroy(endpt->ioqueue); endpt->ioqueue = NULL; } endpt->pf = NULL; pjmedia_codec_mgr_destroy(&endpt->codec_mgr); pjmedia_aud_subsys_shutdown(); /* Call all registered exit callbacks */ ecb = endpt->exit_cb_list.next; while (ecb != &endpt->exit_cb_list) { (*ecb->func)(endpt); ecb = ecb->next; } pj_pool_release (endpt->pool); return PJ_SUCCESS; }
/* Handler to destroy the transport; called by transport manager */ static pj_status_t loop_destroy(pjsip_transport *tp) { struct loop_transport *loop = (struct loop_transport*)tp; PJ_ASSERT_RETURN(tp && (tp->key.type == PJSIP_TRANSPORT_LOOP || tp->key.type == PJSIP_TRANSPORT_LOOP_DGRAM), PJ_EINVAL); loop->thread_quit_flag = 1; /* Unlock transport mutex before joining thread. */ pj_lock_release(tp->lock); pj_thread_join(loop->thread); pj_thread_destroy(loop->thread); /* Clear pending send notifications. */ while (!pj_list_empty(&loop->send_list)) { struct send_list *node = loop->send_list.next; /* Notify callback. */ if (node->callback) { (*node->callback)(&loop->base, node->token, -PJSIP_ESHUTDOWN); } pj_list_erase(node); pjsip_tx_data_dec_ref(node->tdata); } /* Clear "incoming" packets in the queue. */ while (!pj_list_empty(&loop->recv_list)) { struct recv_list *node = loop->recv_list.next; pj_list_erase(node); pjsip_endpt_release_pool(loop->base.endpt, node->rdata.tp_info.pool); } /* Self destruct.. heheh.. */ pj_lock_destroy(loop->base.lock); pj_atomic_destroy(loop->base.ref_cnt); pjsip_endpt_release_pool(loop->base.endpt, loop->base.pool); return PJ_SUCCESS; }
/* * Stop the clock. */ PJ_DEF(pj_status_t) pjmedia_clock_stop(pjmedia_clock *clock) { PJ_ASSERT_RETURN(clock != NULL, PJ_EINVAL); clock->running = PJ_FALSE; clock->quitting = PJ_TRUE; if (clock->thread) { // printf("%s:------------1--------------, 0x%02x, %d\n", THIS_FILE, clock, (int)(clock->quitting)); if (pj_thread_join(clock->thread) == PJ_SUCCESS) { // printf("%s:------------2--------------\n", THIS_FILE); pj_thread_destroy(clock->thread); clock->thread = NULL; pj_pool_reset(clock->pool); } else { // printf("%s:------------3--------------\n", THIS_FILE); clock->quitting = PJ_FALSE; } } return PJ_SUCCESS; }
/* Destroy test session */ static void destroy_sess(struct test_sess *sess, unsigned wait_msec) { unsigned i; if (sess->caller.ice) { pj_ice_strans_destroy(sess->caller.ice); sess->caller.ice = NULL; } if (sess->callee.ice) { pj_ice_strans_destroy(sess->callee.ice); sess->callee.ice = NULL; } sess->param->worker_quit = PJ_TRUE; for (i=0; i<sess->param->worker_cnt; ++i) { if (sess->worker_threads[i]) pj_thread_join(sess->worker_threads[i]); } poll_events(sess->stun_cfg, wait_msec, PJ_FALSE); if (sess->resolver) { pj_dns_resolver_destroy(sess->resolver, PJ_FALSE); sess->resolver = NULL; } if (sess->server) { destroy_test_server(sess->server); sess->server = NULL; } if (sess->pool) { pj_pool_t *pool = sess->pool; sess->pool = NULL; pj_pool_release(pool); } }
static int client_shutdown() { unsigned i; if (g.thread) { g.quit = 1; pj_thread_join(g.thread); pj_thread_destroy(g.thread); g.thread = NULL; } if (g.relay) { pj_turn_sock_destroy(g.relay); g.relay = NULL; } for (i=0; i<PJ_ARRAY_SIZE(g.peer); ++i) { if (g.peer[i].stun_sock) { pj_stun_sock_destroy(g.peer[i].stun_sock); g.peer[i].stun_sock = NULL; } } if (g.stun_config.timer_heap) { pj_timer_heap_destroy(g.stun_config.timer_heap); g.stun_config.timer_heap = NULL; } if (g.stun_config.ioqueue) { pj_ioqueue_destroy(g.stun_config.ioqueue); g.stun_config.ioqueue = NULL; } if (g.pool) { pj_pool_release(g.pool); g.pool = NULL; } pj_pool_factory_dump(&g.cp.factory, PJ_TRUE); pj_caching_pool_destroy(&g.cp); return PJ_SUCCESS; }
int main() { pj_caching_pool cp; pj_pool_t *pool; int i; pj_thread_t *thread1; pj_log_set_level(3); CHECK(__FILE__, pj_init()); pj_srand(123765); pj_caching_pool_init(&cp, NULL, 1024); pool = pj_pool_create(&cp.factory, "objpool", 128, 128, NULL); pj_thread_create(pool, "thread1", &do_test, pool, PJ_THREAD_DEFAULT_STACK_SIZE, 0, &thread1); pj_thread_sleep(500); do_test(pool); pj_thread_join(thread1); pj_pool_release(pool); pj_caching_pool_destroy(&cp); pj_shutdown(); return 0; }
/* API: start stream */ static pj_status_t alsa_stream_start (pjmedia_aud_stream *s) { struct alsa_stream *stream = (struct alsa_stream*)s; pj_status_t status = PJ_SUCCESS; stream->quit = 0; if (stream->param.dir & PJMEDIA_DIR_PLAYBACK) { status = pj_thread_create (stream->pool, "alsasound_playback", pb_thread_func, stream, 0, //ZERO, 0, &stream->pb_thread); if (status != PJ_SUCCESS) return status; } if (stream->param.dir & PJMEDIA_DIR_CAPTURE) { status = pj_thread_create (stream->pool, "alsasound_playback", ca_thread_func, stream, 0, //ZERO, 0, &stream->ca_thread); if (status != PJ_SUCCESS) { stream->quit = PJ_TRUE; pj_thread_join(stream->pb_thread); pj_thread_destroy(stream->pb_thread); stream->pb_thread = NULL; } } return status; }
int transport_rt_test( pjsip_transport_type_e tp_type, pjsip_transport *ref_tp, char *target_url, int *lost) { enum { THREADS = 4, INTERVAL = 10 }; int i; pj_status_t status; pj_pool_t *pool; pj_bool_t logger_enabled; pj_timestamp zero_time, total_time; unsigned usec_rt; unsigned total_sent; unsigned total_recv; PJ_UNUSED_ARG(tp_type); PJ_UNUSED_ARG(ref_tp); PJ_LOG(3,(THIS_FILE, " multithreaded round-trip test (%d threads)...", THREADS)); PJ_LOG(3,(THIS_FILE, " this will take approx %d seconds, please wait..", INTERVAL)); /* Make sure msg logger is disabled. */ logger_enabled = msg_logger_set_enabled(0); /* Register module (if not yet registered) */ if (rt_module.id == -1) { status = pjsip_endpt_register_module( endpt, &rt_module ); if (status != PJ_SUCCESS) { app_perror(" error: unable to register module", status); return -600; } } /* Create pool for this test. */ pool = pjsip_endpt_create_pool(endpt, NULL, 4000, 4000); if (!pool) return -610; /* Initialize static test data. */ pj_ansi_strcpy(rt_target_uri, target_url); rt_call_id = pj_str("RT-Call-Id/"); rt_stop = PJ_FALSE; /* Initialize thread data. */ for (i=0; i<THREADS; ++i) { char buf[1]; pj_str_t str_id; pj_strset(&str_id, buf, 1); pj_bzero(&rt_test_data[i], sizeof(rt_test_data[i])); /* Init timer entry */ rt_test_data[i].tx_timer.id = i; rt_test_data[i].tx_timer.cb = &rt_tx_timer; rt_test_data[i].timeout_timer.id = i; rt_test_data[i].timeout_timer.cb = &rt_timeout_timer; /* Generate Call-ID for each thread. */ rt_test_data[i].call_id.ptr = (char*) pj_pool_alloc(pool, rt_call_id.slen+1); pj_strcpy(&rt_test_data[i].call_id, &rt_call_id); buf[0] = '0' + (char)i; pj_strcat(&rt_test_data[i].call_id, &str_id); /* Init mutex. */ status = pj_mutex_create_recursive(pool, "rt", &rt_test_data[i].mutex); if (status != PJ_SUCCESS) { app_perror(" error: unable to create mutex", status); return -615; } /* Create thread, suspended. */ status = pj_thread_create(pool, "rttest%p", &rt_worker_thread, (void*)(long)i, 0, PJ_THREAD_SUSPENDED, &rt_test_data[i].thread); if (status != PJ_SUCCESS) { app_perror(" error: unable to create thread", status); return -620; } } /* Start threads! */ for (i=0; i<THREADS; ++i) { pj_time_val delay = {0,0}; pj_thread_resume(rt_test_data[i].thread); /* Schedule first message transmissions. */ rt_test_data[i].tx_timer.user_data = (void*)1; pjsip_endpt_schedule_timer(endpt, &rt_test_data[i].tx_timer, &delay); } /* Sleep for some time. */ pj_thread_sleep(INTERVAL * 1000); /* Signal thread to stop. */ rt_stop = PJ_TRUE; /* Wait threads to complete. */ for (i=0; i<THREADS; ++i) { pj_thread_join(rt_test_data[i].thread); pj_thread_destroy(rt_test_data[i].thread); } /* Destroy rt_test_data */ for (i=0; i<THREADS; ++i) { pj_mutex_destroy(rt_test_data[i].mutex); pjsip_endpt_cancel_timer(endpt, &rt_test_data[i].timeout_timer); } /* Gather statistics. */ pj_bzero(&total_time, sizeof(total_time)); pj_bzero(&zero_time, sizeof(zero_time)); usec_rt = total_sent = total_recv = 0; for (i=0; i<THREADS; ++i) { total_sent += rt_test_data[i].sent_request_count; total_recv += rt_test_data[i].recv_response_count; pj_add_timestamp(&total_time, &rt_test_data[i].total_rt_time); } /* Display statistics. */ if (total_recv) total_time.u64 = total_time.u64/total_recv; else total_time.u64 = 0; usec_rt = pj_elapsed_usec(&zero_time, &total_time); PJ_LOG(3,(THIS_FILE, " done.")); PJ_LOG(3,(THIS_FILE, " total %d messages sent", total_sent)); PJ_LOG(3,(THIS_FILE, " average round-trip=%d usec", usec_rt)); pjsip_endpt_release_pool(endpt, pool); *lost = total_sent-total_recv; /* Flush events. */ flush_events(500); /* Restore msg logger. */ msg_logger_set_enabled(logger_enabled); return 0; }
/* * timeslice_test() */ static int timeslice_test(void) { enum { NUM_THREADS = 4 }; pj_pool_t *pool; pj_uint32_t counter[NUM_THREADS], lowest, highest, diff; pj_thread_t *thread[NUM_THREADS]; unsigned i; pj_status_t rc; quit_flag = 0; pool = pj_pool_create(mem, NULL, 4000, 4000, NULL); if (!pool) return -10; PJ_LOG(3,(THIS_FILE, "..timeslice testing with %d threads", NUM_THREADS)); /* Create all threads in suspended mode. */ for (i=0; i<NUM_THREADS; ++i) { counter[i] = i; rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc, &counter[i], PJ_THREAD_DEFAULT_STACK_SIZE, PJ_THREAD_SUSPENDED, &thread[i]); if (rc!=PJ_SUCCESS) { app_perror("...ERROR in pj_thread_create()", rc); return -20; } } /* Sleep for 1 second. * The purpose of this is to test whether all threads are suspended. */ TRACE__((THIS_FILE, " Main thread waiting..")); pj_thread_sleep(1000); TRACE__((THIS_FILE, " Main thread resuming..")); /* Check that all counters are still zero. */ for (i=0; i<NUM_THREADS; ++i) { if (counter[i] > i) { PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!", i)); return -30; } } /* Now resume all threads. */ for (i=0; i<NUM_THREADS; ++i) { TRACE__((THIS_FILE, " Resuming thread %d [%p]..", i, thread[i])); rc = pj_thread_resume(thread[i]); if (rc != PJ_SUCCESS) { app_perror("...ERROR in pj_thread_resume()", rc); return -40; } } /* Main thread sleeps for some time to allow threads to run. * The longer we sleep, the more accurate the calculation will be, * but it'll make user waits for longer for the test to finish. */ TRACE__((THIS_FILE, " Main thread waiting (5s)..")); pj_thread_sleep(5000); TRACE__((THIS_FILE, " Main thread resuming..")); /* Signal all threads to quit. */ quit_flag = 1; /* Wait until all threads quit, then destroy. */ for (i=0; i<NUM_THREADS; ++i) { TRACE__((THIS_FILE, " Main thread joining thread %d [%p]..", i, thread[i])); rc = pj_thread_join(thread[i]); if (rc != PJ_SUCCESS) { app_perror("...ERROR in pj_thread_join()", rc); return -50; } TRACE__((THIS_FILE, " Destroying thread %d [%p]..", i, thread[i])); rc = pj_thread_destroy(thread[i]); if (rc != PJ_SUCCESS) { app_perror("...ERROR in pj_thread_destroy()", rc); return -60; } } TRACE__((THIS_FILE, " Main thread calculating time slices..")); /* Now examine the value of the counters. * Check that all threads had equal proportion of processing. */ lowest = 0xFFFFFFFF; highest = 0; for (i=0; i<NUM_THREADS; ++i) { if (counter[i] < lowest) lowest = counter[i]; if (counter[i] > highest) highest = counter[i]; } /* Check that all threads are running. */ if (lowest < 2) { PJ_LOG(3,(THIS_FILE, "...ERROR: not all threads were running!")); return -70; } /* The difference between lowest and higest should be lower than 50%. */ diff = (highest-lowest)*100 / ((highest+lowest)/2); if ( diff >= 50) { PJ_LOG(3,(THIS_FILE, "...ERROR: thread didn't have equal timeslice!")); PJ_LOG(3,(THIS_FILE, ".....lowest counter=%u, highest counter=%u, diff=%u%%", lowest, highest, diff)); return -80; } else { PJ_LOG(3,(THIS_FILE, "...info: timeslice diff between lowest & highest=%u%%", diff)); } pj_pool_release(pool); return 0; }
/* * simple_thread() */ static int simple_thread(const char *title, unsigned flags) { pj_pool_t *pool; pj_thread_t *thread; pj_status_t rc; pj_uint32_t counter = 0; PJ_LOG(3,(THIS_FILE, "..%s", title)); pool = pj_pool_create(mem, NULL, 4000, 4000, NULL); if (!pool) return -1000; quit_flag = 0; TRACE__((THIS_FILE, " Creating thread 0..")); rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc, &counter, PJ_THREAD_DEFAULT_STACK_SIZE, flags, &thread); if (rc != PJ_SUCCESS) { app_perror("...error: unable to create thread", rc); return -1010; } TRACE__((THIS_FILE, " Main thread waiting..")); pj_thread_sleep(1500); TRACE__((THIS_FILE, " Main thread resuming..")); if (flags & PJ_THREAD_SUSPENDED) { /* Check that counter is still zero */ if (counter != 0) { PJ_LOG(3,(THIS_FILE, "...error: thread is not suspended")); return -1015; } rc = pj_thread_resume(thread); if (rc != PJ_SUCCESS) { app_perror("...error: resume thread error", rc); return -1020; } } PJ_LOG(3,(THIS_FILE, "..waiting for thread to quit..")); pj_thread_sleep(1500); quit_flag = 1; pj_thread_join(thread); pj_pool_release(pool); if (counter == 0) { PJ_LOG(3,(THIS_FILE, "...error: thread is not running")); return -1025; } PJ_LOG(3,(THIS_FILE, "...%s success", title)); return PJ_SUCCESS; }
/* Calculate the bandwidth for the specific test configuration. * The test is simple: * - create sockpair_cnt number of producer-consumer socket pair. * - create thread_cnt number of worker threads. * - each producer will send buffer_size bytes data as fast and * as soon as it can. * - each consumer will read buffer_size bytes of data as fast * as it could. * - measure the total bytes received by all consumers during a * period of time. */ static int perform_test(pj_bool_t allow_concur, int sock_type, const char *type_name, unsigned thread_cnt, unsigned sockpair_cnt, pj_size_t buffer_size, pj_size_t *p_bandwidth) { enum { MSEC_DURATION = 5000 }; pj_pool_t *pool; test_item *items; pj_thread_t **thread; pj_ioqueue_t *ioqueue; pj_status_t rc; pj_ioqueue_callback ioqueue_callback; pj_uint32_t total_elapsed_usec, total_received; pj_highprec_t bandwidth; pj_timestamp start, stop; unsigned i; TRACE_((THIS_FILE, " starting test..")); ioqueue_callback.on_read_complete = &on_read_complete; ioqueue_callback.on_write_complete = &on_write_complete; thread_quit_flag = 0; pool = pj_pool_create(mem, NULL, 4096, 4096, NULL); if (!pool) return -10; items = (test_item*) pj_pool_alloc(pool, sockpair_cnt*sizeof(test_item)); thread = (pj_thread_t**) pj_pool_alloc(pool, thread_cnt*sizeof(pj_thread_t*)); TRACE_((THIS_FILE, " creating ioqueue..")); rc = pj_ioqueue_create(pool, sockpair_cnt*2, &ioqueue); if (rc != PJ_SUCCESS) { app_perror("...error: unable to create ioqueue", rc); return -15; } rc = pj_ioqueue_set_default_concurrency(ioqueue, allow_concur); if (rc != PJ_SUCCESS) { app_perror("...error: pj_ioqueue_set_default_concurrency()", rc); return -16; } /* Initialize each producer-consumer pair. */ for (i=0; i<sockpair_cnt; ++i) { pj_ssize_t bytes; items[i].ioqueue = ioqueue; items[i].buffer_size = buffer_size; items[i].outgoing_buffer = (char*) pj_pool_alloc(pool, buffer_size); items[i].incoming_buffer = (char*) pj_pool_alloc(pool, buffer_size); items[i].bytes_recv = items[i].bytes_sent = 0; /* randomize outgoing buffer. */ pj_create_random_string(items[i].outgoing_buffer, buffer_size); /* Create socket pair. */ TRACE_((THIS_FILE, " calling socketpair..")); rc = app_socketpair(pj_AF_INET(), sock_type, 0, &items[i].server_fd, &items[i].client_fd); if (rc != PJ_SUCCESS) { app_perror("...error: unable to create socket pair", rc); return -20; } /* Register server socket to ioqueue. */ TRACE_((THIS_FILE, " register(1)..")); rc = pj_ioqueue_register_sock(pool, ioqueue, items[i].server_fd, &items[i], &ioqueue_callback, &items[i].server_key); if (rc != PJ_SUCCESS) { app_perror("...error: registering server socket to ioqueue", rc); return -60; } /* Register client socket to ioqueue. */ TRACE_((THIS_FILE, " register(2)..")); rc = pj_ioqueue_register_sock(pool, ioqueue, items[i].client_fd, &items[i], &ioqueue_callback, &items[i].client_key); if (rc != PJ_SUCCESS) { app_perror("...error: registering server socket to ioqueue", rc); return -70; } /* Start reading. */ TRACE_((THIS_FILE, " pj_ioqueue_recv..")); bytes = items[i].buffer_size; rc = pj_ioqueue_recv(items[i].server_key, &items[i].recv_op, items[i].incoming_buffer, &bytes, 0); if (rc != PJ_EPENDING) { app_perror("...error: pj_ioqueue_recv", rc); return -73; } /* Start writing. */ TRACE_((THIS_FILE, " pj_ioqueue_write..")); bytes = items[i].buffer_size; rc = pj_ioqueue_send(items[i].client_key, &items[i].send_op, items[i].outgoing_buffer, &bytes, 0); if (rc != PJ_SUCCESS && rc != PJ_EPENDING) { app_perror("...error: pj_ioqueue_write", rc); return -76; } items[i].has_pending_send = (rc==PJ_EPENDING); } /* Create the threads. */ for (i=0; i<thread_cnt; ++i) { struct thread_arg *arg; arg = (struct thread_arg*) pj_pool_zalloc(pool, sizeof(*arg)); arg->id = i; arg->ioqueue = ioqueue; arg->counter = 0; rc = pj_thread_create( pool, NULL, &worker_thread, arg, PJ_THREAD_DEFAULT_STACK_SIZE, PJ_THREAD_SUSPENDED, &thread[i] ); if (rc != PJ_SUCCESS) { app_perror("...error: unable to create thread", rc); return -80; } } /* Mark start time. */ rc = pj_get_timestamp(&start); if (rc != PJ_SUCCESS) return -90; /* Start the thread. */ TRACE_((THIS_FILE, " resuming all threads..")); for (i=0; i<thread_cnt; ++i) { rc = pj_thread_resume(thread[i]); if (rc != 0) return -100; } /* Wait for MSEC_DURATION seconds. * This should be as simple as pj_thread_sleep(MSEC_DURATION) actually, * but unfortunately it doesn't work when system doesn't employ * timeslicing for threads. */ TRACE_((THIS_FILE, " wait for few seconds..")); do { pj_thread_sleep(1); /* Mark end time. */ rc = pj_get_timestamp(&stop); if (thread_quit_flag) { TRACE_((THIS_FILE, " transfer limit reached..")); break; } if (pj_elapsed_usec(&start,&stop)<MSEC_DURATION * 1000) { TRACE_((THIS_FILE, " time limit reached..")); break; } } while (1); /* Terminate all threads. */ TRACE_((THIS_FILE, " terminating all threads..")); thread_quit_flag = 1; for (i=0; i<thread_cnt; ++i) { TRACE_((THIS_FILE, " join thread %d..", i)); pj_thread_join(thread[i]); } /* Close all sockets. */ TRACE_((THIS_FILE, " closing all sockets..")); for (i=0; i<sockpair_cnt; ++i) { pj_ioqueue_unregister(items[i].server_key); pj_ioqueue_unregister(items[i].client_key); } /* Destroy threads */ for (i=0; i<thread_cnt; ++i) { pj_thread_destroy(thread[i]); } /* Destroy ioqueue. */ TRACE_((THIS_FILE, " destroying ioqueue..")); pj_ioqueue_destroy(ioqueue); /* Calculate actual time in usec. */ total_elapsed_usec = pj_elapsed_usec(&start, &stop); /* Calculate total bytes received. */ total_received = 0; for (i=0; i<sockpair_cnt; ++i) { total_received = (pj_uint32_t)items[i].bytes_recv; } /* bandwidth = total_received*1000/total_elapsed_usec */ bandwidth = total_received; pj_highprec_mul(bandwidth, 1000); pj_highprec_div(bandwidth, total_elapsed_usec); *p_bandwidth = (pj_uint32_t)bandwidth; PJ_LOG(3,(THIS_FILE, " %.4s %2d %2d %8d KB/s", type_name, thread_cnt, sockpair_cnt, *p_bandwidth)); /* Done. */ pj_pool_release(pool); TRACE_((THIS_FILE, " done..")); return 0; }