Attempt to count descramblers used properly
[oscam.git] / oscam-garbage.c
blob15aae5b3ba5e031cc14550f34471ccaa373d5fb6
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 if(j < 3)
144 cs_writeunlock(__func__, &garbage_lock[i]);
147 // list has been taken out before so we don't need a lock here anymore!
148 while(garbage)
150 next = garbage->next;
151 free(garbage->data);
152 free(garbage);
153 garbage = next;
156 sleepms_on_cond(__func__, &sleep_cond_mutex, &sleep_cond, 500);
158 pthread_exit(NULL);
161 void start_garbage_collector(int32_t debug)
163 garbage_debug = debug;
164 int32_t i;
166 SAFE_MUTEX_INIT(&add_lock, NULL);
168 for(i = 0; i < HASH_BUCKETS; ++i)
170 cs_lock_create(__func__, &garbage_lock[i], "garbage_lock", 9000);
172 garbage_first[i] = NULL;
174 cs_pthread_cond_init(__func__, &sleep_cond_mutex, &sleep_cond);
176 garbage_collector_active = 1;
178 int32_t ret = start_thread("garbage", (void *)&garbage_collector, NULL, &garbage_thread, 0, 1);
179 if(ret)
181 cs_exit(1);
185 void stop_garbage_collector(void)
187 if(garbage_collector_active)
189 int32_t i;
191 garbage_collector_active = 0;
192 SAFE_COND_SIGNAL(&sleep_cond);
193 cs_sleepms(300);
194 SAFE_COND_SIGNAL(&sleep_cond);
195 SAFE_THREAD_JOIN(garbage_thread, NULL);
197 for(i = 0; i < HASH_BUCKETS; ++i)
198 { cs_writelock(__func__, &garbage_lock[i]); }
200 for(i = 0; i < HASH_BUCKETS; ++i)
202 while(garbage_first[i])
204 struct cs_garbage *next = garbage_first[i]->next;
205 NULLFREE(garbage_first[i]->data);
206 NULLFREE(garbage_first[i]);
207 garbage_first[i] = next;
211 for(i = 0; i < HASH_BUCKETS; ++i)
213 cs_writeunlock(__func__, &garbage_lock[i]);
214 cs_lock_destroy(__func__, &garbage_lock[i]);
217 pthread_mutex_destroy(&add_lock);
218 pthread_cond_destroy(&sleep_cond);
219 pthread_mutex_destroy(&sleep_cond_mutex);