40 #include "asterisk/res_pjsip.h"
43 #define CATEGORY "/res/res_pjsip/scheduler/"
49 struct timeval test_start;
50 struct timeval task_start;
51 struct timeval task_end;
57 struct ast_test *
test;
60 #define S2U(x) (long int)(x * 1000 * 1000)
61 #define M2U(x) (long int)(x * 1000)
63 static int task_1(
void *data)
67 if (!test->no_clear_done) {
71 test->tid = pthread_self();
73 usleep(M2U(test->sleep));
76 ast_mutex_lock(&test->lock);
78 ast_mutex_unlock(&test->lock);
79 ast_cond_signal(&test->cond);
81 return test->interval;
85 static void data_cleanup(
void *data)
88 ast_mutex_destroy(&test_data->lock);
89 ast_cond_destroy(&test_data->cond);
94 ast_mutex_lock(&(x)->lock); \
95 while (!(x)->done) { \
96 ast_cond_wait(&(x)->cond, &(x)->lock); \
99 ast_mutex_unlock(&(x)->lock); \
102 static int scheduler(
struct ast_test *test,
int serialized)
105 RAII_VAR(
struct test_data *, test_data1, ao2_alloc(
sizeof(*test_data1), data_cleanup), ao2_cleanup);
106 RAII_VAR(
struct test_data *, test_data2, ao2_alloc(
sizeof(*test_data2), data_cleanup), ao2_cleanup);
111 struct timeval task1_start;
113 ast_test_validate(test, test_data1 != NULL);
114 ast_test_validate(test, test_data2 != NULL);
116 test_data1->test = test;
118 test_data1->interval = 2000;
119 test_data1->sleep = 1000;
120 ast_mutex_init(&test_data1->lock);
121 ast_cond_init(&test_data1->cond, NULL);
123 test_data2->test = test;
125 test_data2->interval = 2000;
126 test_data2->sleep = 1000;
127 ast_mutex_init(&test_data2->lock);
128 ast_cond_init(&test_data2->cond, NULL);
131 ast_test_status_update(test,
"This test will take about %3.1f seconds\n",
132 (test_data1->interval + test_data1->sleep + (MAX(test_data1->interval - test_data2->interval, 0)) + test_data2->sleep) / 1000.0);
134 ast_test_validate(test, (tp1 != NULL));
136 ast_test_status_update(test,
"This test will take about %3.1f seconds\n",
137 ((MAX(test_data1->interval, test_data2->interval) + MAX(test_data1->sleep, test_data2->sleep)) / 1000.0));
141 ast_test_validate(test, task1 != NULL);
144 ast_test_validate(test, task2 != NULL);
148 ast_test_validate(test, test_data1->is_servant);
150 duration =
ast_tvdiff_ms(test_data1->task_end, test_data1->test_start);
151 ast_test_validate(test, (duration > ((test_data1->interval + test_data1->sleep) * 0.9))
152 && (duration < ((test_data1->interval + test_data1->sleep) * 1.1)));
156 ast_test_validate(test, (delay > (test_data1->interval * 0.9)
157 && (delay < (test_data1->interval * 1.1))));
161 ast_test_validate(test, test_data2->is_servant);
164 ast_test_validate(test, test_data1->tid == test_data2->tid);
165 ast_test_validate(test,
ast_tvdiff_ms(test_data2->task_start, test_data1->task_end) >= 0);
167 ast_test_validate(test, test_data1->tid != test_data2->tid);
170 return AST_TEST_PASS;
178 info->name = __func__;
180 info->summary =
"Test res_pjsip serialized scheduler";
181 info->description =
"Test res_pjsip serialized scheduler";
182 return AST_TEST_NOT_RUN;
187 return scheduler(test, 1);
195 info->name = __func__;
197 info->summary =
"Test res_pjsip unserialized scheduler";
198 info->description =
"Test res_pjsip unserialized scheduler";
199 return AST_TEST_NOT_RUN;
204 return scheduler(test, 0);
207 static int run_count;
208 static int destruct_count;
210 static int dummy_task(
void *data)
220 static void test_destructor(
void *data)
227 RAII_VAR(
int *, sleep, NULL, ao2_cleanup);
234 info->name = __func__;
236 info->summary =
"Test res_pjsip scheduler cleanup";
237 info->description =
"Test res_pjsip scheduler cleanup";
238 return AST_TEST_NOT_RUN;
246 sleep = ao2_alloc(
sizeof(*sleep), test_destructor);
247 ast_test_validate(test, sleep != NULL);
250 ast_test_status_update(test,
"This test will take about %3.1f seconds\n",
251 ((interval * 1.1) + *sleep) / 1000.0);
255 ast_test_validate(test,
task != NULL);
256 usleep(M2U(interval * 0.5));
258 ast_test_validate(test, (when > (interval * 0.4) && when < (interval * 0.6)));
259 usleep(M2U(interval * 0.6));
266 ast_test_validate(test, (when < 0), res, error);
270 ast_test_validate(test, (destruct_count == 1));
273 return AST_TEST_PASS;
278 RAII_VAR(
int *, sleep, NULL, ao2_cleanup);
285 info->name = __func__;
287 info->summary =
"Test res_pjsip scheduler cancel task";
288 info->description =
"Test res_pjsip scheduler cancel task";
289 return AST_TEST_NOT_RUN;
297 sleep = ao2_alloc(
sizeof(*sleep), test_destructor);
298 ast_test_validate(test, sleep != NULL);
301 ast_test_status_update(test,
"This test will take about %3.1f seconds\n",
302 (interval + *sleep) / 1000.0);
305 ast_test_validate(test,
task != NULL);
307 usleep(M2U(interval * 0.5));
309 ast_test_validate(test, (when > (interval * 0.4) && when < (interval * 0.6)));
316 ast_test_validate(test, when < 0);
318 usleep(M2U(interval));
319 ast_test_validate(test, run_count == 0);
320 ast_test_validate(test, destruct_count == 0);
323 return AST_TEST_PASS;
328 RAII_VAR(
struct test_data *, test_data1, ao2_alloc(
sizeof(*test_data1), data_cleanup), ao2_cleanup);
334 info->name = __func__;
336 info->summary =
"Test res_pjsip scheduler cancel task";
337 info->description =
"Test res_pjsip scheduler cancel task";
338 return AST_TEST_NOT_RUN;
343 ast_test_validate(test, test_data1 != NULL);
347 test_data1->test = test;
349 test_data1->interval = 1000;
350 test_data1->sleep = 500;
351 test_data1->no_clear_done = 1;
352 ast_mutex_init(&test_data1->lock);
353 ast_cond_init(&test_data1->cond, NULL);
355 ast_test_status_update(test,
"This test will take about %3.1f seconds\n",
356 ((test_data1->interval * 4) + test_data1->sleep) / 1000.0);
360 ast_test_validate(test,
task != NULL);
363 when =
ast_tvdiff_ms(test_data1->task_start, test_data1->test_start);
364 ast_test_validate(test, when > test_data1->interval * 0.9 && when < test_data1->interval * 1.1);
367 when =
ast_tvdiff_ms(test_data1->task_start, test_data1->test_start);
368 ast_test_validate(test, when > test_data1->interval * 2 * 0.9 && when < test_data1->interval * 2 * 1.1);
371 when =
ast_tvdiff_ms(test_data1->task_start, test_data1->test_start);
372 ast_test_validate(test, when > test_data1->interval * 3 * 0.9 && when < test_data1->interval * 3 * 1.1);
377 usleep(M2U(test_data1->interval));
379 ast_mutex_lock(&test_data1->lock);
380 if (test_data1->done) {
381 int done = test_data1->done;
383 test_data1->done = 0;
384 ast_mutex_unlock(&test_data1->lock);
386 ast_test_validate(test, done == 1);
389 usleep(M2U(test_data1->interval * 2));
391 ast_mutex_lock(&test_data1->lock);
392 if (test_data1->done != 0) {
393 ast_mutex_unlock(&test_data1->lock);
397 ast_test_status_update(test,
"Failed to cancel task");
398 return AST_TEST_FAIL;
401 ast_mutex_unlock(&test_data1->lock);
403 return AST_TEST_PASS;
406 static int load_module(
void)
408 AST_TEST_REGISTER(serialized_scheduler);
409 AST_TEST_REGISTER(unserialized_scheduler);
410 AST_TEST_REGISTER(scheduler_cleanup);
411 AST_TEST_REGISTER(scheduler_cancel);
412 AST_TEST_REGISTER(scheduler_policy);
416 static int unload_module(
void)
418 AST_TEST_UNREGISTER(scheduler_cancel);
419 AST_TEST_UNREGISTER(scheduler_cleanup);
420 AST_TEST_UNREGISTER(unserialized_scheduler);
421 AST_TEST_UNREGISTER(serialized_scheduler);
422 AST_TEST_UNREGISTER(scheduler_policy);
426 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,
"res_pjsip scheduler test module",
427 .support_level = AST_MODULE_SUPPORT_CORE,
429 .unload = unload_module,
430 .requires =
"res_pjsip",
Asterisk main include file. File version handling, generic pbx functions.
The task is scheduled at multiples of interval.
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
int ast_sip_sched_is_task_running(struct ast_sip_sched_task *schtd)
Checks if the task is currently running.
static int task(void *data)
Queued task for baseline test.
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.
int ast_sip_sched_task_get_next_run_by_name(const char *name)
Gets the number of milliseconds until the next invocation.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
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.
int ast_sip_sched_is_task_running_by_name(const char *name)
Checks if the task is currently running.
int ast_sip_thread_is_servant(void)
Determine if the current thread is a SIP servant thread.
Sorcery object created based on backend data.
struct ast_taskprocessor * ast_sip_create_serializer(const char *name)
Create a new serializer for SIP tasks.
int ast_sip_sched_task_get_next_run(struct ast_sip_sched_task *schtd)
Gets the number of milliseconds until the next invocation.
An API for managing task processing threads that can be shared across modules.
A ast_taskprocessor structure is a singleton by name.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
#define AST_TEST_DEFINE(hdr)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Structure for mutex and tracking information.
int ast_sip_sched_task_cancel_by_name(const char *name)
Cancels the next invocation of a task by name.