00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #define _BSD_SOURCE
00016 #include <unistd.h>
00017 #ifndef __USE_POSIX199309
00018 #define __USE_POSIX199309
00019 #endif
00020 #include <time.h>
00021 #include "iaxclient_lib.h"
00022
00023 #if TIME_WITH_SYS_TIME
00024 # include <sys/time.h>
00025 # include <time.h>
00026 #else
00027 # if HAVE_SYS_TIME_H
00028 # include <sys/time.h>
00029 # else
00030 # include <time.h>
00031 # endif
00032 #endif
00033
00034 #ifndef NULL
00035 #define NULL (0)
00036 #endif
00037
00038
00039
00040 void os_init(void)
00041 {
00042 }
00043
00044 void iaxc_millisleep(long ms)
00045 {
00046 struct timespec req;
00047
00048 req.tv_nsec = (ms%1000)*1000*1000;
00049 req.tv_sec = ms/1000;
00050
00051
00052 nanosleep(&req,NULL);
00053 }
00054
00055
00056
00057 int iaxci_post_event_callback(iaxc_event ev)
00058 {
00059 #if 0
00060 iaxc_event *e;
00061 e = malloc(sizeof(ev));
00062 *e = ev;
00063
00064
00065 PostMessage(post_event_handle,post_event_id,(WPARAM) NULL, (LPARAM) e);
00066 #endif
00067 return 0;
00068 }
00069
00070 #ifdef MACOSX
00071
00072
00073
00074
00075
00076
00077
00078 #include <mach/mach.h>
00079
00080 int iaxci_prioboostbegin()
00081 {
00082 struct thread_time_constraint_policy ttcpolicy;
00083 int params [2] = {CTL_HW,HW_BUS_FREQ};
00084 int hzms;
00085 size_t sz;
00086 int ret;
00087
00088
00089 sz = sizeof (hzms);
00090 sysctl (params, 2, &hzms, &sz, NULL, 0);
00091
00092
00093 hzms /= 1000;
00094
00095
00096 ttcpolicy.period = 10 * hzms;
00097 ttcpolicy.computation = 2 * hzms;
00098 ttcpolicy.constraint = 3 * hzms;
00099 ttcpolicy.preemptible = 1;
00100
00101 if ( (ret = thread_policy_set(mach_thread_self(),
00102 THREAD_TIME_CONSTRAINT_POLICY, (int *)&ttcpolicy,
00103 THREAD_TIME_CONSTRAINT_POLICY_COUNT)) != KERN_SUCCESS )
00104 {
00105 fprintf(stderr, "thread_policy_set failed: %d.\n", ret);
00106 }
00107 return 0;
00108 }
00109
00110 int iaxci_prioboostend()
00111 {
00112
00113 return 0;
00114 }
00115
00116 #else
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 #include <stdio.h>
00158 #include <sys/ioctl.h>
00159 #include <sys/time.h>
00160 #include <fcntl.h>
00161 #include <unistd.h>
00162 #include <signal.h>
00163 #include <sched.h>
00164 #include <pthread.h>
00165 #include <errno.h>
00166
00167
00168 #define DBUG(...)
00169 #define ERR_RPT(...) fprintf(stderr, __VA_ARGS__)
00170
00171 #define SCHEDULER_POLICY SCHED_RR
00172 #define WATCHDOG_INTERVAL_USEC 1000000
00173 #define WATCHDOG_MAX_SECONDS 3
00174
00175 typedef void *(*pthread_function_t)(void *);
00176
00177 typedef struct {
00178 int priority;
00179 pthread_t ThreadID;
00180
00181 struct timeval CanaryTime;
00182 int CanaryRun;
00183 pthread_t CanaryThread;
00184 int IsCanaryThreadValid;
00185
00186 int WatchDogRun;
00187 pthread_t WatchDogThread;
00188 int IsWatchDogThreadValid;
00189
00190 } prioboost;
00191
00192 static prioboost *pb;
00193
00194 static int CanaryProc( prioboost *b)
00195 {
00196 int result = 0;
00197 struct sched_param schat = { 0 };
00198
00199
00200 if( pthread_setschedparam(pthread_self(), SCHED_OTHER, &schat) != 0)
00201 return 1;
00202
00203 while( b->CanaryRun)
00204 {
00205 usleep( WATCHDOG_INTERVAL_USEC );
00206 gettimeofday( &b->CanaryTime, NULL );
00207 }
00208
00209 return result;
00210 }
00211
00212 static int WatchDogProc( prioboost *b )
00213 {
00214 struct sched_param schp = { 0 };
00215 int maxPri;
00216
00217
00218
00219 schp.sched_priority = b->priority + 4;
00220 maxPri = sched_get_priority_max(SCHEDULER_POLICY);
00221 if( schp.sched_priority > maxPri ) schp.sched_priority = maxPri;
00222
00223 if (pthread_setschedparam(pthread_self(), SCHEDULER_POLICY, &schp) != 0)
00224 {
00225 ERR_RPT("WatchDogProc: cannot set watch dog priority!\n");
00226 goto killAudio;
00227 }
00228
00229 DBUG("prioboost: WatchDog priority set to level %d!\n", schp.sched_priority);
00230
00231
00232
00233 while( b->WatchDogRun )
00234 {
00235
00236 int delta;
00237 struct timeval currentTime;
00238
00239 usleep( WATCHDOG_INTERVAL_USEC );
00240 gettimeofday( ¤tTime, NULL );
00241
00242 #if 0
00243
00244 delta = currentTime.tv_sec - b->EntryTime.tv_sec;
00245 DBUG(("WatchDogProc: audio delta = %d\n", delta ));
00246 if( delta > WATCHDOG_MAX_SECONDS )
00247 {
00248 goto killAudio;
00249 }
00250 #endif
00251
00252
00253 delta = currentTime.tv_sec - b->CanaryTime.tv_sec;
00254 DBUG("WatchDogProc: dogging, delta = %ld, mysec=%d\n", delta, currentTime.tv_sec);
00255 if( delta > WATCHDOG_MAX_SECONDS )
00256 {
00257 ERR_RPT("WatchDogProc: canary died!\n");
00258 goto lowerAudio;
00259 }
00260 }
00261
00262 DBUG("WatchDogProc: exiting.\n");
00263 return 0;
00264
00265 lowerAudio:
00266 {
00267 struct sched_param schat = { 0 };
00268 if( pthread_setschedparam(b->ThreadID, SCHED_OTHER, &schat) != 0)
00269 {
00270 ERR_RPT("WatchDogProc: failed to lower audio priority. errno = %d\n", errno );
00271
00272 }
00273 else
00274 {
00275 ERR_RPT("WatchDogProc: lowered audio priority to prevent hogging of CPU.\n");
00276 goto cleanup;
00277 }
00278 }
00279
00280 killAudio:
00281 ERR_RPT("WatchDogProc: killing hung audio thread!\n");
00282
00283
00284 exit(1);
00285
00286 cleanup:
00287 b->CanaryRun = 0;
00288 DBUG("WatchDogProc: cancel Canary\n");
00289 pthread_cancel( b->CanaryThread );
00290 DBUG("WatchDogProc: join Canary\n");
00291 pthread_join( b->CanaryThread, NULL );
00292 DBUG("WatchDogProc: forget Canary\n");
00293 b->IsCanaryThreadValid = 0;
00294
00295 #ifdef GNUSTEP
00296 GSUnregisterCurrentThread();
00297 #endif
00298 return 0;
00299 }
00300
00301 static void StopWatchDog( prioboost *b )
00302 {
00303
00304 if( b->IsWatchDogThreadValid )
00305 {
00306 b->WatchDogRun = 0;
00307 DBUG("StopWatchDog: cancel WatchDog\n");
00308 pthread_cancel( b->WatchDogThread );
00309 pthread_join( b->WatchDogThread, NULL );
00310 b->IsWatchDogThreadValid = 0;
00311 }
00312
00313 if( b->IsCanaryThreadValid )
00314 {
00315 b->CanaryRun = 0;
00316 DBUG("StopWatchDog: cancel Canary\n");
00317 pthread_cancel( b->CanaryThread );
00318 DBUG("StopWatchDog: join Canary\n");
00319 pthread_join( b->CanaryThread, NULL );
00320 b->IsCanaryThreadValid = 0;
00321 }
00322 }
00323
00324
00325 static int StartWatchDog( prioboost *b)
00326 {
00327 int hres;
00328 int result = 0;
00329
00330
00331 gettimeofday( &b->CanaryTime, NULL );
00332
00333
00334 b->CanaryRun = 1;
00335 hres = pthread_create(&(b->CanaryThread),
00336 NULL ,
00337 (pthread_function_t)CanaryProc, b);
00338 if( hres != 0 )
00339 {
00340 b->IsCanaryThreadValid = 0;
00341 result = 1;
00342 goto error;
00343 }
00344 b->IsCanaryThreadValid = 1;
00345
00346
00347 b->WatchDogRun = 1;
00348 hres = pthread_create(&(b->WatchDogThread),
00349 NULL ,
00350 (pthread_function_t)WatchDogProc, b);
00351 if( hres != 0 ) {
00352 b->IsWatchDogThreadValid = 0;
00353 result = 1;
00354 goto error;
00355 }
00356 b->IsWatchDogThreadValid = 1;
00357 return result;
00358
00359 error:
00360 StopWatchDog( b );
00361 return result;
00362 }
00363
00364 int iaxci_prioboostbegin()
00365 {
00366 struct sched_param schp = { 0 };
00367 prioboost *b = calloc(sizeof(*b),1);
00368
00369 int result = 0;
00370
00371 b->priority = (sched_get_priority_max(SCHEDULER_POLICY) -
00372 sched_get_priority_min(SCHEDULER_POLICY)) / 2;
00373 schp.sched_priority = b->priority;
00374
00375 b->ThreadID = pthread_self();
00376
00377 if (pthread_setschedparam(b->ThreadID, SCHEDULER_POLICY, &schp) != 0)
00378 {
00379 DBUG("prioboost: only superuser can use real-time priority.\n");
00380 }
00381 else
00382 {
00383 DBUG("prioboost: priority set to level %d!\n", schp.sched_priority);
00384 result = StartWatchDog( b );
00385 }
00386
00387 if(result == 0) {
00388 pb = b;
00389 } else {
00390 pb = NULL;
00391 schp.sched_priority = 0;
00392 pthread_setschedparam(b->ThreadID, SCHED_OTHER, &schp);
00393 }
00394
00395 return result;
00396 }
00397
00398 int iaxci_prioboostend()
00399 {
00400 if(pb) StopWatchDog(pb);
00401 return 0;
00402 }
00403
00404 #endif
00405