Commit eafc7656 authored by Simon Morlat's avatar Simon Morlat

implement different priorities for audio and video thread.

parent 0d6911fa
......@@ -45,6 +45,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
typedef uint64_t (*MSTickerTimeFunc)(void *);
/**
* Enum for ticker priority
**/
enum _MSTickerPrio{
MS_TICKER_PRIO_NORMAL, /**<the default OS priority for threads*/
MS_TICKER_PRIO_HIGH, /**<Increased priority: done by setpriority() or sched_setschedparams() with SCHED_RR on linux/MacOS*/
MS_TICKER_PRIO_REALTIME /**<Topmost priority, running SCHED_FIFO on linux */
};
typedef enum _MSTickerPrio MSTickerPrio;
struct _MSTicker
{
ms_mutex_t lock;
......@@ -60,6 +71,7 @@ struct _MSTicker
void *get_cur_time_data;
char *name;
double av_load; /*average load of the ticker */
MSTickerPrio prio;
bool_t run; /* flag to indicate whether the ticker must be run or not */
};
......@@ -88,6 +100,11 @@ MS2_PUBLIC MSTicker *ms_ticker_new(void);
**/
MS2_PUBLIC void ms_ticker_set_name(MSTicker *ticker, const char *name);
/**
* Set priority to the ticker
**/
MS2_PUBLIC void ms_ticker_set_priority(MSTicker *ticker, MSTickerPrio prio);
/**
* Attach a chain of filters to a ticker.
* The processing chain will be executed until ms_ticker_detach
......
......@@ -129,6 +129,24 @@ static void disable_checksums(ortp_socket_t sock){
#endif
}
MSTickerPrio __ms_get_default_prio(bool_t is_video){
const char *penv;
if (is_video){
return MS_TICKER_PRIO_NORMAL;
}
penv=getenv("MS_AUDIO_PRIO");
if (penv){
if (strcasecmp(penv,"NORMAL")==0)
return MS_TICKER_PRIO_NORMAL;
if (strcasecmp(penv,"HIGH")==0)
return MS_TICKER_PRIO_HIGH;
if (strcasecmp(penv,"REALTIME")==0)
return MS_TICKER_PRIO_REALTIME;
ms_error("Undefined priority %s", penv);
}
return MS_TICKER_PRIO_NORMAL;
}
RtpSession * create_duplex_rtpsession( int locport, bool_t ipv6){
RtpSession *rtpr;
rtpr=rtp_session_new(RTP_SESSION_SENDRECV);
......@@ -439,6 +457,7 @@ int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char
/* create ticker */
stream->ticker=ms_ticker_new();
ms_ticker_set_name(stream->ticker,"Audio MSTicker");
ms_ticker_set_priority(stream->ticker,__ms_get_default_prio(FALSE));
ms_ticker_attach(stream->ticker,stream->soundread);
ms_ticker_attach(stream->ticker,stream->rtprecv);
......
......@@ -48,7 +48,6 @@ void ms_ticker_start(MSTicker *s){
ms_thread_create(&s->thread,NULL,ms_ticker_run,s);
}
void ms_ticker_init(MSTicker *ticker)
{
ms_mutex_init(&ticker->lock,NULL);
......@@ -62,6 +61,7 @@ void ms_ticker_init(MSTicker *ticker)
ticker->get_cur_time_data=NULL;
ticker->name=ms_strdup("MSTicker");
ticker->av_load=0;
ticker->prio=MS_TICKER_PRIO_NORMAL;
ms_ticker_start(ticker);
}
......@@ -84,6 +84,10 @@ void ms_ticker_set_name(MSTicker *s, const char *name){
s->name=ms_strdup(name);
}
void ms_ticker_set_priority(MSTicker *ticker, MSTickerPrio prio){
ticker->prio=prio;
}
void ms_ticker_uninit(MSTicker *ticker)
{
ms_ticker_stop(ticker);
......@@ -254,62 +258,71 @@ static void sleepMs(int ms){
#endif
}
static int set_high_prio(void){
static int set_high_prio(MSTicker *obj){
int precision=2;
int result=0;
char* env_prio_c=NULL;
int min_prio, max_prio, env_prio;
int prio=obj->prio;
if (prio>MS_TICKER_PRIO_NORMAL){
#ifdef WIN32
MMRESULT mm;
TIMECAPS ptc;
mm=timeGetDevCaps(&ptc,sizeof(ptc));
if (mm==0){
if (ptc.wPeriodMin<(UINT)precision)
ptc.wPeriodMin=precision;
else
precision = ptc.wPeriodMin;
mm=timeBeginPeriod(ptc.wPeriodMin);
if (mm!=TIMERR_NOERROR){
ms_warning("timeBeginPeriod failed.");
MMRESULT mm;
TIMECAPS ptc;
mm=timeGetDevCaps(&ptc,sizeof(ptc));
if (mm==0){
if (ptc.wPeriodMin<(UINT)precision)
ptc.wPeriodMin=precision;
else
precision = ptc.wPeriodMin;
mm=timeBeginPeriod(ptc.wPeriodMin);
if (mm!=TIMERR_NOERROR){
ms_warning("timeBeginPeriod failed.");
}
ms_message("win32 timer resolution set to %i ms",ptc.wPeriodMin);
}else{
ms_warning("timeGetDevCaps failed.");
}
ms_message("win32 timer resolution set to %i ms",ptc.wPeriodMin);
}else{
ms_warning("timeGetDevCaps failed.");
}
if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)){
ms_warning("SetThreadPriority() failed (%d)\n", GetLastError());
}
if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)){
ms_warning("SetThreadPriority() failed (%d)\n", GetLastError());
}
#else
struct sched_param param;
memset(&param,0,sizeof(param));
min_prio = sched_get_priority_min(SCHED_RR);
max_prio = sched_get_priority_max(SCHED_RR);
env_prio_c = getenv("LINPHONE_SCHEDPRIO");
env_prio = (env_prio_c == NULL)?max_prio:atoi(env_prio_c);
env_prio = MAX(MIN(env_prio, max_prio), min_prio);
ms_message("Priority used: %d", env_prio);
param.sched_priority=env_prio;
if((result=pthread_setschedparam(pthread_self(),SCHED_RR, &param))) {
if (result==EPERM){
/*
The linux kernel has
sched_get_priority_max(SCHED_OTHER)=sched_get_priority_max(SCHED_OTHER)=0.
As long as we can't use SCHED_RR or SCHED_FIFO, the only way to increase priority of a calling thread
is to use setpriority().
*/
if (setpriority(PRIO_PROCESS,0,-20)==-1){
ms_message("MSTicker setpriority() failed: %s, nevermind.",strerror(errno));
}else{
ms_message("MSTicker priority increased to maximum.");
}
}else ms_warning("Set pthread_setschedparam failed: %s",strerror(result));
} else {
ms_message("MS ticker priority set to SCHED_RR and max (%i)",param.sched_priority);
struct sched_param param;
int policy=SCHED_RR;
memset(&param,0,sizeof(param));
if (prio==MS_TICKER_PRIO_REALTIME)
policy=SCHED_FIFO;
min_prio = sched_get_priority_min(policy);
max_prio = sched_get_priority_max(policy);
env_prio_c = getenv("MS_TICKER_SCHEDPRIO");
env_prio = (env_prio_c == NULL)?max_prio:atoi(env_prio_c);
env_prio = MAX(MIN(env_prio, max_prio), min_prio);
ms_message("Priority used: %d", env_prio);
param.sched_priority=env_prio;
if((result=pthread_setschedparam(pthread_self(),policy, &param))) {
if (result==EPERM){
/*
The linux kernel has
sched_get_priority_max(SCHED_OTHER)=sched_get_priority_max(SCHED_OTHER)=0.
As long as we can't use SCHED_RR or SCHED_FIFO, the only way to increase priority of a calling thread
is to use setpriority().
*/
if (setpriority(PRIO_PROCESS,0,-20)==-1){
ms_message("%s setpriority() failed: %s, nevermind.",obj->name,strerror(errno));
}else{
ms_message("%s priority increased to maximum.",obj->name);
}
}else ms_warning("%s: Set pthread_setschedparam failed: %s",obj->name,strerror(result));
} else {
ms_message("%s priority set to %s and value (%i)",obj->name,
policy==SCHED_FIFO ? "SCHED_FIFO" : "SCHED_RR", param.sched_priority);
}
}
#endif
return precision;
......@@ -337,7 +350,7 @@ void * ms_ticker_run(void *arg)
int precision=2;
int late;
precision = set_high_prio();
precision = set_high_prio(s);
s->ticks=1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment