source: trunk/oscam-garbage.c @ 5375

Last change on this file since 5375 was 5352, checked in by schlocke, 8 years ago

cccam: fixed auto refresh only for local cards, loadbalancer: do not
block timeouts if we got ecms in the past

File size: 4.6 KB
Line 
1#include <pthread.h>
2
3#include "globals.h"
4#include "module-datastruct-llist.h"
5#define HASH_BUCKETS 16
6
7struct cs_garbage {
8        time_t time;
9        void * data;
10        #ifdef WITH_DEBUG
11        char *file;
12        uint16_t line;
13        #endif
14        struct cs_garbage *next;
15};
16
17struct cs_garbage *garbage_first[HASH_BUCKETS];
18pthread_mutex_t garbage_lock[HASH_BUCKETS];
19pthread_t garbage_thread;
20int32_t garbage_collector_active = 0;
21int32_t garbage_debug = 0;
22
23#ifdef WITH_DEBUG
24void add_garbage_debug(void *data, char *file, uint16_t line) {
25#else
26void add_garbage(void *data) {
27#endif
28        if (!data)
29                return;
30               
31        if (!garbage_collector_active || garbage_debug) {
32          free(data);
33          return;
34        }
35       
36        int32_t bucket = (uintptr_t)data/16 % HASH_BUCKETS;
37        while (cs_trylock(&garbage_lock[bucket])) {
38            cs_debug_mask(D_TRACE, "trylock add_garbage wait"); 
39            cs_sleepms(fast_rnd());
40        }
41       
42        struct cs_garbage *garbagecheck = garbage_first[bucket];
43        while(garbagecheck) {
44            if(garbagecheck->data == data) {
45                cs_log("Found a try to add garbage twice. Not adding the element to garbage list...");
46                #ifdef WITH_DEBUG
47                cs_log("Current garbage addition: %s, line %d.", file, line);
48                cs_log("Original garbage addition: %s, line %d.", garbagecheck->file, garbagecheck->line);
49                #else
50                cs_log("Please compile with debug for exact info.");
51                #endif
52                break;
53            }
54            garbagecheck = garbagecheck->next;
55        }
56       
57        if (garbagecheck == NULL) {
58            struct cs_garbage *garbage = malloc(sizeof(struct cs_garbage));
59            garbage->time = time(NULL);
60            garbage->data = data;
61            garbage->next = garbage_first[bucket];
62            #ifdef WITH_DEBUG
63            garbage->file = file;
64            garbage->line = line;
65            #endif
66            garbage_first[bucket] = garbage;
67        }
68
69        cs_unlock(&garbage_lock[bucket]);
70}
71
72void garbage_collector() {
73        time_t now;
74        int32_t i;
75        struct cs_garbage *garbage, *next, *prev;
76       
77        while (garbage_collector_active) {
78               
79                for(i = 0; i < HASH_BUCKETS; ++i){
80                    while (cs_trylock(&garbage_lock[i])) {
81                        cs_debug_mask(D_TRACE, "trylock garbage_collector wait");
82                        cs_sleepms(fast_rnd());
83                    }
84                    now = time(NULL);
85   
86                    prev = NULL;
87                    garbage = garbage_first[i]; 
88                    while (garbage) {
89                            next = garbage->next;
90                            if (now > garbage->time+5) { //5 seconds!
91                                    free(garbage->data);
92                                   
93                                    if (prev)
94                                            prev->next = next;
95                                    else
96                                            garbage_first[i] = next;
97                                    free(garbage);
98                            }
99                            else
100                                    prev = garbage;
101                            garbage = next;
102                    }
103                    cs_unlock(&garbage_lock[i]);
104                  }
105                cs_sleepms(1000);
106        }
107        pthread_exit(NULL);
108}
109
110void start_garbage_collector(int32_t debug) {
111
112    garbage_debug = debug;
113    int32_t i;
114    for(i = 0; i < HASH_BUCKETS; ++i){
115        pthread_mutex_init(&garbage_lock[i], NULL);
116
117        garbage_first[i] = NULL;
118    }
119    pthread_attr_t attr;
120    pthread_attr_init(&attr);
121
122    garbage_collector_active = 1;
123
124#ifndef TUXBOX
125    pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
126#endif
127    pthread_create(&garbage_thread, &attr, (void*)&garbage_collector, NULL);
128    pthread_detach(garbage_thread);
129    pthread_attr_destroy(&attr);
130}
131
132void stop_garbage_collector()
133{
134        if (garbage_collector_active) {
135                int32_t i;
136               
137                garbage_collector_active = 0;
138                for(i = 0; i < HASH_BUCKETS; ++i)
139                    cs_lock(&garbage_lock[i]);
140               
141                pthread_cancel(garbage_thread);
142                cs_sleepms(100);
143               
144                for(i = 0; i < HASH_BUCKETS; ++i){
145                    while (garbage_first[i]) {
146                      struct cs_garbage *next = garbage_first[i]->next;
147                      free(garbage_first[i]->data);
148                      free(garbage_first[i]);
149                      garbage_first[i] = next;
150                    }
151                    cs_unlock(&garbage_lock[i]);
152                    pthread_mutex_destroy(&garbage_lock[i]);
153                }
154        }
155}
Note: See TracBrowser for help on using the repository browser.