📄 sys_generic.c
字号:
*/ bzero(data, size); else if (com&IOC_VOID) *(caddr_t *)data = SCARG(uap, data); switch (com) { case FIONBIO: if ((tmp = *(int *)data) != 0) fp->f_flag |= FNONBLOCK; else fp->f_flag &= ~FNONBLOCK; error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); break; case FIOASYNC: if ((tmp = *(int *)data) != 0) fp->f_flag |= FASYNC; else fp->f_flag &= ~FASYNC; error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); break; case FIOSETOWN: tmp = *(int *)data; if (fp->f_type == DTYPE_SOCKET) { struct socket *so = (struct socket *)fp->f_data; so->so_pgid = tmp;#ifdef NOTUSE_BY_PMON so->so_siguid = p->p_cred->p_ruid; so->so_sigeuid = p->p_ucred->cr_uid;#else so->so_siguid = 0; so->so_sigeuid = 0;#endif error = 0; break; } if (tmp <= 0) { tmp = -tmp; } else {#ifdef NOTUSED_BY_PMON struct proc *p1 = pfind(tmp); if (p1 == 0) { error = ESRCH; break; } tmp = p1->p_pgrp->pg_id;#else tmp = 0;#endif } error = (*fp->f_ops->fo_ioctl) (fp, TIOCSPGRP, (caddr_t)&tmp, p); break; case FIOGETOWN: if (fp->f_type == DTYPE_SOCKET) { error = 0; *(int *)data = ((struct socket *)fp->f_data)->so_pgid; break; } error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p); *(int *)data = -*(int *)data; break; default: error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); /* * Copy any data to user, size was * already set and checked above. */ if (error == 0 && (com&IOC_OUT) && size) error = copyout(data, SCARG(uap, data), (u_int)size); break; } if (memp) free(memp, M_IOCTLOPS); return (error);}int selwait, nselcoll;/* * Select system call. */intsys_select(p, v, retval) register struct proc *p; void *v; register_t *retval;{ register struct sys_select_args /* { syscallarg(int) nd; syscallarg(fd_set *) in; syscallarg(fd_set *) ou; syscallarg(fd_set *) ex; syscallarg(struct timeval *) tv; } */ *uap = v; fd_set bits[6], *pibits[3], *pobits[3]; struct timeval atv; int s, ncoll, error = 0, timo; u_int ni; if (SCARG(uap, nd) > p->p_fd->fd_nfiles) { /* forgiving; slightly wrong */ SCARG(uap, nd) = p->p_fd->fd_nfiles; } ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask); if (SCARG(uap, nd) > FD_SETSIZE) { caddr_t mbits; if ((mbits = malloc(ni * 6, M_TEMP, M_WAITOK)) == NULL) { error = EINVAL; goto cleanup; } bzero(mbits, ni * 6); pibits[0] = (fd_set *)&mbits[ni * 0]; pibits[1] = (fd_set *)&mbits[ni * 1]; pibits[2] = (fd_set *)&mbits[ni * 2]; pobits[0] = (fd_set *)&mbits[ni * 3]; pobits[1] = (fd_set *)&mbits[ni * 4]; pobits[2] = (fd_set *)&mbits[ni * 5]; } else { bzero((caddr_t)bits, sizeof(bits)); pibits[0] = &bits[0]; pibits[1] = &bits[1]; pibits[2] = &bits[2]; pobits[0] = &bits[3]; pobits[1] = &bits[4]; pobits[2] = &bits[5]; }#define getbits(name, x) \ if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \ (caddr_t)pibits[x], ni))) \ goto done; getbits(in, 0); getbits(ou, 1); getbits(ex, 2);#undef getbits if (SCARG(uap, tv)) { error = copyin((caddr_t)SCARG(uap, tv), (caddr_t)&atv, sizeof (atv)); if (error) goto done; if (itimerfix(&atv)) { error = EINVAL; goto done; } s = splclock(); timeradd(&atv, &time, &atv); timo = hzto(&atv); /* * Avoid inadvertently sleeping forever. */ if (timo == 0) timo = 1; splx(s); } else timo = 0;retry: ncoll = nselcoll; p->p_flag |= P_SELECT; error = selscan(p, pibits[0], pobits[0], SCARG(uap, nd), retval); if (error || *retval) goto done; s = splhigh(); /* this should be timercmp(&time, &atv, >=) */ if (SCARG(uap, tv) && (time.tv_sec > atv.tv_sec || (time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec))) { splx(s); goto done; } if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { splx(s); goto retry; } p->p_flag &= ~P_SELECT; error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); splx(s); if (error == 0) goto retry;done: p->p_flag &= ~P_SELECT; /* select is not restarted after signals... */ if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) error = 0;#define putbits(name, x) \ if (SCARG(uap, name) && (error2 = copyout((caddr_t)pobits[x], \ (caddr_t)SCARG(uap, name), ni))) \ error = error2; if (error == 0) { int error2; putbits(in, 0); putbits(ou, 1); putbits(ex, 2);#undef putbits } cleanup: if (pibits[0] != &bits[0]) free(pibits[0], M_TEMP); return (error);}intselscan(p, ibits, obits, nfd, retval) struct proc *p; fd_set *ibits, *obits; int nfd; register_t *retval;{ caddr_t cibits = (caddr_t)ibits, cobits = (caddr_t)obits; register struct filedesc *fdp = p->p_fd; register int msk, i, j, fd; register fd_mask bits; struct file *fp; int ni, n = 0; static int flag[3] = { FREAD, FWRITE, 0 }; /* * if nfd > FD_SETSIZE then the fd_set's contain nfd bits (rounded * up to the next byte) otherwise the fd_set's are normal sized. */ ni = sizeof(fd_set); if (nfd > FD_SETSIZE) ni = howmany(nfd, NFDBITS) * sizeof(fd_mask); for (msk = 0; msk < 3; msk++) { fd_set *pibits = (fd_set *)&cibits[msk*ni]; fd_set *pobits = (fd_set *)&cobits[msk*ni]; for (i = 0; i < nfd; i += NFDBITS) { bits = pibits->fds_bits[i/NFDBITS]; while ((j = ffs(bits)) && (fd = i + --j) < nfd) { bits &= ~(1 << j); fp = fdp->fd_ofiles[fd]; if (fp == NULL) return (EBADF); if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { FD_SET(fd, pobits); n++; } } } } *retval = n; return (0);}/*ARGSUSED*/intseltrue(dev, flag, p) dev_t dev; int flag; struct proc *p;{ return (1);}/* * Record a select request. */voidselrecord(selector, sip) struct proc *selector; struct selinfo *sip;{ struct proc *p; pid_t mypid; mypid = selector->p_pid; if (sip->si_selpid == mypid) return; if (sip->si_selpid && (p = pfind(sip->si_selpid)) && p->p_wchan == (caddr_t)&selwait) sip->si_flags |= SI_COLL; else sip->si_selpid = mypid;}/* * Do a wakeup when a selectable event occurs. */voidselwakeup(sip) register struct selinfo *sip;{ register struct proc *p; int s; if (sip->si_selpid == 0) return; if (sip->si_flags & SI_COLL) { nselcoll++; sip->si_flags &= ~SI_COLL; wakeup((caddr_t)&selwait); } p = pfind(sip->si_selpid); sip->si_selpid = 0; if (p != NULL) { s = splhigh(); if (p->p_wchan == (caddr_t)&selwait) { if (p->p_stat == SSLEEP) setrunnable(p); else unsleep(p); } else if (p->p_flag & P_SELECT) p->p_flag &= ~P_SELECT; splx(s); }}voidpollscan(p, pl, nfd, retval) struct proc *p; struct pollfd *pl; int nfd; register_t *retval;{ register struct filedesc *fdp = p->p_fd; register int msk, i; struct file *fp; int x, n = 0; static int flag[3] = { FREAD, FWRITE, 0 }; static int pflag[3] = { POLLIN|POLLRDNORM, POLLOUT, POLLERR }; /* * XXX: We need to implement the rest of the flags. */ for (i = 0; i < nfd; i++) { fp = fdp->fd_ofiles[pl[i].fd]; if (fp == NULL) { if (pl[i].events & POLLNVAL) { pl[i].revents |= POLLNVAL; n++; } continue; } for (x = msk = 0; msk < 3; msk++) { if (pl[i].events & pflag[msk]) { if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { pl[i].revents |= pflag[msk] & pl[i].events; x++; } } } if (x) n++; } *retval = n;}/* * We are using the same mechanism as select only we encode/decode args * differently. */intsys_poll(p, v, retval) register struct proc *p; void *v; register_t *retval;{ struct sys_poll_args *uap = v; size_t sz; struct pollfd pfds[4], *pl = pfds; int msec = SCARG(uap, timeout); struct timeval atv; int timo, ncoll, i, s, error, error2; extern int nselcoll, selwait; /* XXX constrain; This may not match standards */ if (SCARG(uap, nfds) > p->p_fd->fd_nfiles) SCARG(uap, nfds) = p->p_fd->fd_nfiles; sz = sizeof(struct pollfd) * SCARG(uap, nfds); /* optimize for the default case, of a small nfds value */ if (sz > sizeof(pfds)) pl = (struct pollfd *) malloc(sz, M_TEMP, M_WAITOK); if ((error = copyin(SCARG(uap, fds), pl, sz)) != 0) goto bad; for (i = 0; i < SCARG(uap, nfds); i++) pl[i].revents = 0; if (msec != -1) { atv.tv_sec = msec / 1000; atv.tv_usec = (msec - (atv.tv_sec * 1000)) * 1000; if (itimerfix(&atv)) { error = EINVAL; goto done; } s = splclock(); timeradd(&atv, &time, &atv); timo = hzto(&atv); /* * Avoid inadvertently sleeping forever. */ if (timo == 0) timo = 1; splx(s); } else timo = 0;retry: ncoll = nselcoll; p->p_flag |= P_SELECT; pollscan(p, pl, SCARG(uap, nfds), retval); if (*retval) goto done; s = splhigh(); if (timo && timercmp(&time, &atv, >=)) { splx(s); goto done; } if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { splx(s); goto retry; } p->p_flag &= ~P_SELECT; error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "poll", timo); splx(s); if (error == 0) goto retry;done: p->p_flag &= ~P_SELECT; /* poll is not restarted after signals... */ if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) error = 0; if ((error2 = copyout(pl, SCARG(uap, fds), sz)) != 0) error = error2;bad: if (pl != pfds) free((char *) pl, M_TEMP); return (error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -