Asterisk - The Open Source Telephony Project GIT-master-650240a
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 1885 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 2079 of file res_pjsip.h.

2079 {
2080 /*!
2081 * The defaults
2082 */
2083 AST_SIP_SCHED_TASK_DEFAULTS = (0 << 0),
2084
2085 /*!
2086 * Run at a fixed interval.
2087 * Stop scheduling if the callback returns <= 0.
2088 * Any other value is ignored.
2089 */
2090 AST_SIP_SCHED_TASK_FIXED = (0 << 0),
2091 /*!
2092 * Run at a variable interval.
2093 * Stop scheduling if the callback returns <= 0.
2094 * Any other return value is used as the new interval.
2095 */
2096 AST_SIP_SCHED_TASK_VARIABLE = (1 << 0),
2097
2098 /*!
2099 * Run just once.
2100 * Return values are ignored.
2101 */
2102 AST_SIP_SCHED_TASK_ONESHOT = (1 << 6),
2103
2104 /*!
2105 * The task data is not an AO2 object.
2106 */
2108 /*!
2109 * The task data is an AO2 object.
2110 * A reference count will be held by the scheduler until
2111 * after the task has run for the final time (if ever).
2112 */
2113 AST_SIP_SCHED_TASK_DATA_AO2 = (1 << 1),
2114
2115 /*!
2116 * Don't take any cleanup action on the data
2117 */
2119 /*!
2120 * If AST_SIP_SCHED_TASK_DATA_AO2 is set, decrement the reference count
2121 * otherwise call ast_free on it.
2122 */
2123 AST_SIP_SCHED_TASK_DATA_FREE = ( 1 << 3 ),
2124
2125 /*!
2126 * \brief The task is scheduled at multiples of interval
2127 * \see Interval
2128 */
2129 AST_SIP_SCHED_TASK_PERIODIC = (0 << 4),
2130 /*!
2131 * \brief The next invocation of the task is at last finish + interval
2132 * \see Interval
2133 */
2134 AST_SIP_SCHED_TASK_DELAY = (1 << 4),
2135 /*!
2136 * \brief The scheduled task's events are tracked in the debug log.
2137 * \details
2138 * Schedule events such as scheduling, running, rescheduling, canceling,
2139 * and destroying are logged about the task.
2140 */
2141 AST_SIP_SCHED_TASK_TRACK = (1 << 5),
2142};
@ AST_SIP_SCHED_TASK_ONESHOT
Definition: res_pjsip.h:2102
@ AST_SIP_SCHED_TASK_DELAY
The next invocation of the task is at last finish + interval.
Definition: res_pjsip.h:2134
@ AST_SIP_SCHED_TASK_TRACK
The scheduled task's events are tracked in the debug log.
Definition: res_pjsip.h:2141
@ AST_SIP_SCHED_TASK_DATA_NOT_AO2
Definition: res_pjsip.h:2107
@ AST_SIP_SCHED_TASK_DEFAULTS
Definition: res_pjsip.h:2083
@ AST_SIP_SCHED_TASK_FIXED
Definition: res_pjsip.h:2090
@ AST_SIP_SCHED_TASK_PERIODIC
The task is scheduled at multiples of interval.
Definition: res_pjsip.h:2129
@ AST_SIP_SCHED_TASK_DATA_AO2
Definition: res_pjsip.h:2113
@ AST_SIP_SCHED_TASK_DATA_FREE
Definition: res_pjsip.h:2123
@ AST_SIP_SCHED_TASK_DATA_NO_CLEANUP
Definition: res_pjsip.h:2118
@ AST_SIP_SCHED_TASK_VARIABLE
Definition: res_pjsip.h:2096

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 2094 of file res_pjsip.c.

2095{
2097}
static const char name[]
Definition: format_mp3.c:68
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:2089
#define NULL
Definition: resample.c:96

References ast_sip_create_serializer_group(), name, 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().

◆ 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 2089 of file res_pjsip.c.

2090{
2092}
static struct ast_serializer_shutdown_group * shutdown_group
Shutdown group for options serializers.
static struct ast_threadpool * sip_threadpool
Definition: res_pjsip.c:76
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:1398

References ast_threadpool_serializer_group(), name, shutdown_group, and sip_threadpool.

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

◆ 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 319 of file pjsip_distributor.c.

320{
321 struct distributor_dialog_data *dist;
322 struct ast_sip_endpoint *endpoint;
323
325 if (dist) {
326 ao2_lock(dist);
327 endpoint = ao2_bump(dist->endpoint);
328 ao2_unlock(dist);
329 ao2_ref(dist, -1);
330 } else {
331 endpoint = NULL;
332 }
333 return endpoint;
334}
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
static struct ao2_container * dialog_associations
An entity with which Asterisk communicates.
Definition: res_pjsip.h:978
struct ast_sip_endpoint * endpoint

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

