123 static void lock_free(
void *data);
125 static int unloading = 0;
129 .destroy = lock_free,
130 .chan_fixup = lock_fixup,
154 static void lock_free(
void *data)
162 ast_mutex_lock(&clframe->lock_frame->mutex);
163 clframe->lock_frame->
count = 0;
164 clframe->lock_frame->
owner = NULL;
165 ast_cond_signal(&clframe->lock_frame->cond);
166 ast_mutex_unlock(&clframe->lock_frame->mutex);
186 list = lock_store->
data;
190 if (clframe->lock_frame->
owner == oldchan) {
191 clframe->lock_frame->
owner = newchan;
198 static int get_lock(
struct ast_channel *chan,
char *lockname,
int trylock)
205 struct timespec timeout = { 0, };
210 ast_log(LOG_ERROR,
"%sLOCK has no datastore and func_lock is unloading, failing.\n",
211 trylock ?
"TRY" :
"");
215 lock_store = ast_datastore_alloc(&lock_info, NULL);
217 ast_log(LOG_ERROR,
"Unable to allocate new datastore. No locks will be obtained.\n");
224 "Unable to allocate datastore list head. %sLOCK will fail.\n",
225 trylock ?
"TRY" :
"");
230 lock_store->
data = list;
237 list = lock_store->
data;
242 if (strcmp(current->
name, lockname) == 0) {
250 "Lock doesn't exist whilst unloading. %sLOCK will fail.\n",
251 trylock ?
"TRY" :
"");
258 current =
ast_calloc(1,
sizeof(*current) + strlen(lockname) + 1);
264 strcpy(current->
name, lockname);
265 if ((res = ast_mutex_init(¤t->mutex))) {
266 ast_log(LOG_ERROR,
"Unable to initialize mutex: %s\n", strerror(res));
271 if ((res = ast_cond_init(¤t->cond, NULL))) {
272 ast_log(LOG_ERROR,
"Unable to initialize condition variable: %s\n", strerror(res));
273 ast_mutex_destroy(¤t->mutex);
281 ast_mutex_lock(¤t->mutex);
283 ast_mutex_unlock(¤t->mutex);
289 if (clframe->lock_frame == current) {
297 "Busy unloading. %sLOCK will fail.\n",
298 trylock ?
"TRY" :
"");
300 ast_mutex_lock(¤t->mutex);
302 ast_mutex_unlock(¤t->mutex);
307 if (!(clframe =
ast_calloc(1,
sizeof(*clframe)))) {
309 "Unable to allocate channel lock frame. %sLOCK will fail.\n",
310 trylock ?
"TRY" :
"");
311 ast_mutex_lock(¤t->mutex);
313 ast_mutex_unlock(¤t->mutex);
318 clframe->lock_frame = current;
328 if (current->
owner == chan) {
330 ast_mutex_lock(¤t->mutex);
332 ast_mutex_unlock(¤t->mutex);
339 timeout.tv_sec = now.tv_sec + 3;
340 timeout.tv_nsec = now.tv_usec * 1000;
342 ast_mutex_lock(¤t->mutex);
345 while (!trylock && !res && current->
owner) {
346 res = ast_cond_timedwait(¤t->cond, ¤t->mutex, &timeout);
348 if (current->
owner) {
357 current->
owner = chan;
363 if (res && unloading)
364 ast_cond_signal(¤t->cond);
365 ast_mutex_unlock(¤t->mutex);
370 static int unlock_read(
struct ast_channel *chan,
const char *cmd,
char *data,
char *buf,
size_t len)
382 ast_log(LOG_WARNING,
"No datastore for dialplan locks. Nothing was ever locked!\n");
387 if (!(list = lock_store->
data)) {
388 ast_debug(1,
"This should NEVER happen\n");
396 if (clframe->lock_frame && clframe->lock_frame->
owner == chan && strcmp(clframe->lock_frame->
name, data) == 0) {
411 if (--clframe->lock_frame->
count == 0) {
412 ast_mutex_lock(&clframe->lock_frame->mutex);
413 clframe->lock_frame->
owner = NULL;
414 ast_cond_signal(&clframe->lock_frame->cond);
415 ast_mutex_unlock(&clframe->lock_frame->mutex);
422 static int lock_read(
struct ast_channel *chan,
const char *cmd,
char *data,
char *buf,
size_t len)
434 static int trylock_read(
struct ast_channel *chan,
const char *cmd,
char *data,
char *buf,
size_t len)
452 e->
command =
"dialplan locks show";
454 "Usage: dialplan locks show\n"
455 " List all locks known to func_lock, along with their current status.\n";
461 ast_cli(a->fd,
"func_lock locks:\n");
462 ast_cli(a->fd,
"%-40s Requesters Owner\n",
"Name");
465 ast_mutex_lock(¤t->mutex);
466 ast_cli(a->fd,
"%-40s %-10d %s\n", current->
name, current->
requesters,
467 current->
owner ? ast_channel_name(current->
owner) :
"(unlocked)");
468 ast_mutex_unlock(¤t->mutex);
472 ast_cli(a->fd,
"%d total locks listed.\n", c);
485 .read = trylock_read,
495 static struct ast_cli_entry cli_locks_show = AST_CLI_DEFINE(handle_cli_locks_show,
"List func_lock locks.");
497 static int unload_module(
void)
514 ast_mutex_lock(¤t->mutex);
517 ast_log(LOG_WARNING,
"Waiting for %d requesters for %s lock %s.\n",
524 ast_cond_wait(¤t->cond, ¤t->mutex);
526 ast_mutex_unlock(¤t->mutex);
531 ast_mutex_destroy(¤t->mutex);
532 ast_cond_destroy(¤t->cond);
544 static int load_module(
void)
Main Channel structure associated with a channel.
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
descriptor for a cli entry.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Structure for a data store type.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Structure for a data store object.
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.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
#define ast_cli_register(e)
Registers a command or an array of commands.
#define ast_custom_function_register_escalating(acf, escalation)
Register a custom function which requires escalated privileges.
General Asterisk PBX channel definitions.
Data structure associated with a custom dialplan function.
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Core PBX routines and definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define ast_module_ref(mod)
Hold a reference to the module.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define ast_calloc(num, len)
A wrapper for calloc()
#define ast_module_unref(mod)
Release a reference to the module.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_channel * owner
struct ast_channel * channel
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Structure for mutex and tracking information.