[gbx] - try fix ecm and cw messages
[oscam.git] / oscam-lock.c
blobf1676da7a36b90060c4307cee2e5546360bb54f1
1 #define MODULE_LOG_PREFIX "lock"
3 #include "globals.h"
4 #include "oscam-lock.h"
5 #include "oscam-time.h"
7 extern char *LOG_LIST;
9 /**
10 * creates a lock
11 **/
12 void cs_lock_create(const char *n, CS_MUTEX_LOCK *l, const char *name, uint32_t timeout_ms)
14 memset(l, 0, sizeof(CS_MUTEX_LOCK));
15 l->timeout = timeout_ms / 1000;
16 l->name = name;
17 SAFE_MUTEX_INIT_R(&l->lock, NULL, n);
18 __cs_pthread_cond_init(n, &l->writecond);
19 __cs_pthread_cond_init(n, &l->readcond);
20 #ifdef WITH_MUTEXDEBUG
21 cs_log_dbg(D_TRACE, "lock %s created", name);
22 #endif
25 /**
26 * creates a lock
27 **/
28 void cs_lock_create_nolog(const char *n, CS_MUTEX_LOCK *l, const char *name, uint32_t timeout_ms)
30 memset(l, 0, sizeof(CS_MUTEX_LOCK));
31 l->timeout = timeout_ms / 1000;
32 l->name = name;
33 SAFE_MUTEX_INIT_NOLOG_R(&l->lock, NULL, n);
34 __cs_pthread_cond_init(n, &l->writecond);
35 __cs_pthread_cond_init(n, &l->readcond);
36 #ifdef WITH_MUTEXDEBUG
37 cs_log_dbg(D_TRACE, "lock %s created", name);
38 #endif
41 void cs_lock_destroy(const char *pn, CS_MUTEX_LOCK *l)
43 if(!l || !l->name || l->flag) { return; }
45 cs_rwlock_int(pn, l, WRITELOCK);
46 #ifdef WITH_DEBUG
47 const char *old_name = l->name;
48 #endif
49 l->name = NULL; // No new locks!
50 cs_rwunlock_int(pn, l, WRITELOCK);
52 // Do not destroy when having pending locks!
53 int32_t n = (l->timeout / 10) + 2;
54 while((--n > 0) && (l->writelock || l->readlock)) { cs_sleepms(10); }
56 cs_rwlock_int(pn, l, WRITELOCK);
57 l->flag++; // No new unlocks!
58 cs_rwunlock_int(pn, l, WRITELOCK);
60 #ifdef WITH_DEBUG
61 if(!n && old_name != LOG_LIST)
62 { cs_log("WARNING lock %s destroy timed out.", old_name); }
63 #endif
65 pthread_mutex_destroy(&l->lock);
66 pthread_cond_destroy(&l->writecond);
67 pthread_cond_destroy(&l->readcond);
68 #ifdef WITH_MUTEXDEBUG
69 cs_log_dbg(D_TRACE, "lock %s destroyed", l->name);
70 #endif
73 void cs_rwlock_int(const char *n, CS_MUTEX_LOCK *l, int8_t type)
75 struct timespec ts;
76 int8_t ret = 0;
78 if(!l || !l->name || l->flag)
79 { return; }
81 SAFE_MUTEX_LOCK_R(&l->lock, n);
83 add_ms_to_timespec(&ts, l->timeout * 1000);
84 ts.tv_nsec = 0; // 100% resemble previous code, I consider it wrong
85 if(type == WRITELOCK)
87 l->writelock++;
88 // if read- or writelock is busy, wait for unlock
89 if(l->writelock > 1 || l->readlock > 0)
90 { ret = pthread_cond_timedwait(&l->writecond, &l->lock, &ts); }
92 else
94 l->readlock++;
95 // if writelock is busy, wait for unlock
96 if(l->writelock > 0)
97 { ret = pthread_cond_timedwait(&l->readcond, &l->lock, &ts); }
100 if(ret > 0)
102 // lock wasn't returned within time, assume locking thread to
103 // be stuck or finished, so enforce lock.
104 l->writelock = (type == WRITELOCK) ? 1 : 0;
105 l->readlock = (type == WRITELOCK) ? 0 : 1;
106 #ifdef WITH_DEBUG
107 if(l->name != LOG_LIST)
108 { cs_log("WARNING lock %s (%s) timed out.", l->name, (type == WRITELOCK) ? "WRITELOCK" : "READLOCK"); }
109 #endif
112 SAFE_MUTEX_UNLOCK_R(&l->lock, n);
113 #ifdef WITH_MUTEXDEBUG
114 //cs_log_dbg(D_TRACE, "lock %s locked", l->name);
115 #endif
116 return;
119 void cs_rwlock_int_nolog(const char *n, CS_MUTEX_LOCK *l, int8_t type)
121 struct timespec ts;
122 int8_t ret = 0;
124 if(!l || !l->name || l->flag)
125 { return; }
127 SAFE_MUTEX_LOCK_NOLOG_R(&l->lock, n);
129 add_ms_to_timespec(&ts, l->timeout * 1000);
130 ts.tv_nsec = 0; // 100% resemble previous code, I consider it wrong
131 if(type == WRITELOCK)
133 l->writelock++;
134 // if read- or writelock is busy, wait for unlock
135 if(l->writelock > 1 || l->readlock > 0)
136 { ret = pthread_cond_timedwait(&l->writecond, &l->lock, &ts); }
138 else
140 l->readlock++;
141 // if writelock is busy, wait for unlock
142 if(l->writelock > 0)
143 { ret = pthread_cond_timedwait(&l->readcond, &l->lock, &ts); }
146 if(ret > 0)
148 // lock wasn't returned within time, assume locking thread to
149 // be stuck or finished, so enforce lock.
150 l->writelock = (type == WRITELOCK) ? 1 : 0;
151 l->readlock = (type == WRITELOCK) ? 0 : 1;
152 #ifdef WITH_DEBUG
153 if(l->name != LOG_LIST)
154 { cs_log("WARNING lock %s (%s) timed out.", l->name, (type == WRITELOCK) ? "WRITELOCK" : "READLOCK"); }
155 #endif
158 SAFE_MUTEX_UNLOCK_NOLOG_R(&l->lock, n);
159 #ifdef WITH_MUTEXDEBUG
160 //cs_log_dbg(D_TRACE, "lock %s locked", l->name);
161 #endif
162 return;
165 void cs_rwunlock_int(const char *n, CS_MUTEX_LOCK *l, int8_t type)
168 if(!l || l->flag) { return; }
170 SAFE_MUTEX_LOCK_R(&l->lock, n);
172 if(type == WRITELOCK)
173 { l->writelock--; }
174 else
175 { l->readlock--; }
177 if(l->writelock < 0) { l->writelock = 0; }
178 if(l->readlock < 0) { l->readlock = 0; }
180 // waiting writelocks always have priority. If one is waiting, signal it
181 if(l->writelock)
182 { SAFE_COND_SIGNAL_R(&l->writecond, n); }
183 // Otherwise signal a waiting readlock (if any)
184 else if(l->readlock && type != READLOCK)
185 { SAFE_COND_BROADCAST_R(&l->readcond, n); }
187 SAFE_MUTEX_UNLOCK_R(&l->lock, n);
189 #ifdef WITH_MUTEXDEBUG
190 #ifdef WITH_DEBUG
191 if(l->name != LOG_LIST)
193 const char *typetxt[] = { "", "write", "read" };
194 cs_log_dbg(D_TRACE, "%slock %s: released", typetxt[type], l->name);
196 #endif
197 #endif
200 void cs_rwunlock_int_nolog(const char *n, CS_MUTEX_LOCK *l, int8_t type)
203 if(!l || l->flag) { return; }
205 SAFE_MUTEX_LOCK_NOLOG_R(&l->lock, n);
207 if(type == WRITELOCK)
208 { l->writelock--; }
209 else
210 { l->readlock--; }
212 if(l->writelock < 0) { l->writelock = 0; }
213 if(l->readlock < 0) { l->readlock = 0; }
215 // waiting writelocks always have priority. If one is waiting, signal it
216 if(l->writelock)
217 { SAFE_COND_SIGNAL_R(&l->writecond, n); }
218 // Otherwise signal a waiting readlock (if any)
219 else if(l->readlock && type != READLOCK)
220 { SAFE_COND_BROADCAST_R(&l->readcond, n); }
222 SAFE_MUTEX_UNLOCK_NOLOG_R(&l->lock, n);
224 #ifdef WITH_MUTEXDEBUG
225 #ifdef WITH_DEBUG
226 if(l->name != LOG_LIST)
228 const char *typetxt[] = { "", "write", "read" };
229 cs_log_dbg(D_TRACE, "%slock %s: released", typetxt[type], l->name);
231 #endif
232 #endif
235 int8_t cs_try_rwlock_int(const char *n, CS_MUTEX_LOCK *l, int8_t type)
237 if(!l || !l->name || l->flag)
238 { return 0; }
240 int8_t status = 0;
242 SAFE_MUTEX_LOCK_R(&l->lock, n);
244 if(type == WRITELOCK)
246 if(l->writelock || l->readlock)
247 { status = 1; }
248 else
249 { l->writelock++; }
251 else
253 if(l->writelock)
254 { status = 1; }
255 else
256 { l->readlock++; }
259 SAFE_MUTEX_UNLOCK_R(&l->lock, n);
261 #ifdef WITH_MUTEXDEBUG
262 #ifdef WITH_DEBUG
263 if(l->name != LOG_LIST)
265 const char *typetxt[] = { "", "write", "read" };
266 cs_log_dbg(D_TRACE, "try_%slock %s: status=%d", typetxt[type], l->name, status);
268 #endif
269 #endif
270 return status;