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
;
142 cs_writeunlock(__func__
, &garbage_lock
[i
]);
144 // list has been taken out before so we don't need a lock here anymore!
147 next
= garbage
->next
;
153 sleepms_on_cond(__func__
, &sleep_cond_mutex
, &sleep_cond
, 500);
158 void start_garbage_collector(int32_t debug
)
160 garbage_debug
= debug
;
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);
182 void stop_garbage_collector(void)
184 if(garbage_collector_active
)
188 garbage_collector_active
= 0;
189 SAFE_COND_SIGNAL(&sleep_cond
);
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
);