Wed Jan 8 2020 09:50:13

Asterisk developer's documentation


func_lock.c File Reference

Dialplan mutexes. More...

#include "asterisk.h"
#include <signal.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/linkedlists.h"
#include "asterisk/astobj2.h"
#include "asterisk/utils.h"

Go to the source code of this file.

Data Structures

struct  channel_lock_frame
 
struct  lock_frame
 
struct  locklist
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int ast_channel_cmp_cb (void *obj, void *arg, int flags)
 
static int ast_channel_hash_cb (const void *obj, const int flags)
 
static int get_lock (struct ast_channel *chan, char *lockname, int trylock)
 
static int load_module (void)
 
static void * lock_broker (void *unused)
 
static void lock_fixup (void *data, struct ast_channel *oldchan, struct ast_channel *newchan)
 
static void lock_free (void *data)
 
static int lock_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int trylock_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int unload_module (void)
 
static int unlock_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Dialplan mutexes" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static struct ast_module_infoast_module_info = &__mod_info
 
static pthread_t broker_tid = AST_PTHREADT_NULL
 
static struct ast_custom_function lock_function
 
static struct ast_datastore_info lock_info
 
static struct locklist locklist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
 
static struct ast_custom_function trylock_function
 
static int unloading = 0
 
static struct ast_custom_function unlock_function
 

Detailed Description

Dialplan mutexes.

Author
Tilghman Lesher func_.nosp@m.lock.nosp@m._2007.nosp@m.@the.nosp@m.-tilg.nosp@m.hman.nosp@m..com

Definition in file func_lock.c.

Function Documentation

static void __reg_module ( void  )
static

Definition at line 534 of file func_lock.c.

static void __unreg_module ( void  )
static

Definition at line 534 of file func_lock.c.

static int ast_channel_cmp_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 226 of file func_lock.c.

References CMP_MATCH, and ast_channel::name.

Referenced by get_lock().

227 {
228  struct ast_channel *chan = obj, *cmp_args = arg;
229  return strcasecmp(chan->name, cmp_args->name) ? 0 : CMP_MATCH;
230 }
Main Channel structure associated with a channel.
Definition: channel.h:742
const ast_string_field name
Definition: channel.h:787
static int ast_channel_hash_cb ( const void *  obj,
const int  flags 
)
static

Definition at line 220 of file func_lock.c.

References ast_str_case_hash(), and ast_channel::name.

Referenced by get_lock().

221 {
222  const struct ast_channel *chan = obj;
223  return ast_str_case_hash(chan->name);
224 }
Main Channel structure associated with a channel.
Definition: channel.h:742
const ast_string_field name
Definition: channel.h:787
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:989
static int get_lock ( struct ast_channel chan,
char *  lockname,
int  trylock 
)
static

Definition at line 232 of file func_lock.c.

