Coverage Report

Created: 2025-07-18 06:32

/src/opensips/lock_ops.h
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