00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2005, Digium, Inc. 00005 * 00006 * Mark Spencer <markster@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! \file 00020 * \brief Scheduler Routines (derived from cheops) 00021 */ 00022 00023 #ifndef _ASTERISK_SCHED_H 00024 #define _ASTERISK_SCHED_H 00025 00026 #if defined(__cplusplus) || defined(c_plusplus) 00027 extern "C" { 00028 #endif 00029 00030 /*! \brief Max num of schedule structs 00031 * \note The max number of schedule structs to keep around 00032 * for use. Undefine to disable schedule structure 00033 * caching. (Only disable this on very low memory 00034 * machines) 00035 */ 00036 #define SCHED_MAX_CACHE 128 00037 00038 /*! \brief a loop construct to ensure that 00039 * the scheduled task get deleted. The idea is that 00040 * if we loop attempting to remove the scheduled task, 00041 * then whatever callback had been running will complete 00042 * and reinsert the task into the scheduler. 00043 * 00044 * Since macro expansion essentially works like pass-by-name 00045 * parameter passing, this macro will still work correctly even 00046 * if the id of the task to delete changes. This holds as long as 00047 * the name of the id which could change is passed to the macro 00048 * and not a copy of the value of the id. 00049 */ 00050 #define AST_SCHED_DEL(sched, id) \ 00051 ({ \ 00052 int _count = 0; \ 00053 int _sched_res = -1; \ 00054 while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) \ 00055 usleep(1); \ 00056 if (_count == 10 && option_debug > 2) { \ 00057 ast_log(LOG_DEBUG, "Unable to cancel schedule ID %d.\n", id); \ 00058 } \ 00059 id = -1; \ 00060 (_sched_res); \ 00061 }) 00062 00063 #define AST_SCHED_DEL_SPINLOCK(sched, id, lock) \ 00064 ({ \ 00065 int _count = 0; \ 00066 int _sched_res = -1; \ 00067 while (id > -1 && (_sched_res = ast_sched_del(sched, id)) && ++_count < 10) { \ 00068 ast_mutex_unlock(lock); \ 00069 usleep(1); \ 00070 ast_mutex_lock(lock); \ 00071 } \ 00072 if (_count == 10 && option_debug > 2) { \ 00073 ast_log(LOG_DEBUG, "Unable to cancel schedule ID %d.\n", id); \ 00074 } \ 00075 id = -1; \ 00076 (_sched_res); \ 00077 }) 00078 00079 struct sched_context; 00080 00081 /*! \brief New schedule context 00082 * \note Create a scheduling context 00083 * \return Returns a malloc'd sched_context structure, NULL on failure 00084 */ 00085 struct sched_context *sched_context_create(void); 00086 00087 /*! \brief destroys a schedule context 00088 * Destroys (free's) the given sched_context structure 00089 * \param c Context to free 00090 * \return Returns 0 on success, -1 on failure 00091 */ 00092 void sched_context_destroy(struct sched_context *c); 00093 00094 /*! \brief callback for a cheops scheduler 00095 * A cheops scheduler callback takes a pointer with callback data and 00096 * \return returns a 0 if it should not be run again, or non-zero if it should be 00097 * rescheduled to run again 00098 */ 00099 typedef int (*ast_sched_cb)(const void *data); 00100 #define AST_SCHED_CB(a) ((ast_sched_cb)(a)) 00101 00102 /*! \brief Adds a scheduled event 00103 * Schedule an event to take place at some point in the future. callback 00104 * will be called with data as the argument, when milliseconds into the 00105 * future (approximately) 00106 * If callback returns 0, no further events will be re-scheduled 00107 * \param con Scheduler context to add 00108 * \param when how many milliseconds to wait for event to occur 00109 * \param callback function to call when the amount of time expires 00110 * \param data data to pass to the callback 00111 * \return Returns a schedule item ID on success, -1 on failure 00112 */ 00113 int ast_sched_add(struct sched_context *con, int when, ast_sched_cb callback, const void *data); 00114 00115 /*!Adds a scheduled event with rescheduling support 00116 * \param con Scheduler context to add 00117 * \param when how many milliseconds to wait for event to occur 00118 * \param callback function to call when the amount of time expires 00119 * \param data data to pass to the callback 00120 * \param variable If true, the result value of callback function will be 00121 * used for rescheduling 00122 * Schedule an event to take place at some point in the future. Callback 00123 * will be called with data as the argument, when milliseconds into the 00124 * future (approximately) 00125 * If callback returns 0, no further events will be re-scheduled 00126 * \return Returns a schedule item ID on success, -1 on failure 00127 */ 00128 int ast_sched_add_variable(struct sched_context *con, int when, ast_sched_cb callback, const void *data, int variable); 00129 00130 /*! \brief Deletes a scheduled event 00131 * Remove this event from being run. A procedure should not remove its 00132 * own event, but return 0 instead. 00133 * \param con scheduling context to delete item from 00134 * \param id ID of the scheduled item to delete 00135 * \return Returns 0 on success, -1 on failure 00136 */ 00137 #ifndef AST_DEVMODE 00138 int ast_sched_del(struct sched_context *con, int id); 00139 #else 00140 int _ast_sched_del(struct sched_context *con, int id, const char *file, int line, const char *function); 00141 #define ast_sched_del(a, b) _ast_sched_del(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__) 00142 #endif 00143 00144 /*! \brief Determines number of seconds until the next outstanding event to take place 00145 * Determine the number of seconds until the next outstanding event 00146 * should take place, and return the number of milliseconds until 00147 * it needs to be run. This value is perfect for passing to the poll 00148 * call. 00149 * \param con context to act upon 00150 * \return Returns "-1" if there is nothing there are no scheduled events 00151 * (and thus the poll should not timeout) 00152 */ 00153 int ast_sched_wait(struct sched_context *con); 00154 00155 /*! \brief Runs the queue 00156 * \param con Scheduling context to run 00157 * Run the queue, executing all callbacks which need to be performed 00158 * at this time. 00159 * \param con context to act upon 00160 * \return Returns the number of events processed. 00161 */ 00162 int ast_sched_runq(struct sched_context *con); 00163 00164 /*! \brief Dumps the scheduler contents 00165 * Debugging: Dump the contents of the scheduler to stderr 00166 * \param con Context to dump 00167 */ 00168 void ast_sched_dump(const struct sched_context *con); 00169 00170 /*! \brief Returns the number of seconds before an event takes place 00171 * \param con Context to use 00172 * \param id Id to dump 00173 */ 00174 long ast_sched_when(struct sched_context *con,int id); 00175 00176 /*! 00177 * \brief Convenience macro for objects and reference (add) 00178 * 00179 */ 00180 #define ast_sched_add_object(obj,con,when,callback) ast_sched_add((con),(when),(callback), ASTOBJ_REF((obj))) 00181 00182 /*! 00183 * \brief Convenience macro for objects and reference (del) 00184 * 00185 */ 00186 #define ast_sched_del_object(obj,destructor,con,id) do { \ 00187 if ((id) > -1) { \ 00188 ast_sched_del((con),(id)); \ 00189 (id) = -1; \ 00190 ASTOBJ_UNREF((obj),(destructor)); \ 00191 } \ 00192 } while(0) 00193 00194 #if defined(__cplusplus) || defined(c_plusplus) 00195 } 00196 #endif 00197 00198 #endif /* _ASTERISK_SCHED_H */