Referenced by digest_create_request_with_auth(), and refer_client_on_evsub_state().

◆ 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 291 of file pjsip_distributor.c.

292{
293 struct distributor_dialog_data *dist;
294
297 if (!dist) {
298 if (endpoint) {
299 dist = ao2_alloc(sizeof(*dist), NULL);
300 if (dist) {
301 dist->dlg = dlg;
302 dist->endpoint = endpoint;
304 ao2_ref(dist, -1);
305 }
306 }
307 } else {
308 ao2_lock(dist);
309 dist->endpoint = endpoint;
310 if (!dist->serializer && !dist->endpoint) {
312 }
313 ao2_unlock(dist);
314 ao2_ref(dist, -1);
315 }
317}
#define ao2_wrlock(a)
Definition: astobj2.h:719
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
struct ast_taskprocessor * serializer

References ao2_alloc, ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlink_flags, ao2_unlock, ao2_wrlock, dialog_associations, 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(), clean_sub_tree(), refer_send(), session_end_completion(), and subscription_setup_dialog().

◆ 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 263 of file pjsip_distributor.c.

264{
265 struct distributor_dialog_data *dist;
266
269 if (!dist) {
270 if (serializer) {
271 dist = ao2_alloc(sizeof(*dist), NULL);
272 if (dist) {
273 dist->dlg = dlg;
274 dist->serializer = serializer;
276 ao2_ref(dist, -1);
277 }
278 }
279 } else {
280 ao2_lock(dist);
281 dist->serializer = serializer;
282 if (!dist->serializer && !dist->endpoint) {
284 }
285 ao2_unlock(dist);
286 ao2_ref(dist, -1);
287 }
289}

References ao2_alloc, ao2_find, ao2_link_flags, ao2_lock, ao2_ref, ao2_unlink_flags, ao2_unlock, ao2_wrlock, dialog_associations, 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(), clean_sub_tree(), session_end_completion(), and subscription_setup_dialog().

◆ 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 445 of file pjsip_distributor.c.

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

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

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

◆ 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 2099 of file res_pjsip.c.

2100{
2101 if (!serializer) {
2103 }
2104
2105 return ast_taskprocessor_push(serializer, sip_task, task_data);
2106}
static struct ast_serializer_pool * sip_serializer_pool
Definition: res_pjsip.c:72
struct ast_taskprocessor * ast_serializer_pool_get(struct ast_serializer_pool *pool)
Retrieve a serializer from the pool.
Definition: serializer.c:127
userdata associated with baseline taskprocessor test
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.

References ast_serializer_pool_get(), ast_taskprocessor_push(), and sip_serializer_pool.

Referenced by aoc_framehook(), 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().

◆ 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 2174 of file res_pjsip.c.

2175{
2177}
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:2165

References ast_sip_push_task_wait_servant().

◆ 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 2179 of file res_pjsip.c.

2180{
2181 if (!serializer) {
2182 /* Caller doesn't care which PJSIP serializer the task executes under. */
2184 if (!serializer) {
2185 /* No serializer picked to execute the task */
2186 return -1;
2187 }
2188 }
2190 /*
2191 * We are the requested serializer so we must execute
2192 * the task now or deadlock waiting on ourself to
2193 * execute it.
2194 */
2195 return sip_task(task_data);
2196 }
2197
2198 return ast_sip_push_task_wait(serializer, sip_task, task_data);
2199}
static int ast_sip_push_task_wait(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Definition: res_pjsip.c:2137
int ast_taskprocessor_is_task(struct ast_taskprocessor *tps)
Am I the given taskprocessor's current task.

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

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_read_param(), func_response_read_header(), func_response_read_headers(), func_write_header(), func_write_param(), pjsip_acf_channel_read(), pjsip_acf_dtmf_mode_write(), pjsip_acf_media_offer_write(), pjsip_acf_parse_uri_read(), pjsip_acf_session_refresh_write(), pjsip_app_hangup_handler(), 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(), sip_refer_send(), subscription_persistence_recreate(), and websocket_cb().

◆ 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 2165 of file res_pjsip.c.

2166{
2168 return sip_task(task_data);
2169 }
2170
2171 return ast_sip_push_task_wait(serializer, sip_task, task_data);
2172}
int ast_sip_thread_is_servant(void)
Determine if the current thread is a SIP servant thread.
Definition: res_pjsip.c:2310

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(), refer_out_of_dialog_destroy(), reload_module(), sip_outbound_publisher_alloc(), sip_transport_state_destroy(), subscription_tree_destructor(), and unload_module().

