00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <unistd.h>
00036 #include <sys/select.h>
00037 #include <sys/time.h>
00038 #include <sys/types.h>
00039 #include <unistd.h>
00040
00041 #include "timer.h"
00042 #include "dprint.h"
00043 #include "error.h"
00044 #include "pt.h"
00045 #include "config.h"
00046 #include "sr_module.h"
00047 #include "mem/mem.h"
00048 #include "mem/shm_mem.h"
00049
00050 #include <stdlib.h>
00051
00052
00053 struct sr_timer_process {
00054 unsigned int flags;
00055 struct sr_timer *timer_list;
00056 struct sr_timer *utimer_list;
00057 struct sr_timer_process *next;
00058 };
00059
00060
00061 static struct sr_timer_process *timer_proc_list = 0;
00062
00063 static unsigned int *jiffies=0;
00064 static utime_t *ujiffies=0;
00065 static unsigned int timer_id=0;
00066
00067
00068
00069
00070
00071 static struct sr_timer_process* new_timer_process_list(unsigned int flags)
00072 {
00073 struct sr_timer_process *tpl;
00074 struct sr_timer_process *tpl_it;
00075
00076 tpl = pkg_malloc( sizeof(struct sr_timer_process) );
00077 if (tpl==NULL) {
00078 LM_ERR("no more pkg memory\n");
00079 return 0;
00080 }
00081 memset( tpl, 0, sizeof(struct sr_timer_process));
00082 tpl->flags = flags;
00083
00084 if (timer_proc_list==NULL) {
00085 timer_proc_list = tpl;
00086 } else {
00087 for(tpl_it=timer_proc_list ; tpl_it->next ; tpl_it=tpl_it->next);
00088 tpl_it->next = tpl;
00089 }
00090
00091 return tpl;
00092 }
00093
00094
00095
00096
00097
00098
00099 int init_timer(void)
00100 {
00101 jiffies = shm_malloc(sizeof(unsigned int));
00102 ujiffies = shm_malloc(sizeof(utime_t));
00103
00104 if (jiffies==0 || ujiffies==0){
00105 LM_CRIT("could not init jiffies\n");
00106 return E_OUT_OF_MEM;
00107 }
00108
00109 if (UTIMER_TICK>TIMER_TICK*1000000) {
00110 LM_CRIT("UTIMER > TIMER!!\n");
00111 return E_CFG;
00112 }
00113
00114 if ( ((TIMER_TICK*1000000) % UTIMER_TICK)!=0 ) {
00115 LM_CRIT("TIMER must be multiple of UTIMER!!\n");
00116 return E_CFG;
00117 }
00118
00119 *jiffies=0;
00120 *ujiffies=0;
00121
00122
00123 if (new_timer_process_list(TIMER_PROC_INIT_FLAG)==NULL) {
00124 LM_ERR("failed to create default timer process list\n");
00125 return E_OUT_OF_MEM;
00126 }
00127
00128 return 0;
00129 }
00130
00131
00132
00133
00134
00135 void destroy_timer(void)
00136 {
00137 if (jiffies){
00138 shm_free(jiffies); jiffies=0;
00139 shm_free(ujiffies); ujiffies=0;
00140 }
00141 }
00142
00143
00144
00145
00146
00147
00148 static inline struct sr_timer* new_sr_timer(timer_function f,
00149 void* param, unsigned int interval)
00150 {
00151 struct sr_timer* t;
00152
00153 t=pkg_malloc(sizeof(struct sr_timer));
00154 if (t==0){
00155 LM_ERR("out of pkg memory\n");
00156 return NULL;
00157 }
00158 t->id=timer_id++;
00159 t->u.timer_f=f;
00160 t->t_param=param;
00161 t->interval=interval;
00162 t->expires=*jiffies+interval;
00163 return t;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173 int register_timer(timer_function f, void* param, unsigned int interval)
00174 {
00175 struct sr_timer* t;
00176
00177 t = new_sr_timer( f, param, interval);
00178 if (t==NULL)
00179 return E_OUT_OF_MEM;
00180
00181 t->next = timer_proc_list->timer_list;
00182 timer_proc_list->timer_list = t;
00183 return t->id;
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 int register_utimer(utimer_function f, void* param, unsigned int interval)
00194 {
00195 struct sr_timer* t;
00196
00197 t = new_sr_timer((timer_function*)f, param, interval);
00198 if (t==NULL)
00199 return E_OUT_OF_MEM;
00200
00201 t->next = timer_proc_list->utimer_list;
00202 timer_proc_list->utimer_list = t;
00203 return t->id;
00204 }
00205
00206
00207
00208
00209
00210
00211 int register_timer_process(timer_function f,void* param,unsigned int interval,
00212 unsigned int flags)
00213 {
00214 struct sr_timer* t;
00215 struct sr_timer_process* tpl;
00216
00217
00218 tpl = new_timer_process_list(flags);
00219 if (tpl==NULL)
00220 return E_OUT_OF_MEM;
00221
00222 t = new_sr_timer(f, param, interval);
00223 if (t==NULL)
00224 return E_OUT_OF_MEM;
00225
00226 t->next = tpl->timer_list;
00227 tpl->timer_list = t;
00228 return t->id;
00229 }
00230
00231
00232
00233
00234
00235 unsigned int get_ticks(void)
00236 {
00237 if (jiffies==0){
00238 LM_CRIT("bug -> jiffies not initialized\n");
00239 return 0;
00240 }
00241 return *jiffies;
00242 }
00243
00244
00245
00246
00247
00248 utime_t get_uticks(void)
00249 {
00250 if (ujiffies==0){
00251 LM_CRIT("bug -> ujiffies not initialized\n");
00252 return 0;
00253 }
00254 return *ujiffies;
00255 }
00256
00257
00258
00259
00260
00261 static inline void timer_ticker(struct sr_timer *timer_list)
00262 {
00263 struct sr_timer* t;
00264 unsigned int prev_jiffies;
00265
00266 prev_jiffies=*jiffies;
00267 *jiffies+=TIMER_TICK;
00268
00269 if (*jiffies<prev_jiffies){
00270
00271
00272 for(t=timer_list;t;t=t->next){
00273 t->expires=*jiffies+t->interval;
00274 t->u.timer_f(*jiffies, t->t_param);
00275 }
00276 return;
00277 }
00278
00279 for (t=timer_list;t; t=t->next){
00280 if (*jiffies>=t->expires){
00281 t->expires=*jiffies+t->interval;
00282 t->u.timer_f(*jiffies, t->t_param);
00283 }
00284 }
00285 }
00286
00287
00288
00289
00290
00291 static inline void utimer_ticker(struct sr_timer *utimer_list)
00292 {
00293 struct sr_timer* t;
00294
00295 *ujiffies+=UTIMER_TICK;
00296
00297
00298
00299 for ( t=utimer_list ; t ; t=t->next){
00300 if (*ujiffies>=t->expires){
00301 t->expires=*ujiffies+t->interval;
00302 t->u.utimer_f(*ujiffies, t->t_param);
00303 }
00304 }
00305 }
00306
00307
00308
00309
00310
00311 static void run_timer_process(struct sr_timer_process *tpl, int do_jiffies)
00312 {
00313 unsigned int local_jiffies=0;
00314 utime_t local_ujiffies=0;
00315 unsigned int multiple;
00316 unsigned int cnt;
00317 struct timeval o_tv;
00318 struct timeval tv;
00319
00320 if ( (tpl->utimer_list==NULL) || ((TIMER_TICK*1000000) == UTIMER_TICK) ) {
00321 o_tv.tv_sec = TIMER_TICK;
00322 o_tv.tv_usec = 0;
00323 multiple = 1;
00324 } else {
00325 o_tv.tv_sec = UTIMER_TICK / 1000000;
00326 o_tv.tv_usec = UTIMER_TICK % 1000000;
00327 multiple = (( TIMER_TICK * 1000000 ) / UTIMER_TICK ) / 1000000;
00328 }
00329
00330 LM_DBG("tv = %ld, %ld , m=%d\n",
00331 o_tv.tv_sec,o_tv.tv_usec,multiple);
00332
00333 if (!do_jiffies) {
00334 jiffies = &local_jiffies;
00335 ujiffies = &local_ujiffies;
00336 }
00337
00338 if (tpl->utimer_list==NULL) {
00339 for( ; ; ) {
00340 tv = o_tv;
00341 select( 0, 0, 0, 0, &tv);
00342 timer_ticker(tpl->timer_list);
00343 }
00344
00345 } else
00346 if (tpl->timer_list==NULL) {
00347 for( ; ; ) {
00348 tv = o_tv;
00349 select( 0, 0, 0, 0, &tv);
00350 utimer_ticker(tpl->utimer_list);
00351 }
00352
00353 } else
00354 if (multiple==1) {
00355 for( ; ; ) {
00356 tv = o_tv;
00357 select( 0, 0, 0, 0, &tv);
00358 timer_ticker(tpl->timer_list);
00359 utimer_ticker(tpl->utimer_list);
00360 }
00361
00362 } else {
00363 for( cnt=1 ; ; cnt++ ) {
00364 tv = o_tv;
00365 select( 0, 0, 0, 0, &tv);
00366 utimer_ticker(tpl->utimer_list);
00367 if (cnt==multiple) {
00368 timer_ticker(tpl->timer_list);
00369 cnt = 0;
00370 }
00371 }
00372 }
00373 }
00374
00375
00376
00377
00378
00379
00380 int start_timer_processes(void)
00381 {
00382 struct sr_timer_process *tpl;
00383 pid_t pid;
00384 unsigned int first;
00385
00386 for( tpl=timer_proc_list, first=1 ; tpl ; tpl=tpl->next,first=0 ) {
00387 if (tpl->timer_list==NULL && tpl->utimer_list==NULL)
00388 continue;
00389
00390 if ( (pid=internal_fork("timer"))<0 ) {
00391 LM_CRIT("cannot fork timer process\n");
00392 goto error;
00393 } else if (pid==0) {
00394
00395
00396 if ( tpl->flags&TIMER_PROC_INIT_FLAG && init_child(PROC_TIMER)<0 ){
00397 LM_ERR("init_child failed for timer proc\n");
00398 exit(-1);
00399 }
00400 run_timer_process( tpl, first);
00401 exit(-1);
00402 }
00403 }
00404
00405 return 0;
00406 error:
00407 return -1;
00408 }
00409
00410
00411
00412
00413
00414
00415 int count_timer_procs(void)
00416 {
00417 struct sr_timer_process *tpl;
00418 int n;
00419
00420 n = 0;
00421 for( tpl=timer_proc_list; tpl ; tpl=tpl->next ) {
00422 if (tpl->timer_list==NULL && tpl->utimer_list==NULL)
00423 continue;
00424 n++;
00425 }
00426
00427 return n;
00428 }