- fix compile warnings for unused variables (thanks to gabberhead for reporting and...
[oscam.git] / oscam-garbage.c
blob1b0373b23a5f9329dc2d5597ca57babd658cd2d7
1 #define MODULE_LOG_PREFIX "gc"
3 #include "globals.h"
4 #include "oscam-garbage.h"
5 #include "oscam-lock.h"
6 #include "oscam-string.h"
7 #include "oscam-time.h"
9 #define HASH_BUCKETS 250
11 struct cs_garbage
13 time_t time;
14 void *data;
15 #ifdef WITH_DEBUG
16 char *file;
17 uint32_t line;
18 #endif
19 struct cs_garbage *next;
22 static int32_t counter = 0;
23 static pthread_mutex_t add_lock;
24 static struct cs_garbage *garbage_first[HASH_BUCKETS];
25 static CS_MUTEX_LOCK garbage_lock[HASH_BUCKETS];
26 static pthread_t garbage_thread;
27 static int32_t garbage_collector_active;
28 static int32_t garbage_debug;
30 #ifdef WITH_DEBUG
31 void add_garbage_debug(void *data, char *file, uint32_t line)
33 #else
34 void add_garbage(void *data)
36 #endif
37 if(!data)
38 { return; }
40 if(!garbage_collector_active || garbage_debug == 1)
42 NULLFREE(data);
43 return;
46 SAFE_MUTEX_LOCK(&add_lock);
48 int32_t bucket = counter++;
50 if(counter >= HASH_BUCKETS)
52 counter = 0;
55 SAFE_MUTEX_UNLOCK(&add_lock);
57 struct cs_garbage *garbage = (struct cs_garbage*)malloc(sizeof(struct cs_garbage));
58 if(garbage == NULL)
60 cs_log("*** MEMORY FULL -> FREEING DIRECT MAY LEAD TO INSTABILITY!!! ***");
61 NULLFREE(data);
62 return;
64 garbage->time = time(NULL);
65 garbage->data = data;
66 garbage->next = NULL;
67 #ifdef WITH_DEBUG
68 garbage->file = file;
69 garbage->line = line;
70 #endif
72 cs_writelock(__func__, &garbage_lock[bucket]);
74 #ifdef WITH_DEBUG
75 if(garbage_debug == 2)
77 struct cs_garbage *garbagecheck = garbage_first[bucket];
78 while(garbagecheck)
80 if(garbagecheck->data == data)
82 cs_log("Found a try to add garbage twice. Not adding the element to garbage list...");
83 cs_log("Current garbage addition: %s, line %d.", file, line);
84 cs_log("Original garbage addition: %s, line %d.", garbagecheck->file, garbagecheck->line);
85 cs_writeunlock(__func__, &garbage_lock[bucket]);
86 NULLFREE(garbage);
87 return;
89 garbagecheck = garbagecheck->next;
92 #endif
94 garbage->next = garbage_first[bucket];
95 garbage_first[bucket] = garbage;
97 cs_writeunlock(__func__, &garbage_lock[bucket]);
100 static pthread_cond_t sleep_cond;
101 static pthread_mutex_t sleep_cond_mutex;
103 static void garbage_collector(void)
105 int32_t i,j;
106 struct cs_garbage *garbage, *next, *prev, *first;
107 set_thread_name(__func__);
108 int32_t timeout_time = 2 * cfg.ctimeout / 1000 + 6;
110 while(garbage_collector_active)
112 time_t deltime = time(NULL) - timeout_time;
114 for(i = 0; i < HASH_BUCKETS; ++i)
116 j = 0;
117 cs_writelock(__func__, &garbage_lock[i]);
118 first = garbage_first[i];
120 for(garbage = first, prev = NULL; garbage; prev = garbage, garbage = garbage->next, j++)
122 if(j == 2)
124 j++;
125 cs_writeunlock(__func__, &garbage_lock[i]);
128 if(garbage->time < deltime) // all following elements are too new
130 if(prev)
132 prev->next = NULL;
134 else
136 garbage_first[i] = NULL;
138 break;
142 cs_writeunlock(__func__, &garbage_lock[i]);
144 // list has been taken out before so we don't need a lock here anymore!
145 while(garbage)
147 next = garbage->next;
148 free(garbage->data);
149 free(garbage);
150 garbage = next;
153 sleepms_on_cond(__func__, &sleep_cond_mutex, &sleep_cond, 500);
155 pthread_exit(NULL);
158 void start_garbage_collector(int32_t debug)
160 garbage_debug = debug;
161 int32_t i;
163 SAFE_MUTEX_INIT(&add_lock, NULL);
165 for(i = 0; i < HASH_BUCKETS; ++i)
167 cs_lock_create(__func__, &garbage_lock[i], "garbage_lock", 9000);
169 garbage_first[i] = NULL;
171 cs_pthread_cond_init(__func__, &sleep_cond_mutex, &sleep_cond);
173 garbage_collector_active = 1;
175 int32_t ret = start_thread("garbage", (void *)&garbage_collector, NULL, &garbage_thread, 0, 1);
176 if(ret)
178 cs_exit(1);
182 void stop_garbage_collector(void)
184 if(garbage_collector_active)
186 int32_t i;
188 garbage_collector_active = 0;
189 SAFE_COND_SIGNAL(&sleep_cond);
190 cs_sleepms(300);
191 SAFE_COND_SIGNAL(&sleep_cond);
192 SAFE_THREAD_JOIN(garbage_thread, NULL);
194 for(i = 0; i < HASH_BUCKETS; ++i)
195 { cs_writelock(__func__, &garbage_lock[i]); }
197 for(i = 0; i < HASH_BUCKETS; ++i)
199 while(garbage_first[i])
201 struct cs_garbage *next = garbage_first[i]->next;
202 NULLFREE(garbage_first[i]->data);
203 NULLFREE(garbage_first[i]);
204 garbage_first[i] = next;
208 for(i = 0; i < HASH_BUCKETS; ++i)
210 cs_writeunlock(__func__, &garbage_lock[i]);
211 cs_lock_destroy(__func__, &garbage_lock[i]);
214 pthread_mutex_destroy(&add_lock);
215 pthread_cond_destroy(&sleep_cond);
216 pthread_mutex_destroy(&sleep_cond_mutex);