1 | #ifndef TIMERTHREAD_H |
---|
2 | #define TIMERTHREAD_H |
---|
3 | |
---|
4 | struct stimerthread* gettimerbythread(pthread_t thread) |
---|
5 | { |
---|
6 | struct stimerthread *node = NULL; |
---|
7 | |
---|
8 | m_lock(&status.timerthreadmutex, 6); |
---|
9 | node = stimerthread; |
---|
10 | while(node != NULL) |
---|
11 | { |
---|
12 | if(node->thread == thread) |
---|
13 | { |
---|
14 | m_unlock(&status.timerthreadmutex, 6); |
---|
15 | return node; |
---|
16 | } |
---|
17 | |
---|
18 | node = node->next; |
---|
19 | } |
---|
20 | |
---|
21 | m_unlock(&status.timerthreadmutex, 6); |
---|
22 | return NULL; |
---|
23 | } |
---|
24 | |
---|
25 | struct stimerthread* gettimer(struct stimerthread* timernode) |
---|
26 | { |
---|
27 | struct stimerthread *node = NULL; |
---|
28 | |
---|
29 | m_lock(&status.timerthreadmutex, 6); |
---|
30 | node = stimerthread; |
---|
31 | while(node != NULL) |
---|
32 | { |
---|
33 | if(node == timernode) |
---|
34 | { |
---|
35 | m_unlock(&status.timerthreadmutex, 6); |
---|
36 | return node; |
---|
37 | } |
---|
38 | |
---|
39 | node = node->next; |
---|
40 | } |
---|
41 | |
---|
42 | m_unlock(&status.timerthreadmutex, 6); |
---|
43 | debug(100, "timerthread not found (timer=%p)", timernode); |
---|
44 | return NULL; |
---|
45 | } |
---|
46 | |
---|
47 | struct stimerthread* addtimer(void* func, int aktion, int delay, int count, void* param1, void* param2, struct stimerthread* last) |
---|
48 | { |
---|
49 | struct stimerthread *newnode = NULL, *prev = NULL, *node = NULL; |
---|
50 | |
---|
51 | newnode = (struct stimerthread*)calloc(1, sizeof(struct stimerthread)); |
---|
52 | if(newnode == NULL) |
---|
53 | { |
---|
54 | err("no memory"); |
---|
55 | return NULL; |
---|
56 | } |
---|
57 | |
---|
58 | newnode->func = func; |
---|
59 | newnode->aktion = aktion; |
---|
60 | newnode->delay = delay; |
---|
61 | newnode->count = count; |
---|
62 | newnode->param1 = param1; |
---|
63 | newnode->param2 = param2; |
---|
64 | |
---|
65 | m_lock(&status.timerthreadmutex, 6); |
---|
66 | node = stimerthread; |
---|
67 | |
---|
68 | if(last == NULL) |
---|
69 | { |
---|
70 | while(node != NULL) |
---|
71 | { |
---|
72 | prev = node; |
---|
73 | node = node->next; |
---|
74 | } |
---|
75 | } |
---|
76 | else |
---|
77 | { |
---|
78 | prev = last; |
---|
79 | node = last->next; |
---|
80 | } |
---|
81 | |
---|
82 | if(prev == NULL) |
---|
83 | stimerthread = newnode; |
---|
84 | else |
---|
85 | prev->next = newnode; |
---|
86 | newnode->next = node; |
---|
87 | |
---|
88 | m_unlock(&status.timerthreadmutex, 6); |
---|
89 | return newnode; |
---|
90 | } |
---|
91 | |
---|
92 | //flag 0: lock |
---|
93 | //flag 1: no lock |
---|
94 | void deltimer(struct stimerthread *tnode, int flag) |
---|
95 | { |
---|
96 | int i = 0; |
---|
97 | void* threadstatus; |
---|
98 | |
---|
99 | if(flag == 0) m_lock(&status.timerthreadmutex, 6); |
---|
100 | struct stimerthread *node = stimerthread, *prev = stimerthread; |
---|
101 | |
---|
102 | while(node != NULL) |
---|
103 | { |
---|
104 | if(node == tnode) |
---|
105 | { |
---|
106 | //stop timer sub thread |
---|
107 | node->aktion = STOP; |
---|
108 | while(node->status != DEACTIVE) |
---|
109 | { |
---|
110 | usleep(100000); |
---|
111 | i++; if(i > 50) break; |
---|
112 | } |
---|
113 | |
---|
114 | if(i > 50) |
---|
115 | { |
---|
116 | err("detect hanging timer sub thread"); |
---|
117 | } |
---|
118 | else //only free mem if we can stop thread |
---|
119 | { |
---|
120 | if(node->thread != '\0') |
---|
121 | pthread_join(node->thread, &threadstatus); |
---|
122 | pthread_attr_destroy(&node->attr); |
---|
123 | |
---|
124 | if(node == stimerthread) |
---|
125 | stimerthread = node->next; |
---|
126 | else |
---|
127 | prev->next = node->next; |
---|
128 | |
---|
129 | free(node); |
---|
130 | node = NULL; |
---|
131 | } |
---|
132 | break; |
---|
133 | } |
---|
134 | |
---|
135 | prev = node; |
---|
136 | node = node->next; |
---|
137 | } |
---|
138 | |
---|
139 | if(flag == 0) m_unlock(&status.timerthreadmutex, 6); |
---|
140 | } |
---|
141 | |
---|
142 | //flag 0 = stop all |
---|
143 | //flag 1 = stop only threads with thread->flag bit 0 = 1 |
---|
144 | void freetimer(int flag) |
---|
145 | { |
---|
146 | struct stimerthread *node = stimerthread, *prev = stimerthread; |
---|
147 | |
---|
148 | while(node != NULL) |
---|
149 | { |
---|
150 | prev = node; |
---|
151 | node = node->next; |
---|
152 | if(prev != NULL) |
---|
153 | { |
---|
154 | if(flag == 0) |
---|
155 | deltimer(prev, 0); |
---|
156 | else if(flag == 1 && checkbit(prev->flag, 0) == 1) |
---|
157 | deltimer(prev, 0); |
---|
158 | } |
---|
159 | } |
---|
160 | } |
---|
161 | |
---|
162 | void* timerthreadsubfunc(void *param) |
---|
163 | { |
---|
164 | int count = 0; |
---|
165 | struct stimerthread* node = (struct stimerthread*)param; |
---|
166 | |
---|
167 | if(param == NULL) |
---|
168 | { |
---|
169 | err("NULL detect"); |
---|
170 | pthread_exit(NULL); |
---|
171 | } |
---|
172 | |
---|
173 | node->status = ACTIVE; |
---|
174 | while(node->aktion != STOP) |
---|
175 | { |
---|
176 | if(node->aktion != PAUSE) |
---|
177 | { |
---|
178 | node->status = ACTIVE; |
---|
179 | node->func(node, node->param1, node->param2); |
---|
180 | node->notfirst = 1; |
---|
181 | if(node->count > -1 && node->aktion != PAUSE) node->count--; |
---|
182 | if(node->count == 0) break; |
---|
183 | } |
---|
184 | else |
---|
185 | node->status = INPAUSE; |
---|
186 | |
---|
187 | if(node->delay > 1000) |
---|
188 | { |
---|
189 | count = node->delay; |
---|
190 | while(count > 1000) |
---|
191 | { |
---|
192 | usleep(1000000); |
---|
193 | count = count - 1000; |
---|
194 | if(node->aktion == STOP || node->aktion == PAUSE) count = 0; |
---|
195 | } |
---|
196 | usleep(count); |
---|
197 | } |
---|
198 | else |
---|
199 | usleep(node->delay * 1000); |
---|
200 | } |
---|
201 | |
---|
202 | node->aktion = STOP; |
---|
203 | node->status = DEACTIVE; |
---|
204 | |
---|
205 | pthread_exit(NULL); |
---|
206 | } |
---|
207 | |
---|
208 | void* timerthreadfunc(void *param) |
---|
209 | { |
---|
210 | int ret = 0; |
---|
211 | struct stimerthread* node = NULL; |
---|
212 | //struct sched_param schedparam; |
---|
213 | |
---|
214 | //set timer threads scheduler priority |
---|
215 | //schedparam.sched_priority = 0; |
---|
216 | //pthread_setschedparam(pthread_self(), SCHED_OTHER, &schedparam); |
---|
217 | |
---|
218 | status.timerthreadstatus = ACTIVE; |
---|
219 | while(status.timerthreadaktion != STOP) |
---|
220 | { |
---|
221 | if(status.timerthreadaktion != PAUSE) |
---|
222 | { |
---|
223 | status.timerthreadstatus = ACTIVE; |
---|
224 | |
---|
225 | m_lock(&status.timerthreadmutex, 6); |
---|
226 | node = stimerthread; |
---|
227 | while(node != NULL) |
---|
228 | { |
---|
229 | if(node->status == DEACTIVE && node->aktion == STOP && node->count == 0) |
---|
230 | { |
---|
231 | struct stimerthread* prev = node; |
---|
232 | node = node->next; |
---|
233 | deltimer(prev, 1); |
---|
234 | continue; |
---|
235 | } |
---|
236 | |
---|
237 | if(node->status == DEACTIVE && node->aktion == START && node->count != 0) |
---|
238 | { |
---|
239 | pthread_attr_init(&node->attr); |
---|
240 | pthread_attr_setstacksize(&node->attr, 151552); |
---|
241 | pthread_attr_setdetachstate(&node->attr, PTHREAD_CREATE_JOINABLE); |
---|
242 | node->status = ACTIVE; |
---|
243 | debug(10, "start timer sub thread"); |
---|
244 | ret = pthread_create(&node->thread, &node->attr, timerthreadsubfunc, (void*)node); |
---|
245 | if(ret) |
---|
246 | { |
---|
247 | node->status = ERROR; |
---|
248 | perr("create timer sub thread"); |
---|
249 | pthread_attr_destroy(&node->attr); |
---|
250 | } |
---|
251 | } |
---|
252 | node = node->next; |
---|
253 | } |
---|
254 | m_unlock(&status.timerthreadmutex, 6); |
---|
255 | |
---|
256 | } |
---|
257 | else |
---|
258 | status.timerthreadstatus = INPAUSE; |
---|
259 | |
---|
260 | usleep(1 * 1000000); |
---|
261 | } |
---|
262 | status.timerthreadstatus = DEACTIVE; |
---|
263 | |
---|
264 | pthread_exit(NULL); |
---|
265 | } |
---|
266 | |
---|
267 | #endif |
---|