diff options
author | Lukas Larsson <[email protected]> | 2014-01-10 17:17:58 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2014-02-24 15:16:03 +0100 |
commit | c64851d619fb916362abc8db9c28534eff39f53c (patch) | |
tree | 2407b3e10442243777c2a5e0f8d509d169cbd278 /erts/emulator/sys/ose | |
parent | 6930aacf7236bbf1db67c8ad1bc1953127ac43f9 (diff) | |
download | otp-c64851d619fb916362abc8db9c28534eff39f53c.tar.gz otp-c64851d619fb916362abc8db9c28534eff39f53c.tar.bz2 otp-c64851d619fb916362abc8db9c28534eff39f53c.zip |
ose: Rewrite resolve_signal API for ose drivers
This new API has less impact on the check_io code and
also removes the callback from ErlDrvEntry. The downside
is that you have to give the resolve function when creating
each event.
Also the mode if the resolve was removed as this mimics the
win32 code and decreases complexity.
Diffstat (limited to 'erts/emulator/sys/ose')
-rw-r--r-- | erts/emulator/sys/ose/erl_ose_sys.h | 14 | ||||
-rw-r--r-- | erts/emulator/sys/ose/erl_poll.c | 116 | ||||
-rw-r--r-- | erts/emulator/sys/ose/sys.c | 49 |
3 files changed, 98 insertions, 81 deletions
diff --git a/erts/emulator/sys/ose/erl_ose_sys.h b/erts/emulator/sys/ose/erl_ose_sys.h index 8c72afa9a5..db8607b650 100644 --- a/erts/emulator/sys/ose/erl_ose_sys.h +++ b/erts/emulator/sys/ose/erl_ose_sys.h @@ -56,20 +56,6 @@ # include "sys/mman.h" #endif -typedef struct ErtsPollOseMsgList_ { - struct ErtsPollOseMsgList_ *next; - void *data; -} ErtsPollOseMsgList; - -struct erts_sys_fd_type { - SIGSELECT signo; - int id; - ErtsPollOseMsgList *imsgs; - ErtsPollOseMsgList *omsgs; - ethr_mutex mtx; -}; - - /* * Min number of async threads */ diff --git a/erts/emulator/sys/ose/erl_poll.c b/erts/emulator/sys/ose/erl_poll.c index b1e256afc3..78dc275c06 100644 --- a/erts/emulator/sys/ose/erl_poll.c +++ b/erts/emulator/sys/ose/erl_poll.c @@ -103,7 +103,7 @@ typedef struct erts_sigsel_info_ ErtsSigSelInfo; struct erts_sigsel_info_ { ErtsSigSelInfo *next; SIGSELECT signo; - int (*decode)(OseSignal* sig, int* mode); + ErlDrvOseEventId (*decode)(union SIGNAL* sig); ErtsSigSelItem *fds; }; @@ -131,8 +131,10 @@ static int max_fds = -1; /* signal list prototypes */ static ErtsSigSelInfo *get_sigsel_info(ErtsPollSet ps, SIGSELECT signo); static ErtsSigSelItem *get_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd); -static ErtsSigSelInfo *add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, int (*decode)(OseSignal* sig, int* mode)); -static ErtsSigSelItem *add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd, int (*decode)(OseSignal* sig, int* mode)); +static ErtsSigSelInfo *add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, + ErlDrvOseEventId (*decode)(union SIGNAL* sig)); +static ErtsSigSelItem *add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd, + ErlDrvOseEventId (*decode)(union SIGNAL* sig)); static int del_sigsel_info(ErtsPollSet ps, ErtsSigSelInfo *info); static int del_sigsel_item(ErtsPollSet ps, ErtsSigSelItem *item); static int update_sigsel(ErtsPollSet ps); @@ -170,7 +172,7 @@ get_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd) { static ErtsSigSelInfo * add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, - int (*decode)(OseSignal* sig, int* mode)) { + ErlDrvOseEventId (*decode)(union SIGNAL* sig)) { ErtsSigSelInfo *info = SEL_ALLOC(ERTS_ALC_T_POLLSET, sizeof(ErtsSigSelInfo)); info->next = ps->info; @@ -184,7 +186,7 @@ add_sigsel_info(ErtsPollSet ps, ErtsSysFdType fd, static ErtsSigSelItem * add_sigsel_item(ErtsPollSet ps, ErtsSysFdType fd, - int (*decode)(OseSignal* sig, int* mode)) { + ErlDrvOseEventId (*decode)(union SIGNAL* sig)) { ErtsSigSelInfo *info = get_sigsel_info(ps,fd->signo); ErtsSigSelItem *item = SEL_ALLOC(ERTS_ALC_T_POLLSET, sizeof(ErtsSigSelItem)); @@ -394,8 +396,7 @@ void erts_poll_interrupt_timed(ErtsPollSet ps,int set,erts_short_time_t msec) { } ErtsPollEvents erts_poll_control(ErtsPollSet ps, ErtsSysFdType fd, - ErtsPollEvents pe, int on, int* do_wake, - int(*decode)(OseSignal* sig, int* mode)) { + ErtsPollEvents pe, int on, int* do_wake) { ErtsSigSelItem *curr; ErtsPollEvents new_events; int old_sig_count; @@ -406,11 +407,17 @@ ErtsPollEvents erts_poll_control(ErtsPollSet ps, ErtsSysFdType fd, ERTS_POLLSET_LOCK(ps); + if (on && (pe & ERTS_POLL_EV_IN) && (pe & ERTS_POLL_EV_OUT)) { + /* Check to make sure both in and out are not used at the same time */ + new_events = ERTS_POLL_EV_NVAL; + goto done; + } + curr = get_sigsel_item(ps, fd); old_sig_count = ps->sig_count; if (curr == NULL && on) { - curr = add_sigsel_item(ps, fd, decode); + curr = add_sigsel_item(ps, fd, fd->resolve_signal); } else if (curr == NULL && !on) { new_events = ERTS_POLL_EV_NVAL; goto done; @@ -451,7 +458,7 @@ int erts_poll_wait(ErtsPollSet ps, SysTimeval *utvp) { int res = ETIMEDOUT, no_fds, currid = 0; OSTIME timeout; - OseSignal *sig; + union SIGNAL *sig; // HARDTRACEF("%ux: In erts_poll_wait",ps); if (ps->interrupt == (PROCESS)0) ps->interrupt = current_process(); @@ -515,8 +522,7 @@ int erts_poll_wait(ErtsPollSet ps, } { ErtsSigSelInfo *info = get_sigsel_info(ps, sig->sig_no); - int mode = -1; - struct erts_sys_fd_type fd = { sig->sig_no, info->decode(sig, &mode) }; + struct erts_sys_fd_type fd = { sig->sig_no, info->decode(sig) }; ErtsSigSelItem *item = get_sigsel_item(ps, &fd); ASSERT(sig); @@ -546,38 +552,16 @@ int erts_poll_wait(ErtsPollSet ps, erts_send_error_to_logger_nogl(dsbufp); timeout = 0; ASSERT(0); - } else if (mode == -1 && item->events == (ERTS_POLL_EV_IN|ERTS_POLL_EV_OUT)) { - erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); - erts_dsprintf( - dsbufp, - "erts_poll_wait() failed: found ambigous signal id %d (signo %u) " - "(curr_proc 0x%x /sender 0x%x)\n You have to give a specify a mode " - "in the resolve_signal callback for this signal.\n", - fd.id, fd.signo, current_process(), sender(&sig)); - erts_send_error_to_logger_nogl(dsbufp); - timeout = 0; - ASSERT(0); - } else { + } else { int i; struct erts_sys_fd_type *fd = NULL; ErtsPollOseMsgList *tl,*new; - /* Figure out which mode to set and which queue to store - the signal in */ - if (mode == -1) - mode = item->events; - else if (mode == 0) - mode = ERTS_POLL_EV_IN; - else if (mode == 1) - mode = ERTS_POLL_EV_OUT; - else - abort(); - /* Check if this fd has already been triggered by a previous signal */ for (i = 0; i < currid;i++) { if (pr[i].fd == item->fd) { fd = pr[i].fd; - pr[i].events |= mode; + pr[i].events |= item->events; break; } } @@ -585,7 +569,7 @@ int erts_poll_wait(ErtsPollSet ps, /* First time this fd is triggered */ if (fd == NULL) { pr[currid].fd = item->fd; - pr[currid].events = mode; + pr[currid].events = item->events; fd = item->fd; timeout = 0; currid++; @@ -597,16 +581,10 @@ int erts_poll_wait(ErtsPollSet ps, new->data = sig; ethr_mutex_lock(&fd->mtx); - if (mode & ERTS_POLL_EV_IN) - tl = fd->imsgs; - else if (mode & ERTS_POLL_EV_OUT) - tl = fd->omsgs; + tl = fd->msgs; if (tl == NULL) { - if (mode & ERTS_POLL_EV_IN) - fd->imsgs = new; - else if (mode & ERTS_POLL_EV_OUT) - fd->omsgs = new; + fd->msgs = new; } else { while (tl->next != NULL) tl = tl->next; @@ -742,3 +720,53 @@ void erts_poll_init(void) HARDTRACEF("Out %s", __FUNCTION__); } + + +/* OSE driver functions */ + +union SIGNAL *erl_drv_ose_get_signal(ErlDrvEvent drv_ev) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + ethr_mutex_lock(&ev->mtx); + if (ev->msgs == NULL) { + ethr_mutex_unlock(&ev->mtx); + return NULL; + } else { + ErtsPollOseMsgList *msg = ev->msgs; + union SIGNAL *sig = (union SIGNAL*)msg->data; + ASSERT(msg->data); + ev->msgs = msg->next; + ethr_mutex_unlock(&ev->mtx); + erts_free(ERTS_ALC_T_FD_SIG_LIST,msg); + restore(sig); + return sig; + } +} + +ErlDrvEvent +erl_drv_ose_event_alloc(SIGSELECT signo, ErlDrvOseEventId id, + ErlDrvOseEventId (*resolve_signal)(union SIGNAL *sig)) { + struct erts_sys_fd_type *ev = erts_alloc(ERTS_ALC_T_DRV_EV, + sizeof(struct erts_sys_fd_type)); + ev->signo = signo; + ev->id = id; + ev->msgs = NULL; + ev->resolve_signal = resolve_signal; + ethr_mutex_init(&ev->mtx); + return (ErlDrvEvent)ev; +} + +void erl_drv_ose_event_free(ErlDrvEvent drv_ev) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + ASSERT(ev->msgs == NULL); + ethr_mutex_destroy(&ev->mtx); + erts_free(ERTS_ALC_T_DRV_EV,ev); +} + +void erl_drv_ose_event_fetch(ErlDrvEvent drv_ev, SIGSELECT *signo, + ErlDrvOseEventId *id) { + struct erts_sys_fd_type *ev = (struct erts_sys_fd_type *)drv_ev; + if (signo) + *signo = ev->signo; + if (id) + *id = ev->id; +} diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index b786d19ecf..ad82e4587d 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -576,7 +576,7 @@ static void ready_output(ErlDrvData, ErlDrvEvent); static void output(ErlDrvData, char*, ErlDrvSizeT); static void outputv(ErlDrvData, ErlIOVec*); static void stop_select(ErlDrvEvent, void*); -static int resolve_signal(OseSignal* sig, int *mode) { +static ErlDrvOseEventId resolve_signal(union SIGNAL* sig) { return sig->sig_no == ERTS_SIGNAL_FD_DRV_ASYNC ? sig->sys_async.type : -1; } @@ -605,8 +605,7 @@ struct erl_drv_entry spawn_driver_entry = { ERL_DRV_EXTENDED_MINOR_VERSION, ERL_DRV_FLAG_USE_PORT_LOCKING, NULL, NULL, - stop_select, - resolve_signal + stop_select }; struct erl_drv_entry fd_driver_entry = { NULL, @@ -631,8 +630,7 @@ struct erl_drv_entry fd_driver_entry = { 0, /* ERL_DRV_FLAGs */ NULL, /* handle2 */ NULL, /* process_exit */ - stop_select, - resolve_signal + stop_select }; static int set_driver_data(ErlDrvPort port_num, @@ -645,7 +643,7 @@ static int set_driver_data(ErlDrvPort port_num, { Port *prt; ErtsSysReportExit *report_exit; - OseSignal *sig; + union SIGNAL *sig; /*erts_fprintf(stderr, " %s / pid %x / ofd %d / ifd %d\n", __FUNCTION__, current_process(), ofd, ifd);*/ @@ -664,10 +662,12 @@ static int set_driver_data(ErlDrvPort port_num, if (read_write & DO_READ) report_exit->in_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ifd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ifd, + resolve_signal); if (read_write & DO_WRITE) report_exit->out_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ofd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC, ofd, + resolve_signal); report_exit_list = report_exit; } @@ -684,7 +684,8 @@ static int set_driver_data(ErlDrvPort port_num, driver_data[ifd].alive = 1; driver_data[ifd].status = 0; driver_data[ifd].in_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ifd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ifd, + resolve_signal); driver_data[ifd].in_proc = create_process(OS_PRI_PROC,"beam_fd_reader", fd_reader_process, 0x800, @@ -700,7 +701,8 @@ static int set_driver_data(ErlDrvPort port_num, if (read_write & DO_WRITE) { driver_data[ifd].ofd = ofd; driver_data[ifd].out_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd, + resolve_signal); driver_data[ifd].pdl = driver_pdl_create(port_num); driver_data[ifd].out_proc = create_process(OS_PRI_PROC,"beam_fd_writer", @@ -729,7 +731,8 @@ static int set_driver_data(ErlDrvPort port_num, driver_data[ofd].alive = 1; driver_data[ofd].status = 0; driver_data[ofd].in_sig_descr = - erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd); + erl_drv_ose_event_alloc(ERTS_SIGNAL_FD_DRV_ASYNC,ofd, + resolve_signal); driver_data[ofd].out_sig_descr = driver_data[ofd].in_sig_descr; driver_data[ofd].out_proc = create_process(OS_PRI_PROC, "beam_fd_writer", @@ -783,7 +786,7 @@ static ErlDrvData spawn_start(ErlDrvPort port_num, } OS_PROCESS(fd_reader_process) { - OseSignal *sig; + union SIGNAL *sig; PROCESS parent; int fd; byte *read_buf; @@ -844,7 +847,7 @@ OS_PROCESS(fd_reader_process) { } OS_PROCESS(fd_writer_process) { - OseSignal *sig; + union SIGNAL *sig; PROCESS parent; int fd; SIGSELECT sigsel[] = { 1, ERTS_SIGNAL_FD_DRV_CONFIG, @@ -1105,7 +1108,7 @@ static void outputv(ErlDrvData e, ErlIOVec* ev) driver_pdl_unlock(driver_data[fd].pdl); } else { - OseSignal *sig; + union SIGNAL *sig; /* fprintf(stderr,"0x%x: outputv, enq+sel\n", current_process()); */ driver_enqv(ix, ev, 0); /* n is the skip value */ driver_pdl_unlock(driver_data[fd].pdl); @@ -1151,7 +1154,7 @@ static void output(ErlDrvData e, char* buf, ErlDrvSizeT len) set_busy_port(ix, 1); } else { - OseSignal *sig; + union SIGNAL *sig; /* fprintf(stderr,"0x%x: output, enq+select\n", current_process()); */ #if 0 iv[0].iov_base = lbp; @@ -1219,13 +1222,13 @@ static int port_inp_failure(ErlDrvPort port_num, ErlDrvEvent ready_fd, int res) } static int async_read(ErlDrvEvent fd, byte *buff, int size) { - OseSignal *sigptr = erl_drv_ose_get_input_signal(fd); + union SIGNAL *sigptr = erl_drv_ose_get_signal(fd); int res = sigptr->sys_async.res; if (res > 0) memcpy(buff,sigptr->sys_async.buff,sigptr->sys_async.res); errno = sigptr->sys_async.errno_copy; send(&sigptr,sender(&sigptr)); - ASSERT(erl_drv_ose_get_input_signal(fd) == NULL); + ASSERT(erl_drv_ose_get_signal(fd) == NULL); return res; } @@ -1360,7 +1363,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) { int fd = (int)(long)e; ErlDrvPort ix = driver_data[fd].port_num; - OseSignal *sigptr = erl_drv_ose_get_output_signal(ready_fd); + union SIGNAL *sigptr = erl_drv_ose_get_signal(ready_fd); ssize_t n; struct iovec* iv; int vsize; @@ -1374,7 +1377,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) driver_select(ix, ready_fd, ERL_DRV_WRITE, 0); set_busy_port(ix, 0); free_buf(&sigptr); - if ((sigptr = erl_drv_ose_get_output_signal(ready_fd)) == NULL) + if ((sigptr = erl_drv_ose_get_signal(ready_fd)) == NULL) return; /* 0; */ continue; } @@ -1384,7 +1387,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) if (errno == ERRNO_BLOCK || errno == EINTR) { /* fprintf(stderr,"0x%x: ready_output, send to %x\n", current_process(),driver_data[fd].out_proc);*/ send(&sigptr,driver_data[fd].out_proc); - if ((sigptr = erl_drv_ose_get_output_signal(ready_fd)) == NULL) + if ((sigptr = erl_drv_ose_get_signal(ready_fd)) == NULL) return; /* 0; */ continue; } else { @@ -1393,7 +1396,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) free_buf(&sigptr); driver_select(ix, ready_fd, ERL_DRV_WRITE, 0); driver_failure_posix(ix, res); - if ((sigptr = erl_drv_ose_get_output_signal(ready_fd)) == NULL) + if ((sigptr = erl_drv_ose_get_signal(ready_fd)) == NULL) return; /* -1; */ continue; } @@ -1410,7 +1413,7 @@ static void ready_output(ErlDrvData e, ErlDrvEvent ready_fd) else continue; } - sigptr = erl_drv_ose_get_output_signal(ready_fd); + sigptr = erl_drv_ose_get_signal(ready_fd); } return; /* 0; */ } @@ -1752,7 +1755,7 @@ erts_sys_main_thread(void) while (1) { static const SIGSELECT sigsel[] = {0}; - OseSignal *msg = receive(sigsel); + union SIGNAL *msg = receive(sigsel); fprintf(stderr,"Main thread got message %d from 0x%x!!\r\n", msg->sig_no, sender(&msg)); |