Asterisk - The Open Source Telephony Project  GIT-master-a1fa8df
Typedefs | Enumerations | Functions
PJSIP Threading Model

Typedefs

typedef int(* ast_sip_task) (void *user_data)
 

Enumerations

enum  ast_sip_scheduler_task_flags {
  AST_SIP_SCHED_TASK_DEFAULTS = (0 << 0), AST_SIP_SCHED_TASK_FIXED = (0 << 0), AST_SIP_SCHED_TASK_VARIABLE = (1 << 0), AST_SIP_SCHED_TASK_ONESHOT = (1 << 6),
  AST_SIP_SCHED_TASK_DATA_NOT_AO2 = (0 << 1), AST_SIP_SCHED_TASK_DATA_AO2 = (1 << 1), AST_SIP_SCHED_TASK_DATA_NO_CLEANUP = (0 << 3), AST_SIP_SCHED_TASK_DATA_FREE = ( 1 << 3 ),
  AST_SIP_SCHED_TASK_PERIODIC = (0 << 4), AST_SIP_SCHED_TASK_DELAY = (1 << 4), AST_SIP_SCHED_TASK_TRACK = (1 << 5)
}
 Task flags for the res_pjsip scheduler. More...
 

Functions

struct ast_taskprocessorast_sip_create_serializer (const char *name)
 Create a new serializer for SIP tasks. More...
 
struct ast_taskprocessorast_sip_create_serializer_group (const char *name, struct ast_serializer_shutdown_group *shutdown_group)
 Create a new serializer for SIP tasks. More...
 
struct ast_sip_endpointast_sip_dialog_get_endpoint (pjsip_dialog *dlg)
 Get the endpoint associated with this dialog. More...
 
void ast_sip_dialog_set_endpoint (pjsip_dialog *dlg, struct ast_sip_endpoint *endpoint)
 Set an endpoint on a SIP dialog so in-dialog requests do not undergo endpoint lookup. More...
 
void ast_sip_dialog_set_serializer (pjsip_dialog *dlg, struct ast_taskprocessor *serializer)
 Set a serializer on a SIP dialog so requests and responses are automatically serialized. More...
 
struct ast_taskprocessorast_sip_get_distributor_serializer (pjsip_rx_data *rdata)
 Determine the distributor serializer for the SIP message. More...
 