◆ 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.

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

References ast_sip_sched_task::is_running.

Referenced by AST_TEST_DEFINE().

◆ 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.

381{
382 int is_running;
383 struct ast_sip_sched_task *schtd;
384
385 if (ast_strlen_zero(name)) {
386 return 0;
387 }
388
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 struct ao2_container * tasks
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

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

Referenced by AST_TEST_DEFINE().

◆ 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.

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
209 schtd->current_scheduler_id = -1;
210 ao2_unlock(schtd);
212
213 ao2_unlink(tasks, schtd);
214
215 return res;
216}
#define ast_log
Definition: astobj2.c:42
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define LOG_DEBUG
static struct ast_sched_context * scheduler_context
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
Definition: sched.c:614
enum ast_sip_scheduler_task_flags flags
Scheduler ID holder.
Definition: sched.c:70

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, ast_sip_sched_task::name, scheduler_context, and tasks.

Referenced by ast_sip_destroy_scheduler(), ast_sip_sched_task_cancel_by_name(), AST_TEST_DEFINE(), clean_sub_tree(), 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().

◆ 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.

219{
220 int res;
221 struct ast_sip_sched_task *schtd;
222
223 if (ast_strlen_zero(name)) {
224 return -1;
225 }
226
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}
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.

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

Referenced by AST_TEST_DEFINE().

◆ 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
name,maxlen
Return values
0success
1failure

Definition at line 334 of file pjsip_scheduler.c.

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}
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425

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

Referenced by clean_sub_tree(), and pubsub_on_rx_refresh().

◆ 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.

348{
349 int delay;
350
352
353 return delay;
354}
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.

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().

◆ 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.

357{
358 int next_run;
359 struct ast_sip_sched_task *schtd;
360
361 if (ast_strlen_zero(name)) {
362 return -1;
363 }
364
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}
int ast_sip_sched_task_get_next_run(struct ast_sip_sched_task *schtd)
Gets the number of milliseconds until the next invocation.

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

Referenced by AST_TEST_DEFINE().

◆ 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.

301{
302 return ast_sip_sched_task_get_times2(schtd, queued, last_start, last_end, NULL, NULL, NULL);
303}

References ast_sip_sched_task_get_times2(), and NULL.

Referenced by scheduler().

◆ 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]next_startPointer 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.

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 last_end
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235

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().

◆ 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.

329{
330 return ast_sip_sched_task_get_times_by_name2(name, queued, last_start, last_end,
331 NULL, NULL, NULL);
332}
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.

References ast_sip_sched_task_get_times_by_name2(), ast_sip_sched_task::last_end, ast_sip_sched_task::last_start, name, and NULL.

◆ 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]next_startPointer 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.

308{
309 int res;
310 struct ast_sip_sched_task *schtd;
311
312 if (ast_strlen_zero(name)) {
313 return -1;
314 }
315
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}

References ao2_find, ao2_ref, ast_sip_sched_task_get_times2(), ast_strlen_zero(), ast_sip_sched_task::interval, ast_sip_sched_task::last_end, ast_sip_sched_task::last_start, name, OBJ_SEARCH_KEY, and tasks.

Referenced by ast_sip_sched_task_get_times_by_name().

◆ 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.
Serialization

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.

Interval

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 example: 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.

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
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}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
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:757
static int task_count
static void schtd_dtor(void *data)
#define ID_LEN
static int push_to_serializer(const void *data)
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:567
struct timeval next_periodic
struct ast_taskprocessor * serializer
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:282

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, name, ast_sip_sched_task::next_periodic, NULL, push_to_serializer(), scheduler_context, schtd_dtor(), ast_sip_sched_task::serializer, ast_sip_sched_task::task, task_count, ast_sip_sched_task::task_data, tasks, 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().

◆ 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 2310 of file res_pjsip.c.

2311{
2312 uint32_t *servant_id;
2313
2314 if (monitor_thread &&
2315 pthread_self() == *(pthread_t *)pj_thread_get_os_handle(monitor_thread)) {
2316 return 1;
2317 }
2318
2319 servant_id = ast_threadstorage_get(&servant_id_storage, sizeof(*servant_id));
2320 if (!servant_id) {
2321 return 0;
2322 }
2323
2324 return *servant_id == SIP_SERVANT_ID;
2325}
pj_thread_t * monitor_thread
Definition: res_pjsip.c:2263
#define SIP_SERVANT_ID
Definition: res_pjsip.c:2283
static struct ast_threadstorage servant_id_storage
Definition: res_pjsip.c:2282
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.

References ast_threadstorage_get(), monitor_thread, servant_id_storage, and SIP_SERVANT_ID.

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