References ao2_container_alloc, ao2_link, ao2_unlink, ast_calloc, ast_channel_cmp_cb(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_hash_cb(), ast_cond_destroy, ast_cond_init, ast_cond_timedwait, ast_datastore_alloc(), ast_datastore_free(), ast_debug, ast_free, AST_LIST_HEAD, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_tvnow(), channel_lock_frame::channel, lock_frame::cond, lock_frame::count, ast_datastore::data, channel_lock_frame::list, channel_lock_frame::lock_frame, LOG_ERROR, lock_frame::mutex, lock_frame::name, ast_channel::name, lock_frame::owner, and lock_frame::requesters.

Referenced by lock_read(), and trylock_read().

233 {
234  struct ast_datastore *lock_store = ast_channel_datastore_find(chan, &lock_info, NULL);
235  struct lock_frame *current;
236  struct channel_lock_frame *clframe = NULL;
238  int res = 0;
239  struct timespec timeout = { 0, };
240  struct timeval now;
241 
242  if (!lock_store) {
243  ast_debug(1, "Channel %s has no lock datastore, so we're allocating one.\n", chan->name);
244  lock_store = ast_datastore_alloc(&lock_info, NULL);
245  if (!lock_store) {
246  ast_log(LOG_ERROR, "Unable to allocate new datastore. No locks will be obtained.\n");
247  return -1;
248  }
249 
250  list = ast_calloc(1, sizeof(*list));
251  if (!list) {
253  "Unable to allocate datastore list head. %sLOCK will fail.\n",
254  trylock ? "TRY" : "");
255  ast_datastore_free(lock_store);
256  return -1;
257  }
258 
259  lock_store->data = list;
260  AST_LIST_HEAD_INIT(list);
261  ast_channel_datastore_add(chan, lock_store);
262  } else
263  list = lock_store->data;
264 
265  /* Lock already exists? */
267  AST_LIST_TRAVERSE(&locklist, current, entries) {
268  if (strcmp(current->name, lockname) == 0) {
269  break;
270  }
271  }
272 
273  if (!current) {
274  if (unloading) {
275  /* Don't bother */
277  return -1;
278  }
279 
280  /* Create new lock entry */
281  current = ast_calloc(1, sizeof(*current) + strlen(lockname) + 1);
282  if (!current) {
284  return -1;
285  }
286 
287  strcpy(current->name, lockname); /* SAFE */
288  if ((res = ast_mutex_init(&current->mutex))) {
289  ast_log(LOG_ERROR, "Unable to initialize mutex: %s\n", strerror(res));
290  ast_free(current);
292  return -1;
293  }
294  if ((res = ast_cond_init(&current->cond, NULL))) {
295  ast_log(LOG_ERROR, "Unable to initialize condition variable: %s\n", strerror(res));
296  ast_mutex_destroy(&current->mutex);
297  ast_free(current);
299  return -1;
300  }
302  ast_mutex_destroy(&current->mutex);
303  ast_cond_destroy(&current->cond);
304  ast_free(current);
306  return -1;
307  }
308  AST_LIST_INSERT_TAIL(&locklist, current, entries);
309  }
311 
312  /* Found lock or created one - now find or create the corresponding link in the channel */
313  AST_LIST_LOCK(list);
314  AST_LIST_TRAVERSE(list, clframe, list) {
315  if (clframe->lock_frame == current) {
316  break;
317  }
318  }
319 
320  if (!clframe) {
321  if (unloading) {
322  /* Don't bother */
323  AST_LIST_UNLOCK(list);
324  return -1;
325  }
326 
327  if (!(clframe = ast_calloc(1, sizeof(*clframe)))) {
329  "Unable to allocate channel lock frame. %sLOCK will fail.\n",
330  trylock ? "TRY" : "");
331  AST_LIST_UNLOCK(list);
332  return -1;
333  }
334 
335  clframe->lock_frame = current;
336  clframe->channel = chan;
337  AST_LIST_INSERT_TAIL(list, clframe, list);
338  }
339  AST_LIST_UNLOCK(list);
340 
341  /* If we already own the lock, then we're being called recursively.
342  * Keep track of how many times that is, because we need to unlock
343  * the same amount, before we'll release this one.
344  */
345  if (current->owner == chan) {
346  current->count++;
347  return 0;
348  }
349 
350  /* Okay, we have both frames, so now we need to try to lock.
351  *
352  * Locking order: always lock locklist first. We need the
353  * locklist lock because the broker thread counts whether
354  * there are requesters with the locklist lock held, and we
355  * need to hold it, so that when we send our signal, below,
356  * to wake up the broker thread, it definitely will see that
357  * a requester exists at that point in time. Otherwise, we
358  * could add to the requesters after it has already seen that
359  * that lock is unoccupied and wait forever for another signal.
360  */
362  ast_mutex_lock(&current->mutex);
363  /* Add to requester list */
364  ao2_link(current->requesters, chan);
365  pthread_kill(broker_tid, SIGURG);
367 
368  /* Wait up to three seconds from now for LOCK. */
369  now = ast_tvnow();
370  timeout.tv_sec = now.tv_sec + 3;
371  timeout.tv_nsec = now.tv_usec * 1000;
372 
373  if (!current->owner
374  || (!trylock
375  && !(res = ast_cond_timedwait(&current->cond, &current->mutex, &timeout)))) {
376  res = 0;
377  current->owner = chan;
378  current->count++;
379  } else {
380  res = -1;
381  }
382  /* Remove from requester list */
383  ao2_unlink(current->requesters, chan);
384  ast_mutex_unlock(&current->mutex);
385 
386  return res;
387 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
static int unloading
Definition: func_lock.c:114
struct lock_frame * lock_frame
Definition: func_lock.c:141
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct ao2_container * requesters
Definition: func_lock.c:130
#define ast_cond_init(cond, attr)
Definition: lock.h:167
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define ast_mutex_lock(a)
Definition: lock.h:155
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
struct channel_lock_frame::@135 list
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
static int ast_channel_hash_cb(const void *obj, const int flags)
Definition: func_lock.c:220
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
ast_mutex_t mutex
Definition: func_lock.c:125
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_cond_destroy(cond)
Definition: lock.h:168
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
ast_cond_t cond
Definition: func_lock.c:126
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
Definition: linkedlists.h:611
#define ast_free(a)
Definition: astmm.h:97
char name[0]
Definition: func_lock.c:134
void * data
Definition: datastore.h:56
#define ast_calloc(a, b)
Definition: astmm.h:82
struct ast_channel * owner
Definition: func_lock.c:132
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
struct ast_channel * channel
Definition: func_lock.c:140
static struct ast_datastore_info lock_info
Definition: func_lock.c:117
#define ast_mutex_init(pmutex)
Definition: lock.h:152
#define ast_mutex_destroy(a)
Definition: lock.h:154
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
#define ao2_unlink(arg1, arg2)
Definition: astobj2.h:817
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:172
unsigned int count
Definition: func_lock.c:128
static int ast_channel_cmp_cb(void *obj, void *arg, int flags)
Definition: func_lock.c:226
static pthread_t broker_tid
Definition: func_lock.c:115
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int load_module ( void  )
static

