From e9b756c7ad7d51b41b2ccf0f72eb904b0eea2169 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 10 Sep 2014 03:16:43 +0200 Subject: input: remove central select() call This is now unused. Get rid of it and all surrounding infrastructure, and replace the remaining "wakeup pipe" with a semaphore. --- input/input.c | 404 +++++------------------------------------------------- input/input.h | 41 +----- input/lirc.c | 4 +- old-configure | 1 - player/loadfile.c | 1 - wscript | 7 - 6 files changed, 37 insertions(+), 421 deletions(-) diff --git a/input/input.c b/input/input.c index cc4cc6285c..5415b369d7 100644 --- a/input/input.c +++ b/input/input.c @@ -35,6 +35,7 @@ #include #include "osdep/io.h" +#include "osdep/semaphore.h" #include "misc/rendezvous.h" #include "input.h" @@ -80,24 +81,7 @@ struct cmd_bind_section { struct cmd_bind_section *next; }; -#define MP_MAX_FDS 10 - -struct input_fd { - struct mp_log *log; - int fd; - int (*read_key)(void *ctx, int fd); - int (*read_cmd)(void *ctx, int fd, char *dest, int size); - int (*close_func)(void *ctx, int fd); - void *ctx; - unsigned eof : 1; - unsigned drop : 1; - unsigned dead : 1; - unsigned got_cmd : 1; - unsigned select : 1; - // These fields are for the cmd fds. - char *buffer; - int pos, size; -}; +#define MP_MAX_SOURCES 10 #define MAX_ACTIVE_SECTIONS 50 @@ -112,9 +96,7 @@ struct cmd_queue { struct input_ctx { pthread_mutex_t mutex; - pthread_cond_t wakeup; - pthread_t mainthread; - bool mainthread_set; + sem_t wakeup; struct mp_log *log; struct mpv_global *global; struct input_opts *opts; @@ -170,16 +152,10 @@ struct input_ctx { unsigned int mouse_event_counter; - struct input_fd fds[MP_MAX_FDS]; - unsigned int num_fds; - struct mp_input_src *sources[MP_MAX_FDS]; + struct mp_input_src *sources[MP_MAX_SOURCES]; int num_sources; struct cmd_queue cmd_queue; - - bool need_wakeup; - bool in_select; - int wakeup_pipe[2]; }; static int parse_config(struct input_ctx *ictx, bool builtin, bstr data, @@ -812,283 +788,13 @@ unsigned int mp_input_get_mouse_event_counter(struct input_ctx *ictx) return ret; } -int input_default_read_cmd(void *ctx, int fd, char *buf, int l) -{ - while (1) { - int r = read(fd, buf, l); - // Error ? - if (r < 0) { - if (errno == EINTR) - continue; - else if (errno == EAGAIN) - return MP_INPUT_NOTHING; - return MP_INPUT_ERROR; - // EOF ? - } - return r; - } -} - -int mp_input_add_fd(struct input_ctx *ictx, int unix_fd, int select, - int read_cmd_func(void *ctx, int fd, char *dest, int size), - int read_key_func(void *ctx, int fd), - int close_func(void *ctx, int fd), void *ctx) -{ - if (select && unix_fd < 0) { - MP_ERR(ictx, "Invalid fd %d in mp_input_add_fd", unix_fd); - return 0; - } - - input_lock(ictx); - struct input_fd *fd = NULL; - if (ictx->num_fds == MP_MAX_FDS) { - MP_ERR(ictx, "Too many file descriptors.\n"); - } else { - fd = &ictx->fds[ictx->num_fds]; - *fd = (struct input_fd){ - .log = ictx->log, - .fd = unix_fd, - .select = select, - .read_cmd = read_cmd_func, - .read_key = read_key_func, - .close_func = close_func, - .ctx = ctx, - }; - ictx->num_fds++; - } - input_unlock(ictx); - return !!fd; -} - -static void mp_input_rm_fd(struct input_ctx *ictx, int fd) -{ - struct input_fd *fds = ictx->fds; - unsigned int i; - - for (i = 0; i < ictx->num_fds; i++) { - if (fds[i].fd == fd) - break; - } - if (i == ictx->num_fds) - return; - if (fds[i].close_func) - fds[i].close_func(fds[i].ctx, fds[i].fd); - talloc_free(fds[i].buffer); - - if (i + 1 < ictx->num_fds) - memmove(&fds[i], &fds[i + 1], - (ictx->num_fds - i - 1) * sizeof(struct input_fd)); - ictx->num_fds--; -} - -void mp_input_rm_key_fd(struct input_ctx *ictx, int fd) -{ - input_lock(ictx); - mp_input_rm_fd(ictx, fd); - input_unlock(ictx); -} - -#define MP_CMD_MAX_SIZE 4096 - -static int read_cmd(struct input_fd *mp_fd, char **ret) -{ - char *end; - *ret = NULL; - - // Allocate the buffer if it doesn't exist - if (!mp_fd->buffer) { - mp_fd->buffer = talloc_size(NULL, MP_CMD_MAX_SIZE); - mp_fd->pos = 0; - mp_fd->size = MP_CMD_MAX_SIZE; - } - - // Get some data if needed/possible - while (!mp_fd->got_cmd && !mp_fd->eof && (mp_fd->size - mp_fd->pos > 1)) { - int r = mp_fd->read_cmd(mp_fd->ctx, mp_fd->fd, mp_fd->buffer + mp_fd->pos, - mp_fd->size - 1 - mp_fd->pos); - // Error ? - if (r < 0) { - switch (r) { - case MP_INPUT_ERROR: - case MP_INPUT_DEAD: - MP_ERR(mp_fd, "Error while reading command file descriptor %d: %s\n", - mp_fd->fd, strerror(errno)); - case MP_INPUT_NOTHING: - return r; - case MP_INPUT_RETRY: - continue; - } - // EOF ? - } else if (r == 0) { - mp_fd->eof = 1; - break; - } - mp_fd->pos += r; - break; - } - - mp_fd->got_cmd = 0; - - while (1) { - int l = 0; - // Find the cmd end - mp_fd->buffer[mp_fd->pos] = '\0'; - end = strchr(mp_fd->buffer, '\r'); - if (end) - *end = '\n'; - end = strchr(mp_fd->buffer, '\n'); - // No cmd end ? - if (!end) { - // If buffer is full we must drop all until the next \n - if (mp_fd->size - mp_fd->pos <= 1) { - MP_ERR(mp_fd, "Command buffer of file descriptor %d is full: " - "dropping content.\n", mp_fd->fd); - mp_fd->pos = 0; - mp_fd->drop = 1; - } - break; - } - // We already have a cmd : set the got_cmd flag - else if ((*ret)) { - mp_fd->got_cmd = 1; - break; - } - - l = end - mp_fd->buffer; - - // Not dropping : put the cmd in ret - if (!mp_fd->drop) - *ret = talloc_strndup(NULL, mp_fd->buffer, l); - else - mp_fd->drop = 0; - mp_fd->pos -= l + 1; - memmove(mp_fd->buffer, end + 1, mp_fd->pos); - } - - if (*ret) - return 1; - else - return MP_INPUT_NOTHING; -} - -static void read_cmd_fd(struct input_ctx *ictx, struct input_fd *cmd_fd) -{ - int r; - char *text; - while ((r = read_cmd(cmd_fd, &text)) >= 0) { - mp_input_wakeup(ictx); - struct mp_cmd *cmd = mp_input_parse_cmd(ictx, bstr0(text), ""); - talloc_free(text); - if (cmd) - queue_add_tail(&ictx->cmd_queue, cmd); - if (!cmd_fd->got_cmd) - return; - } - if (r == MP_INPUT_ERROR) - MP_ERR(ictx, "Error on command file descriptor %d\n", cmd_fd->fd); - else if (r == MP_INPUT_DEAD) - cmd_fd->dead = true; -} - -static void read_key_fd(struct input_ctx *ictx, struct input_fd *key_fd) -{ - int code = key_fd->read_key(key_fd->ctx, key_fd->fd); - if (code >= 0 || code == MP_INPUT_RELEASE_ALL) { - mp_input_feed_key(ictx, code, 1); - return; - } - - if (code == MP_INPUT_ERROR) - MP_ERR(ictx, "Error on key input file descriptor %d\n", key_fd->fd); - else if (code == MP_INPUT_DEAD) { - MP_ERR(ictx, "Dead key input on file descriptor %d\n", key_fd->fd); - key_fd->dead = true; - } -} - -static void read_fd(struct input_ctx *ictx, struct input_fd *fd) -{ - if (fd->read_cmd) { - read_cmd_fd(ictx, fd); - } else { - read_key_fd(ictx, fd); - } -} - -static void remove_dead_fds(struct input_ctx *ictx) -{ - for (int i = 0; i < ictx->num_fds; i++) { - if (ictx->fds[i].dead) { - mp_input_rm_fd(ictx, ictx->fds[i].fd); - i--; - } - } -} - -#if HAVE_POSIX_SELECT - -static void input_wait_read(struct input_ctx *ictx, int time) -{ - fd_set fds; - FD_ZERO(&fds); - int max_fd = 0; - for (int i = 0; i < ictx->num_fds; i++) { - if (!ictx->fds[i].select) - continue; - if (ictx->fds[i].fd > max_fd) - max_fd = ictx->fds[i].fd; - FD_SET(ictx->fds[i].fd, &fds); - } - struct timeval tv, *time_val; - tv.tv_sec = time / 1000; - tv.tv_usec = (time % 1000) * 1000; - time_val = &tv; - ictx->in_select = true; - input_unlock(ictx); - if (select(max_fd + 1, &fds, NULL, NULL, time_val) < 0) { - if (errno != EINTR) - MP_ERR(ictx, "Select error: %s\n", strerror(errno)); - FD_ZERO(&fds); - } - input_lock(ictx); - ictx->in_select = false; - for (int i = 0; i < ictx->num_fds; i++) { - if (ictx->fds[i].select && !FD_ISSET(ictx->fds[i].fd, &fds)) - continue; - read_fd(ictx, &ictx->fds[i]); - } -} - -#else - -static void input_wait_read(struct input_ctx *ictx, int time) -{ - if (time > 0) - mpthread_cond_timedwait_rel(&ictx->wakeup, &ictx->mutex, time / 1000.0); - - for (int i = 0; i < ictx->num_fds; i++) - read_fd(ictx, &ictx->fds[i]); -} - -#endif - -/** - * \param time time to wait at most for an event in milliseconds - */ -static void read_events(struct input_ctx *ictx, int time) +// adjust min time to wait until next repeat event +static void adjust_max_wait_time(struct input_ctx *ictx, double *time) { if (ictx->last_key_down && ictx->ar_rate > 0 && ictx->ar_state >= 0) { - time = FFMIN(time, 1000 / ictx->ar_rate); - time = FFMIN(time, ictx->ar_delay); + *time = FFMIN(*time, 1000 / ictx->ar_rate); + *time = FFMIN(*time, ictx->ar_delay); } - time = FFMAX(time, 0); - - if (ictx->need_wakeup) - time = 0; - - remove_dead_fds(ictx); - - input_wait_read(ictx, time); } int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd) @@ -1132,20 +838,33 @@ void mp_input_wait(struct input_ctx *ictx, double seconds) { input_lock(ictx); if (ictx->cmd_queue.first) - seconds = 0; + seconds = -1; + adjust_max_wait_time(ictx, &seconds); + input_unlock(ictx); + while (sem_trywait(&ictx->wakeup) == 0) + seconds = -1; if (seconds > 0) { MP_STATS(ictx, "start sleep"); - read_events(ictx, MPMIN(seconds * 1000, INT_MAX)); + struct timespec ts = + mp_time_us_to_timespec(mp_add_timeout(mp_time_us(), seconds)); + sem_timedwait(&ictx->wakeup, &ts); MP_STATS(ictx, "end sleep"); } - ictx->need_wakeup = false; - input_unlock(ictx); +} + +void mp_input_wakeup(struct input_ctx *ictx) +{ + sem_post(&ictx->wakeup); +} + +void mp_input_wakeup_nolock(struct input_ctx *ictx) +{ + mp_input_wakeup(ictx); } mp_cmd_t *mp_input_read_cmd(struct input_ctx *ictx) { input_lock(ictx); - read_events(ictx, 0); struct cmd_queue *queue = &ictx->cmd_queue; if (!queue->first) { struct mp_cmd *repeated = check_autorepeat(ictx); @@ -1480,15 +1199,6 @@ done: return r; } -#ifndef __MINGW32__ -static int read_wakeup(void *ctx, int fd) -{ - char buf[100]; - read(fd, buf, sizeof(buf)); - return MP_INPUT_NOTHING; -} -#endif - struct input_ctx *mp_input_init(struct mpv_global *global) { struct input_opts *input_conf = global->opts->input_opts; @@ -1506,11 +1216,14 @@ struct input_ctx *mp_input_init(struct mpv_global *global) .default_bindings = input_conf->default_bindings, .mouse_section = "default", .test = input_conf->test, - .wakeup_pipe = {-1, -1}, }; + if (sem_init(&ictx->wakeup, 0, 0)) { + MP_FATAL(ictx, "mpv doesn't work on systems without POSIX semaphores.\n"); + abort(); + } + mpthread_mutex_init_recursive(&ictx->mutex); - pthread_cond_init(&ictx->wakeup, NULL); // Setup default section, so that it does nothing. mp_input_enable_section(ictx, NULL, MP_INPUT_ALLOW_VO_DRAGGING | @@ -1527,15 +1240,6 @@ struct input_ctx *mp_input_init(struct mpv_global *global) parse_config(ictx, true, line, "", NULL); } -#ifndef __MINGW32__ - int ret = mp_make_wakeup_pipe(ictx->wakeup_pipe); - if (ret < 0) - MP_ERR(ictx, "Failed to initialize wakeup pipe.\n"); - else - mp_input_add_fd(ictx, ictx->wakeup_pipe[0], true, NULL, read_wakeup, - NULL, NULL); -#endif - bool config_ok = false; if (input_conf->config_file) config_ok = parse_config_file(ictx, input_conf->config_file, true); @@ -1607,60 +1311,18 @@ void mp_input_uninit(struct input_ctx *ictx) } #endif - for (int i = 0; i < ictx->num_fds; i++) { - if (ictx->fds[i].close_func) - ictx->fds[i].close_func(ictx->fds[i].ctx, ictx->fds[i].fd); - } close_input_sources(ictx); - for (int i = 0; i < 2; i++) { - if (ictx->wakeup_pipe[i] != -1) - close(ictx->wakeup_pipe[i]); - } clear_queue(&ictx->cmd_queue); talloc_free(ictx->current_down_cmd); pthread_mutex_destroy(&ictx->mutex); - pthread_cond_destroy(&ictx->wakeup); + sem_destroy(&ictx->wakeup); talloc_free(ictx); } -void mp_input_wakeup(struct input_ctx *ictx) -{ - input_lock(ictx); - bool send_wakeup = ictx->in_select; - ictx->need_wakeup = true; - pthread_cond_signal(&ictx->wakeup); - input_unlock(ictx); - // Safe without locking - if (send_wakeup && ictx->wakeup_pipe[1] >= 0) - write(ictx->wakeup_pipe[1], &(char){0}, 1); -} - -void mp_input_wakeup_nolock(struct input_ctx *ictx) -{ - if (ictx->wakeup_pipe[1] >= 0) { - write(ictx->wakeup_pipe[1], &(char){0}, 1); - } else { - // Not race condition free. Done for the sake of jackaudio+windows. - ictx->need_wakeup = true; - pthread_cond_signal(&ictx->wakeup); - } -} - -void mp_input_set_main_thread(struct input_ctx *ictx) -{ - ictx->mainthread = pthread_self(); - ictx->mainthread_set = true; -} - bool mp_input_check_interrupt(struct input_ctx *ictx) { input_lock(ictx); bool res = queue_has_abort_cmds(&ictx->cmd_queue); - if (!res && ictx->mainthread_set && - pthread_equal(ictx->mainthread, pthread_self())) - { - read_events(ictx, 0); - } input_unlock(ictx); return res; } @@ -1697,7 +1359,7 @@ struct mp_input_src_internal { struct mp_input_src *mp_input_add_src(struct input_ctx *ictx) { input_lock(ictx); - if (ictx->num_sources == MP_MAX_FDS) { + if (ictx->num_sources == MP_MAX_SOURCES) { input_unlock(ictx); return NULL; } diff --git a/input/input.h b/input/input.h index ff3740e21b..56544a99ee 100644 --- a/input/input.h +++ b/input/input.h @@ -25,18 +25,8 @@ #include "cmd_list.h" #include "cmd_parse.h" -// Error codes for the drivers - -// An error occurred but we can continue -#define MP_INPUT_ERROR -1 -// A fatal error occurred, this driver should be removed -#define MP_INPUT_DEAD -2 -// No input was available -#define MP_INPUT_NOTHING -3 -//! Input will be available if you try again -#define MP_INPUT_RETRY -4 -// Key FIFO was full - release events may be lost, zero button-down status -#define MP_INPUT_RELEASE_ALL -5 +// For mp_input_put_key(): release all keys that are down. +#define MP_INPUT_RELEASE_ALL -1 enum mp_cmd_flags { MP_ON_OSD_NO = 0, // prefer not using OSD @@ -142,28 +132,6 @@ void mp_input_src_kill(struct mp_input_src *src); // Feed text data, which will be split into lines of commands. void mp_input_src_feed_cmd_text(struct mp_input_src *src, char *buf, size_t len); -/* Add a new command input source. (Old version.) - * "fd" is a file descriptor (use -1 if you don't use any fd) - * "select" tells whether to use select() on the fd to determine when to - * try reading. - * "read_cmd_func" is optional. It must return either text data or one of the - * MP_INPUT error codes above. For return values >= 0, it behaves like UNIX - * read() and returns the number of bytes copied to the dest buffer. - * "read_key_func" is optional. It returns either key codes (ASCII, keycodes.h), - * or MP_INPUT error codes. - * "close_func" will be called when closing. Can be NULL. Its return value - * is ignored (it's only there to allow using standard close() as the func). - * "ctx" is for free use, and is passed to the callbacks. - */ -int mp_input_add_fd(struct input_ctx *ictx, int fd, int select, - int read_cmd_func(void *ctx, int fd, char *dest, int size), - int read_key_func(void *ctx, int fd), - int close_func(void *ctx, int fd), void *ctx); - -/* Can be passed as read_func for above function in order to read() from the FD. - */ -int input_default_read_cmd(void *ctx, int fd, char *buf, int l); - // Process keyboard input. code is a key code from keycodes.h, possibly // with modifiers applied. MP_INPUT_RELEASE_ALL is also a valid value. void mp_input_put_key(struct input_ctx *ictx, int code); @@ -191,9 +159,6 @@ struct mp_rect; void mp_input_set_mouse_transform(struct input_ctx *ictx, struct mp_rect *dst, struct mp_rect *src); -// As for the cmd one you usually don't need this function. -void mp_input_rm_key_fd(struct input_ctx *ictx, int fd); - // Add a command to the command queue. int mp_input_queue_cmd(struct input_ctx *ictx, struct mp_cmd *cmd); @@ -278,6 +243,4 @@ void mp_input_add_pipe(struct input_ctx *ictx, const char *filename); void mp_input_joystick_add(struct input_ctx *ictx, char *dev); void mp_input_lirc_add(struct input_ctx *ictx, char *lirc_configfile); -void mp_input_set_main_thread(struct input_ctx *ictx); - #endif /* MPLAYER_INPUT_H */ diff --git a/input/lirc.c b/input/lirc.c index ce3b979149..2805043c03 100644 --- a/input/lirc.c +++ b/input/lirc.c @@ -93,10 +93,10 @@ static int mp_input_lirc_read(void *pctx,int fd,char* dest, int s) { // Nothing in the buffer, poll the lirc fd if(lirc_nextcode(&code) != 0) { MP_ERR(ctx, "Lirc error.\n"); - return MP_INPUT_DEAD; + return -1; } - if(!code) return MP_INPUT_NOTHING; + if(!code) return 0; // We put all cmds in a single buffer separated by \n while((r = lirc_code2char(ctx->lirc_config,code,&c))==0 && c!=NULL) { diff --git a/old-configure b/old-configure index 3661afa8f8..16890b4a55 100755 --- a/old-configure +++ b/old-configure @@ -961,7 +961,6 @@ cat > $TMPC << EOF #define HAVE_DOS_PATHS 0 #define HAVE_PRIORITY 0 #define HAVE_GLOB 1 -#define HAVE_POSIX_SELECT 1 #define HAVE_SYS_MMAN_H 1 #define HAVE_NANOSLEEP 1 #define HAVE_SDL1 0 diff --git a/player/loadfile.c b/player/loadfile.c index 2917569017..4f4db2a376 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -1406,7 +1406,6 @@ struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction, // Return if all done. void mp_play_files(struct MPContext *mpctx) { - mp_input_set_main_thread(mpctx->input); mpctx->quit_player_rc = EXIT_NONE; for (;;) { idle_loop(mpctx); diff --git a/wscript b/wscript index 7d52cdc043..0b64d7a0b1 100644 --- a/wscript +++ b/wscript @@ -185,13 +185,6 @@ iconv support use --disable-iconv.", 'desc': 'shm', 'func': check_statement(['sys/types.h', 'sys/ipc.h', 'sys/shm.h'], 'shmget(0, 0, 0); shmat(0, 0, 0); shmctl(0, 0, 0)') - }, { - 'name': 'posix-select', - 'desc': 'POSIX select()', - 'func': check_statement('sys/select.h', """ - int rc; - rc = select(0, (fd_set *)(0), (fd_set *)(0), (fd_set *)(0), - (struct timeval *)(0))""") }, { 'name': 'glob', 'desc': 'glob()', -- cgit v1.2.3