42 static int sched_cb(
const void *data)
47 static int order_check;
48 static int order_check_failed;
50 static void sched_order_check(
struct ast_test *
test,
int order)
53 if (order_check != order) {
54 ast_test_status_update(test,
"Unexpected execution order: expected:%d got:%d\n",
56 order_check_failed = 1;
60 static int sched_order_1_cb(
const void *data)
62 sched_order_check((
void *) data, 1);
66 static int sched_order_2_cb(
const void *data)
68 sched_order_check((
void *) data, 2);
72 static int sched_order_3_cb(
const void *data)
74 sched_order_check((
void *) data, 3);
78 static int sched_order_4_cb(
const void *data)
80 sched_order_check((
void *) data, 4);
84 static int sched_order_5_cb(
const void *data)
86 sched_order_check((
void *) data, 5);
90 static int sched_order_6_cb(
const void *data)
92 sched_order_check((
void *) data, 6);
96 static int sched_order_7_cb(
const void *data)
98 sched_order_check((
void *) data, 7);
102 static int sched_order_8_cb(
const void *data)
104 sched_order_check((
void *) data, 8);
111 enum ast_test_result_state res = AST_TEST_FAIL;
112 int id1, id2, id3, wait;
116 info->name =
"sched_test_order";
117 info->category =
"/main/sched/";
118 info->summary =
"Test ordering of events in the scheduler API";
120 "This test ensures that events are properly ordered by the "
121 "time they are scheduled to execute in the scheduler API.";
122 return AST_TEST_NOT_RUN;
128 ast_test_status_update(test,
129 "Test failed - could not create scheduler context\n");
130 return AST_TEST_FAIL;
137 ast_test_status_update(test,
138 "ast_sched_wait() should have returned -1, returned '%d'\n",
143 if ((id1 =
ast_sched_add(con, 100000, sched_cb, NULL)) == -1) {
144 ast_test_status_update(test,
"Failed to add scheduler entry\n");
149 ast_test_status_update(test,
150 "ast_sched_wait() should have returned <= 100000, returned '%d'\n",
155 if ((id2 =
ast_sched_add(con, 10000, sched_cb, NULL)) == -1) {
156 ast_test_status_update(test,
"Failed to add scheduler entry\n");
161 ast_test_status_update(test,
162 "ast_sched_wait() should have returned <= 10000, returned '%d'\n",
167 if ((id3 =
ast_sched_add(con, 1000, sched_cb, NULL)) == -1) {
168 ast_test_status_update(test,
"Failed to add scheduler entry\n");
173 ast_test_status_update(test,
174 "ast_sched_wait() should have returned <= 1000, returned '%d'\n",
180 ast_test_status_update(test,
"Failed to remove scheduler entry\n");
185 ast_test_status_update(test,
186 "ast_sched_wait() should have returned > 1000, returned '%d'\n",
192 ast_test_status_update(test,
"Failed to remove scheduler entry\n");
197 ast_test_status_update(test,
198 "ast_sched_wait() should have returned > 10000, returned '%d'\n",
204 ast_test_status_update(test,
"Failed to remove scheduler entry\n");
209 ast_test_status_update(test,
210 "ast_sched_wait() should have returned -1, returned '%d'\n",
220 #define DELAYED_SAME_EXPIRE 300
221 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, DELAYED_SAME_EXPIRE, sched_order_1_cb, test), res, return_cleanup);
222 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, 0, sched_order_1_cb, test), res, return_cleanup);
223 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, DELAYED_SAME_EXPIRE, sched_order_2_cb, test), res, return_cleanup);
224 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, 0, sched_order_2_cb, test), res, return_cleanup);
225 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, DELAYED_SAME_EXPIRE, sched_order_3_cb, test), res, return_cleanup);
226 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, 0, sched_order_3_cb, test), res, return_cleanup);
227 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, DELAYED_SAME_EXPIRE, sched_order_4_cb, test), res, return_cleanup);
228 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, 0, sched_order_4_cb, test), res, return_cleanup);
229 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, DELAYED_SAME_EXPIRE, sched_order_5_cb, test), res, return_cleanup);
230 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, 0, sched_order_5_cb, test), res, return_cleanup);
231 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, DELAYED_SAME_EXPIRE, sched_order_6_cb, test), res, return_cleanup);
232 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, 0, sched_order_6_cb, test), res, return_cleanup);
233 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, DELAYED_SAME_EXPIRE, sched_order_7_cb, test), res, return_cleanup);
234 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, 0, sched_order_7_cb, test), res, return_cleanup);
235 ast_test_validate_cleanup(test, -1 <
ast_sched_add(con, DELAYED_SAME_EXPIRE, sched_order_8_cb, test), res, return_cleanup);
239 order_check_failed = 0;
241 ast_test_validate_cleanup(test, 7 ==
ast_sched_runq(con), res, return_cleanup);
242 ast_test_validate_cleanup(test, !order_check_failed, res, return_cleanup);
246 order_check_failed = 0;
247 usleep((DELAYED_SAME_EXPIRE + 50) * 1000);
248 ast_test_validate_cleanup(test, 8 ==
ast_sched_runq(con), res, return_cleanup);
249 ast_test_validate_cleanup(test, !order_check_failed, res, return_cleanup);
252 ast_test_status_update(test,
253 "ast_sched_wait() should have returned -1, returned '%d'\n",
269 struct timeval start;
271 int *sched_ids = NULL;
275 e->
command =
"sched benchmark";
277 "Usage: sched benchmark <num>\n"
284 if (a->argc != e->
args + 1) {
285 return CLI_SHOWUSAGE;
288 if (sscanf(a->argv[e->
args],
"%u", &num) != 1) {
289 return CLI_SHOWUSAGE;
293 ast_cli(a->fd,
"Test failed - could not create scheduler context\n");
297 if (!(sched_ids =
ast_malloc(
sizeof(*sched_ids) * num))) {
298 ast_cli(a->fd,
"Test failed - memory allocation failure\n");
302 ast_cli(a->fd,
"Testing ast_sched_add() performance - timing how long it takes "
303 "to add %u entries at random time intervals from 0 to 60 seconds\n", num);
307 for (i = 0; i < num; i++) {
308 long when = labs(ast_random()) % 60000;
309 if ((sched_ids[i] =
ast_sched_add(con, when, sched_cb, NULL)) == -1) {
310 ast_cli(a->fd,
"Test failed - sched_add returned -1\n");
317 ast_cli(a->fd,
"Testing ast_sched_del() performance - timing how long it takes "
318 "to delete %u entries with random time intervals from 0 to 60 seconds\n", num);
322 for (i = 0; i < num; i++) {
324 ast_cli(a->fd,
"Test failed - sched_del returned -1\n");
343 int scheduledCBstarted;
347 static void test_obj_cleanup(
void *data)
350 ast_mutex_destroy(&obj->lock);
351 ast_cond_destroy(&obj->cond);
354 static int lockingcb(
const void *data)
357 struct timespec delay = {3,0};
359 ast_mutex_lock(&obj->lock);
361 obj->scheduledCBstarted = 1;
362 ast_cond_signal(&obj->cond);
364 ast_mutex_unlock(&obj->lock);
367 while (nanosleep(&delay, &delay));
380 enum ast_test_result_state res = AST_TEST_FAIL;
385 info->name =
"sched_test_freebird";
386 info->category =
"/main/sched/";
387 info->summary =
"Test deadlock avoidance and double-unref";
389 "This tests a call to AST_SCHED_DEL_UNREF on a running event.";
390 return AST_TEST_NOT_RUN;
396 obj = ao2_alloc(
sizeof(
struct test_obj), test_obj_cleanup);
398 ast_test_status_update(test,
399 "ao2_alloc() did not return an object\n");
400 return AST_TEST_FAIL;
403 obj->scheduledCBstarted = 0;
407 ast_test_status_update(test,
408 "ast_sched_context_create() did not return a context\n");
410 return AST_TEST_FAIL;
414 ast_test_status_update(test,
"Failed to start test thread\n");
417 return AST_TEST_FAIL;
424 if ((obj->id =
ast_sched_add(con, 0, lockingcb, obj)) == -1) {
425 ast_test_status_update(test,
"Failed to add scheduler entry\n");
428 return AST_TEST_FAIL;
431 ast_mutex_lock(&obj->lock);
432 while(obj->scheduledCBstarted == 0) {
436 ast_cond_wait(&obj->cond,&obj->lock);
438 ast_mutex_unlock(&obj->lock);
440 ast_test_status_update(test,
"Received signal, calling Scedule and UNREF\n");
441 ast_test_status_update(test,
"ID: %d\n", obj->id);
448 ast_test_status_update(test,
"Correct number of references '2'\n");
451 ast_test_status_update(test,
"Incorrect number of references '%d'\n",
467 AST_CLI_DEFINE(handle_cli_sched_bench,
"Benchmark ast_sched add/del performance"),
470 static int unload_module(
void)
472 AST_TEST_UNREGISTER(sched_test_order);
473 AST_TEST_UNREGISTER(sched_test_freebird);
478 static int load_module(
void)
480 AST_TEST_REGISTER(sched_test_order);
481 AST_TEST_REGISTER(sched_test_freebird);
486 AST_MODULE_INFO_STANDARD(
ASTERISK_GPL_KEY,
"ast_sched performance test module");
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Asterisk main include file. File version handling, generic pbx functions.
int ast_sched_runq(struct ast_sched_context *con)
Runs the queue.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
descriptor for a cli entry.
#define AST_SCHED_DEL_UNREF(sched, id, refcall)
schedule task to get deleted and call unref function
#define ast_cli_register_multiple(e, len)
Register multiple commands.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int args
This gets set in ast_cli_register()
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Scheduler Routines (derived from cheops)
#define ast_malloc(len)
A wrapper for malloc()
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
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.
Standard Command Line Interface.
int ast_sched_wait(struct ast_sched_context *con) attribute_warn_unused_result
Determines number of seconds until the next outstanding event to take place.
#define AST_TEST_DEFINE(hdr)
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Structure for mutex and tracking information.