1 /*
2  * Copyright 2005 Renzo Davoli
3  * Licensed under the GPLv2
4  */
5 
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <signal.h>
9 #include <sys/time.h>
10 #include <syslog.h>
11 #include <errno.h>
12 #include <string.h>
13 #include "switch.h"
14 #include <stdio.h>
15 #include "consmgmt.h" /* just for printlog def */
16 
17 #include <config.h>
18 #include <vde.h>
19 #include <vdecommon.h>
20 
21 #define QT_ALLOC_STEP 4
22 
23 struct qt_timer {
24 	int qt_n; //timer ID
25 	time_t qt_period; //timer period
26 	time_t qt_nextcall; //next call time  (in secs)
27 	unsigned int qt_times; //number of times to be activated <0 = infinity
28 	void (* qt_call)(); //funct. to call
29 	void *qt_arg; // opt arg to the funct.
30 };
31 
32 struct qt_timer **qth; // head of the active timer array
33 struct qt_timer *qtf; // free list
34 int maxqt; //size of active timer array
35 
36 static time_t gqtime; // global time in secs, secs from the epoch
37 static int activeqt; // number of active timers
38 static int countqt; // counter for timer ID
39 
qtime()40 time_t qtime() // returns global time (faster than time())
41 {
42 	return gqtime;
43 }
44 
45 static sigset_t ss_alarm, ss_old;
qtime_csenter()46 void qtime_csenter()
47 {
48 	if (sigprocmask(SIG_BLOCK,&ss_alarm,&ss_old) < 0)
49 		printlog(LOG_WARNING,"error qtime_csenter\n");
50 }
51 
qtime_csexit()52 void qtime_csexit()
53 {
54 	if (sigprocmask(SIG_SETMASK,&ss_old,NULL) < 0)
55 		printlog(LOG_WARNING,"error qtime_csexit\n");
56 }
57 
qtimer_add(time_t period,int times,void (* call)(),void * arg)58 unsigned int qtimer_add(time_t period,int times,void (*call)(),void *arg)
59 {
60 	register int n;
61 	if (period>0 && call && times>=0) {
62 		qtime_csenter();
63 		if (activeqt >= maxqt) {
64 			int newmaxqt=maxqt+QT_ALLOC_STEP;
65 			qth=realloc(qth,newmaxqt*sizeof(struct qt_timer *));
66 			if (qth == NULL) {
67 				return -1;
68 			}
69 			/* it is not possible to use unitialized elements */
70 			/*memset(qth+maxqt,0,QT_ALLOC_STEP*sizeof(struct qt_timer *));*/
71 			maxqt=newmaxqt;
72 		}
73 		n=activeqt++;
74 		if (qtf == NULL) {
75 			qtf=malloc(sizeof(struct qt_timer));
76 			if (qth == NULL) {
77 				return -1;
78 			}
79 			/*all the fields but qt_arg get initialized */
80 			/*memset(qtf,0,sizeof(struct qt_timer));*/
81 			qtf->qt_arg=NULL;
82 		}
83 		qth[n]=qtf;
84 		qtf=qtf->qt_arg;
85 		qth[n]->qt_n=countqt++;
86 		qth[n]->qt_period=period;
87 		qth[n]->qt_nextcall=gqtime+period;
88 		qth[n]->qt_call=call;
89 		qth[n]->qt_arg=arg;
90 		qth[n]->qt_times=(times==0)?-1:times;
91 		qtime_csexit();
92 		return qth[n]->qt_n;
93 	} else
94 		return -1;
95 }
96 
qtimer_del(unsigned int n)97 void qtimer_del(unsigned int n)
98 {
99 	register int i;
100 	for (i=0; i<activeqt; i++) {
101 		if (n==qth[i]->qt_n) {
102 			qth[i]->qt_times=0;
103 			break;
104 		}
105 	}
106 }
107 
sig_alarm(int sig)108 static void sig_alarm(int sig)
109 {
110 	register int i;
111 	register int j;
112 	gqtime++;
113 	//printf("%d\n",gqtime);
114 	for (i=0,j=0; i<activeqt; i++) {
115 		if (qth[i]->qt_times == 0)
116 		{
117 			//printf("timer %d eliminated\n",qth[i]->qt_n);
118 			qth[i]->qt_arg=qtf;
119 			qtf=qth[i];
120 		}
121 		else {
122 			if (gqtime >= qth[i]->qt_nextcall) {
123 				//printf("timer %d fires\n",qth[i]->qt_n);
124 				qth[i]->qt_call(qth[i]->qt_arg);
125 				qth[i]->qt_nextcall+=qth[i]->qt_period;
126 				if (qth[i]->qt_times > 0 )
127 					(qth[i]->qt_times)--;
128 			}
129 			//printf("%d -> %d \n",i,j);
130 			if (i-j) qth[j]=qth[i];
131 			j++;
132 		}
133 	}
134 	activeqt=j;
135 }
136 
qtimer_init()137 void qtimer_init()
138 {
139 	struct itimerval it;
140 	struct sigaction sa;
141 
142 	sa.sa_handler = sig_alarm;
143 	sa.sa_flags = SA_RESTART;
144 	sigemptyset(&sa.sa_mask);
145 
146 	if(sigaction(SIGALRM, &sa, NULL) < 0){
147 	  printlog(LOG_WARNING,"Setting handler for SIGALRM %s", strerror(errno));
148 	    return;
149 	}
150 
151 	sigemptyset(&ss_alarm);
152 	sigaddset(&ss_alarm, SIGALRM);
153 
154 	it.it_value.tv_sec = 1;
155 	it.it_value.tv_usec = 0 ;
156 	it.it_interval.tv_sec = 1;
157 	it.it_interval.tv_usec = 0 ;
158 	setitimer(ITIMER_REAL, &it, NULL);
159 }
160 
161 /*
162  * test stub */
163 /*
164 void fun(void *arg)
165 {
166 	printf("FUN\n");
167 }
168 
169 main()
170 {
171 	qtimer_init();
172 	qtimer_add(7,0,fun,NULL);
173 	qtimer_add(3,0,fun,NULL);
174 	qtimer_add(4,2,fun,NULL);
175 	while(1)
176 		pause();
177 }
178 */
179