1 #define MODULE_LOG_PREFIX "gc"
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
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
;
31 void add_garbage_debug(void *data
, char *file
, uint32_t line
)
34 void add_garbage(void *data
)
40 if(!garbage_collector_active
|| garbage_debug
== 1)
46 SAFE_MUTEX_LOCK(&add_lock
);
48 int32_t bucket
= counter
++;
50 if(counter
>= HASH_BUCKETS
)
55 SAFE_MUTEX_UNLOCK(&add_lock
);
57 struct cs_garbage
*garbage
= (struct cs_garbage
*)malloc(sizeof(struct cs_garbage
));
60 cs_log("*** MEMORY FULL -> FREEING DIRECT MAY LEAD TO INSTABILITY!!! ***");
64 garbage
->time
= time(NULL
);
72 cs_writelock(__func__
, &garbage_lock
[bucket
]);
75 if(garbage_debug
== 2)
77 struct cs_garbage
*garbagecheck
= garbage_first
[bucket
];
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
]);
89 garbagecheck
= garbagecheck
->next
;
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)
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
)
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
++)
125 cs_writeunlock(__func__
, &garbage_lock
[i
]);
128 if(garbage
->time
< deltime
) // all following elements are too new
136 garbage_first
[i
] = NULL
;
144 cs_writeunlock(__func__
, &garbage_lock
[i
]);
147 // list has been taken out before so we don't need a lock here anymore!
150 next
= garbage
->next
;
156 sleepms_on_cond(__func__
, &sleep_cond_mutex
, &sleep_cond
, 500);
161 void start_garbage_collector(int32_t debug
)
163 garbage_debug
= debug
;
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);
185 void stop_garbage_collector(void)
187 if(garbage_collector_active
)
191 garbage_collector_active
= 0;
192 SAFE_COND_SIGNAL(&sleep_cond
);
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
);