Deleted Added
full compact
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.

--- 22 unchanged lines hidden (view full) ---

31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94
39 * $FreeBSD: head/sys/kern/sys_generic.c 91972 2002-03-09 22:44:37Z alfred $
39 * $FreeBSD: head/sys/kern/sys_generic.c 92252 2002-03-14 01:32:30Z alfred $
40 */
41
42#include "opt_ktrace.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/sysproto.h>
47#include <sys/filedesc.h>

--- 643 unchanged lines hidden (view full) ---

691 if (memp)
692 free(memp, M_IOCTLOPS);
693 fdrop(fp, td);
694done:
695 mtx_unlock(&Giant);
696 return (error);
697}
698
699static int nselcoll; /* Select collisions since boot */
699/*
700 * sellock and selwait are initialized in selectinit() via SYSINIT.
701 */
702struct mtx sellock;
703struct cv selwait;
704int nselcoll; /* Select collisions since boot */
705SYSCTL_INT(_kern, OID_AUTO, nselcoll, CTLFLAG_RD, &nselcoll, 0, "");
706
707/*
708 * Select system call.
709 */
710#ifndef _SYS_SYSPROTO_H_
711struct select_args {
712 int nd;

--- 61 unchanged lines hidden (view full) ---

774 if (uap->name == NULL) \
775 ibits[x] = NULL; \
776 else { \
777 ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
778 obits[x] = sbp; \
779 sbp += ncpbytes / sizeof *sbp; \
780 error = copyin(uap->name, ibits[x], ncpbytes); \
781 if (error != 0) \
778 goto done_noproclock; \
782 goto done_nosellock; \
783 } \
784 } while (0)
785 getbits(in, 0);
786 getbits(ou, 1);
787 getbits(ex, 2);
788#undef getbits
789 if (nbufbytes != 0)
790 bzero(selbits, nbufbytes / 2);
791
792 if (uap->tv) {
793 error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
794 sizeof (atv));
795 if (error)
792 goto done_noproclock;
796 goto done_nosellock;
797 if (itimerfix(&atv)) {
798 error = EINVAL;
795 goto done_noproclock;
799 goto done_nosellock;
800 }
801 getmicrouptime(&rtv);
802 timevaladd(&atv, &rtv);
803 } else {
804 atv.tv_sec = 0;
805 atv.tv_usec = 0;
806 }
807 timo = 0;
804 PROC_LOCK(td->td_proc);
808 mtx_lock(&sellock);
809retry:
810 ncoll = nselcoll;
811 mtx_lock_spin(&sched_lock);
812 td->td_flags |= TDF_SELECT;
813 mtx_unlock_spin(&sched_lock);
810 PROC_UNLOCK(td->td_proc);
814 mtx_unlock(&sellock);
815
816 /* XXX Is there a better place for this? */
817 TAILQ_INIT(&td->td_selq);
818 error = selscan(td, ibits, obits, uap->nd);
812 PROC_LOCK(td->td_proc);
819 mtx_lock(&sellock);
820 if (error || td->td_retval[0])
821 goto done;
822 if (atv.tv_sec || atv.tv_usec) {
823 getmicrouptime(&rtv);
817 if (timevalcmp(&rtv, &atv, >=)) {
818 /*
819 * An event of our interest may occur during locking a process.
820 * In order to avoid missing the event that occured during locking
821 * the process, test TDF_SELECT and rescan file descriptors if
822 * necessary.
823 */
824 mtx_lock_spin(&sched_lock);
825 if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
826 ncoll = nselcoll;
827 td->td_flags |= TDF_SELECT;
828 mtx_unlock_spin(&sched_lock);
829 PROC_UNLOCK(td->td_proc);
830 error = selscan(td, ibits, obits, uap->nd);
831 PROC_LOCK(td->td_proc);
832 } else
833 mtx_unlock_spin(&sched_lock);
824 if (timevalcmp(&rtv, &atv, >=))
825 goto done;
835 }
826 ttv = atv;
827 timevalsub(&ttv, &rtv);
828 timo = ttv.tv_sec > 24 * 60 * 60 ?
829 24 * 60 * 60 * hz : tvtohz(&ttv);
830 }
831
832 /*
833 * An event of interest may occur while we do not hold
834 * sellock, so check TDF_SELECT and the number of
835 * collisions and rescan the file descriptors if
836 * necessary.
837 */
838 mtx_lock_spin(&sched_lock);
842 td->td_flags &= ~TDF_SELECT;
839 if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
840 mtx_unlock_spin(&sched_lock);
841 goto retry;
842 }
843 mtx_unlock_spin(&sched_lock);
844
845 if (timo > 0)
846 error = cv_timedwait_sig(&selwait, &td->td_proc->p_mtx, timo);
846 error = cv_timedwait_sig(&selwait, &sellock, timo);
847 else
848 error = cv_wait_sig(&selwait, &td->td_proc->p_mtx);
848 error = cv_wait_sig(&selwait, &sellock);
849
850 if (error == 0)
851 goto retry;
852
853done:
854 clear_selinfo_list(td);
855 mtx_lock_spin(&sched_lock);
856 td->td_flags &= ~TDF_SELECT;
857 mtx_unlock_spin(&sched_lock);
857 PROC_UNLOCK(td->td_proc);
858done_noproclock:
858 mtx_unlock(&sellock);
859
860done_nosellock:
861 /* select is not restarted after signals... */
862 if (error == ERESTART)
863 error = EINTR;
864 if (error == EWOULDBLOCK)
865 error = 0;
866#define putbits(name, x) \
867 if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \
868 error = error2;