Definition at line 518 of file func_lock.c.

References AST_CFE_READ, ast_custom_function_register_escalating, ast_log(), AST_MODULE_LOAD_DECLINE, ast_pthread_create_background, AST_PTHREADT_NULL, lock_broker(), LOG_ERROR, and unload_module().

519 {
523 
525  ast_log(LOG_ERROR, "Failed to start lock broker thread. Unloading func_lock module.\n");
527  unload_module();
529  }
530 
531  return res;
532 }
static struct ast_custom_function trylock_function
Definition: func_lock.c:468
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:426
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
Definition: pbx.h:1173
static void * lock_broker(void *unused)
Definition: func_lock.c:184
#define AST_PTHREADT_NULL
Definition: lock.h:65
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_custom_function unlock_function
Definition: func_lock.c:474
static int unload_module(void)
Definition: func_lock.c:480
static struct ast_custom_function lock_function
Definition: func_lock.c:462
static pthread_t broker_tid
Definition: func_lock.c:115
static void* lock_broker ( void *  unused)
static

Definition at line 184 of file func_lock.c.

References ao2_container_count(), ast_cond_signal, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, lock_frame::cond, lock_frame::mutex, lock_frame::owner, and lock_frame::requesters.

Referenced by load_module().

185 {
186  struct lock_frame *frame;
187  struct timespec forever = { 1000000, 0 };
188  for (;;) {
189  int found_requester = 0;
190 
191  /* Test for cancel outside of the lock */
192  pthread_testcancel();
194 
195  AST_LIST_TRAVERSE(&locklist, frame, entries) {
196  if (ao2_container_count(frame->requesters)) {
197  found_requester++;
198  ast_mutex_lock(&frame->mutex);
199  if (!frame->owner) {
200  ast_cond_signal(&frame->cond);
201  }
202  ast_mutex_unlock(&frame->mutex);
203  }
204  }
205 
207  pthread_testcancel();
208 
209  /* If there are no requesters, then wait for a signal */
210  if (!found_requester) {
211  nanosleep(&forever, NULL);
212  } else {
213  sched_yield();
214  }
215  }
216  /* Not reached */
217  return NULL;
218 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct ao2_container * requesters
Definition: func_lock.c:130
#define ast_mutex_lock(a)
Definition: lock.h:155
#define ast_cond_signal(cond)
Definition: lock.h:169
ast_mutex_t mutex
Definition: func_lock.c:125
ast_cond_t cond
Definition: func_lock.c:126
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_channel * owner
Definition: func_lock.c:132
#define ast_mutex_unlock(a)
Definition: lock.h:156
static void lock_fixup ( void *  data,
struct ast_channel oldchan,
struct ast_channel newchan 
)
static

Definition at line 162 of file func_lock.c.

References ast_channel_datastore_find(), AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, channel_lock_frame::channel, ast_datastore::data, channel_lock_frame::list, channel_lock_frame::lock_frame, and lock_frame::owner.

163 {
164  struct ast_datastore *lock_store = ast_channel_datastore_find(oldchan, &lock_info, NULL);
166  struct channel_lock_frame *clframe = NULL;
167 
168  if (!lock_store) {
169  return;
170  }
171  list = lock_store->data;
172 
174  AST_LIST_TRAVERSE(list, clframe, list) {
175  if (clframe->lock_frame->owner == oldchan) {
176  clframe->lock_frame->owner = newchan;
177  }
178  /* We don't move requesters, because the thread stack is different */
179  clframe->channel = newchan;
180  }
182 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
struct lock_frame * lock_frame
Definition: func_lock.c:141
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
struct channel_lock_frame::@135 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
void * data
Definition: datastore.h:56
struct ast_channel * owner
Definition: func_lock.c:132
struct ast_channel * channel
Definition: func_lock.c:140
static struct ast_datastore_info lock_info
Definition: func_lock.c:117
static void lock_free ( void *  data)
static

Definition at line 144 of file func_lock.c.

References ast_free, AST_LIST_HEAD, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, channel_lock_frame::channel, lock_frame::count, channel_lock_frame::lock_frame, and lock_frame::owner.

145 {
146  AST_LIST_HEAD(, channel_lock_frame) *oldlist = data;
147  struct channel_lock_frame *clframe;
148  AST_LIST_LOCK(oldlist);
149  while ((clframe = AST_LIST_REMOVE_HEAD(oldlist, list))) {
150  /* Only unlock if we own the lock */
151  if (clframe->channel == clframe->lock_frame->owner) {
152  clframe->lock_frame->count = 0;
153  clframe->lock_frame->owner = NULL;
154  }
155  ast_free(clframe);
156  }
157  AST_LIST_UNLOCK(oldlist);
158  AST_LIST_HEAD_DESTROY(oldlist);
159  ast_free(oldlist);
160 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
struct lock_frame * lock_frame
Definition: func_lock.c:141
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct channel_lock_frame::@135 list
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
Definition: linkedlists.h:638
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
struct ast_channel * owner
Definition: func_lock.c:132
struct ast_channel * channel
Definition: func_lock.c:140
unsigned int count
Definition: func_lock.c:128
static int lock_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 438 of file func_lock.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), and get_lock().

439 {
440  if (!chan) {
441  return -1;
442  }
443  ast_autoservice_start(chan);
444  ast_copy_string(buf, get_lock(chan, data, 0) ? "0" : "1", len);
445  ast_autoservice_stop(chan);
446 
447  return 0;
448 }
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int get_lock(struct ast_channel *chan, char *lockname, int trylock)
Definition: func_lock.c:232
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int trylock_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 450 of file func_lock.c.

References ast_autoservice_start(), ast_autoservice_stop(), ast_copy_string(), and get_lock().

451 {
452  if (!chan) {
453  return -1;
454  }
455  ast_autoservice_start(chan);
456  ast_copy_string(buf, get_lock(chan, data, 1) ? "0" : "1", len);
457  ast_autoservice_stop(chan);
458 
459  return 0;
460 }
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int get_lock(struct ast_channel *chan, char *lockname, int trylock)
Definition: func_lock.c:232
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int unload_module ( void  )
static

Definition at line 480 of file func_lock.c.

References ao2_container_count(), ao2_ref, ast_custom_function_unregister(), ast_free, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_mutex_destroy, AST_PTHREADT_NULL, lock_frame::mutex, lock_frame::owner, and lock_frame::requesters.

Referenced by load_module().

481 {
482  struct lock_frame *current;
483 
484  /* Module flag */
485  unloading = 1;
486 
488  while ((current = AST_LIST_REMOVE_HEAD(&locklist, entries))) {
489  /* If any locks are currently in use, then we cannot unload this module */
490  if (current->owner || ao2_container_count(current->requesters)) {
491  /* Put it back */
494  unloading = 0;
495  return -1;
496  }
497  ast_mutex_destroy(&current->mutex);
498  ao2_ref(current->requesters, -1);
499  ast_free(current);
500  }
501 
502  /* No locks left, unregister functions */
506 
507  if (broker_tid != AST_PTHREADT_NULL) {
508  pthread_cancel(broker_tid);
509  pthread_kill(broker_tid, SIGURG);
510  pthread_join(broker_tid, NULL);
511  }
512 
514 
515  return 0;
516 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
static int unloading
Definition: func_lock.c:114
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static struct ast_custom_function trylock_function
Definition: func_lock.c:468
struct ao2_container * requesters
Definition: func_lock.c:130
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
#define AST_PTHREADT_NULL
Definition: lock.h:65
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
ast_mutex_t mutex
Definition: func_lock.c:125
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
#define ast_free(a)
Definition: astmm.h:97
static struct ast_custom_function unlock_function
Definition: func_lock.c:474
struct ast_channel * owner
Definition: func_lock.c:132
#define ast_mutex_destroy(a)
Definition: lock.h:154
struct lock_frame::@134 entries
static struct ast_custom_function lock_function
Definition: func_lock.c:462
static pthread_t broker_tid
Definition: func_lock.c:115
static int unlock_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 389 of file func_lock.c.

References ast_channel_datastore_find(), ast_copy_string(), ast_debug, AST_LIST_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), lock_frame::count, ast_datastore::data, channel_lock_frame::list, channel_lock_frame::lock_frame, LOG_WARNING, lock_frame::name, and lock_frame::owner.

390 {
391  struct ast_datastore *lock_store;
392  struct channel_lock_frame *clframe;
394 
395  if (!chan) {
396  return -1;
397  }
398 
399  lock_store = ast_channel_datastore_find(chan, &lock_info, NULL);
400  if (!lock_store) {
401  ast_log(LOG_WARNING, "No datastore for dialplan locks. Nothing was ever locked!\n");
402  ast_copy_string(buf, "0", len);
403  return 0;
404  }
405 
406  if (!(list = lock_store->data)) {
407  ast_debug(1, "This should NEVER happen\n");
408  ast_copy_string(buf, "0", len);
409  return 0;
410  }
411 
412  /* Find item in the channel list */
414  AST_LIST_TRAVERSE(list, clframe, list) {
415  if (clframe->lock_frame && clframe->lock_frame->owner == chan && strcmp(clframe->lock_frame->name, data) == 0) {
416  break;
417  }
418  }
419  /* We never destroy anything until channel destruction, which will never
420  * happen while this routine is executing, so we don't need to hold the
421  * lock beyond this point. */
423 
424  if (!clframe) {
425  /* We didn't have this lock in the first place */
426  ast_copy_string(buf, "0", len);
427  return 0;
428  }
429 
430  if (--clframe->lock_frame->count == 0) {
431  clframe->lock_frame->owner = NULL;
432  }
433 
434  ast_copy_string(buf, "1", len);
435  return 0;
436 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:172
struct lock_frame * lock_frame
Definition: func_lock.c:141
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
struct channel_lock_frame::@135 list
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char name[0]
Definition: func_lock.c:134
void * data
Definition: datastore.h:56
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
struct ast_channel * owner
Definition: func_lock.c:132
static struct ast_datastore_info lock_info
Definition: func_lock.c:117
unsigned int count
Definition: func_lock.c:128

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Dialplan mutexes" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 534 of file func_lock.c.

Definition at line 534 of file func_lock.c.

pthread_t broker_tid = AST_PTHREADT_NULL
static

Definition at line 115 of file func_lock.c.

struct ast_custom_function lock_function
static
Initial value:
= {
.name = "LOCK",
.read = lock_read,
.read_max = 2,
}
static int lock_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_lock.c:438

Definition at line 462 of file func_lock.c.

struct ast_datastore_info lock_info
static
Initial value:
= {
.type = "MUTEX",
.destroy = lock_free,
.chan_fixup = lock_fixup,
}
static void lock_free(void *data)
Definition: func_lock.c:144
static void lock_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: func_lock.c:162

Definition at line 117 of file func_lock.c.

Referenced by dummy_start().

struct locklist locklist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
static
struct ast_custom_function trylock_function
static
Initial value:
= {
.name = "TRYLOCK",
.read = trylock_read,
.read_max = 2,
}
static int trylock_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_lock.c:450

Definition at line 468 of file func_lock.c.

int unloading = 0
static

Definition at line 114 of file func_lock.c.

struct ast_custom_function unlock_function
static
Initial value:
= {
.name = "UNLOCK",
.read = unlock_read,
.read_max = 2,
}
static int unlock_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_lock.c:389

Definition at line 474 of file func_lock.c.