int ast_sched_runq(struct sched_context *con) { /* * Launch all events which need to be run at this time. */ struct sched *current; struct timeval tv; int x=0; int res; DEBUG(ast_log(LOG_DEBUG, "ast_sched_runq()\n")); ast_mutex_lock(&con->lock); tv = ast_tvadd(ast_tvnow(), ast_tv(0, 1000)); for(;;) { if (!con->schedq) break; /* schedule all events which are going to expire within 1ms. * We only care about millisecond accuracy anyway, so this will * help us get more than one event at one time if they are very * close together. */ if (SOONER(con->schedq->when, tv)) { current = con->schedq; con->schedq = con->schedq->next; con->schedcnt--; /* * At this point, the schedule queue is still intact. We * have removed the first event and the rest is still there, * so it's permissible for the callback to add new events, but * trying to delete itself won't work because it isn't in * the schedule queue. If that's what it wants to do, it * should return 0. */ ast_mutex_unlock(&con->lock); res = current->callback(current->data); ast_mutex_lock(&con->lock); if (res) { /* * If they return non-zero, we should schedule them to be * run again. */ if (sched_settime(¤t->when, current->variable? res : current->resched)) { sched_release(con, current); } else schedule(con, current); } else { /* No longer needed, so release it */ sched_release(con, current); } x++; } else break; } ast_mutex_unlock(&con->lock); return x; }
int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, void *data, int variable) { /* * Schedule callback(data) to happen when ms into the future */ struct sched *tmp; int res = -1; DEBUG(ast_log(LOG_DEBUG, "ast_sched_add()\n")); if (!when) { ast_log(LOG_NOTICE, "Scheduled event in 0 ms?\n"); return -1; } ast_mutex_lock(&con->lock); if ((tmp = sched_alloc(con))) { tmp->id = con->eventcnt++; tmp->callback = callback; tmp->data = data; tmp->resched = when; tmp->variable = variable; tmp->when = ast_tv(0, 0); if (sched_settime(&tmp->when, when)) { sched_release(con, tmp); } else { schedule(con, tmp); res = tmp->id; } } #ifdef DUMP_SCHEDULER /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */ ast_sched_dump(con); #endif ast_mutex_unlock(&con->lock); return res; }
int cw_sched_runq(struct sched_context *con) { /* * Launch all events which need to be run at this time. */ struct sched *runq, **endq, *current; struct timeval tv; int x=0; int res; #ifdef DEBUG_SCHED DEBUG_LOG(cw_log(LOG_DEBUG, "cw_sched_runq()\n")); #endif cw_mutex_lock(&con->lock); /* schedule all events which are going to expire within 1ms. * We only care about millisecond accuracy anyway, so this will * help us get more than one event at one time if they are very * close together. */ tv = cw_tvadd(cw_tvnow(), cw_tv(0, 1000)); runq = con->schedq; endq = &runq; while (con->schedq && SOONER(con->schedq->when, tv)) { endq = &con->schedq->next; con->schedq = con->schedq->next; con->schedcnt--; } *endq = NULL; cw_mutex_unlock(&con->lock); while ((current = runq)) { runq = runq->next; x++; res = current->callback(current->data); if (res) { /* * If they return non-zero, we should schedule them to be * run again. */ current->when = cw_tvadd(current->when, cw_samp2tv((current->variable ? res : current->resched), 1000)); schedule(con, current); } else { /* No longer needed, so release it */ sched_release(con, current); } } return x; }
int cw_sched_del(struct sched_context *con, int id) { /* * Delete the schedule entry with number * "id". It's nearly impossible that there * would be two or more in the list with that * id. */ struct sched *last=NULL, *s; int deleted = 0; #ifdef DEBUG_SCHED DEBUG_LOG(cw_log(LOG_DEBUG, "cw_sched_del()\n")); #endif cw_mutex_lock(&con->lock); s = con->schedq; while(s) { if (s->id == id) { if (last) last->next = s->next; else con->schedq = s->next; con->schedcnt--; sched_release(con, s); deleted = 1; break; } last = s; s = s->next; } #ifdef DUMP_SCHEDULER /* Dump contents of the context while we have the lock so nothing gets screwed up by accident. */ cw_sched_dump(con); #endif cw_mutex_unlock(&con->lock); if (!deleted) { if (option_debug) cw_log(LOG_DEBUG, "Attempted to delete nonexistent schedule entry %d!\n", id); return -1; } else return 0; }