--- 95 unchanged lines hidden (view full) ---

964 }
965 ni = nfds * sizeof(struct pollfd);
966 if (ni > sizeof(smallbits))
967 bits = malloc(ni, M_TEMP, M_WAITOK);
968 else
969 bits = smallbits;
970 error = copyin(SCARG(uap, fds), bits, ni);
971 if (error)
970 goto done_noproclock;
972 goto done_nosellock;
973 if (SCARG(uap, timeout) != INFTIM) {
974 atv.tv_sec = SCARG(uap, timeout) / 1000;
975 atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000;
976 if (itimerfix(&atv)) {
977 error = EINVAL;
976 goto done_noproclock;
978 goto done_nosellock;
979 }
980 getmicrouptime(&rtv);
981 timevaladd(&atv, &rtv);
982 } else {
983 atv.tv_sec = 0;
984 atv.tv_usec = 0;
985 }
986 timo = 0;
985 PROC_LOCK(td->td_proc);
987 mtx_lock(&sellock);
988retry:
989 ncoll = nselcoll;
990 mtx_lock_spin(&sched_lock);
991 td->td_flags |= TDF_SELECT;
992 mtx_unlock_spin(&sched_lock);
991 PROC_UNLOCK(td->td_proc);
993 mtx_unlock(&sellock);
994
995 /* XXX Is there a better place for this? */
996 TAILQ_INIT(&td->td_selq);
997 error = pollscan(td, (struct pollfd *)bits, nfds);
993 PROC_LOCK(td->td_proc);
998 mtx_lock(&sellock);
999 if (error || td->td_retval[0])
1000 goto done;
1001 if (atv.tv_sec || atv.tv_usec) {
1002 getmicrouptime(&rtv);
998 if (timevalcmp(&rtv, &atv, >=)) {
999 /*
1000 * An event of our interest may occur during locking a process.
1001 * In order to avoid missing the event that occured during locking
1002 * the process, test TDF_SELECT and rescan file descriptors if
1003 * necessary.
1004 */
1005 mtx_lock_spin(&sched_lock);
1006 if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
1007 ncoll = nselcoll;
1008 td->td_flags |= TDF_SELECT;
1009 mtx_unlock_spin(&sched_lock);
1010 PROC_UNLOCK(td->td_proc);
1011 error = pollscan(td, (struct pollfd *)bits, nfds);
1012 PROC_LOCK(td->td_proc);
1013 } else
1014 mtx_unlock_spin(&sched_lock);
1003 if (timevalcmp(&rtv, &atv, >=))
1004 goto done;
1016 }
1005 ttv = atv;
1006 timevalsub(&ttv, &rtv);
1007 timo = ttv.tv_sec > 24 * 60 * 60 ?
1008 24 * 60 * 60 * hz : tvtohz(&ttv);
1009 }
1010 /*
1011 * An event of interest may occur while we do not hold
1012 * sellock, so check TDF_SELECT and the number of collisions
1013 * and rescan the file descriptors if necessary.
1014 */
1015 mtx_lock_spin(&sched_lock);
1023 td->td_flags &= ~TDF_SELECT;
1016 if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
1017 mtx_unlock_spin(&sched_lock);
1018 goto retry;
1019 }
1020 mtx_unlock_spin(&sched_lock);
1021
1022 if (timo > 0)
1026 error = cv_timedwait_sig(&selwait, &td->td_proc->p_mtx, timo);
1023 error = cv_timedwait_sig(&selwait, &sellock, timo);
1024 else
1028 error = cv_wait_sig(&selwait, &td->td_proc->p_mtx);
1025 error = cv_wait_sig(&selwait, &sellock);
1026
1027 if (error == 0)
1028 goto retry;
1029
1030done:
1031 clear_selinfo_list(td);
1032 mtx_lock_spin(&sched_lock);
1033 td->td_flags &= ~TDF_SELECT;
1034 mtx_unlock_spin(&sched_lock);
1036 PROC_UNLOCK(td->td_proc);
1037done_noproclock:
1035 mtx_unlock(&sellock);
1036
1037done_nosellock:
1038 /* poll is not restarted after signals... */
1039 if (error == ERESTART)
1040 error = EINTR;
1041 if (error == EWOULDBLOCK)
1042 error = 0;
1043 if (error == 0) {
1044 error = copyout(bits, SCARG(uap, fds), ni);
1045 if (error)

--- 64 unchanged lines hidden (view full) ---

1110int
1111openbsd_poll(td, uap)
1112 register struct thread *td;
1113 register struct openbsd_poll_args *uap;
1114{
1115 return (poll(td, (struct poll_args *)uap));
1116}
1117
1118/*
1119 * Remove the references to the thread from all of the objects
1120 * we were polling.
1121 *
1122 * This code assumes that the underlying owner of the selinfo
1123 * structure will hold sellock before it changes it, and that
1124 * it will unlink itself from our list if it goes away.
1125 */
1126void
1127clear_selinfo_list(td)
1128 struct thread *td;
1129{
1130 struct selinfo *si;
1131
1132 mtx_assert(&sellock, MA_OWNED);
1133 TAILQ_FOREACH(si, &td->td_selq, si_thrlist)
1134 si->si_thread = NULL;
1135 TAILQ_INIT(&td->td_selq);
1136}
1137
1138/*ARGSUSED*/
1139int
1140seltrue(dev, events, td)
1141 dev_t dev;
1142 int events;
1143 struct thread *td;
1144{
1145
1146 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1147}
1148
1129static int
1130find_thread_in_proc(struct proc *p, struct thread *td)
1131{
1132 struct thread *td2;
1133 FOREACH_THREAD_IN_PROC(p, td2) {
1134 if (td2 == td) {
1135 return (1);
1136 }
1137 }
1138 return (0);
1139}
1140
1149/*
1150 * Record a select request.
1151 */
1152void
1153selrecord(selector, sip)
1154 struct thread *selector;
1155 struct selinfo *sip;
1156{
1149 struct proc *p;
1150 pid_t mypid;
1157
1152 mypid = selector->td_proc->p_pid;
1153 if ((sip->si_pid == mypid) &&
1154 (sip->si_thread == selector)) { /* XXXKSE should be an ID? */
1155 return;
1158 mtx_lock(&sellock);
1159 /*
1160 * If the thread is NULL then take ownership of selinfo
1161 * however if the thread is not NULL and the thread points to
1162 * someone else, then we have a collision, otherwise leave it alone
1163 * as we've owned it in a previous selrecord on this selinfo.
1164 */
1165 if (sip->si_thread == NULL) {
1166 sip->si_thread = selector;
1167 TAILQ_INSERT_TAIL(&selector->td_selq, sip, si_thrlist);
1168 } else if (sip->si_thread != selector) {
1169 sip->si_flags |= SI_COLL;
1170 }
1157 if (sip->si_pid &&
1158 (p = pfind(sip->si_pid)) &&
1159 (find_thread_in_proc(p, sip->si_thread))) {
1160 mtx_lock_spin(&sched_lock);
1161 if (sip->si_thread->td_wchan == (caddr_t)&selwait) {
1162 mtx_unlock_spin(&sched_lock);
1163 PROC_UNLOCK(p);
1164 sip->si_flags |= SI_COLL;
1165 return;
1166 }
1167 mtx_unlock_spin(&sched_lock);
1168 PROC_UNLOCK(p);
1169 }
1170 sip->si_pid = mypid;
1171 sip->si_thread = selector;
1171
1172 mtx_unlock(&sellock);
1173}
1174
1175/*
1176 * Do a wakeup when a selectable event occurs.
1177 */
1178void
1179selwakeup(sip)
1179 register struct selinfo *sip;
1180 struct selinfo *sip;
1181{
1182 struct thread *td;
1182 register struct proc *p;
1183
1184 if (sip->si_pid == 0)
1185 return;
1186 if (sip->si_flags & SI_COLL) {
1184 mtx_lock(&sellock);
1185 td = sip->si_thread;
1186 if ((sip->si_flags & SI_COLL) != 0) {
1187 nselcoll++;
1188 sip->si_flags &= ~SI_COLL;
1189 cv_broadcast(&selwait);
1190 }
1191 p = pfind(sip->si_pid);
1192 sip->si_pid = 0;
1193 td = sip->si_thread;
1194 if (p != NULL) {
1195 if (!find_thread_in_proc(p, td)) {
1196 PROC_UNLOCK(p); /* lock is in pfind() */;
1197 return;
1198 }
1199 mtx_lock_spin(&sched_lock);
1200 if (td->td_wchan == (caddr_t)&selwait) {
1201 if (td->td_proc->p_stat == SSLEEP)
1202 setrunnable(td);
1203 else
1204 cv_waitq_remove(td);
1205 } else
1206 td->td_flags &= ~TDF_SELECT;
1207 mtx_unlock_spin(&sched_lock);
1208 PROC_UNLOCK(p); /* Lock is in pfind() */
1191 if (td == NULL) {
1192 mtx_unlock(&sellock);
1193 return;
1194 }
1195 TAILQ_REMOVE(&td->td_selq, sip, si_thrlist);
1196 sip->si_thread = NULL;
1197 mtx_lock_spin(&sched_lock);
1198 if (td->td_wchan == (caddr_t)&selwait) {
1199 if (td->td_proc->p_stat == SSLEEP)
1200 setrunnable(td);
1201 else
1202 cv_waitq_remove(td);
1203 } else
1204 td->td_flags &= ~TDF_SELECT;
1205 mtx_unlock_spin(&sched_lock);
1206 mtx_unlock(&sellock);
1207}
1208
1209static void selectinit __P((void *));
1210SYSINIT(select, SI_SUB_LOCK, SI_ORDER_FIRST, selectinit, NULL)
1211
1212/* ARGSUSED*/
1213static void
1214selectinit(dummy)
1215 void *dummy;
1216{
1217 cv_init(&selwait, "select");
1218 mtx_init(&sellock, "sellck", MTX_DEF);
1219}