Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2001-2003 FhG Fokus |
3 | | * |
4 | | * This file is part of opensips, a free SIP server. |
5 | | * |
6 | | * opensips is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version |
10 | | * |
11 | | * opensips is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | * History: |
20 | | * -------- |
21 | | * 2002-12-16 created by andrei |
22 | | * 2003-02-20 s/gen_lock_t/gen_lock_t/ to avoid a type conflict |
23 | | * on solaris (andrei) |
24 | | * 2003-03-05 lock set support added for FAST_LOCK & SYSV (andrei) |
25 | | * 2003-03-06 removed *_alloc,*_dealloc & moved them to lock_alloc.h |
26 | | * renamed locking.h to lock_ops.h (all this to solve |
27 | | * the locking.h<->shm_mem.h interdependency) (andrei) |
28 | | * 2003-03-10 lock set support added also for PTHREAD_MUTEX & POSIX_SEM |
29 | | * (andrei) |
30 | | * 2003-03-17 possible signal interruptions treated for sysv (andrei) |
31 | | * 2004-07-28 s/lock_set_t/gen_lock_set_t/ because of a type conflict |
32 | | * on darwin (andrei) |
33 | | */ |
34 | | |
35 | | /*! |
36 | | * \file |
37 | | * \brief OpenSIPS locking operations |
38 | | * |
39 | | * Implements simple locks and lock sets. |
40 | | * |
41 | | * simple locks: |
42 | | * - gen_lock_t* lock_init(gen_lock_t* lock); - inits the lock |
43 | | * - void lock_destroy(gen_lock_t* lock); - removes the lock (e.g sysv rmid) |
44 | | * - void lock_get(gen_lock_t* lock); - lock (mutex down) |
45 | | * - void lock_release(gen_lock_t* lock); - unlock (mutex up) |
46 | | * |
47 | | * lock sets: [implemented only for FL & SYSV so far] |
48 | | * - gen_lock_set_t* lock_set_init(gen_lock_set_t* set); - inits the lock set |
49 | | * - void lock_set_destroy(gen_lock_set_t* s); - removes the lock set |
50 | | * - void lock_set_get(gen_lock_set_t* s, int i); - locks sem i from the set |
51 | | * - void lock_set_release(gen_lock_set_t* s, int i)- unlocks sem i from the set |
52 | | * |
53 | | * WARNING: |
54 | | * - lock_set_init may fail for large number of sems (e.g. sysv). |
55 | | * - signals are not treated! (some locks are "awakened" by the signals) |
56 | | * |
57 | | * \note Warning: do not include this file directly, use instead locking.h |
58 | | * (unless you don't need to alloc/dealloc locks). |
59 | | * \todo investigate futex support on linux |
60 | | */ |
61 | | |
62 | | |
63 | | #ifndef _lock_ops_h |
64 | | #define _lock_ops_h |
65 | | |
66 | | |
67 | | #ifdef FAST_LOCK |
68 | | |
69 | | #ifdef USE_FUTEX |
70 | | #include "futex_lock.h" |
71 | | |
72 | | typedef fx_lock_t gen_lock_t; |
73 | | |
74 | | #elif defined FAST_LOCK |
75 | | |
76 | | #include "fastlock.h" |
77 | | |
78 | | typedef fl_lock_t gen_lock_t; |
79 | | |
80 | | #endif |
81 | | |
82 | | #define lock_destroy(lock) /* do nothing */ |
83 | | |
84 | | inline static gen_lock_t* lock_init(gen_lock_t* lock) |
85 | 0 | { |
86 | 0 | init_lock(*lock); |
87 | 0 | return lock; |
88 | 0 | } Unexecuted instantiation: fuzz_csv_parser.c:lock_init Unexecuted instantiation: csv.c:lock_init Unexecuted instantiation: dprint.c:lock_init Unexecuted instantiation: pt.c:lock_init Unexecuted instantiation: ut.c:lock_init Unexecuted instantiation: statistics.c:lock_init Unexecuted instantiation: route.c:lock_init Unexecuted instantiation: ipc.c:lock_init Unexecuted instantiation: core_stats.c:lock_init Unexecuted instantiation: route_struct.c:lock_init Unexecuted instantiation: dset.c:lock_init Unexecuted instantiation: pt_load.c:lock_init Unexecuted instantiation: sr_module.c:lock_init Unexecuted instantiation: action.c:lock_init Unexecuted instantiation: db_insertq.c:lock_init Unexecuted instantiation: db.c:lock_init Unexecuted instantiation: proto_tcp.c:lock_init Unexecuted instantiation: proto_udp.c:lock_init Unexecuted instantiation: net_tcp_proc.c:lock_init Unexecuted instantiation: net_tcp.c:lock_init Unexecuted instantiation: tcp_common.c:lock_init Unexecuted instantiation: net_udp.c:lock_init Unexecuted instantiation: tcp_conn_profile.c:lock_init Unexecuted instantiation: trans_trace.c:lock_init Unexecuted instantiation: net_tcp_report.c:lock_init Unexecuted instantiation: shm_mem.c:lock_init Unexecuted instantiation: f_parallel_malloc.c:lock_init Unexecuted instantiation: common.c:lock_init Unexecuted instantiation: q_malloc.c:lock_init Unexecuted instantiation: rpm_mem.c:lock_init Unexecuted instantiation: mem.c:lock_init Unexecuted instantiation: mi.c:lock_init Unexecuted instantiation: item.c:lock_init Unexecuted instantiation: msg_parser.c:lock_init Unexecuted instantiation: parse_uri.c:lock_init Unexecuted instantiation: parse_fline.c:lock_init Unexecuted instantiation: parse_hname2.c:lock_init Unexecuted instantiation: parse_content.c:lock_init Unexecuted instantiation: hf.c:lock_init Unexecuted instantiation: parse_to.c:lock_init Unexecuted instantiation: parse_via.c:lock_init Unexecuted instantiation: event_interface.c:lock_init Unexecuted instantiation: evi_params.c:lock_init Unexecuted instantiation: receive.c:lock_init Unexecuted instantiation: ip_addr.c:lock_init Unexecuted instantiation: async.c:lock_init Unexecuted instantiation: daemonize.c:lock_init Unexecuted instantiation: timer.c:lock_init Unexecuted instantiation: trace_api.c:lock_init Unexecuted instantiation: mod_fix.c:lock_init Unexecuted instantiation: reactor.c:lock_init Unexecuted instantiation: strcommon.c:lock_init Unexecuted instantiation: forward.c:lock_init Unexecuted instantiation: xlog.c:lock_init Unexecuted instantiation: blacklists.c:lock_init Unexecuted instantiation: usr_avp.c:lock_init Unexecuted instantiation: sdp_ops.c:lock_init Unexecuted instantiation: resolve.c:lock_init Unexecuted instantiation: io_wait.c:lock_init Unexecuted instantiation: transformations.c:lock_init Unexecuted instantiation: pvar.c:lock_init Unexecuted instantiation: sr_module_deps.c:lock_init Unexecuted instantiation: cfg_reload.c:lock_init Unexecuted instantiation: socket_info.c:lock_init Unexecuted instantiation: time_rec.c:lock_init Unexecuted instantiation: map.c:lock_init Unexecuted instantiation: status_report.c:lock_init Unexecuted instantiation: pt_scaling.c:lock_init Unexecuted instantiation: signals.c:lock_init Unexecuted instantiation: flags.c:lock_init Unexecuted instantiation: db_id.c:lock_init Unexecuted instantiation: trans.c:lock_init Unexecuted instantiation: cJSON.c:lock_init Unexecuted instantiation: sdp.c:lock_init Unexecuted instantiation: sdp_helpr_funcs.c:lock_init Unexecuted instantiation: digest_parser.c:lock_init Unexecuted instantiation: param_parser.c:lock_init Unexecuted instantiation: parse_contact.c:lock_init Unexecuted instantiation: parse_body.c:lock_init Unexecuted instantiation: parse_security.c:lock_init Unexecuted instantiation: parse_call_info.c:lock_init Unexecuted instantiation: parse_event.c:lock_init Unexecuted instantiation: parse_disposition.c:lock_init Unexecuted instantiation: parse_authenticate.c:lock_init Unexecuted instantiation: parser_f.c:lock_init Unexecuted instantiation: parse_rpid.c:lock_init Unexecuted instantiation: parse_ppi.c:lock_init Unexecuted instantiation: parse_fcaps.c:lock_init Unexecuted instantiation: parse_rr.c:lock_init Unexecuted instantiation: parse_param.c:lock_init Unexecuted instantiation: parse_diversion.c:lock_init Unexecuted instantiation: parse_nameaddr.c:lock_init Unexecuted instantiation: parse_expires.c:lock_init Unexecuted instantiation: parse_refer_to.c:lock_init Unexecuted instantiation: parse_from.c:lock_init Unexecuted instantiation: parse_pai.c:lock_init Unexecuted instantiation: evi_transport.c:lock_init Unexecuted instantiation: msg_translator.c:lock_init Unexecuted instantiation: md5utils.c:lock_init Unexecuted instantiation: cfg.tab.c:lock_init Unexecuted instantiation: modparam.c:lock_init Unexecuted instantiation: crc.c:lock_init Unexecuted instantiation: lex.yy.c:lock_init Unexecuted instantiation: cfg_pp.c:lock_init Unexecuted instantiation: proxy.c:lock_init Unexecuted instantiation: shutdown.c:lock_init Unexecuted instantiation: core_cmds.c:lock_init Unexecuted instantiation: cachedb.c:lock_init Unexecuted instantiation: cachedb_id.c:lock_init |
89 | | |
90 | 0 | #define lock_release(lock) release_lock(lock) |
91 | | |
92 | | #ifndef DBG_LOCK |
93 | 0 | #define lock_get(lock) get_lock(lock) |
94 | | #else |
95 | | #define lock_get(lock) get_lock(lock, __FILE__, __FUNCTION__, __LINE__) |
96 | | #endif |
97 | | |
98 | | #elif defined USE_PTHREAD_MUTEX |
99 | | # if defined(__FreeBSD__) |
100 | | # warning Inter-process mutexes are not supported on FreeBSD as if yet :( |
101 | | # endif |
102 | | |
103 | | #include <pthread.h> |
104 | | |
105 | | typedef pthread_mutex_t gen_lock_t; |
106 | | |
107 | | inline static gen_lock_t* lock_init(gen_lock_t* lock) |
108 | | { |
109 | | pthread_mutexattr_t attr; |
110 | | |
111 | | if (pthread_mutexattr_init(&attr) != 0) |
112 | | return 0; |
113 | | |
114 | | if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) != 0) { |
115 | | pthread_mutexattr_destroy(&attr); |
116 | | return 0; |
117 | | } |
118 | | |
119 | | if (pthread_mutex_init(lock, &attr) != 0) { |
120 | | pthread_mutexattr_destroy(&attr); |
121 | | return 0; |
122 | | } |
123 | | |
124 | | pthread_mutexattr_destroy(&attr); |
125 | | return lock; |
126 | | } |
127 | | |
128 | | #define lock_destroy(lock) pthread_mutex_destroy(lock) |
129 | | #define lock_get(lock) pthread_mutex_lock(lock) |
130 | | #define lock_release(lock) pthread_mutex_unlock(lock) |
131 | | |
132 | | #elif defined USE_UMUTEX |
133 | | # if !defined(USE_UMUTEX_DECL) |
134 | | # define USE_UMUTEX_DECL 1 |
135 | | #include <sys/types.h> |
136 | | |
137 | | #include <errno.h> |
138 | | #include <string.h> |
139 | | |
140 | | #define u_long unsigned long |
141 | | #include <sys/umtx.h> |
142 | | |
143 | | typedef struct umutex gen_lock_t; |
144 | | |
145 | | #define lock_destroy(lock) /* do nothing */ |
146 | | |
147 | | inline static int |
148 | | _umtx_op_err(void *obj, int op, u_long val, void *uaddr, void *uaddr2) |
149 | | { |
150 | | |
151 | | if (_umtx_op(obj, op, val, uaddr, uaddr2) == -1) |
152 | | return (errno); |
153 | | return (0); |
154 | | } |
155 | | |
156 | | inline static gen_lock_t * |
157 | | lock_init(gen_lock_t *lock) |
158 | | { |
159 | | |
160 | | memset(lock, '\0', sizeof(gen_lock_t)); |
161 | | lock->m_flags = USYNC_PROCESS_SHARED; |
162 | | |
163 | | return (lock); |
164 | | } |
165 | | |
166 | | inline static int |
167 | | lock_get(gen_lock_t *lock) |
168 | | { |
169 | | |
170 | | return (_umtx_op_err(lock, UMTX_OP_MUTEX_LOCK, 0, 0, 0)); |
171 | | } |
172 | | |
173 | | inline static int |
174 | | lock_release(gen_lock_t *lock) |
175 | | { |
176 | | |
177 | | return (_umtx_op_err(lock, UMTX_OP_MUTEX_UNLOCK, 0, 0, 0)); |
178 | | } |
179 | | |
180 | | # endif /* USE_UMUTEX_DECL */ |
181 | | #elif defined USE_POSIX_SEM |
182 | | #include <semaphore.h> |
183 | | |
184 | | typedef sem_t gen_lock_t; |
185 | | |
186 | | #define lock_destroy(lock) /* do nothing */ |
187 | | |
188 | | inline static gen_lock_t* lock_init(gen_lock_t* lock) |
189 | | { |
190 | | |
191 | | if (sem_init(lock, 1, 1)<0) return 0; |
192 | | return lock; |
193 | | } |
194 | | |
195 | | #define lock_get(lock) sem_wait(lock) |
196 | | #define lock_release(lock) sem_post(lock) |
197 | | |
198 | | #elif defined USE_SYSV_SEM |
199 | | #include <sys/ipc.h> |
200 | | #include <sys/sem.h> |
201 | | |
202 | | #include <errno.h> |
203 | | #include <string.h> |
204 | | #include <sys/types.h> |
205 | | #include <unistd.h> |
206 | | #include "dprint.h" |
207 | | extern int uid; /* from main.c */ |
208 | | |
209 | | #if ((defined(HAVE_UNION_SEMUN) || defined(__GNU_LIBRARY__) )&& !defined(_SEM_SEMUN_UNDEFINED)) |
210 | | |
211 | | /* union semun is defined by including sem.h */ |
212 | | #else |
213 | | /* according to X/OPEN we have to define it ourselves */ |
214 | | union semun { |
215 | | int val; /* value for SETVAL */ |
216 | | struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ |
217 | | unsigned short int *array; /* array for GETALL, SETALL */ |
218 | | struct seminfo *__buf; /* buffer for IPC_INFO */ |
219 | | }; |
220 | | #endif |
221 | | |
222 | | typedef int gen_lock_t; |
223 | | |
224 | | inline static gen_lock_t* lock_init(gen_lock_t* lock) |
225 | | { |
226 | | union semun su; |
227 | | int euid; |
228 | | |
229 | | euid=geteuid(); |
230 | | if (uid && uid!=euid) |
231 | | seteuid(uid); /* set euid to the cfg. requested one */ |
232 | | *lock=semget(IPC_PRIVATE, 1, 0700); |
233 | | if (uid && uid!=euid) |
234 | | seteuid(euid); /* restore it */ |
235 | | if (*lock==-1) return 0; |
236 | | su.val=1; |
237 | | if (semctl(*lock, 0, SETVAL, su)==-1){ |
238 | | /* init error*/ |
239 | | return 0; |
240 | | } |
241 | | |
242 | | return lock; |
243 | | |
244 | | } |
245 | | |
246 | | //TODO if is init |
247 | | inline static void lock_destroy(gen_lock_t* lock) |
248 | | { |
249 | | union semun su; |
250 | | su.val = 0; |
251 | | semctl(*lock, 0, IPC_RMID, su); |
252 | | } |
253 | | |
254 | | |
255 | | inline static void lock_get(gen_lock_t* lock) |
256 | | { |
257 | | struct sembuf sop; |
258 | | |
259 | | sop.sem_num=0; |
260 | | sop.sem_op=-1; /* down */ |
261 | | sop.sem_flg=0; |
262 | | tryagain: |
263 | | if (semop(*lock, &sop, 1)==-1){ |
264 | | if (errno==EINTR){ |
265 | | LM_DBG("signal received while waiting for on a mutex\n"); |
266 | | goto tryagain; |
267 | | }else{ |
268 | | LM_CRIT("%s (%d)\n", strerror(errno), errno); |
269 | | } |
270 | | } |
271 | | |
272 | | } |
273 | | |
274 | | inline static void lock_release(gen_lock_t* lock) |
275 | | { |
276 | | struct sembuf sop; |
277 | | |
278 | | sop.sem_num=0; |
279 | | sop.sem_op=1; /* up */ |
280 | | sop.sem_flg=0; |
281 | | tryagain: |
282 | | |
283 | | if (semop(*lock, &sop, 1)==-1){ |
284 | | if (errno==EINTR){ |
285 | | /* very improbable*/ |
286 | | LM_DBG("signal received while releasing a mutex\n"); |
287 | | goto tryagain; |
288 | | }else{ |
289 | | LM_CRIT("%s (%d)\n", strerror(errno), errno); |
290 | | } |
291 | | } |
292 | | } |
293 | | |
294 | | |
295 | | #else |
296 | | #error "no locking method selected" |
297 | | #endif |
298 | | |
299 | | |
300 | | /* lock sets */ |
301 | | |
302 | | #if defined(FAST_LOCK) || defined(USE_PTHREAD_MUTEX) || defined(USE_POSIX_SEM) || defined(USE_UMUTEX) |
303 | | #define GEN_LOCK_T_PREFERED |
304 | | |
305 | | struct gen_lock_set_t_ { |
306 | | long size; |
307 | | gen_lock_t* locks; |
308 | | }; /* must be aligned (32 bits or 64 depending on the arch)*/ |
309 | | typedef struct gen_lock_set_t_ gen_lock_set_t; |
310 | | |
311 | | |
312 | | #define lock_set_destroy(lock_set) /* do nothing */ |
313 | | |
314 | | inline static gen_lock_set_t* lock_set_init(gen_lock_set_t* s) |
315 | 0 | { |
316 | 0 | int r; |
317 | 0 | for (r=0; r<s->size; r++) if (lock_init(&s->locks[r])==0) return 0; |
318 | 0 | return s; |
319 | 0 | } Unexecuted instantiation: fuzz_csv_parser.c:lock_set_init Unexecuted instantiation: csv.c:lock_set_init Unexecuted instantiation: dprint.c:lock_set_init Unexecuted instantiation: pt.c:lock_set_init Unexecuted instantiation: ut.c:lock_set_init Unexecuted instantiation: statistics.c:lock_set_init Unexecuted instantiation: route.c:lock_set_init Unexecuted instantiation: ipc.c:lock_set_init Unexecuted instantiation: core_stats.c:lock_set_init Unexecuted instantiation: route_struct.c:lock_set_init Unexecuted instantiation: dset.c:lock_set_init Unexecuted instantiation: pt_load.c:lock_set_init Unexecuted instantiation: sr_module.c:lock_set_init Unexecuted instantiation: action.c:lock_set_init Unexecuted instantiation: db_insertq.c:lock_set_init Unexecuted instantiation: db.c:lock_set_init Unexecuted instantiation: proto_tcp.c:lock_set_init Unexecuted instantiation: proto_udp.c:lock_set_init Unexecuted instantiation: net_tcp_proc.c:lock_set_init Unexecuted instantiation: net_tcp.c:lock_set_init Unexecuted instantiation: tcp_common.c:lock_set_init Unexecuted instantiation: net_udp.c:lock_set_init Unexecuted instantiation: tcp_conn_profile.c:lock_set_init Unexecuted instantiation: trans_trace.c:lock_set_init Unexecuted instantiation: net_tcp_report.c:lock_set_init Unexecuted instantiation: shm_mem.c:lock_set_init Unexecuted instantiation: f_parallel_malloc.c:lock_set_init Unexecuted instantiation: common.c:lock_set_init Unexecuted instantiation: q_malloc.c:lock_set_init Unexecuted instantiation: rpm_mem.c:lock_set_init Unexecuted instantiation: mem.c:lock_set_init Unexecuted instantiation: mi.c:lock_set_init Unexecuted instantiation: item.c:lock_set_init Unexecuted instantiation: msg_parser.c:lock_set_init Unexecuted instantiation: parse_uri.c:lock_set_init Unexecuted instantiation: parse_fline.c:lock_set_init Unexecuted instantiation: parse_hname2.c:lock_set_init Unexecuted instantiation: parse_content.c:lock_set_init Unexecuted instantiation: hf.c:lock_set_init Unexecuted instantiation: parse_to.c:lock_set_init Unexecuted instantiation: parse_via.c:lock_set_init Unexecuted instantiation: event_interface.c:lock_set_init Unexecuted instantiation: evi_params.c:lock_set_init Unexecuted instantiation: receive.c:lock_set_init Unexecuted instantiation: ip_addr.c:lock_set_init Unexecuted instantiation: async.c:lock_set_init Unexecuted instantiation: daemonize.c:lock_set_init Unexecuted instantiation: timer.c:lock_set_init Unexecuted instantiation: trace_api.c:lock_set_init Unexecuted instantiation: mod_fix.c:lock_set_init Unexecuted instantiation: reactor.c:lock_set_init Unexecuted instantiation: strcommon.c:lock_set_init Unexecuted instantiation: forward.c:lock_set_init Unexecuted instantiation: xlog.c:lock_set_init Unexecuted instantiation: blacklists.c:lock_set_init Unexecuted instantiation: usr_avp.c:lock_set_init Unexecuted instantiation: sdp_ops.c:lock_set_init Unexecuted instantiation: resolve.c:lock_set_init Unexecuted instantiation: io_wait.c:lock_set_init Unexecuted instantiation: transformations.c:lock_set_init Unexecuted instantiation: pvar.c:lock_set_init Unexecuted instantiation: sr_module_deps.c:lock_set_init Unexecuted instantiation: cfg_reload.c:lock_set_init Unexecuted instantiation: socket_info.c:lock_set_init Unexecuted instantiation: time_rec.c:lock_set_init Unexecuted instantiation: map.c:lock_set_init Unexecuted instantiation: status_report.c:lock_set_init Unexecuted instantiation: pt_scaling.c:lock_set_init Unexecuted instantiation: signals.c:lock_set_init Unexecuted instantiation: flags.c:lock_set_init Unexecuted instantiation: db_id.c:lock_set_init Unexecuted instantiation: trans.c:lock_set_init Unexecuted instantiation: cJSON.c:lock_set_init Unexecuted instantiation: sdp.c:lock_set_init Unexecuted instantiation: sdp_helpr_funcs.c:lock_set_init Unexecuted instantiation: digest_parser.c:lock_set_init Unexecuted instantiation: param_parser.c:lock_set_init Unexecuted instantiation: parse_contact.c:lock_set_init Unexecuted instantiation: parse_body.c:lock_set_init Unexecuted instantiation: parse_security.c:lock_set_init Unexecuted instantiation: parse_call_info.c:lock_set_init Unexecuted instantiation: parse_event.c:lock_set_init Unexecuted instantiation: parse_disposition.c:lock_set_init Unexecuted instantiation: parse_authenticate.c:lock_set_init Unexecuted instantiation: parser_f.c:lock_set_init Unexecuted instantiation: parse_rpid.c:lock_set_init Unexecuted instantiation: parse_ppi.c:lock_set_init Unexecuted instantiation: parse_fcaps.c:lock_set_init Unexecuted instantiation: parse_rr.c:lock_set_init Unexecuted instantiation: parse_param.c:lock_set_init Unexecuted instantiation: parse_diversion.c:lock_set_init Unexecuted instantiation: parse_nameaddr.c:lock_set_init Unexecuted instantiation: parse_expires.c:lock_set_init Unexecuted instantiation: parse_refer_to.c:lock_set_init Unexecuted instantiation: parse_from.c:lock_set_init Unexecuted instantiation: parse_pai.c:lock_set_init Unexecuted instantiation: evi_transport.c:lock_set_init Unexecuted instantiation: msg_translator.c:lock_set_init Unexecuted instantiation: md5utils.c:lock_set_init Unexecuted instantiation: cfg.tab.c:lock_set_init Unexecuted instantiation: modparam.c:lock_set_init Unexecuted instantiation: crc.c:lock_set_init Unexecuted instantiation: lex.yy.c:lock_set_init Unexecuted instantiation: cfg_pp.c:lock_set_init Unexecuted instantiation: proxy.c:lock_set_init Unexecuted instantiation: shutdown.c:lock_set_init Unexecuted instantiation: core_cmds.c:lock_set_init Unexecuted instantiation: cachedb.c:lock_set_init Unexecuted instantiation: cachedb_id.c:lock_set_init |
320 | | |
321 | | /* WARNING: no boundary checks!*/ |
322 | | #define lock_set_get(set, i) lock_get(&set->locks[i]) |
323 | | #define lock_set_release(set, i) lock_release(&set->locks[i]) |
324 | | |
325 | | #elif defined(USE_SYSV_SEM) |
326 | | #undef GEN_LOCK_T_PREFERED |
327 | | |
328 | | struct gen_lock_set_t_ { |
329 | | int size; |
330 | | int semid; |
331 | | }; |
332 | | |
333 | | |
334 | | typedef struct gen_lock_set_t_ gen_lock_set_t; |
335 | | inline static gen_lock_set_t* lock_set_init(gen_lock_set_t* s) |
336 | | { |
337 | | union semun su; |
338 | | int r; |
339 | | int euid; |
340 | | |
341 | | euid=geteuid(); |
342 | | if (uid && uid!=euid) |
343 | | seteuid(uid); /* set euid to the cfg. requested one */ |
344 | | s->semid=semget(IPC_PRIVATE, s->size, 0700); |
345 | | if (uid && uid!=euid) |
346 | | seteuid(euid); /* restore euid */ |
347 | | if (s->semid==-1){ |
348 | | LM_CRIT("semget (..., %d, 0700) failed: %s\n", |
349 | | s->size, strerror(errno)); |
350 | | return 0; |
351 | | } |
352 | | su.val=1; |
353 | | for (r=0; r<s->size; r++){ |
354 | | if (semctl(s->semid, r, SETVAL, su)==-1){ |
355 | | LM_CRIT("semctl failed on sem %d: %s\n", |
356 | | r, strerror(errno)); |
357 | | su.val = 0; |
358 | | semctl(s->semid, 0, IPC_RMID, su); |
359 | | return 0; |
360 | | } |
361 | | } |
362 | | return s; |
363 | | } |
364 | | |
365 | | inline static void lock_set_destroy(gen_lock_set_t* s) |
366 | | { |
367 | | union semun su; |
368 | | |
369 | | su.val = 0; |
370 | | semctl(s->semid, 0, IPC_RMID, su); |
371 | | } |
372 | | |
373 | | inline static void lock_set_get(gen_lock_set_t* s, int n) |
374 | | { |
375 | | struct sembuf sop; |
376 | | sop.sem_num=n; |
377 | | sop.sem_op=-1; /* down */ |
378 | | sop.sem_flg=0; |
379 | | tryagain: |
380 | | if (semop(s->semid, &sop, 1)==-1){ |
381 | | if (errno==EINTR){ |
382 | | LM_DBG("signal received while waiting on a mutex\n"); |
383 | | goto tryagain; |
384 | | }else{ |
385 | | LM_CRIT("%s (%d)\n", strerror(errno), errno); |
386 | | } |
387 | | } |
388 | | } |
389 | | |
390 | | inline static void lock_set_release(gen_lock_set_t* s, int n) |
391 | | { |
392 | | struct sembuf sop; |
393 | | sop.sem_num=n; |
394 | | sop.sem_op=1; /* up */ |
395 | | sop.sem_flg=0; |
396 | | tryagain: |
397 | | if (semop(s->semid, &sop, 1)==-1){ |
398 | | if (errno==EINTR){ |
399 | | /* very improbable */ |
400 | | LM_DBG("signal received while releasing mutex\n"); |
401 | | goto tryagain; |
402 | | }else{ |
403 | | LM_CRIT("%s (%d)\n", strerror(errno), errno); |
404 | | } |
405 | | } |
406 | | |
407 | | } |
408 | | #else |
409 | | #error "no lock set method selected" |
410 | | #endif |
411 | | |
412 | | |
413 | | #endif |