/*! * \internal * \brief Find the request tdata to get the serializer it used. * \since 14.0.0 * * \param rdata The incoming message. * * \retval serializer on success. * \retval NULL on error or could not find the serializer. */ static struct ast_taskprocessor *find_request_serializer(pjsip_rx_data *rdata) { struct ast_taskprocessor *serializer = NULL; pj_str_t tsx_key; pjsip_transaction *tsx; pjsip_tsx_create_key(rdata->tp_info.pool, &tsx_key, PJSIP_ROLE_UAC, &rdata->msg_info.cseq->method, rdata); tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE); if (!tsx) { ast_debug(1, "Could not find %.*s transaction for %d response.\n", (int) pj_strlen(&rdata->msg_info.cseq->method.name), pj_strbuf(&rdata->msg_info.cseq->method.name), rdata->msg_info.msg->line.status.code); return NULL; } if (tsx->last_tx) { const char *serializer_name; serializer_name = tsx->last_tx->mod_data[distributor_mod.id]; if (!ast_strlen_zero(serializer_name)) { serializer = ast_taskprocessor_get(serializer_name, TPS_REF_IF_EXISTS); } } #ifdef HAVE_PJ_TRANSACTION_GRP_LOCK pj_grp_lock_release(tsx->grp_lock); #else pj_mutex_unlock(tsx->mutex); #endif return serializer; }
struct stasis_subscription *internal_stasis_subscribe( struct stasis_topic *topic, stasis_subscription_cb callback, void *data, int needs_mailbox, int use_thread_pool) { RAII_VAR(struct stasis_subscription *, sub, NULL, ao2_cleanup); if (!topic) { return NULL; } /* The ao2 lock is used for join_cond. */ sub = ao2_t_alloc(sizeof(*sub), subscription_dtor, stasis_topic_name(topic)); if (!sub) { return NULL; } ast_uuid_generate_str(sub->uniqueid, sizeof(sub->uniqueid)); if (needs_mailbox) { char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1]; /* Create name with seq number appended. */ ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "sub%c:%s", use_thread_pool ? 'p' : 'm', stasis_topic_name(topic)); /* * With a small number of subscribers, a thread-per-sub is * acceptable. For a large number of subscribers, a thread * pool should be used. */ if (use_thread_pool) { sub->mailbox = ast_threadpool_serializer(tps_name, pool); } else { sub->mailbox = ast_taskprocessor_get(tps_name, TPS_REF_DEFAULT); } if (!sub->mailbox) { return NULL; } ast_taskprocessor_set_local(sub->mailbox, sub); /* Taskprocessor has a reference */ ao2_ref(sub, +1); } ao2_ref(topic, +1); sub->topic = topic; sub->callback = callback; sub->data = data; ast_cond_init(&sub->join_cond, NULL); if (topic_add_subscription(topic, sub) != 0) { return NULL; } send_subscription_subscribe(topic, sub); ao2_ref(sub, +1); return sub; }
struct stasis_subscription *internal_stasis_subscribe( struct stasis_topic *topic, stasis_subscription_cb callback, void *data, int needs_mailbox, int use_thread_pool) { RAII_VAR(struct stasis_subscription *, sub, NULL, ao2_cleanup); if (!topic) { return NULL; } /* The ao2 lock is used for join_cond. */ sub = ao2_t_alloc(sizeof(*sub), subscription_dtor, topic->name); if (!sub) { return NULL; } ast_uuid_generate_str(sub->uniqueid, sizeof(sub->uniqueid)); if (needs_mailbox) { /* With a small number of subscribers, a thread-per-sub is * acceptable. For larger number of subscribers, a thread * pool should be used. */ if (use_thread_pool) { sub->mailbox = ast_threadpool_serializer(sub->uniqueid, pool); } else { sub->mailbox = ast_taskprocessor_get(sub->uniqueid, TPS_REF_DEFAULT); } if (!sub->mailbox) { return NULL; } ast_taskprocessor_set_local(sub->mailbox, sub); /* Taskprocessor has a reference */ ao2_ref(sub, +1); } ao2_ref(topic, +1); sub->topic = topic; sub->callback = callback; sub->data = data; ast_cond_init(&sub->join_cond, NULL); if (topic_add_subscription(topic, sub) != 0) { return NULL; } send_subscription_subscribe(topic, sub); ao2_ref(sub, +1); return sub; }
/*! * \brief Initializes the resolver. * * \retval 0 on success * \retval -1 on failure */ int ast_dns_system_resolver_init(void) { /* Register the base resolver */ int res = ast_dns_resolver_register(&dns_system_resolver_base); if (res) { return DNS_SYSTEM_RESOLVER_FAILURE; } /* Instantiate the task processor */ dns_system_resolver_tp = ast_taskprocessor_get("dns_system_resolver_tp", TPS_REF_DEFAULT); /* Return error if the task processor failed to instantiate */ if (!dns_system_resolver_tp) { dns_system_resolver_destroy(); return DNS_SYSTEM_RESOLVER_FAILURE; } /* Register the cleanup function */ ast_register_cleanup(dns_system_resolver_destroy); return DNS_SYSTEM_RESOLVER_SUCCESS; }
/* * \brief Allocate a threadpool * * This is implemented as a taskprocessor listener's alloc callback. This * is because the threadpool exists as the private data on a taskprocessor * listener. * * \param name The name of the threadpool. * \param options The options the threadpool uses. * \retval NULL Could not initialize threadpool properly * \retval non-NULL The newly-allocated threadpool */ static struct ast_threadpool *threadpool_alloc(const char *name, const struct ast_threadpool_options *options) { RAII_VAR(struct ast_threadpool *, pool, NULL, ao2_cleanup); struct ast_str *control_tps_name; pool = ao2_alloc(sizeof(*pool), threadpool_destructor); control_tps_name = ast_str_create(64); if (!pool || !control_tps_name) { ast_free(control_tps_name); return NULL; } ast_str_set(&control_tps_name, 0, "%s-control", name); pool->control_tps = ast_taskprocessor_get(ast_str_buffer(control_tps_name), TPS_REF_DEFAULT); ast_free(control_tps_name); if (!pool->control_tps) { return NULL; } pool->active_threads = ao2_container_alloc(THREAD_BUCKETS, worker_thread_hash, worker_thread_cmp); if (!pool->active_threads) { return NULL; } pool->idle_threads = ao2_container_alloc(THREAD_BUCKETS, worker_thread_hash, worker_thread_cmp); if (!pool->idle_threads) { return NULL; } pool->zombie_threads = ao2_container_alloc(THREAD_BUCKETS, worker_thread_hash, worker_thread_cmp); if (!pool->zombie_threads) { return NULL; } pool->options = *options; ao2_ref(pool, +1); return pool; }