I/O Managment (Derived from Cheops-NG). More...
#include "asterisk.h"#include <termios.h>#include <sys/ioctl.h>#include "asterisk/io.h"#include "asterisk/utils.h"
Go to the source code of this file.
Data Structures | |
| struct | io_context |
| Global IO variables are now in a struct in order to be made threadsafe. More... | |
| struct | io_rec |
| Kept for each file descriptor. More... | |
Defines | |
| #define | DEBUG(a) |
| #define | GROW_SHRINK_SIZE 512 |
Functions | |
| int | ast_get_termcols (int fd) |
| int | ast_hide_password (int fd) |
| int * | ast_io_add (struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data) |
| Add a new I/O entry for this file descriptor with the given event mask, to call callback with data as an argument. | |
| int * | ast_io_change (struct io_context *ioc, int *id, int fd, ast_io_cb callback, short events, void *data) |
| Changes an IO handler. | |
| void | ast_io_dump (struct io_context *ioc) |
| Dumps the IO array. Debugging: Dump everything in the I/O array. | |
| int | ast_io_remove (struct io_context *ioc, int *_id) |
| Removes an IO context. | |
| int | ast_io_wait (struct io_context *ioc, int howlong) |
| Make the poll call, and call the callbacks for anything that needs to be handled. | |
| int | ast_restore_tty (int fd, int oldstate) |
| Restores TTY mode. Call with result from previous ast_hide_password. | |
| struct io_context * | io_context_create (void) |
| Create an I/O context. | |
| void | io_context_destroy (struct io_context *ioc) |
| Destroys a context. | |
| static int | io_grow (struct io_context *ioc) |
| Grow the size of our arrays. | |
| static int | io_shrink (struct io_context *ioc) |
I/O Managment (Derived from Cheops-NG).
Definition in file io.c.
| #define DEBUG | ( | a | ) |
Definition at line 39 of file io.c.
Referenced by ast_io_add(), ast_io_wait(), ast_sched_add_variable(), ast_sched_del(), ast_sched_runq(), ast_sched_wait(), ast_sched_when(), and io_grow().
| #define GROW_SHRINK_SIZE 512 |
Definition at line 58 of file io.c.
Referenced by io_context_create(), and io_grow().
| int ast_get_termcols | ( | int | fd | ) |
Definition at line 364 of file io.c.
Referenced by ast_cli_display_match_list().
00365 { 00366 struct winsize win; 00367 int cols = 0; 00368 00369 if (!isatty(fd)) 00370 return -1; 00371 00372 if ( ioctl(fd, TIOCGWINSZ, &win) != -1 ) { 00373 if ( !cols && win.ws_col > 0 ) 00374 cols = (int) win.ws_col; 00375 } else { 00376 /* assume 80 characters if the ioctl fails for some reason */ 00377 cols = 80; 00378 } 00379 00380 return cols; 00381 }
| int ast_hide_password | ( | int | fd | ) |
Set fd into non-echoing mode (if fd is a tty)
Definition at line 328 of file io.c.
References ECHO.
Referenced by pw_cb().
00329 { 00330 struct termios tios; 00331 int res; 00332 int old; 00333 if (!isatty(fd)) 00334 return -1; 00335 res = tcgetattr(fd, &tios); 00336 if (res < 0) 00337 return -1; 00338 old = tios.c_lflag & (ECHO | ECHONL); 00339 tios.c_lflag &= ~ECHO; 00340 tios.c_lflag |= ECHONL; 00341 res = tcsetattr(fd, TCSAFLUSH, &tios); 00342 if (res < 0) 00343 return -1; 00344 return old; 00345 }
| int* ast_io_add | ( | struct io_context * | ioc, | |
| int | fd, | |||
| ast_io_cb | callback, | |||
| short | events, | |||
| void * | data | |||
| ) |
Add a new I/O entry for this file descriptor with the given event mask, to call callback with data as an argument.
Adds an IO context.
Definition at line 153 of file io.c.
References ast_debug, ast_malloc, io_rec::callback, io_rec::data, DEBUG, io_context::fdcnt, io_context::fds, io_rec::id, io_grow(), io_context::ior, and io_context::maxfdcnt.
Referenced by ast_netsock_bindaddr(), ast_rtp_new_with_bindaddr(), ast_udptl_new_with_bindaddr(), do_monitor(), network_thread(), and p2p_callback_disable().
00154 { 00155 int *ret; 00156 00157 DEBUG(ast_debug(1, "ast_io_add()\n")); 00158 00159 if (ioc->fdcnt >= ioc->maxfdcnt) { 00160 /* 00161 * We don't have enough space for this entry. We need to 00162 * reallocate maxfdcnt poll fd's and io_rec's, or back out now. 00163 */ 00164 if (io_grow(ioc)) 00165 return NULL; 00166 } 00167 00168 /* 00169 * At this point, we've got sufficiently large arrays going 00170 * and we can make an entry for it in the pollfd and io_r 00171 * structures. 00172 */ 00173 ioc->fds[ioc->fdcnt].fd = fd; 00174 ioc->fds[ioc->fdcnt].events = events; 00175 ioc->fds[ioc->fdcnt].revents = 0; 00176 ioc->ior[ioc->fdcnt].callback = callback; 00177 ioc->ior[ioc->fdcnt].data = data; 00178 00179 if (!(ioc->ior[ioc->fdcnt].id = ast_malloc(sizeof(*ioc->ior[ioc->fdcnt].id)))) { 00180 /* Bonk if we couldn't allocate an int */ 00181 return NULL; 00182 } 00183 00184 *(ioc->ior[ioc->fdcnt].id) = ioc->fdcnt; 00185 ret = ioc->ior[ioc->fdcnt].id; 00186 ioc->fdcnt++; 00187 00188 return ret; 00189 }
| int* ast_io_change | ( | struct io_context * | ioc, | |
| int * | id, | |||
| int | fd, | |||
| ast_io_cb | callback, | |||
| short | events, | |||
| void * | data | |||
| ) |
Changes an IO handler.
| ioc | which context to use | |
| id | ||
| fd | the fd you wish it to contain now | |
| callback | new callback function | |
| events | event mask to wait for | |
| data | data to pass to the callback function Change an I/O handler, updating fd if > -1, callback if non-null, and revents if >-1, and data if non-null. |
| a | pointer to the ID of the IO event | |
| NULL | on failure |
Definition at line 191 of file io.c.
References io_rec::callback, io_rec::data, io_context::fdcnt, io_context::fds, and io_context::ior.
Referenced by do_monitor().
00192 { 00193 /* If this id exceeds our file descriptor count it doesn't exist here */ 00194 if (*id > ioc->fdcnt) 00195 return NULL; 00196 00197 if (fd > -1) 00198 ioc->fds[*id].fd = fd; 00199 if (callback) 00200 ioc->ior[*id].callback = callback; 00201 if (events) 00202 ioc->fds[*id].events = events; 00203 if (data) 00204 ioc->ior[*id].data = data; 00205 00206 return id; 00207 }
| void ast_io_dump | ( | struct io_context * | ioc | ) |
Dumps the IO array. Debugging: Dump everything in the I/O array.
Definition at line 303 of file io.c.
References ast_debug, io_rec::callback, io_rec::data, io_context::fdcnt, io_context::fds, io_rec::id, io_context::ior, and io_context::maxfdcnt.
00304 { 00305 /* 00306 * Print some debugging information via 00307 * the logger interface 00308 */ 00309 int x; 00310 00311 ast_debug(1, "Asterisk IO Dump: %d entries, %d max entries\n", ioc->fdcnt, ioc->maxfdcnt); 00312 ast_debug(1, "================================================\n"); 00313 ast_debug(1, "| ID FD Callback Data Events |\n"); 00314 ast_debug(1, "+------+------+-----------+-----------+--------+\n"); 00315 for (x = 0; x < ioc->fdcnt; x++) { 00316 ast_debug(1, "| %.4d | %.4d | %p | %p | %.6x |\n", 00317 *ioc->ior[x].id, 00318 ioc->fds[x].fd, 00319 ioc->ior[x].callback, 00320 ioc->ior[x].data, 00321 ioc->fds[x].events); 00322 } 00323 ast_debug(1, "================================================\n"); 00324 }
| int ast_io_remove | ( | struct io_context * | ioc, | |
| int * | id | |||
| ) |
Removes an IO context.
| ioc | which io_context to remove it from | |
| id | which ID to remove Remove an I/O id from consideration |
| 0 | on success | |
| -1 | on failure |
Definition at line 236 of file io.c.
References ast_free, ast_log(), io_context::current_ioc, io_context::fdcnt, io_context::fds, io_rec::id, io_shrink(), io_context::ior, LOG_NOTICE, LOG_WARNING, and io_context::needshrink.
Referenced by ast_io_wait(), ast_netsock_destroy(), ast_rtp_destroy(), ast_udptl_destroy(), do_monitor(), p2p_callback_disable(), and reload_config().
00237 { 00238 int x; 00239 00240 if (!_id) { 00241 ast_log(LOG_WARNING, "Asked to remove NULL?\n"); 00242 return -1; 00243 } 00244 00245 for (x = 0; x < ioc->fdcnt; x++) { 00246 if (ioc->ior[x].id == _id) { 00247 /* Free the int immediately and set to NULL so we know it's unused now */ 00248 ast_free(ioc->ior[x].id); 00249 ioc->ior[x].id = NULL; 00250 ioc->fds[x].events = 0; 00251 ioc->fds[x].revents = 0; 00252 ioc->needshrink = 1; 00253 if (ioc->current_ioc == -1) 00254 io_shrink(ioc); 00255 return 0; 00256 } 00257 } 00258 00259 ast_log(LOG_NOTICE, "Unable to remove unknown id %p\n", _id); 00260 00261 return -1; 00262 }
| int ast_io_wait | ( | struct io_context * | ioc, | |
| int | howlong | |||
| ) |
Make the poll call, and call the callbacks for anything that needs to be handled.
Waits for IO.
Definition at line 269 of file io.c.
References ast_debug, ast_io_remove(), ast_poll, io_rec::callback, io_context::current_ioc, io_rec::data, DEBUG, io_context::fdcnt, io_context::fds, io_rec::id, io_shrink(), io_context::ior, and io_context::needshrink.
Referenced by do_monitor(), network_thread(), and reload_config().
00270 { 00271 int res, x, origcnt; 00272 00273 DEBUG(ast_debug(1, "ast_io_wait()\n")); 00274 00275 if ((res = ast_poll(ioc->fds, ioc->fdcnt, howlong)) <= 0) { 00276 return res; 00277 } 00278 00279 /* At least one event tripped */ 00280 origcnt = ioc->fdcnt; 00281 for (x = 0; x < origcnt; x++) { 00282 /* Yes, it is possible for an entry to be deleted and still have an 00283 event waiting if it occurs after the original calling id */ 00284 if (ioc->fds[x].revents && ioc->ior[x].id) { 00285 /* There's an event waiting */ 00286 ioc->current_ioc = *ioc->ior[x].id; 00287 if (ioc->ior[x].callback) { 00288 if (!ioc->ior[x].callback(ioc->ior[x].id, ioc->fds[x].fd, ioc->fds[x].revents, ioc->ior[x].data)) { 00289 /* Time to delete them since they returned a 0 */ 00290 ast_io_remove(ioc, ioc->ior[x].id); 00291 } 00292 } 00293 ioc->current_ioc = -1; 00294 } 00295 } 00296 00297 if (ioc->needshrink) 00298 io_shrink(ioc); 00299 00300 return res; 00301 }
| int ast_restore_tty | ( | int | fd, | |
| int | oldstate | |||
| ) |
Restores TTY mode. Call with result from previous ast_hide_password.
Definition at line 347 of file io.c.
References ECHO.
Referenced by pw_cb().
00348 { 00349 int res; 00350 struct termios tios; 00351 if (oldstate < 0) 00352 return 0; 00353 res = tcgetattr(fd, &tios); 00354 if (res < 0) 00355 return -1; 00356 tios.c_lflag &= ~(ECHO | ECHONL); 00357 tios.c_lflag |= oldstate; 00358 res = tcsetattr(fd, TCSAFLUSH, &tios); 00359 if (res < 0) 00360 return -1; 00361 return 0; 00362 }
| struct io_context* io_context_create | ( | void | ) | [read] |
Create an I/O context.
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up some default values.
Definition at line 72 of file io.c.
References ast_calloc, ast_free, ast_malloc, io_context::current_ioc, io_context::fdcnt, io_context::fds, GROW_SHRINK_SIZE, io_context::ior, io_context::maxfdcnt, and io_context::needshrink.
Referenced by load_module().
00073 { 00074 struct io_context *tmp = NULL; 00075 00076 if (!(tmp = ast_malloc(sizeof(*tmp)))) 00077 return NULL; 00078 00079 tmp->needshrink = 0; 00080 tmp->fdcnt = 0; 00081 tmp->maxfdcnt = GROW_SHRINK_SIZE/2; 00082 tmp->current_ioc = -1; 00083 00084 if (!(tmp->fds = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->fds)))) { 00085 ast_free(tmp); 00086 tmp = NULL; 00087 } else { 00088 if (!(tmp->ior = ast_calloc(1, (GROW_SHRINK_SIZE / 2) * sizeof(*tmp->ior)))) { 00089 ast_free(tmp->fds); 00090 ast_free(tmp); 00091 tmp = NULL; 00092 } 00093 } 00094 00095 return tmp; 00096 }
| void io_context_destroy | ( | struct io_context * | ioc | ) |
Destroys a context.
| ioc | structure to destroy Destroy a context for I/O operations Frees all memory associated with the given io_context structure along with the structure itself |
Definition at line 98 of file io.c.
References ast_free, io_context::fds, and io_context::ior.
Referenced by load_module(), and unload_module().
| static int io_grow | ( | struct io_context * | ioc | ) | [static] |
Grow the size of our arrays.
Definition at line 113 of file io.c.
References ast_debug, ast_realloc, DEBUG, io_context::fds, GROW_SHRINK_SIZE, io_context::ior, and io_context::maxfdcnt.
Referenced by ast_io_add().
00114 { 00115 void *tmp; 00116 00117 DEBUG(ast_debug(1, "io_grow()\n")); 00118 00119 ioc->maxfdcnt += GROW_SHRINK_SIZE; 00120 00121 if ((tmp = ast_realloc(ioc->ior, (ioc->maxfdcnt + 1) * sizeof(*ioc->ior)))) { 00122 ioc->ior = tmp; 00123 if ((tmp = ast_realloc(ioc->fds, (ioc->maxfdcnt + 1) * sizeof(*ioc->fds)))) { 00124 ioc->fds = tmp; 00125 } else { 00126 /* 00127 * Failed to allocate enough memory for the pollfd. Not 00128 * really any need to shrink back the iorec's as we'll 00129 * probably want to grow them again soon when more memory 00130 * is available, and then they'll already be the right size 00131 */ 00132 ioc->maxfdcnt -= GROW_SHRINK_SIZE; 00133 return -1; 00134 } 00135 } else { 00136 /* 00137 * Memory allocation failure. We return to the old size, and 00138 * return a failure 00139 */ 00140 ioc->maxfdcnt -= GROW_SHRINK_SIZE; 00141 return -1; 00142 } 00143 00144 return 0; 00145 }
| static int io_shrink | ( | struct io_context * | ioc | ) | [static] |
Definition at line 209 of file io.c.
References io_context::fdcnt, io_context::fds, io_rec::id, io_context::ior, and io_context::needshrink.
Referenced by ast_io_remove(), and ast_io_wait().
00210 { 00211 int getfrom, putto = 0; 00212 00213 /* 00214 * Bring the fields from the very last entry to cover over 00215 * the entry we are removing, then decrease the size of the 00216 * arrays by one. 00217 */ 00218 for (getfrom = 0; getfrom < ioc->fdcnt; getfrom++) { 00219 if (ioc->ior[getfrom].id) { 00220 /* In use, save it */ 00221 if (getfrom != putto) { 00222 ioc->fds[putto] = ioc->fds[getfrom]; 00223 ioc->ior[putto] = ioc->ior[getfrom]; 00224 *(ioc->ior[putto].id) = putto; 00225 } 00226 putto++; 00227 } 00228 } 00229 ioc->fdcnt = putto; 00230 ioc->needshrink = 0; 00231 /* FIXME: We should free some memory if we have lots of unused 00232 io structs */ 00233 return 0; 00234 }
1.6.1