int uiomoveco(void *cp, int n, struct uio *uio, int disposable) { struct iovec *iov; u_int cnt; int error; KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, ("uiomoveco: mode")); KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, ("uiomoveco proc")); while (n > 0 && uio->uio_resid) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { uio->uio_iov++; uio->uio_iovcnt--; continue; } if (cnt > n) cnt = n; switch (uio->uio_segflg) { case UIO_USERSPACE: maybe_yield(); error = userspaceco(cp, cnt, uio, disposable); if (error) return (error); break; case UIO_SYSSPACE: if (uio->uio_rw == UIO_READ) bcopy(cp, iov->iov_base, cnt); else bcopy(iov->iov_base, cp, cnt); break; case UIO_NOCOPY: break; } iov->iov_base = (char *)iov->iov_base + cnt; iov->iov_len -= cnt; uio->uio_resid -= cnt; uio->uio_offset += cnt; cp = (char *)cp + cnt; n -= cnt; } return (0); }
/* * Implement uiomove(9) from physical memory using sf_bufs to reduce * the creation and destruction of ephemeral mappings. */ int uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) { struct sf_buf *sf; struct thread *td = curthread; struct iovec *iov; void *cp; vm_offset_t page_offset; size_t cnt; int error = 0; int save = 0; KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, ("uiomove_fromphys: mode")); KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, ("uiomove_fromphys proc")); save = td->td_pflags & TDP_DEADLKTREAT; td->td_pflags |= TDP_DEADLKTREAT; while (n > 0 && uio->uio_resid) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { uio->uio_iov++; uio->uio_iovcnt--; continue; } if (cnt > n) cnt = n; page_offset = offset & PAGE_MASK; cnt = min(cnt, PAGE_SIZE - page_offset); sched_pin(); sf = sf_buf_alloc(ma[offset >> PAGE_SHIFT], SFB_CPUPRIVATE); cp = (char *)sf_buf_kva(sf) + page_offset; switch (uio->uio_segflg) { case UIO_USERSPACE: maybe_yield(); if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else error = copyin(iov->iov_base, cp, cnt); if (error) { sf_buf_free(sf); sched_unpin(); goto out; } break; case UIO_SYSSPACE: if (uio->uio_rw == UIO_READ) bcopy(cp, iov->iov_base, cnt); else bcopy(iov->iov_base, cp, cnt); break; case UIO_NOCOPY: break; } sf_buf_free(sf); sched_unpin(); iov->iov_base = (char *)iov->iov_base + cnt; iov->iov_len -= cnt; uio->uio_resid -= cnt; uio->uio_offset += cnt; offset += cnt; n -= cnt; } out: if (save == 0) td->td_pflags &= ~TDP_DEADLKTREAT; return (error); }
/* * Implement uiomove(9) from physical memory using a combination * of the direct mapping and sf_bufs to reduce the creation and * destruction of ephemeral mappings. */ int uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) { struct sf_buf *sf; struct thread *td = curthread; struct iovec *iov; void *cp; vm_offset_t page_offset; vm_paddr_t pa; vm_page_t m; size_t cnt; int error = 0; int save = 0; KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, ("uiomove_fromphys: mode")); KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, ("uiomove_fromphys proc")); save = td->td_pflags & TDP_DEADLKTREAT; td->td_pflags |= TDP_DEADLKTREAT; while (n > 0 && uio->uio_resid) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { uio->uio_iov++; uio->uio_iovcnt--; continue; } if (cnt > n) cnt = n; page_offset = offset & PAGE_MASK; cnt = ulmin(cnt, PAGE_SIZE - page_offset); m = ma[offset >> PAGE_SHIFT]; pa = VM_PAGE_TO_PHYS(m); if (dcache_color_ignore == 0 && m->md.color != DCACHE_COLOR(pa)) { sf = sf_buf_alloc(m, 0); cp = (char *)sf_buf_kva(sf) + page_offset; } else { sf = NULL; cp = (char *)TLB_PHYS_TO_DIRECT(pa) + page_offset; } switch (uio->uio_segflg) { case UIO_USERSPACE: maybe_yield(); if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else error = copyin(iov->iov_base, cp, cnt); if (error) { if (sf != NULL) sf_buf_free(sf); goto out; } break; case UIO_SYSSPACE: if (uio->uio_rw == UIO_READ) bcopy(cp, iov->iov_base, cnt); else bcopy(iov->iov_base, cp, cnt); break; case UIO_NOCOPY: break; } if (sf != NULL) sf_buf_free(sf); iov->iov_base = (char *)iov->iov_base + cnt; iov->iov_len -= cnt; uio->uio_resid -= cnt; uio->uio_offset += cnt; offset += cnt; n -= cnt; } out: if (save == 0) td->td_pflags &= ~TDP_DEADLKTREAT; return (error); }
/* * Implement uiomove(9) from physical memory using a combination * of the direct mapping and sf_bufs to reduce the creation and * destruction of ephemeral mappings. */ int uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) { struct sf_buf *sf; struct thread *td = curthread; struct iovec *iov; void *cp; vm_offset_t page_offset; vm_paddr_t pa; vm_page_t m; size_t cnt; int error = 0; int save = 0; KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, ("uiomove_fromphys: mode")); KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, ("uiomove_fromphys proc")); save = td->td_pflags & TDP_DEADLKTREAT; td->td_pflags |= TDP_DEADLKTREAT; while (n > 0 && uio->uio_resid) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { uio->uio_iov++; uio->uio_iovcnt--; continue; } if (cnt > n) cnt = n; page_offset = offset & PAGE_MASK; cnt = ulmin(cnt, PAGE_SIZE - page_offset); m = ma[offset >> PAGE_SHIFT]; pa = VM_PAGE_TO_PHYS(m); if (MIPS_DIRECT_MAPPABLE(pa)) { sf = NULL; cp = (char *)MIPS_PHYS_TO_DIRECT(pa) + page_offset; /* * flush all mappings to this page, KSEG0 address first * in order to get it overwritten by correct data */ mips_dcache_wbinv_range((vm_offset_t)cp, cnt); pmap_flush_pvcache(m); } else { sf = sf_buf_alloc(m, 0); cp = (char *)sf_buf_kva(sf) + page_offset; } switch (uio->uio_segflg) { case UIO_USERSPACE: maybe_yield(); if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else error = copyin(iov->iov_base, cp, cnt); if (error) { if (sf != NULL) sf_buf_free(sf); goto out; } break; case UIO_SYSSPACE: if (uio->uio_rw == UIO_READ) bcopy(cp, iov->iov_base, cnt); else bcopy(iov->iov_base, cp, cnt); break; case UIO_NOCOPY: break; } if (sf != NULL) sf_buf_free(sf); else mips_dcache_wbinv_range((vm_offset_t)cp, cnt); iov->iov_base = (char *)iov->iov_base + cnt; iov->iov_len -= cnt; uio->uio_resid -= cnt; uio->uio_offset += cnt; offset += cnt; n -= cnt; } out: if (save == 0) td->td_pflags &= ~TDP_DEADLKTREAT; return (error); }
__declspec(dllexport) void __cdecl VDDDispatch(void) { char str[512]; DWORD count; DWORD msgs; int retval; int node_num; BYTE* p; vdd_status_t* status; static DWORD writes; static DWORD bytes_written; static DWORD reads; static DWORD bytes_read; static DWORD inbuf_poll; static DWORD online_poll; static DWORD status_poll; static DWORD vdd_yields; static DWORD vdd_calls; VDD_IO_HANDLERS IOHandlers = { NULL }; static VDD_IO_PORTRANGE PortRange; retval=0; node_num=getBH(); lprintf(LOG_DEBUG,"VDD_OP: (handle=%d) %d (arg=%X)", getAX(),getBL(),getCX()); vdd_calls++; switch(getBL()) { case VDD_OPEN: sscanf("$Revision: 1.40 $", "%*s %s", revision); lprintf(LOG_INFO,"Synchronet Virtual Device Driver, rev %s %s %s" ,revision, __DATE__, __TIME__); #if 0 sprintf(str,"sbbsexec%d.log",node_num); fp=fopen(str,"wb"); #endif sprintf(str,"\\\\.\\mailslot\\sbbsexec\\wr%d",node_num); rdslot=CreateMailslot(str ,0 //LINEAR_RX_BUFLEN /* Max message size (0=any) */ ,MAILSLOT_WAIT_FOREVER /* Read timeout */ ,NULL); if(rdslot==INVALID_HANDLE_VALUE) { lprintf(LOG_ERR,"!VDD_OPEN: Error %d opening %s" ,GetLastError(),str); retval=1; break; } sprintf(str,"\\\\.\\mailslot\\sbbsexec\\rd%d",node_num); wrslot=CreateFile(str ,GENERIC_WRITE ,FILE_SHARE_READ ,NULL ,OPEN_EXISTING ,FILE_ATTRIBUTE_NORMAL ,(HANDLE) NULL); if(wrslot==INVALID_HANDLE_VALUE) { lprintf(LOG_ERR,"!VDD_OPEN: Error %d opening %s" ,GetLastError(),str); retval=2; break; } if(RingBufInit(&rdbuf, RINGBUF_SIZE_IN)!=0) { retval=3; break; } sprintf(str,"sbbsexec_hungup%d",node_num); hungup_event=OpenEvent( EVENT_ALL_ACCESS, /* access flag */ FALSE, /* inherit flag */ str); /* pointer to event-object name */ if(hungup_event==NULL) { lprintf(LOG_ERR,"!VDD_OPEN: Error %d opening %s" ,GetLastError(),str); retval=4; break; } sprintf(str,"sbbsexec_hangup%d",node_num); hangup_event=OpenEvent( EVENT_ALL_ACCESS, /* access flag */ FALSE, /* inherit flag */ str); /* pointer to event-object name */ if(hangup_event==NULL) { lprintf(LOG_WARNING,"!VDD_OPEN: Error %d opening %s" ,GetLastError(),str); } status_poll=0; inbuf_poll=0; online_poll=0; yields=0; lprintf(LOG_INFO,"Yield interval: %f milliseconds", yield_interval); if(virtualize_uart) { lprintf(LOG_INFO,"Virtualizing UART (0x%x, IRQ %u)" ,uart_io_base, uart_irq); IOHandlers.inb_handler = uart_rdport; IOHandlers.outb_handler = uart_wrport; PortRange.First=uart_io_base; PortRange.Last=uart_io_base + UART_IO_RANGE; VDDInstallIOHook((HANDLE)getAX(), 1, &PortRange, &IOHandlers); interrupt_event=CreateEvent(NULL,FALSE,FALSE,NULL); InitializeCriticalSection(&interrupt_mutex); _beginthread(interrupt_thread, 0, NULL); } lprintf(LOG_DEBUG,"VDD_OPEN: Opened successfully (wrslot=%p)", wrslot); _beginthread(input_thread, 0, NULL); retval=0; break; case VDD_CLOSE: lprintf(LOG_INFO,"VDD_CLOSE: rdbuf=%u " "status_poll=%u inbuf_poll=%u online_poll=%u yields=%u vdd_yields=%u vdd_calls=%u" ,RingBufFull(&rdbuf),status_poll,inbuf_poll,online_poll ,yields,vdd_yields,vdd_calls); lprintf(LOG_INFO," read=%u bytes (in %u calls)",bytes_read,reads); lprintf(LOG_INFO," wrote=%u bytes (in %u calls)",bytes_written,writes); if(virtualize_uart) { lprintf(LOG_INFO,"Uninstalling Virtualizaed UART IO Hook"); VDDDeInstallIOHook((HANDLE)getAX(), 1, &PortRange); } CloseHandle(rdslot); CloseHandle(wrslot); if(hungup_event!=NULL) CloseHandle(hungup_event); if(hangup_event!=NULL) CloseHandle(hangup_event); #if 0 /* This isn't strictly necessary... and possibly the cause of a NULL dereference in the input_thread */ RingBufDispose(&rdbuf); #endif status_poll=0; retval=0; break; case VDD_READ: count = getCX(); if(count != 1) lprintf(LOG_DEBUG,"VDD_READ of %d",count); p = (BYTE*) GetVDMPointer((ULONG)((getES() << 16)|getDI()) ,count,FALSE); retval=vdd_read(p, count); reads++; bytes_read+=retval; reset_yield(); break; case VDD_PEEK: count = getCX(); if(count != 1) lprintf(LOG_DEBUG,"VDD_PEEK of %d",count); p = (BYTE*) GetVDMPointer((ULONG)((getES() << 16)|getDI()) ,count,FALSE); retval=RingBufPeek(&rdbuf,p,count); reset_yield(); break; case VDD_WRITE: count = getCX(); if(count != 1) lprintf(LOG_DEBUG,"VDD_WRITE of %d",count); p = (BYTE*) GetVDMPointer((ULONG)((getES() << 16)|getDI()) ,count,FALSE); if(!WriteFile(wrslot,p,count,&retval,NULL)) { lprintf(LOG_ERR,"!VDD_WRITE: WriteFile Error %d (size=%d)" ,GetLastError(),retval); retval=0; } else { writes++; bytes_written+=retval; reset_yield(); } break; case VDD_STATUS: status_poll++; count = getCX(); if(count != sizeof(vdd_status_t)) { lprintf(LOG_DEBUG,"!VDD_STATUS: wrong size (%d!=%d)",count,sizeof(vdd_status_t)); retval=sizeof(vdd_status_t); break; } status = (vdd_status_t*) GetVDMPointer((ULONG)((getES() << 16)|getDI()) ,count,FALSE); status->inbuf_size=RINGBUF_SIZE_IN; status->inbuf_full=RingBufFull(&rdbuf); msgs=0; /* OUTBUF FULL/SIZE */ if(!GetMailslotInfo( wrslot, /* mailslot handle */ &status->outbuf_size, /* address of maximum message size */ &status->outbuf_full, /* address of size of next message */ &msgs, /* address of number of messages */ NULL /* address of read time-out */ )) { lprintf(LOG_ERR,"!VDD_STATUS: GetMailSlotInfo(%p) failed, error %u (msgs=%u, inbuf_full=%u, inbuf_size=%u)" ,wrslot ,GetLastError(), msgs, status->inbuf_full, status->inbuf_size); status->outbuf_full=0; status->outbuf_size=DEFAULT_MAX_MSG_SIZE; } else lprintf(LOG_DEBUG,"VDD_STATUS: MailSlot maxmsgsize=%u, nextmsgsize=%u, msgs=%u" ,status->outbuf_size ,status->outbuf_full ,msgs); if(status->outbuf_full==MAILSLOT_NO_MESSAGE) status->outbuf_full=0; status->outbuf_full*=msgs; /* ONLINE */ if(WaitForSingleObject(hungup_event,0)==WAIT_OBJECT_0) status->online=0; else status->online=1; retval=0; /* success */ break; case VDD_INBUF_PURGE: RingBufReInit(&rdbuf); retval=0; break; case VDD_OUTBUF_PURGE: lprintf(LOG_WARNING,"!VDD_OUTBUF_PURGE: NOT IMPLEMENTED"); retval=0; break; case VDD_INBUF_FULL: retval=RingBufFull(&rdbuf); inbuf_poll++; break; case VDD_INBUF_SIZE: retval=RINGBUF_SIZE_IN; break; case VDD_OUTBUF_FULL: if(!GetMailslotInfo( wrslot, /* mailslot handle */ NULL, /* address of maximum message size */ &retval, /* address of size of next message */ &msgs, /* address of number of messages */ NULL /* address of read time-out */ )) retval=0; if(retval==MAILSLOT_NO_MESSAGE) retval=0; retval*=msgs; break; case VDD_OUTBUF_SIZE: if(!GetMailslotInfo( wrslot, /* mailslot handle */ &retval, /* address of maximum message size */ NULL, /* address of size of next message */ NULL, /* address of number of messages */ NULL /* address of read time-out */ )) retval=DEFAULT_MAX_MSG_SIZE; break; case VDD_ONLINE: if(WaitForSingleObject(hungup_event,0)==WAIT_OBJECT_0) retval=0; else retval=1; online_poll++; break; case VDD_YIELD: /* forced yield */ vdd_yields++; yield(); break; case VDD_MAYBE_YIELD: /* yield if YieldInterval is enabled and expired */ maybe_yield(); break; case VDD_LOAD_INI_FILE: /* Load and parse settings file */ { FILE* fp; char cwd[MAX_PATH+1]; /* Load exec/sbbsexec.ini first (setting default values) */ count = getCX(); p = (BYTE*)GetVDMPointer((ULONG)((getES() << 16)|getDI()) ,count,FALSE); iniFileName(ini_fname, sizeof(ini_fname), p, INI_FILENAME); if((fp=fopen(ini_fname,"r"))!=NULL) { ini=iniReadFile(fp); fclose(fp); parse_ini(ROOT_SECTION); } /* Load cwd/sbbsexec.ini second (over-riding default values) */ GetCurrentDirectory(sizeof(cwd),cwd); iniFileName(ini_fname, sizeof(ini_fname), cwd, INI_FILENAME); if((fp=fopen(ini_fname,"r"))!=NULL) { ini=iniReadFile(fp); fclose(fp); parse_ini(ROOT_SECTION); } } break; case VDD_LOAD_INI_SECTION: /* Parse (program-specific) sub-section of settings file */ count = getCX(); p = (BYTE*)GetVDMPointer((ULONG)((getES() << 16)|getDI()) ,count,FALSE); parse_ini(p); break; case VDD_DEBUG_OUTPUT: /* Send string to debug output */ count = getCX(); p = (BYTE*)GetVDMPointer((ULONG)((getES() << 16)|getDI()) ,count,FALSE); lputs(LOG_INFO, p); break; case VDD_HANGUP: hangup(); break; default: lprintf(LOG_ERR,"!UNKNOWN VDD_OP: %d",getBL()); break; } setAX((WORD)retval); }
VOID uart_rdport(WORD port, PBYTE data) { int reg = port - uart_io_base; DWORD avail; lprintf(LOG_DEBUG,"read of port: %x (%s)", port, uart_reg_desc[reg]); switch(reg) { case UART_BASE: if(uart_lcr_reg&UART_LCR_DLAB) { lprintf(LOG_DEBUG,"reading divisor latch LSB"); *data = uart_divisor_latch_lsb; break; } if((avail=RingBufFull(&rdbuf))!=0) { vdd_read(data,sizeof(BYTE)); lprintf(LOG_DEBUG,"READ DATA: %s", chr(*data)); avail--; reset_yield(); } else *data=0; if(avail==0) { lprintf(LOG_DEBUG,"No more data"); /* Clear the data ready bit in the LSR */ uart_lsr_reg &= ~UART_LSR_DATA_READY; /* Clear data ready interrupt identification in IIR */ deassert_interrupt(UART_IER_RX_DATA); } else /* re-assert RX data (increment the semaphore) */ assert_interrupt(UART_IER_RX_DATA); break; case UART_IER: if(uart_lcr_reg&UART_LCR_DLAB) { lprintf(LOG_DEBUG,"reading divisor latch MSB"); *data = uart_divisor_latch_msb; } else *data = uart_ier_reg; break; case UART_IIR: /* Report IIR based on *priority* of pending interrupts */ if(pending_interrupts & UART_IER_LINE_STATUS) *data = UART_IIR_LINE_STATUS; else if(pending_interrupts & UART_IER_RX_DATA) *data = UART_IIR_RX_DATA; else if(pending_interrupts & UART_IER_TX_EMPTY) { *data = UART_IIR_TX_EMPTY; /* "Transmit Holding Register Empty" interrupt */ /* is reset on read of IIR */ deassert_interrupt(UART_IER_TX_EMPTY); } else if(pending_interrupts & UART_IER_MODEM_STATUS) *data = UART_IIR_MODEM_STATUS; else *data = UART_IIR_NONE; break; case UART_LCR: *data = uart_lcr_reg; break; case UART_MCR: *data = uart_mcr_reg; break; case UART_LSR: *data = uart_lsr_reg; maybe_yield(); /* Clear line status interrupt pending */ deassert_interrupt(UART_IER_LINE_STATUS); break; case UART_MSR: if(WaitForSingleObject(hungup_event,0)==WAIT_OBJECT_0) uart_msr_reg &=~ UART_MSR_DCD; else uart_msr_reg |= UART_MSR_DCD; *data = uart_msr_reg; maybe_yield(); /* Clear modem status interrupt pending */ deassert_interrupt(UART_IER_MODEM_STATUS); break; case UART_SCRATCH: *data = uart_scratch_reg; break; default: lprintf(LOG_ERR,"UNSUPPORTED register: %u", reg); break; } if(reg!=UART_BASE) lprintf(LOG_DEBUG, "returning 0x%02X", *data); }
static int uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault) { struct thread *td; struct iovec *iov; size_t cnt; int error, newflags, save; td = curthread; error = 0; KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, ("uiomove: mode")); KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == td, ("uiomove proc")); if (!nofault) WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "Calling uiomove()"); /* XXX does it make a sense to set TDP_DEADLKTREAT for UIO_SYSSPACE ? */ newflags = TDP_DEADLKTREAT; if (uio->uio_segflg == UIO_USERSPACE && nofault) { /* * Fail if a non-spurious page fault occurs. */ newflags |= TDP_NOFAULTING | TDP_RESETSPUR; } save = curthread_pflags_set(newflags); while (n > 0 && uio->uio_resid) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { uio->uio_iov++; uio->uio_iovcnt--; continue; } if (cnt > n) cnt = n; switch (uio->uio_segflg) { case UIO_USERSPACE: maybe_yield(); if (uio->uio_rw == UIO_READ) error = copyout(cp, iov->iov_base, cnt); else error = copyin(iov->iov_base, cp, cnt); if (error) goto out; break; case UIO_SYSSPACE: if (uio->uio_rw == UIO_READ) bcopy(cp, iov->iov_base, cnt); else bcopy(iov->iov_base, cp, cnt); break; case UIO_NOCOPY: break; } iov->iov_base = (char *)iov->iov_base + cnt; iov->iov_len -= cnt; uio->uio_resid -= cnt; uio->uio_offset += cnt; cp = (char *)cp + cnt; n -= cnt; } out: curthread_pflags_restore(save); return (error); }
int uiofill(uint8_t val, int n, struct uio *uio) { struct thread *td; struct iovec *iov; size_t cnt; int error, save; #define UIOFILL_MAXBUF 256 uint8_t buf[UIOFILL_MAXBUF]; td = curthread; error = 0; KASSERT(uio->uio_rw == UIO_READ, ("uiofill: mode")); KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == td, ("uiofill proc")); WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "Calling uiofill()"); /* XXX does it make a sense to set TDP_DEADLKTREAT for UIO_SYSSPACE ? */ save = curthread_pflags_set(TDP_DEADLKTREAT); if (uio->uio_segflg == UIO_USERSPACE) memset(buf, val, imax(UIOFILL_MAXBUF, n)); while (n > 0 && uio->uio_resid) { iov = uio->uio_iov; cnt = iov->iov_len; if (cnt == 0) { uio->uio_iov++; uio->uio_iovcnt--; continue; } if (cnt > n) cnt = n; switch (uio->uio_segflg) { case UIO_USERSPACE: maybe_yield(); error = copyout(buf, iov->iov_base, cnt); if (error) goto out; break; case UIO_SYSSPACE: memset(iov->iov_base, val, cnt); break; case UIO_NOCOPY: break; } iov->iov_base = (char *)iov->iov_base + cnt; iov->iov_len -= cnt; uio->uio_resid -= cnt; uio->uio_offset += cnt; n -= cnt; } out: curthread_pflags_restore(save); return (error); }
int # ifdef LUABIND_INVOKE_MEMBER invoke_member # else invoke_normal # endif ( lua_State* L, F const& f, Signature, Policies const&, mpl::long_<N> # ifdef LUABIND_INVOKE_VOID , mpl::true_ # else , mpl::false_ # endif ) { typedef typename mpl::begin<Signature>::type first; # ifndef LUABIND_INVOKE_VOID typedef typename mpl::deref<first>::type result_type; typedef typename find_conversion_policy<0, Policies>::type result_policy; typename mpl::apply_wrap2< result_policy, result_type, cpp_to_lua>::type result_converter; # endif # if N > 0 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_DECLARE_CONVERTER(n) # define BOOST_PP_LOCAL_LIMITS (0,N-1) # include BOOST_PP_LOCAL_ITERATE() # endif int const arguments = lua_gettop(L); # ifndef LUABIND_INVOKE_VOID result_converter.apply( L, # endif # ifdef LUABIND_INVOKE_MEMBER (c0.apply(L, LUABIND_DECORATE_TYPE(a0), index0).*f)( BOOST_PP_ENUM(BOOST_PP_DEC(N), LUABIND_INVOKE_ARG, BOOST_PP_INC) ) # else # define LUABIND_INVOKE_IDENTITY(x) x f( BOOST_PP_ENUM(N, LUABIND_INVOKE_ARG, LUABIND_INVOKE_IDENTITY) ) # undef LUABIND_INVOKE_IDENTITY # endif # ifndef LUABIND_INVOKE_VOID ) # endif ; # if N > 0 # define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_CONVERTER_POSTCALL(n) # define BOOST_PP_LOCAL_LIMITS (0,N-1) # include BOOST_PP_LOCAL_ITERATE() # endif int const results = lua_gettop(L) - arguments; int const indices[] = { arguments + results BOOST_PP_ENUM_TRAILING_PARAMS(N, index) }; policy_list_postcall<Policies>::apply(L, indices); return maybe_yield(L, results, (Policies*)0); }