Deleted Added
full compact
sys_generic.c (91972) sys_generic.c (92252)
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
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
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;
700struct cv selwait;
703struct cv selwait;
704int nselcoll; /* Select collisions since boot */
701SYSCTL_INT(_kern, OID_AUTO, nselcoll, CTLFLAG_RD, &nselcoll, 0, "");
702
703/*
704 * Select system call.
705 */
706#ifndef _SYS_SYSPROTO_H_
707struct select_args {
708 int nd;

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

770 if (uap->name == NULL) \
771 ibits[x] = NULL; \
772 else { \
773 ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
774 obits[x] = sbp; \
775 sbp += ncpbytes / sizeof *sbp; \
776 error = copyin(uap->name, ibits[x], ncpbytes); \
777 if (error != 0) \
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; \
779 } \
780 } while (0)
781 getbits(in, 0);
782 getbits(ou, 1);
783 getbits(ex, 2);
784#undef getbits
785 if (nbufbytes != 0)
786 bzero(selbits, nbufbytes / 2);
787
788 if (uap->tv) {
789 error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
790 sizeof (atv));
791 if (error)
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;
793 if (itimerfix(&atv)) {
794 error = EINVAL;
797 if (itimerfix(&atv)) {
798 error = EINVAL;
795 goto done_noproclock;
799 goto done_nosellock;
796 }
797 getmicrouptime(&rtv);
798 timevaladd(&atv, &rtv);
799 } else {
800 atv.tv_sec = 0;
801 atv.tv_usec = 0;
802 }
803 timo = 0;
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);
805retry:
806 ncoll = nselcoll;
807 mtx_lock_spin(&sched_lock);
808 td->td_flags |= TDF_SELECT;
809 mtx_unlock_spin(&sched_lock);
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);
811 error = selscan(td, ibits, obits, uap->nd);
818 error = selscan(td, ibits, obits, uap->nd);
812 PROC_LOCK(td->td_proc);
819 mtx_lock(&sellock);
813 if (error || td->td_retval[0])
814 goto done;
815 if (atv.tv_sec || atv.tv_usec) {
816 getmicrouptime(&rtv);
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, >=))
834 goto done;
825 goto done;
835 }
836 ttv = atv;
837 timevalsub(&ttv, &rtv);
838 timo = ttv.tv_sec > 24 * 60 * 60 ?
839 24 * 60 * 60 * hz : tvtohz(&ttv);
840 }
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 */
841 mtx_lock_spin(&sched_lock);
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)
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
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:
849
850 if (error == 0)
851 goto retry;
852
853done:
854 clear_selinfo_list(td);
854 mtx_lock_spin(&sched_lock);
855 td->td_flags &= ~TDF_SELECT;
856 mtx_unlock_spin(&sched_lock);
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:
859 /* select is not restarted after signals... */
860 if (error == ERESTART)
861 error = EINTR;
862 if (error == EWOULDBLOCK)
863 error = 0;
864#define putbits(name, x) \
865 if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \
866 error = error2;

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

962 }
963 ni = nfds * sizeof(struct pollfd);
964 if (ni > sizeof(smallbits))
965 bits = malloc(ni, M_TEMP, M_WAITOK);
966 else
967 bits = smallbits;
968 error = copyin(SCARG(uap, fds), bits, ni);
969 if (error)
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;
971 if (SCARG(uap, timeout) != INFTIM) {
972 atv.tv_sec = SCARG(uap, timeout) / 1000;
973 atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000;
974 if (itimerfix(&atv)) {
975 error = EINVAL;
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;
977 }
978 getmicrouptime(&rtv);
979 timevaladd(&atv, &rtv);
980 } else {
981 atv.tv_sec = 0;
982 atv.tv_usec = 0;
983 }
984 timo = 0;
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);
986retry:
987 ncoll = nselcoll;
988 mtx_lock_spin(&sched_lock);
989 td->td_flags |= TDF_SELECT;
990 mtx_unlock_spin(&sched_lock);
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);
992 error = pollscan(td, (struct pollfd *)bits, nfds);
997 error = pollscan(td, (struct pollfd *)bits, nfds);
993 PROC_LOCK(td->td_proc);
998 mtx_lock(&sellock);
994 if (error || td->td_retval[0])
995 goto done;
996 if (atv.tv_sec || atv.tv_usec) {
997 getmicrouptime(&rtv);
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, >=))
1015 goto done;
1004 goto done;
1016 }
1017 ttv = atv;
1018 timevalsub(&ttv, &rtv);
1019 timo = ttv.tv_sec > 24 * 60 * 60 ?
1020 24 * 60 * 60 * hz : tvtohz(&ttv);
1021 }
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 */
1022 mtx_lock_spin(&sched_lock);
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 }
1024 mtx_unlock_spin(&sched_lock);
1020 mtx_unlock_spin(&sched_lock);
1021
1025 if (timo > 0)
1022 if (timo > 0)
1026 error = cv_timedwait_sig(&selwait, &td->td_proc->p_mtx, timo);
1023 error = cv_timedwait_sig(&selwait, &sellock, timo);
1027 else
1024 else
1028 error = cv_wait_sig(&selwait, &td->td_proc->p_mtx);
1025 error = cv_wait_sig(&selwait, &sellock);
1026
1029 if (error == 0)
1030 goto retry;
1031
1032done:
1027 if (error == 0)
1028 goto retry;
1029
1030done:
1031 clear_selinfo_list(td);
1033 mtx_lock_spin(&sched_lock);
1034 td->td_flags &= ~TDF_SELECT;
1035 mtx_unlock_spin(&sched_lock);
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
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
1118/*ARGSUSED*/
1119int
1120seltrue(dev, events, td)
1121 dev_t dev;
1122 int events;
1123 struct thread *td;
1124{
1125
1126 return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
1127}
1128
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
1141/*
1142 * Record a select request.
1143 */
1144void
1145selrecord(selector, sip)
1146 struct thread *selector;
1147 struct selinfo *sip;
1148{
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;
1151
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;
1156 }
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);
1172}
1173
1174/*
1175 * Do a wakeup when a selectable event occurs.
1176 */
1177void
1178selwakeup(sip)
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;
1180{
1181 struct thread *td;
1181{
1182 struct thread *td;
1182 register struct proc *p;
1183
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 }
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;
1209 }
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);
1210}
1211
1212static void selectinit __P((void *));
1213SYSINIT(select, SI_SUB_LOCK, SI_ORDER_FIRST, selectinit, NULL)
1214
1215/* ARGSUSED*/
1216static void
1217selectinit(dummy)
1218 void *dummy;
1219{
1220 cv_init(&selwait, "select");
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);
1221}
1219}