int rtpp_proc_async_init(struct cfg *cf) { struct rtpp_proc_async_cf *proc_cf; proc_cf = malloc(sizeof(*proc_cf)); if (proc_cf == NULL) return (-1); memset(proc_cf, '\0', sizeof(*proc_cf)); init_rstats(cf->stable->rtpp_stats, &proc_cf->rstats); #if RTPP_DEBUG recfilter_init(&proc_cf->sleep_time, 0.999, 0.0, 0); recfilter_init(&proc_cf->poll_time, 0.999, 0.0, 0); recfilter_init(&proc_cf->proc_time, 0.999, 0.0, 0); #endif proc_cf->time_q = rtpp_queue_init(1, "RTP_PROC(time)"); if (proc_cf->time_q == NULL) { free(proc_cf); return (-1); } proc_cf->op = rtpp_netio_async_init(cf, 10); if (proc_cf->op == NULL) { rtpp_queue_destroy(proc_cf->time_q); free(proc_cf); return (-1); } cf->stable->rtpp_proc_cf = proc_cf; if (pthread_create(&proc_cf->thread_id, NULL, (void *(*)(void *))&rtpp_proc_async_run, cf) != 0) { rtpp_queue_destroy(proc_cf->time_q); rtpp_netio_async_destroy(proc_cf->op); free(proc_cf); cf->stable->rtpp_proc_cf = NULL; return (-1); } return (0); }
int main(int argc, char **argv) { int i, len, controlfd; double eval, clk; long long ncycles_ref, counter; double eptime; double add_delay; struct cfg cf; char buf[256]; struct recfilter loop_error; struct PFD phase_detector; useconds_t usleep_time; struct sched_param sparam; #if RTPP_DEBUG double sleep_time, filter_lastval; #endif memset(&cf, 0, sizeof(cf)); cf.stable = malloc(sizeof(struct rtpp_cfg_stable)); if (cf.stable == NULL) { err(1, "can't allocate memory for the struct rtpp_cfg_stable"); /* NOTREACHED */ } memset(cf.stable, '\0', sizeof(struct rtpp_cfg_stable)); init_config(&cf, argc, argv); seedrandom(); cf.stable->sessions_ht = rtpp_hash_table_ctor(); if (cf.stable->sessions_ht == NULL) { err(1, "can't allocate memory for the hash table"); /* NOTREACHED */ } cf.stable->rtpp_stats = rtpp_stats_ctor(); if (cf.stable->rtpp_stats == NULL) { err(1, "can't allocate memory for the stats data"); /* NOTREACHED */ } init_port_table(&cf); controlfd = init_controlfd(&cf); if (cf.stable->nodaemon == 0) { if (rtpp_daemon(0, 0) == -1) err(1, "can't switch into daemon mode"); /* NOTREACHED */ } if (rtpp_notify_init() != 0) errx(1, "can't start notification thread"); cf.stable->glog = rtpp_log_open(cf.stable, "rtpproxy", NULL, LF_REOPEN); rtpp_log_setlevel(cf.stable->glog, cf.stable->log_level); _sig_cf = &cf; atexit(ehandler); rtpp_log_write(RTPP_LOG_INFO, cf.stable->glog, "rtpproxy started, pid %d", getpid()); i = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE); if (i >= 0) { len = sprintf(buf, "%u\n", (unsigned int)getpid()); write(i, buf, len); close(i); } else { rtpp_log_ewrite(RTPP_LOG_ERR, cf.stable->glog, "can't open pidfile for writing"); } signal(SIGHUP, sighup); signal(SIGINT, fatsignal); signal(SIGKILL, fatsignal); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, fatsignal); signal(SIGXCPU, fatsignal); signal(SIGXFSZ, fatsignal); signal(SIGVTALRM, fatsignal); signal(SIGPROF, fatsignal); signal(SIGUSR1, fatsignal); signal(SIGUSR2, fatsignal); if (cf.stable->sched_policy != SCHED_OTHER) { sparam.sched_priority = sched_get_priority_max(cf.stable->sched_policy); if (sched_setscheduler(0, cf.stable->sched_policy, &sparam) == -1) { rtpp_log_ewrite(RTPP_LOG_ERR, cf.stable->glog, "sched_setscheduler(SCHED_%s, %d)", (cf.stable->sched_policy == SCHED_FIFO) ? "FIFO" : "RR", sparam.sched_priority); } } if (cf.stable->run_uname != NULL || cf.stable->run_gname != NULL) { if (drop_privileges(&cf) != 0) { rtpp_log_ewrite(RTPP_LOG_ERR, cf.stable->glog, "can't switch to requested user/group"); exit(1); } } set_rlimits(&cf); cf.stable->controlfd = controlfd; cf.sessinfo.sessions[0] = NULL; cf.sessinfo.nsessions = 0; cf.rtp_nsessions = 0; rtpp_command_async_init(&cf); rtpp_proc_async_init(&cf); counter = 0; recfilter_init(&loop_error, 0.96, 0.0, 0); PFD_init(&phase_detector, 2.0); for (;;) { eptime = getdtime(); clk = (eptime + cf.stable->sched_offset) * cf.stable->target_pfreq; ncycles_ref = llrint(clk); eval = PFD_get_error(&phase_detector, clk); #if RTPP_DEBUG filter_lastval = loop_error.lastval; #endif if (eval != 0.0) { recfilter_apply(&loop_error, sigmoid(eval)); } #if RTPP_DEBUG if (counter % (unsigned int)cf.stable->target_pfreq == 0 || counter < 1000) { rtpp_log_write(RTPP_LOG_DBUG, cf.stable->glog, "run %lld ncycles %f raw error1 %f, filter lastval %f, filter nextval %f", counter, clk, eval, filter_lastval, loop_error.lastval); } #endif add_delay = freqoff_to_period(cf.stable->target_pfreq, 1.0, loop_error.lastval); usleep_time = add_delay * 1000000.0; #if RTPP_DEBUG if (counter % (unsigned int)cf.stable->target_pfreq == 0 || counter < 1000) { rtpp_log_write(RTPP_LOG_DBUG, cf.stable->glog, "run %lld filter lastval %f, filter nextval %f, error %f", counter, filter_lastval, loop_error.lastval, sigmoid(eval)); rtpp_log_write(RTPP_LOG_DBUG, cf.stable->glog, "run %lld extra sleeping time %llu", counter, usleep_time); } sleep_time = getdtime(); #endif rtpp_proc_async_wakeup(cf.stable->rtpp_proc_cf, counter, ncycles_ref); usleep(usleep_time); #if RTPP_DEBUG sleep_time = getdtime() - sleep_time; if (counter % (unsigned int)cf.stable->target_pfreq == 0 || counter < 1000 || sleep_time > add_delay * 2.0) { rtpp_log_write(RTPP_LOG_DBUG, cf.stable->glog, "run %lld sleeping time required %llu sleeping time actual %f, CSV: %f,%f,%f", \ counter, usleep_time, sleep_time, (double)counter / cf.stable->target_pfreq, ((double)usleep_time) / 1000.0, sleep_time * 1000.0); } #endif counter += 1; if (cf.stable->slowshutdown != 0) { pthread_mutex_lock(&cf.sessinfo.lock); if (cf.sessinfo.nsessions == 0) { /* The below unlock is not necessary, but does not hurt either */ pthread_mutex_unlock(&cf.sessinfo.lock); rtpp_log_write(RTPP_LOG_INFO, cf.stable->glog, "deorbiting-burn sequence completed, exiting"); break; } pthread_mutex_unlock(&cf.sessinfo.lock); } } exit(0); }
struct rtpp_cmd_async_obj * rtpp_command_async_ctor(struct cfg *cf) { struct rtpp_cmd_async_cf *cmd_cf; int need_acptr, i; cmd_cf = malloc(sizeof(*cmd_cf)); if (cmd_cf == NULL) goto e0; memset(cmd_cf, '\0', sizeof(*cmd_cf)); if (init_pollset(cf, &cmd_cf->pset) == -1) { goto e1; } need_acptr = init_accptset(cf, &cmd_cf->aset); if (need_acptr == -1) { goto e2; } init_cstats(cf->stable->rtpp_stats, &cmd_cf->cstats); if (pthread_cond_init(&cmd_cf->cmd_cond, NULL) != 0) { goto e3; } if (pthread_mutex_init(&cmd_cf->cmd_mutex, NULL) != 0) { goto e4; } assert(cf->stable->rtpp_timed_cf != NULL); cmd_cf->rcache = rtpp_cmd_rcache_ctor(cf->stable->rtpp_timed_cf, 30.0); if (cmd_cf->rcache == NULL) { goto e5; } #if 0 recfilter_init(&cmd_cf->average_load, 0.999, 0.0, 1); #endif cmd_cf->cf_save = cf; if (need_acptr != 0) { if (pthread_create(&cmd_cf->acpt_thread_id, NULL, (void *(*)(void *))&rtpp_cmd_acceptor_run, cmd_cf) != 0) { goto e6; } cmd_cf->acceptor_started = 1; } if (pthread_create(&cmd_cf->thread_id, NULL, (void *(*)(void *))&rtpp_cmd_queue_run, cmd_cf) != 0) { goto e7; } cmd_cf->pub.dtor = &rtpp_command_async_dtor; cmd_cf->pub.wakeup = &rtpp_command_async_wakeup; cmd_cf->pub.get_aload = &rtpp_command_async_get_aload; return (&cmd_cf->pub); e7: if (cmd_cf->acceptor_started != 0) { for (i = 0; i < cmd_cf->aset.pfds_used; i ++) { close(cmd_cf->aset.pfds[i].fd); } pthread_join(cmd_cf->acpt_thread_id, NULL); } e6: CALL_METHOD(cmd_cf->rcache, dtor); e5: pthread_mutex_destroy(&cmd_cf->cmd_mutex); e4: pthread_cond_destroy(&cmd_cf->cmd_cond); e3: free_accptset(&cmd_cf->aset); e2: free_pollset(&cmd_cf->pset); e1: free(cmd_cf); e0: return (NULL); }
struct rtpp_anetio_cf * rtpp_netio_async_init(struct cfg *cf, int qlen) { struct rtpp_anetio_cf *netio_cf; int i, ri; netio_cf = rtpp_zmalloc(sizeof(*netio_cf)); if (netio_cf == NULL) return (NULL); for (i = 0; i < SEND_THREADS; i++) { netio_cf->args[i].out_q = rtpp_queue_init(qlen, "RTPP->NET%.2d", i); if (netio_cf->args[i].out_q == NULL) { for (ri = i - 1; ri >= 0; ri--) { rtpp_queue_destroy(netio_cf->args[ri].out_q); } goto e0; } netio_cf->args[i].glog = cf->stable->glog; netio_cf->args[i].dmode = cf->stable->dmode; #ifdef RTPP_DEBUG recfilter_init(&netio_cf->args[i].average_load, 0.9, 0.0, 0); #endif } for (i = 0; i < SEND_THREADS; i++) { netio_cf->args[i].sigterm = rtpp_wi_malloc_sgnl(SIGTERM, NULL, 0); if (netio_cf->args[i].sigterm == NULL) { for (ri = i - 1; ri >= 0; ri--) { rtpp_wi_free(netio_cf->args[ri].sigterm); } goto e1; } } cf->stable->rtpp_netio_cf = netio_cf; for (i = 0; i < SEND_THREADS; i++) { if (pthread_create(&(netio_cf->thread_id[i]), NULL, (void *(*)(void *))&rtpp_anetio_sthread, &netio_cf->args[i]) != 0) { for (ri = i - 1; ri >= 0; ri--) { rtpp_queue_put_item(netio_cf->args[ri].sigterm, netio_cf->args[ri].out_q); pthread_join(netio_cf->thread_id[ri], NULL); } for (ri = i; ri < SEND_THREADS; ri++) { rtpp_wi_free(netio_cf->args[ri].sigterm); } goto e1; } } return (netio_cf); #if 0 e2: for (i = 0; i < SEND_THREADS; i++) { rtpp_wi_free(netio_cf->args[i].sigterm); } #endif e1: for (i = 0; i < SEND_THREADS; i++) { rtpp_queue_destroy(netio_cf->args[i].out_q); } e0: free(netio_cf); return (NULL); }