int ast_sip_push_task (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 Pushes a task to SIP servants. More...
 
int ast_sip_push_task_synchronous (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 Push a task to SIP servants and wait for it to complete. More...
 
int ast_sip_push_task_wait_serializer (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 Push a task to the serializer and wait for it to complete. More...
 
int ast_sip_push_task_wait_servant (struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
 Push a task to SIP servants and wait for it to complete. More...
 
int ast_sip_sched_is_task_running (struct ast_sip_sched_task *schtd)
 Checks if the task is currently running. More...
 
int ast_sip_sched_is_task_running_by_name (const char *name)
 Checks if the task is currently running. More...
 
int ast_sip_sched_task_cancel (struct ast_sip_sched_task *schtd)
 Cancels the next invocation of a task. More...
 
int ast_sip_sched_task_cancel_by_name (const char *name)
 Cancels the next invocation of a task by name. More...
 
int ast_sip_sched_task_get_name (struct ast_sip_sched_task *schtd, char *name, size_t maxlen)
 Gets the task name. More...
 
int ast_sip_sched_task_get_next_run (struct ast_sip_sched_task *schtd)
 Gets the number of milliseconds until the next invocation. More...
 
int ast_sip_sched_task_get_next_run_by_name (const char *name)
 Gets the number of milliseconds until the next invocation. More...
 
int ast_sip_sched_task_get_times (struct ast_sip_sched_task *schtd, struct timeval *when_queued, struct timeval *last_start, struct timeval *last_end)
 Gets the last start and end times of the task. More...
 
int ast_sip_sched_task_get_times2 (struct ast_sip_sched_task *schtd, struct timeval *when_queued, struct timeval *last_start, struct timeval *last_end, int *interval, int *time_left, struct timeval *next_start)
 Gets the queued, last start, last_end, time left, interval, next run. More...
 
int ast_sip_sched_task_get_times_by_name (const char *name, struct timeval *when_queued, struct timeval *last_start, struct timeval *last_end)
 Gets the last start and end times of the task by name. More...
 
int ast_sip_sched_task_get_times_by_name2 (const char *name, struct timeval *when_queued, struct timeval *last_start, struct timeval *last_end, int *interval, int *time_left, struct timeval *next_start)
 Gets the queued, last start, last_end, time left, interval, next run by task name. More...
 
struct ast_sip_sched_taskast_sip_schedule_task (struct ast_taskprocessor *serializer, int interval, ast_sip_task sip_task, const char *name, void *task_data, enum ast_sip_scheduler_task_flags flags)
 Schedule a task to run in the res_pjsip thread pool. More...
 
int ast_sip_thread_is_servant (void)
 Determine if the current thread is a SIP servant thread. More...
 

Detailed Description

PJSIP Threading Model

There are three major types of threads that SIP will have to deal with:

Asterisk Threads

Asterisk threads are those that originate from outside of SIP but within Asterisk. The most common of these threads are PBX (channel) threads and the autoservice thread. Most interaction with these threads will be through channel technology callbacks. Within these threads, it is fine to handle Asterisk data from outside of SIP, but any handling of SIP data should be left to servants, especially if you wish to call into PJSIP for anything. Asterisk threads are not registered with PJLIB, so attempting to call into PJSIP will cause an assertion to be triggered, thus causing the program to crash.

PJSIP Threads

PJSIP threads are those that originate from handling of PJSIP events, such as an incoming SIP request or response, or a transaction timeout. The role of these threads is to process information as quickly as possible so that the next item on the SIP socket(s) can be serviced. On incoming messages, Asterisk automatically will push the request to a servant thread. When your module callback is called, processing will already be in a servant. However, for other PJSIP events, such as transaction state changes due to timer expirations, your module will be called into from a PJSIP thread. If you are called into from a PJSIP thread, then you should push whatever processing is needed to a servant as soon as possible. You can discern if you are currently in a SIP servant thread using the ast_sip_thread_is_servant function.

Servants

Servants are where the bulk of SIP work should be performed. These threads exist in order to do the work that Asterisk threads and PJSIP threads hand off to them. Servant threads register themselves with PJLIB, meaning that they are capable of calling PJSIP and PJLIB functions if they wish.

Serializer

Tasks are handed off to servant threads using the API call ast_sip_push_task. The first parameter of this call is a serializer. If this pointer is NULL, then the work will be handed off to whatever servant can currently handle the task. If this pointer is non-NULL, then the task will not be executed until previous tasks pushed with the same serializer have completed. For more information on serializers and the benefits they provide, see ast_threadpool_serializer

Scheduler

Some situations require that a task run periodically or at a future time. Normally the ast_sched functionality would be used but ast_sched only uses 1 thread for all tasks and that thread isn't registered with PJLIB and therefore can't do any PJSIP related work.ast_sip_sched uses ast_sched only as a scheduled queue. When a task is ready to run, it's pushed to a Serializer to be invoked asynchronously by a Servant. This ensures that the task is executed in a PJLIB registered thread and allows the ast_sched thread to immediately continue processing the queue. The Serializer used by ast_sip_sched is one of your choosing or a random one from the res_pjsip pool if you don't choose one.

Note

Do not make assumptions about individual threads based on a corresponding serializer. In other words, just because several tasks use the same serializer when being pushed to servants, it does not mean that the same thread is necessarily going to execute those tasks, even though they are all guaranteed to be executed in sequence.

Typedef Documentation

◆ ast_sip_task

typedef int(* ast_sip_task) (void *user_data)

Definition at line 1573 of file res_pjsip.h.

Enumeration Type Documentation

◆ ast_sip_scheduler_task_flags

Task flags for the res_pjsip scheduler.

The default is AST_SIP_SCHED_TASK_FIXED | AST_SIP_SCHED_TASK_DATA_NOT_AO2 | AST_SIP_SCHED_TASK_DATA_NO_CLEANUP | AST_SIP_SCHED_TASK_PERIODIC

Enumerator
AST_SIP_SCHED_TASK_DEFAULTS 

The defaults

AST_SIP_SCHED_TASK_FIXED 

Run at a fixed interval. Stop scheduling if the callback returns <= 0. Any other value is ignored.

AST_SIP_SCHED_TASK_VARIABLE 

Run at a variable interval. Stop scheduling if the callback returns <= 0. Any other return value is used as the new interval.

AST_SIP_SCHED_TASK_ONESHOT 

Run just once. Return values are ignored.

AST_SIP_SCHED_TASK_DATA_NOT_AO2 

The task data is not an AO2 object.

AST_SIP_SCHED_TASK_DATA_AO2 

The task data is an AO2 object. A reference count will be held by the scheduler until after the task has run for the final time (if ever).

AST_SIP_SCHED_TASK_DATA_NO_CLEANUP 

Don't take any cleanup action on the data

AST_SIP_SCHED_TASK_DATA_FREE 

If AST_SIP_SCHED_TASK_DATA_AO2 is set, decrement the reference count otherwise call ast_free on it.

AST_SIP_SCHED_TASK_PERIODIC 

The task is scheduled at multiples of interval.

See also
Interval
AST_SIP_SCHED_TASK_DELAY 

The next invocation of the task is at last finish + interval.

See also
Interval
AST_SIP_SCHED_TASK_TRACK 

The scheduled task's events are tracked in the debug log.

Schedule events such as scheduling, running, rescheduling, canceling, and destroying are logged about the task.

Definition at line 1767 of file res_pjsip.h.

1781  {
1782  /*!
1783  * The defaults
1784  */
1785  AST_SIP_SCHED_TASK_DEFAULTS = (0 << 0),
1786 
1787  /*!
1788  * Run at a fixed interval.
1789  * Stop scheduling if the callback returns <= 0.
1790  * Any other value is ignored.
1791  */
1792  AST_SIP_SCHED_TASK_FIXED = (0 << 0),
1793  /*!
1794  * Run at a variable interval.
1795  * Stop scheduling if the callback returns <= 0.
1796  * Any other return value is used as the new interval.
1797  */
1798  AST_SIP_SCHED_TASK_VARIABLE = (1 << 0),
1799 
1800  /*!
1801  * Run just once.
1802  * Return values are ignored.
1803  */
1804  AST_SIP_SCHED_TASK_ONESHOT = (1 << 6),
1805 
1806  /*!
1807  * The task data is not an AO2 object.
1808  */
1810  /*!
1811  * The task data is an AO2 object.
1812  * A reference count will be held by the scheduler until
1813  * after the task has run for the final time (if ever).
1814  */
1815  AST_SIP_SCHED_TASK_DATA_AO2 = (1 << 1),
1816 
1817  /*!
1818  * Don't take any cleanup action on the data
1819  */
1821  /*!
1822  * If AST_SIP_SCHED_TASK_DATA_AO2 is set, decrement the reference count
1823  * otherwise call ast_free on it.
1824  */
1825  AST_SIP_SCHED_TASK_DATA_FREE = ( 1 << 3 ),
1826 
1827  /*!
1828  * \brief The task is scheduled at multiples of interval
1829  * \see Interval
1830  */

Function Documentation

◆ ast_sip_create_serializer()

struct ast_taskprocessor* ast_sip_create_serializer ( const char *  name)

Create a new serializer for SIP tasks.

Since
13.8.0

See ast_threadpool_serializer for more information on serializers. SIP creates serializers so that tasks operating on similar data will run in sequence.

Parameters
nameName of the serializer. (must be unique)
Return values
NULLFailure
non-NULLNewly-created serializer

Definition at line 5133 of file res_pjsip.c.

References ast_sip_create_serializer_group(), and NULL.

Referenced by allocate_subscription_tree(), ast_res_pjsip_init_options_handling(), ast_sip_session_alloc(), create_websocket_serializer(), distributor_pool_setup(), load_module(), refer_progress_alloc(), and scheduler().

5134 {
5136 }
static const char name[]
Definition: format_mp3.c:68
#define NULL
Definition: resample.c:96
struct ast_taskprocessor * ast_sip_create_serializer_group(const char *name, struct ast_serializer_shutdown_group *shutdown_group)
Create a new serializer for SIP tasks.
Definition: res_pjsip.c:5128

◆ ast_sip_create_serializer_group()

struct ast_taskprocessor* ast_sip_create_serializer_group ( const char *  name,
struct ast_serializer_shutdown_group shutdown_group 
)

Create a new serializer for SIP tasks.

Since
13.8.0

See ast_threadpool_serializer for more information on serializers. SIP creates serializers so that tasks operating on similar data will run in sequence.

Parameters
nameName of the serializer. (must be unique)
shutdown_groupGroup shutdown controller. (NULL if no group association)
Return values
NULLFailure
non-NULLNewly-created serializer

Definition at line 5128 of file res_pjsip.c.

References ast_threadpool_serializer_group().

Referenced by ast_sip_create_serializer(), sip_options_aor_alloc(), sip_outbound_publisher_alloc(), and sip_outbound_registration_state_alloc().

5129 {
5130  return ast_threadpool_serializer_group(name, sip_threadpool, shutdown_group);
5131 }
static const char name[]
Definition: format_mp3.c:68
static struct ast_threadpool * sip_threadpool
Definition: res_pjsip.c:3274
struct ast_taskprocessor * ast_threadpool_serializer_group(const char *name, struct ast_threadpool *pool, struct ast_serializer_shutdown_group *shutdown_group)
Serialized execution of tasks within a ast_threadpool.
Definition: threadpool.c:1402

◆ ast_sip_dialog_get_endpoint()

struct ast_sip_endpoint* ast_sip_dialog_get_endpoint ( pjsip_dialog *  dlg)

Get the endpoint associated with this dialog.

This function increases the refcount of the endpoint by one. Release the reference once you are finished with the endpoint.

Parameters
dlgThe SIP dialog from which to retrieve the endpoint
Return values
NULLNo endpoint associated with this dialog
non-NULLThe endpoint.

Definition at line 322 of file pjsip_distributor.c.

References ao2_bump, ao2_find, ao2_lock, ao2_ref, ao2_unlock, distributor_dialog_data::endpoint, NULL, and OBJ_SEARCH_KEY.

Referenced by digest_create_request_with_auth().

323 {
324  struct distributor_dialog_data *dist;
325  struct ast_sip_endpoint *endpoint;
326 
328  if (dist) {
329  ao2_lock(dist);
330  endpoint = ao2_bump(dist->endpoint);
331  ao2_unlock(dist);
332  ao2_ref(dist, -1);
333  } else {
334  endpoint = NULL;
335  }
336  return endpoint;
337 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
static struct ao2_container * dialog_associations
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_sip_endpoint * endpoint
An entity with which Asterisk communicates.
Definition: res_pjsip.h:812
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ ast_sip_dialog_set_endpoint()

void ast_sip_dialog_set_endpoint ( pjsip_dialog *  dlg,
struct ast_sip_endpoint endpoint 
)

Set an endpoint on a SIP dialog so in-dialog requests do not undergo endpoint lookup.

Parameters
dlgThe SIP dialog itself
endpointThe endpoint that this dialog is communicating with

Definition at line 294 of file pjsip_distributor.c.

References ao2_alloc, ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlink_flags, ao2_unlock, ao2_wrlock, distributor_dialog_data::dlg, distributor_dialog_data::endpoint, NULL, OBJ_NOLOCK, OBJ_SEARCH_KEY, and distributor_dialog_data::serializer.

Referenced by ast_sip_session_alloc(), pubsub_on_evsub_state(), session_end_completion(), and subscription_setup_dialog().

295 {
296  struct distributor_dialog_data *dist;
297 
300  if (!dist) {
301  if (endpoint) {
302  dist = ao2_alloc(sizeof(*dist), NULL);
303  if (dist) {
304  dist->dlg = dlg;
305  dist->endpoint = endpoint;
307  ao2_ref(dist, -1);
308  }
309  }
310  } else {
311  ao2_lock(dist);
312  dist->endpoint = endpoint;
313  if (!dist->serializer && !dist->endpoint) {
315  }
316  ao2_unlock(dist);
317  ao2_ref(dist, -1);
318  }
320 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_wrlock(a)
Definition: astobj2.h:720
static struct ao2_container * dialog_associations
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_sip_endpoint * endpoint
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_taskprocessor * serializer
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622

◆ ast_sip_dialog_set_serializer()

void ast_sip_dialog_set_serializer ( pjsip_dialog *  dlg,
struct ast_taskprocessor serializer 
)

Set a serializer on a SIP dialog so requests and responses are automatically serialized.

Passing a NULL serializer is a way to remove a serializer from a dialog.

Parameters
dlgThe SIP dialog itself
serializerThe serializer to use

Definition at line 266 of file pjsip_distributor.c.

References ao2_alloc, ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlink_flags, ao2_unlock, ao2_wrlock, distributor_dialog_data::dlg, distributor_dialog_data::endpoint, NULL, OBJ_NOLOCK, OBJ_SEARCH_KEY, and distributor_dialog_data::serializer.

Referenced by ast_sip_session_alloc(), pubsub_on_evsub_state(), session_end_completion(), and subscription_setup_dialog().

267 {
268  struct distributor_dialog_data *dist;
269 
272  if (!dist) {
273  if (serializer) {
274  dist = ao2_alloc(sizeof(*dist), NULL);
275  if (dist) {
276  dist->dlg = dlg;
277  dist->serializer = serializer;
279  ao2_ref(dist, -1);
280  }
281  }
282  } else {
283  ao2_lock(dist);
284  dist->serializer = serializer;
285  if (!dist->serializer && !dist->endpoint) {
287  }
288  ao2_unlock(dist);
289  ao2_ref(dist, -1);
290  }
292 }
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
#define ao2_wrlock(a)
Definition: astobj2.h:720
static struct ao2_container * dialog_associations
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_sip_endpoint * endpoint
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_taskprocessor * serializer
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622

◆ ast_sip_get_distributor_serializer()

struct ast_taskprocessor* ast_sip_get_distributor_serializer ( pjsip_rx_data *  rdata)

Determine the distributor serializer for the SIP message.

Since
13.10.0
Parameters
rdataThe incoming message.
Return values
Calculateddistributor serializer on success.
NULLon error.

Definition at line 448 of file pjsip_distributor.c.

References ao2_bump, ARRAY_LEN, ast_debug, ast_str_hash_restrict(), ast_taskprocessor_name(), endpoint_lookup(), NULL, pjstr_hash(), and pjstr_hash_add().

Referenced by allocate_subscription_tree(), ast_sip_session_alloc(), distributor(), and subscription_persistence_recreate().

449 {
450  int hash;
451  pj_str_t *remote_tag;
453 
454  if (!rdata->msg_info.msg) {
455  return NULL;
456  }
457 
458  if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) {
459  remote_tag = &rdata->msg_info.from->tag;
460  } else {
461  remote_tag = &rdata->msg_info.to->tag;
462  }
463 
464  /* Compute the hash from the SIP message call-id and remote-tag */
465  hash = pjstr_hash(&rdata->msg_info.cid->id);
466  hash = pjstr_hash_add(remote_tag, hash);
467  hash = ast_str_hash_restrict(hash);
468 
469  serializer = ao2_bump(distributor_pool[hash % ARRAY_LEN(distributor_pool)]);
470  if (serializer) {
471  ast_debug(3, "Calculated serializer %s to use for %s\n",
472  ast_taskprocessor_name(serializer), pjsip_rx_data_get_info(rdata));
473  }
474  return serializer;
475 }
const char * ast_taskprocessor_name(struct ast_taskprocessor *tps)
Return the name of the taskprocessor singleton.
#define NULL
Definition: resample.c:96
#define ao2_bump(obj)
Definition: astobj2.h:491
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ARRAY_LEN(a)
Definition: utils.h:639
static int pjstr_hash_add(pj_str_t *str, int hash)
static struct ast_taskprocessor * distributor_pool[DISTRIBUTOR_POOL_SIZE]
static int pjstr_hash(pj_str_t *str)
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
static force_inline int attribute_pure ast_str_hash_restrict(unsigned int hash)
Restrict hash value range.
Definition: strings.h:1193

◆ ast_sip_push_task()

int ast_sip_push_task ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data 
)

Pushes a task to SIP servants.

This uses the serializer provided to determine how to push the task. If the serializer is NULL, then the task will be pushed to the servants directly. If the serializer is non-NULL, then the task will be queued behind other tasks associated with the same serializer.

Parameters
serializerThe serializer to which the task belongs. Can be NULL
sip_taskThe task to execute
task_dataThe parameter to pass to the task when it executes
Return values
0Success
-1Failure

Definition at line 5138 of file res_pjsip.c.

References ast_serializer_pool_get(), ast_taskprocessor_push(), cond, and lock.

Referenced by ast_sip_push_task_wait(), ast_sip_session_suspend(), auth_observer(), cancel_and_unpublish(), chan_pjsip_call(), chan_pjsip_digit_end(), chan_pjsip_hangup(), chan_pjsip_indicate(), chan_pjsip_sendtext_data(), chan_pjsip_set_rtp_peer(), chan_pjsip_transfer(), check_delayed_requests(), contact_observer_updated(), distributor(), exten_state_publisher_state_cb(), handle_topology_request_change(), load_module(), mwi_startup_event_cb(), mwi_stasis_cb(), pjsip_set_history(), pjsip_show_history(), publish_expire(), publisher_client_send(), pubsub_on_client_refresh(), pubsub_on_rx_refresh(), pubsub_on_rx_subscribe_request(), pubsub_on_server_timeout(), push_notify(), push_notify_channel(), push_notify_uri(), push_to_serializer(), qualify_contact_cb(), queue_register(), queue_unregister(), refer_attended_task(), refer_blind_callback(), refer_incoming_attended_request(), refer_incoming_refer_request(), refer_progress_bridge(), refer_progress_destroy(), refer_progress_framehook(), refer_progress_framehook_destroy(), register_contact_transport_shutdown_cb(), registration_transport_shutdown_cb(), resend_reinvite(), sched_cb(), send_contact_notify(), send_notify(), session_end_if_disconnected(), session_inv_on_state_changed(), session_termination_cb(), sip_options_contact_status_update(), sip_outbound_publish_callback(), sip_outbound_publish_client_add_publisher(), sip_outbound_registration_apply(), sip_outbound_registration_response_cb(), sip_outbound_registration_state_destroy(), sip_outbound_registration_timer_cb(), sip_publisher_service_queue(), state_changed(), sub_persistence_recreate(), sub_tree_transport_cb(), subscription_persistence_event_cb(), t38_automatic_reject_timer_cb(), and t38_framehook().

5139 {
5140  if (!serializer) {
5142  }
5143 
5144  return ast_taskprocessor_push(serializer, sip_task, task_data);
5145 }
userdata associated with baseline taskprocessor test
static struct ast_serializer_pool * sip_serializer_pool
Definition: res_pjsip.c:3270
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127

◆ ast_sip_push_task_synchronous()

int ast_sip_push_task_synchronous ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data 
)

Push a task to SIP servants and wait for it to complete.

Deprecated:
Replaced with ast_sip_push_task_wait_servant().

Definition at line 5213 of file res_pjsip.c.

References ast_sip_push_task_wait_servant().

5214 {
5215  return ast_sip_push_task_wait_servant(serializer, sip_task, task_data);
5216 }
int ast_sip_push_task_wait_servant(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to SIP servants and wait for it to complete.
Definition: res_pjsip.c:5204
userdata associated with baseline taskprocessor test

◆ ast_sip_push_task_wait_serializer()

int ast_sip_push_task_wait_serializer ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data 
)

Push a task to the serializer and wait for it to complete.

Like ast_sip_push_task except that it blocks until the task is completed by the specified serializer. If the specified serializer is the current thread then the task executes immediately.

Note
PJPROJECT callbacks tend to have locks already held when called.
Warning
Never hold locks that may be acquired by a SIP servant thread when calling this function. Doing so may cause a deadlock if all SIP servant threads are blocked waiting to acquire the lock while the thread holding the lock is waiting for a free SIP servant thread for the serializer to execute in.
Never hold locks that may be acquired by the serializer when calling this function. Doing so will cause a deadlock.
Never use this function in the pjsip monitor thread (It is a SIP servant thread). This is likely to cause a deadlock.
Use of this function in an ao2 destructor callback is a bad idea. You don't have control over which thread executes the destructor. Attempting to shift execution to another thread with this function is likely to cause deadlock.
Parameters
serializerThe SIP serializer to execute the task. NULL if any of the default serializers can be used.
sip_taskThe task to execute
task_dataThe parameter to pass to the task when it executes
Note
It is generally better to call ast_sip_push_task_wait_servant() if you pass NULL for the serializer parameter.
The sip_task() return value may need to be distinguished from the failure to push the task.
Returns
sip_task() return value on success.
Return values
-1Failure to push the task.

Definition at line 5218 of file res_pjsip.c.

References ast_serializer_pool_get(), ast_sip_push_task_wait(), and ast_taskprocessor_is_task().

Referenced by ami_sip_qualify(), aor_observer_deleted(), aor_observer_modified(), ast_res_pjsip_cleanup_options_handling(), ast_res_pjsip_init_options_handling(), chan_pjsip_answer(), cli_qualify(), cli_reload_qualify_aor(), cli_reload_qualify_endpoint(), contact_observer_created(), contact_observer_deleted(), contact_observer_updated(), endpoint_observer_deleted(), endpoint_observer_modified(), func_read_header(), func_read_headers(), func_write_header(), pjsip_acf_channel_read(), pjsip_acf_dtmf_mode_write(), pjsip_acf_media_offer_write(), pjsip_acf_parse_uri_read(), pjsip_acf_session_refresh_write(), refer_incoming_invite_request(), sip_msg_send(), sip_options_aor_observer_deleted_task(), sip_options_aor_observer_modified_task(), sip_options_cleanup_task(), sip_options_contact_add_management_task(), sip_options_contact_delete_management_task(), sip_options_endpoint_unlink_aor_feeders(), sip_options_synchronize(), sip_options_synchronize_aor(), sip_options_synchronize_endpoint(), sip_options_unused_aor(), sip_outbound_registration_apply(), subscription_persistence_recreate(), and websocket_cb().

5219 {
5220  if (!serializer) {
5221  /* Caller doesn't care which PJSIP serializer the task executes under. */
5223  if (!serializer) {
5224  /* No serializer picked to execute the task */
5225  return -1;
5226  }
5227  }
5228  if (ast_taskprocessor_is_task(serializer)) {
5229  /*
5230  * We are the requested serializer so we must execute
5231  * the task now or deadlock waiting on ourself to
5232  * execute it.
5233  */
5234  return sip_task(task_data);
5235  }
5236 
5237  return ast_sip_push_task_wait(serializer, sip_task, task_data);
5238 }
static int ast_sip_push_task_wait(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Definition: res_pjsip.c:5176
userdata associated with baseline taskprocessor test
static struct ast_serializer_pool * sip_serializer_pool
Definition: res_pjsip.c:3270
int ast_taskprocessor_is_task(struct ast_taskprocessor *tps)
Am I the given taskprocessor&#39;s current task.
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127

◆ ast_sip_push_task_wait_servant()

int ast_sip_push_task_wait_servant ( struct ast_taskprocessor serializer,
int(*)(void *)  sip_task,
void *  task_data 
)

Push a task to SIP servants and wait for it to complete.

Like ast_sip_push_task except that it blocks until the task completes. If the current thread is a SIP servant thread then the task executes immediately. Otherwise, the specified serializer executes the task and the current thread waits for it to complete.

Note
PJPROJECT callbacks tend to have locks already held when called.
Warning
Never hold locks that may be acquired by a SIP servant thread when calling this function. Doing so may cause a deadlock if all SIP servant threads are blocked waiting to acquire the lock while the thread holding the lock is waiting for a free SIP servant thread.
Use of this function in an ao2 destructor callback is a bad idea. You don't have control over which thread executes the destructor. Attempting to shift execution to another thread with this function is likely to cause deadlock.
Parameters
serializerThe SIP serializer to execute the task if the current thread is not a SIP servant. NULL if any of the default serializers can be used.
sip_taskThe task to execute
task_dataThe parameter to pass to the task when it executes
Note
The sip_task() return value may need to be distinguished from the failure to push the task.
Returns
sip_task() return value on success.
Return values
-1Failure to push the task.

Definition at line 5204 of file res_pjsip.c.

References ast_sip_push_task_wait(), and ast_sip_thread_is_servant().

Referenced by ami_outbound_registration_detail(), ast_sip_initialize_dns(), ast_sip_push_task_synchronous(), ast_sip_register_service(), ast_sip_unregister_service(), chan_pjsip_request_with_stream_topology(), cli_dump_endpt(), current_state_reusable(), reload_module(), sip_outbound_publisher_alloc(), sip_transport_state_destroy(), subscription_tree_destructor(), and unload_module().

5205 {
5206  if (ast_sip_thread_is_servant()) {
5207  return sip_task(task_data);
5208  }
5209 
5210  return ast_sip_push_task_wait(serializer, sip_task, task_data);
5211 }
static int ast_sip_push_task_wait(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Definition: res_pjsip.c:5176
int ast_sip_thread_is_servant(void)
Determine if the current thread is a SIP servant thread.
Definition: res_pjsip.c:5321
userdata associated with baseline taskprocessor test

◆ ast_sip_sched_is_task_running()

int ast_sip_sched_is_task_running ( struct ast_sip_sched_task schtd)

Checks if the task is currently running.

Since
13.9.0
Parameters
schtdThe task structure pointer
Return values
0not running
1running

Definition at line 375 of file pjsip_scheduler.c.

References ast_sip_sched_task::is_running.

Referenced by AST_TEST_DEFINE().

376 {
377  return schtd ? schtd->is_running : 0;
378 }

◆ ast_sip_sched_is_task_running_by_name()

int ast_sip_sched_is_task_running_by_name ( const char *  name)

Checks if the task is currently running.

Since
13.9.0
Parameters
nameThe task name
Return values
0not running or not found
1running

Definition at line 380 of file pjsip_scheduler.c.

References ao2_find, ao2_ref, ast_strlen_zero(), ast_sip_sched_task::is_running, and OBJ_SEARCH_KEY.

Referenced by AST_TEST_DEFINE().

381 {
382  int is_running;
383  struct ast_sip_sched_task *schtd;
384 
385  if (ast_strlen_zero(name)) {
386  return 0;
387  }
388 
389  schtd = ao2_find(tasks, name, OBJ_SEARCH_KEY);
390  if (!schtd) {
391  return 0;
392  }
393 
394  is_running = schtd->is_running;
395  ao2_ref(schtd, -1);
396  return is_running;
397 }
static const char name[]
Definition: format_mp3.c:68
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct ao2_container * tasks

◆ ast_sip_sched_task_cancel()

int ast_sip_sched_task_cancel ( struct ast_sip_sched_task schtd)

Cancels the next invocation of a task.

Since
13.9.0
Parameters
schtdThe task structure pointer
Return values
0Success
-1Failure
Note
Only cancels future invocations not the currently running invocation.

Definition at line 191 of file pjsip_scheduler.c.

References ao2_lock, ao2_unlink, ao2_unlock, ast_log, ast_sched_del(), AST_SIP_SCHED_TASK_TRACK, ast_sip_sched_task::current_scheduler_id, ast_sip_sched_task::flags, ast_sip_sched_task::interval, LOG_DEBUG, and ast_sip_sched_task::name.

Referenced by ast_sip_destroy_scheduler(), ast_sip_sched_task_cancel_by_name(), AST_TEST_DEFINE(), pubsub_on_evsub_state(), pubsub_on_rx_refresh(), scheduler(), sip_options_aor_remove_task(), sip_options_apply_aor_configuration(), sip_options_cleanup_aor_task(), sip_options_contact_add_task(), and sip_options_contact_delete_task().

192 {
193  int res;
194  int sched_id;
195 
196  if (schtd->flags & AST_SIP_SCHED_TASK_TRACK) {
197  ast_log(LOG_DEBUG, "Sched %p: Canceling %s\n", schtd, schtd->name);
198  }
199 
200  /*
201  * Prevent any tasks in the serializer queue from
202  * running and restarting the scheduled item on us
203  * first.
204  */
205  ao2_lock(schtd);
206  schtd->interval = 0;
207 
208  sched_id = schtd->current_scheduler_id;
209  schtd->current_scheduler_id = -1;
210  ao2_unlock(schtd);
211  res = ast_sched_del(scheduler_context, sched_id);
212 
213  ao2_unlink(tasks, schtd);
214 
215  return res;
216 }
static struct ast_sched_context * scheduler_context
Scheduler ID holder.
Definition: sched.c:70
#define ao2_unlock(a)
Definition: astobj2.h:730
#define LOG_DEBUG
Definition: logger.h:241
#define ast_log
Definition: astobj2.c:42
#define ao2_lock(a)
Definition: astobj2.h:718
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
enum ast_sip_scheduler_task_flags flags
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition: sched.c:610
The scheduled task&#39;s events are tracked in the debug log.
Definition: res_pjsip.h:1829
static struct ao2_container * tasks

◆ ast_sip_sched_task_cancel_by_name()

int ast_sip_sched_task_cancel_by_name ( const char *  name)

Cancels the next invocation of a task by name.

Since
13.9.0
Parameters
nameThe task name
Return values
0Success
-1Failure
Note
Only cancels future invocations not the currently running invocation.

Definition at line 218 of file pjsip_scheduler.c.

References ao2_find, ao2_ref, ast_sip_sched_task_cancel(), ast_strlen_zero(), and OBJ_SEARCH_KEY.

Referenced by AST_TEST_DEFINE().

219 {
220  int res;
221  struct ast_sip_sched_task *schtd;
222 
223  if (ast_strlen_zero(name)) {
224  return -1;
225  }
226 
227  schtd = ao2_find(tasks, name, OBJ_SEARCH_KEY);
228  if (!schtd) {
229  return -1;
230  }
231 
232  res = ast_sip_sched_task_cancel(schtd);
233  ao2_ref(schtd, -1);
234  return res;
235 }
static const char name[]
Definition: format_mp3.c:68
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct ao2_container * tasks

◆ ast_sip_sched_task_get_name()

int ast_sip_sched_task_get_name ( struct ast_sip_sched_task schtd,
char *  name,
size_t  maxlen 
)

Gets the task name.

Since
13.9.0
Parameters
schtdThe task structure pointer
Return values
0success
1failure

Definition at line 334 of file pjsip_scheduler.c.

References ao2_lock, ao2_unlock, ast_copy_string(), and ast_sip_sched_task::name.

Referenced by pubsub_on_evsub_state(), and pubsub_on_rx_refresh().

335 {
336  if (maxlen <= 0) {
337  return -1;
338  }
339 
340  ao2_lock(schtd);
341  ast_copy_string(name, schtd->name, maxlen);
342  ao2_unlock(schtd);
343 
344  return 0;
345 }
static const char name[]
Definition: format_mp3.c:68
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ao2_lock(a)
Definition: astobj2.h:718
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ ast_sip_sched_task_get_next_run()

int ast_sip_sched_task_get_next_run ( struct ast_sip_sched_task schtd)

Gets the number of milliseconds until the next invocation.

Since
13.9.0
Parameters
schtdThe task structure pointer
Returns
The number of milliseconds until the next invocation or -1 if the task isn't scheduled

Definition at line 347 of file pjsip_scheduler.c.

References ast_sip_sched_task_get_times2(), and NULL.

Referenced by ast_sip_sched_task_get_next_run_by_name(), AST_TEST_DEFINE(), and cli_show_tasks().

348 {
349  int delay;
350 
351  ast_sip_sched_task_get_times2(schtd, NULL, NULL, NULL, NULL, &delay, NULL);
352 
353  return delay;
354 }
#define NULL
Definition: resample.c:96
int ast_sip_sched_task_get_times2(struct ast_sip_sched_task *schtd, struct timeval *queued, struct timeval *last_start, struct timeval *last_end, int *interval, int *time_left, struct timeval *next_start)
Gets the queued, last start, last_end, time left, interval, next run.

◆ ast_sip_sched_task_get_next_run_by_name()

int ast_sip_sched_task_get_next_run_by_name ( const char *  name)

Gets the number of milliseconds until the next invocation.

Since
13.9.0
Parameters
nameThe task name
Returns
The number of milliseconds until the next invocation or -1 if the task isn't scheduled

Definition at line 356 of file pjsip_scheduler.c.

References ao2_find, ao2_ref, ast_sip_sched_task_get_next_run(), ast_strlen_zero(), and OBJ_SEARCH_KEY.

Referenced by AST_TEST_DEFINE().

357 {
358  int next_run;
359  struct ast_sip_sched_task *schtd;
360 
361  if (ast_strlen_zero(name)) {
362  return -1;
363  }
364 
365  schtd = ao2_find(tasks, name, OBJ_SEARCH_KEY);
366  if (!schtd) {
367  return -1;
368  }
369 
370  next_run = ast_sip_sched_task_get_next_run(schtd);
371  ao2_ref(schtd, -1);
372  return next_run;
373 }
static const char name[]
Definition: format_mp3.c:68
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_sip_sched_task_get_next_run(struct ast_sip_sched_task *schtd)
Gets the number of milliseconds until the next invocation.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct ao2_container * tasks

◆ ast_sip_sched_task_get_times()

int ast_sip_sched_task_get_times ( struct ast_sip_sched_task schtd,
struct timeval *  when_queued,
struct timeval *  last_start,
struct timeval *  last_end 
)

Gets the last start and end times of the task.

Since
13.9.0
Parameters
schtdThe task structure pointer
[out]when_queuedPointer to a timeval structure to contain the time when queued
[out]last_startPointer to a timeval structure to contain the time when last started
[out]last_endPointer to a timeval structure to contain the time when last ended
Return values
0Success
-1Failure
Note
Any of the pointers can be NULL if you don't need them.

Definition at line 299 of file pjsip_scheduler.c.

References ast_sip_sched_task_get_times2(), and NULL.

Referenced by scheduler().

301 {
302  return ast_sip_sched_task_get_times2(schtd, queued, last_start, last_end, NULL, NULL, NULL);
303 }
struct timeval last_start
#define NULL
Definition: resample.c:96
int ast_sip_sched_task_get_times2(struct ast_sip_sched_task *schtd, struct timeval *queued, struct timeval *last_start, struct timeval *last_end, int *interval, int *time_left, struct timeval *next_start)
Gets the queued, last start, last_end, time left, interval, next run.
struct timeval last_end

◆ ast_sip_sched_task_get_times2()

int ast_sip_sched_task_get_times2 ( struct ast_sip_sched_task schtd,
struct timeval *  when_queued,
struct timeval *  last_start,
struct timeval *  last_end,
int *  interval,
int *  time_left,
struct timeval *  next_start 
)

Gets the queued, last start, last_end, time left, interval, next run.

Since
16.15.0
18.1.0
Parameters
schtdThe task structure pointer
[out]when_queuedPointer to a timeval structure to contain the time when queued
[out]last_startPointer to a timeval structure to contain the time when last started
[out]last_endPointer to a timeval structure to contain the time when last ended
[out]intervalPointer to an int to contain the interval in ms
[out]time_leftPointer to an int to contain the ms left to the next run
[out]last_endPointer to a timeval structure to contain the next run time
Return values
0Success
-1Failure
Note
Any of the pointers can be NULL if you don't need them.

Definition at line 237 of file pjsip_scheduler.c.

References ao2_lock, ao2_unlock, AST_SIP_SCHED_TASK_DELAY, ast_tv(), ast_tvadd(), ast_tvdiff_ms(), ast_tvnow(), ast_sip_sched_task::flags, ast_sip_sched_task::interval, ast_sip_sched_task::is_running, ast_sip_sched_task::last_end, ast_sip_sched_task::last_start, and ast_sip_sched_task::when_queued.

Referenced by ast_sip_sched_task_get_next_run(), ast_sip_sched_task_get_times(), and ast_sip_sched_task_get_times_by_name2().

240 {
241  ao2_lock(schtd);
242  if (queued) {
243  memcpy(queued, &schtd->when_queued, sizeof(struct timeval));
244  }
245  if (last_start) {
246  memcpy(last_start, &schtd->last_start, sizeof(struct timeval));
247  }
248  if (last_end) {
249  memcpy(last_end, &schtd->last_end, sizeof(struct timeval));
250  }
251 
252  if (interval) {
253  *interval = schtd->interval;
254  }
255 
256  if (time_left || next_start) {
257  int delay;
258  struct timeval since_when;
259  struct timeval now;
260  struct timeval next;
261 
262  if (schtd->interval) {
263  delay = schtd->interval;
264  now = ast_tvnow();
265 
266  if (schtd->flags & AST_SIP_SCHED_TASK_DELAY) {
267  since_when = schtd->is_running ? now : schtd->last_end;
268  } else {
269  since_when = schtd->last_start.tv_sec ? schtd->last_start : schtd->when_queued;
270  }
271 
272  delay -= ast_tvdiff_ms(now, since_when);
273 
274  delay = delay < 0 ? 0 : delay;
275 
276 
277  if (time_left) {
278  *time_left = delay;
279  }
280 
281  if (next_start) {
282  next = ast_tvadd(now, ast_tv(delay / 1000, (delay % 1000) * 1000));
283  memcpy(next_start, &next, sizeof(struct timeval));
284  }
285  } else {
286  if (time_left) {
287  *time_left = -1;
288  }
289  }
290 
291  }
292 
293  ao2_unlock(schtd);
294 
295  return 0;
296 }
struct timeval last_start
struct timeval when_queued
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_unlock(a)
Definition: astobj2.h:730
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define ao2_lock(a)
Definition: astobj2.h:718
enum ast_sip_scheduler_task_flags flags
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
The next invocation of the task is at last finish + interval.
Definition: res_pjsip.h:1822
struct timeval last_end
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226

◆ ast_sip_sched_task_get_times_by_name()

int ast_sip_sched_task_get_times_by_name ( const char *  name,
struct timeval *  when_queued,
struct timeval *  last_start,
struct timeval *  last_end 
)

Gets the last start and end times of the task by name.

Since
13.9.0
Parameters
nameThe task name
[out]when_queuedPointer to a timeval structure to contain the time when queued
[out]last_startPointer to a timeval structure to contain the time when last started
[out]last_endPointer to a timeval structure to contain the time when last ended
Return values
0Success
-1Failure
Note
Any of the pointers can be NULL if you don't need them.

Definition at line 327 of file pjsip_scheduler.c.

References ast_sip_sched_task_get_times_by_name2(), and NULL.

329 {
330  return ast_sip_sched_task_get_times_by_name2(name, queued, last_start, last_end,
331  NULL, NULL, NULL);
332 }
static const char name[]
Definition: format_mp3.c:68
#define NULL
Definition: resample.c:96
int ast_sip_sched_task_get_times_by_name2(const char *name, struct timeval *queued, struct timeval *last_start, struct timeval *last_end, int *interval, int *time_left, struct timeval *next_start)
Gets the queued, last start, last_end, time left, interval, next run by task name.

◆ ast_sip_sched_task_get_times_by_name2()

int ast_sip_sched_task_get_times_by_name2 ( const char *  name,
struct timeval *  when_queued,
struct timeval *  last_start,
struct timeval *  last_end,
int *  interval,
int *  time_left,
struct timeval *  next_start 
)

Gets the queued, last start, last_end, time left, interval, next run by task name.

Since
16.15.0
18.1.0
Parameters
nameThe task name
[out]when_queuedPointer to a timeval structure to contain the time when queued
[out]last_startPointer to a timeval structure to contain the time when last started
[out]last_endPointer to a timeval structure to contain the time when last ended
[out]intervalPointer to an int to contain the interval in ms
[out]time_leftPointer to an int to contain the ms left to the next run
[out]last_endPointer to a timeval structure to contain the next run time
Return values
0Success
-1Failure
Note
Any of the pointers can be NULL if you don't need them.

Definition at line 305 of file pjsip_scheduler.c.

References ao2_find, ao2_ref, ast_sip_sched_task_get_times2(), ast_strlen_zero(), and OBJ_SEARCH_KEY.

Referenced by ast_sip_sched_task_get_times_by_name().

308 {
309  int res;
310  struct ast_sip_sched_task *schtd;
311 
312  if (ast_strlen_zero(name)) {
313  return -1;
314  }
315 
316  schtd = ao2_find(tasks, name, OBJ_SEARCH_KEY);
317  if (!schtd) {
318  return -1;
319  }
320 
321  res = ast_sip_sched_task_get_times2(schtd, queued, last_start, last_end, interval, time_left,
322  next_start);
323  ao2_ref(schtd, -1);
324  return res;
325 }
static const char name[]
Definition: format_mp3.c:68
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
struct timeval last_start
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_sip_sched_task_get_times2(struct ast_sip_sched_task *schtd, struct timeval *queued, struct timeval *last_start, struct timeval *last_end, int *interval, int *time_left, struct timeval *next_start)
Gets the queued, last start, last_end, time left, interval, next run.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct timeval last_end
static struct ao2_container * tasks

◆ ast_sip_schedule_task()

struct ast_sip_sched_task* ast_sip_schedule_task ( struct ast_taskprocessor serializer,
int  interval,
ast_sip_task  sip_task,
const char *  name,
void *  task_data,
enum ast_sip_scheduler_task_flags  flags 
)

Schedule a task to run in the res_pjsip thread pool.

Since
13.9.0
Parameters
serializerThe serializer to use. If NULL, don't use a serializer (see note below)
intervalThe invocation interval in milliseconds (see note below)
sip_taskThe task to invoke
nameAn optional name to associate with the task
task_dataOptional data to pass to the task
flagsOne of enum ast_sip_scheduler_task_type
Returns
Pointer to ast_sip_sched_task ao2 object which must be dereferenced when done.

Specifying a serializer guarantees serialized execution but NOT specifying a serializer may still result in tasks being effectively serialized if the thread pool is busy. The point of the serializer BTW is not to prevent parallel executions of the SAME task. That happens automatically (see below). It's to prevent the task from running at the same time as other work using the same serializer, whether or not it's being run by the scheduler.

The interval is used to calculate the next time the task should run. There are two models.

AST_SIP_SCHED_TASK_PERIODIC specifies that the invocations of the task occur at the specific interval. That is, every "interval" milliseconds, regardless of how long the task takes. If the task takes longer than interval, it will be scheduled at the next available multiple of interval. For exmaple: If the task has an interval of 60 seconds and the task takes 70 seconds, the next invocation will happen at 120 seconds.

AST_SIP_SCHED_TASK_DELAY specifies that the next invocation of the task should start at interval milliseconds after the current invocation has finished.

Definition at line 415 of file pjsip_scheduler.c.

References ao2_alloc, ao2_bump, ao2_link, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, ast_atomic_fetchadd_int(), ast_log, ast_samp2tv(), ast_sched_add(), AST_SIP_SCHED_TASK_DATA_AO2, AST_SIP_SCHED_TASK_DELAY, AST_SIP_SCHED_TASK_TRACK, ast_strlen_zero(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_sip_sched_task::current_scheduler_id, ast_sip_sched_task::flags, ID_LEN, ast_sip_sched_task::interval, ast_sip_sched_task::last_start, LOG_DEBUG, ast_sip_sched_task::name, ast_sip_sched_task::next_periodic, NULL, push_to_serializer(), schtd_dtor(), ast_sip_sched_task::serializer, ast_sip_sched_task::task, task_count, ast_sip_sched_task::task_data, and ast_sip_sched_task::when_queued.

Referenced by AST_TEST_DEFINE(), initial_notify_task(), scheduler(), sip_options_apply_aor_configuration(), and sip_options_contact_add_task().

418 {
419 #define ID_LEN 13 /* task_deadbeef */
420  struct ast_sip_sched_task *schtd;
421  int res;
422 
423  if (interval <= 0) {
424  return NULL;
425  }
426 
427  schtd = ao2_alloc((sizeof(*schtd) + (!ast_strlen_zero(name) ? strlen(name) : ID_LEN) + 1),
428  schtd_dtor);
429  if (!schtd) {
430  return NULL;
431  }
432 
433  schtd->serializer = ao2_bump(serializer);
434  schtd->task_data = task_data;
435  schtd->task = sip_task;
436  schtd->interval = interval;
437  schtd->flags = flags;
438  schtd->last_start = ast_tv(0, 0);
439  if (!ast_strlen_zero(name)) {
440  strcpy(schtd->name, name); /* Safe */
441  } else {
442  uint32_t task_id;
443 
444  task_id = ast_atomic_fetchadd_int(&task_count, 1);
445  sprintf(schtd->name, "task_%08x", task_id);
446  }
447  if (schtd->flags & AST_SIP_SCHED_TASK_TRACK) {
448  ast_log(LOG_DEBUG, "Sched %p: Scheduling %s for %d ms\n", schtd, schtd->name,
449  interval);
450  }
451  schtd->when_queued = ast_tvnow();
452  if (!(schtd->flags & AST_SIP_SCHED_TASK_DELAY)) {
453  schtd->next_periodic = ast_tvadd(schtd->when_queued,
454  ast_samp2tv(schtd->interval, 1000));
455  }
456 
458  ao2_ref(task_data, +1);
459  }
460 
461  /*
462  * We must put it in the 'tasks' container before scheduling
463  * the task because we don't want the push_to_serializer()
464  * sched task to "remove" it on failure before we even put
465  * it in. If this happens then nothing would remove it from
466  * the 'tasks' container.
467  */
468  ao2_link(tasks, schtd);
469 
470  /*
471  * Lock so we are guaranteed to get the sched id set before
472  * the push_to_serializer() sched task can clear it.
473  */
474  ao2_lock(schtd);
476  schtd->current_scheduler_id = res;
477  ao2_unlock(schtd);
478  if (res < 0) {
479  ao2_unlink(tasks, schtd);
480  ao2_ref(schtd, -1);
481  return NULL;
482  }
483 
484  return schtd;
485 #undef ID_LEN
486 }
static const char name[]
Definition: format_mp3.c:68
struct timeval last_start
static struct ast_sched_context * scheduler_context
struct timeval when_queued
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ID_LEN
#define NULL
Definition: resample.c:96
#define LOG_DEBUG
Definition: logger.h:241
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define ao2_bump(obj)
Definition: astobj2.h:491
static int push_to_serializer(const void *data)
#define ast_log
Definition: astobj2.c:42
struct timeval next_periodic
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:238
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
enum ast_sip_scheduler_task_flags flags
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
userdata associated with baseline taskprocessor test
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
The next invocation of the task is at last finish + interval.
Definition: res_pjsip.h:1822
static int task_count
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
Definition: sched.c:565
The scheduled task&#39;s events are tracked in the debug log.
Definition: res_pjsip.h:1829
static struct ao2_container * tasks
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
struct ast_taskprocessor * serializer
static void schtd_dtor(void *data)
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ ast_sip_thread_is_servant()

int ast_sip_thread_is_servant ( void  )

Determine if the current thread is a SIP servant thread.

Return values
0This is not a SIP servant thread
1This is a SIP servant thread

Definition at line 5321 of file res_pjsip.c.

References ast_threadstorage_get(), servant_id_storage, and SIP_SERVANT_ID.

Referenced by ast_sip_push_task_wait_servant(), refer_progress_destroy(), and task_1().

5322 {
5323  uint32_t *servant_id;
5324 
5325  if (monitor_thread &&
5326  pthread_self() == *(pthread_t *)pj_thread_get_os_handle(monitor_thread)) {
5327  return 1;
5328  }
5329 
5330  servant_id = ast_threadstorage_get(&servant_id_storage, sizeof(*servant_id));
5331  if (!servant_id) {
5332  return 0;
5333  }
5334 
5335  return *servant_id == SIP_SERVANT_ID;
5336 }
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
pj_thread_t * monitor_thread
Definition: res_pjsip.c:5274
#define SIP_SERVANT_ID
Definition: res_pjsip.c:5294
static struct ast_threadstorage servant_id_storage
Definition: res_pjsip.c:5293