Ticket #635: base.diff
| File base.diff, 15.0 KB (added by bos, 2 years ago) |
|---|
-
configure.ac
diff -rN -u old-base/configure.ac new-base/configure.ac
old new 17 17 AC_HEADER_STDC 18 18 19 19 # check for specific header (.h) files that we are interested in 20 AC_CHECK_HEADERS([ctype.h errno.h fcntl.h inttypes.h limits.h signal.h sys/resource.h sys/select.h sys/stat.h sys/syscall.h sys/time.h sys/timeb.h sys/timers.h sys/times.h sys/types.h sys/utsname.h sys/wait.h termios.h time.h unistd.h utime.h windows.h winsock.h langinfo.h])20 AC_CHECK_HEADERS([ctype.h errno.h fcntl.h inttypes.h limits.h poll.h signal.h sys/resource.h sys/select.h sys/stat.h sys/syscall.h sys/time.h sys/timeb.h sys/timers.h sys/times.h sys/types.h sys/utsname.h sys/wait.h termios.h time.h unistd.h utime.h windows.h winsock.h langinfo.h]) 21 21 22 22 # Enable large file support. Do this before testing the types ino_t, off_t, and 23 23 # rlim_t, because it will affect the result of that test. -
GHC/Conc.lhs
diff -rN -u old-base/GHC/Conc.lhs new-base/GHC/Conc.lhs
old new 22 22 -- higher level modules be the home. Hence: 23 23 24 24 #include "Typeable.h" 25 #include "HsBaseConfig.h" 26 27 #if HAVE_POLL_H 28 # define USE_POLL 1 29 #endif 25 30 26 31 -- #not-home 27 32 module GHC.Conc … … 747 752 -- and delays (threadDelay). 748 753 -- 749 754 -- We can do this because in the threaded RTS the IO Manager can make 750 -- a non-blocking call to select(), so we don't have to do select()in755 -- a non-blocking poll call, so we don't have to poll in 751 756 -- the scheduler as we have to in the non-threaded RTS. We get performance 752 -- benefits from doing it this way, because we only have to restart the select()753 -- when a new request arrives, rather than doing one select()each time757 -- benefits from doing it this way, because we only have to restart the poll 758 -- when a new request arrives, rather than doing one poll each time 754 759 -- around the scheduler loop. Furthermore, the scheduler can be simplified 755 760 -- by not having to check for completed IO requests. 756 761 … … 985 990 986 991 #else 987 992 -- ---------------------------------------------------------------------------- 988 -- Unix IO manager thread, using select() 993 -- Unix IO manager thread 994 995 data EventType = ReadEvent 996 | WriteEvent 997 998 class EventManager e where 999 resetEventManager :: e -> IO () 1000 registerFd :: e -> EventType -> Fd -> IO () 1001 isFdReady :: e -> EventType -> Fd -> IO CInt 1002 pollForEvents :: e -> Ptr CTimeVal -> IO CInt 1003 1004 #if USE_POLL 1005 1006 data PollManager = PollManager { 1007 pollFds :: !(ForeignPtr CPollFd) 1008 } 1009 1010 newPollManager :: IO PollManager 1011 newPollManager = do 1012 pfd <- newForeignPtr finalizerFree =<< c_pollfd_resize nullPtr 1013 return PollManager { pollFds = pfd } 1014 1015 instance EventManager PollManager where 1016 resetEventManager mgr = withForeignPtr (pollFds mgr) c_pollfd_reset 1017 1018 registerFd mgr ReadEvent fd = do 1019 withForeignPtr (pollFds mgr) $ \p -> c_pollfd_add p fd pollReadEvent 1020 registerFd mgr WriteEvent fd = do 1021 withForeignPtr (pollFds mgr) $ \p -> c_pollfd_add p fd pollWriteEvent 1022 1023 isFdReady mgr ReadEvent fd = 1024 withForeignPtr (pollFds mgr) $ \p -> c_pollfd_test p fd pollReadEvent 1025 isFdReady mgr WriteEvent fd = 1026 withForeignPtr (pollFds mgr) $ \p -> c_pollfd_test p fd pollWriteEvent 1027 1028 pollForEvents mgr timeout = 1029 withForeignPtr (pollFds mgr) $ \p -> c_poll p timeout 1030 1031 newEventManager = newPollManager 1032 1033 #else 1034 1035 data SelectManager = SelectManager { 1036 selReadFds :: !(ForeignPtr CFdSet) 1037 , selWriteFds :: !(ForeignPtr CFdSet) 1038 , selMaxFd :: !(IORef Fd) 1039 } 1040 1041 newSelectManager :: IO SelectManager 1042 newSelectManager = do 1043 rfds <- newForeignPtr finalizerFree =<< mallocBytes sizeofFdSet 1044 wfds <- newForeignPtr finalizerFree =<< mallocBytes sizeofFdSet 1045 mfd <- newIORef (-1) 1046 return SelectManager { selReadFds = rfds 1047 , selWriteFds = wfds 1048 , selMaxFd = mfd } 1049 1050 updateMaxFd :: SelectManager -> Fd -> IO () 1051 updateMaxFd mgr fd = do 1052 oldMax <- readIORef (selMaxFd mgr) 1053 when (fd > oldMax) $ 1054 writeIORef (selMaxFd mgr) fd 1055 1056 instance EventManager SelectManager where 1057 resetEventManager mgr = do 1058 withForeignPtr (selReadFds mgr) fdZero 1059 withForeignPtr (selWriteFds mgr) fdZero 1060 writeIORef (selMaxFd mgr) (-1) 1061 1062 registerFd _ _ fd | fd >= fD_SETSIZE = 1063 error "registerFd: file descriptor out of range" 1064 registerFd mgr ReadEvent fd = do 1065 withForeignPtr (selReadFds mgr) $ fdSet fd 1066 updateMaxFd mgr fd 1067 registerFd mgr WriteEvent fd = do 1068 withForeignPtr (selWriteFds mgr) $ fdSet fd 1069 updateMaxFd mgr fd 1070 1071 isFdReady mgr ReadEvent fd = 1072 withForeignPtr (selReadFds mgr) $ fdIsSet fd 1073 isFdReady mgr WriteEvent fd = 1074 withForeignPtr (selWriteFds mgr) $ fdIsSet fd 1075 1076 pollForEvents mgr timeout = 1077 withForeignPtr (selReadFds mgr) $ \readFds -> 1078 withForeignPtr (selWriteFds mgr) $ \writeFds -> do 1079 maxFd <- readIORef (selMaxFd mgr) 1080 let numFds = fromIntegral maxFd + 1 1081 c_select numFds readFds writeFds nullPtr timeout 1082 1083 newEventManager = newSelectManager 1084 1085 #endif 989 1086 990 1087 ioManager :: IO () 991 1088 ioManager = do … … 998 1095 setCloseOnExec rd_end 999 1096 setCloseOnExec wr_end 1000 1097 c_setIOManagerPipe wr_end 1001 allocaBytes sizeofFdSet $ \readfds -> do 1002 allocaBytes sizeofFdSet $ \writefds -> do 1098 mgr <- newEventManager 1003 1099 allocaBytes sizeofTimeVal $ \timeval -> do 1004 service_loop (fromIntegral rd_end) readfds writefdstimeval [] []1100 service_loop (fromIntegral rd_end) mgr timeval [] [] 1005 1101 return () 1006 1102 1007 1103 service_loop 1008 :: Fd -- listen to this for wakeup calls1009 -> Ptr CFdSet1010 -> Ptr CFdSet1104 :: EventManager mgr => 1105 Fd -- listen to this for wakeup calls 1106 -> mgr 1011 1107 -> Ptr CTimeVal 1012 1108 -> [IOReq] 1013 1109 -> [DelayReq] 1014 1110 -> IO () 1015 service_loop wakeup readfds writefdsptimeval old_reqs old_delays = do1111 service_loop wakeup mgr ptimeval old_reqs old_delays = do 1016 1112 1017 1113 -- pick up new IO requests 1018 1114 new_reqs <- atomicModifyIORef pendingEvents (\a -> ([],a)) … … 1022 1118 new_delays <- atomicModifyIORef pendingDelays (\a -> ([],a)) 1023 1119 let delays0 = foldr insertDelay old_delays new_delays 1024 1120 1025 -- build the FDSets for select() 1026 fdZero readfds 1027 fdZero writefds 1028 fdSet wakeup readfds 1029 maxfd <- buildFdSets 0 readfds writefds reqs 1121 -- build the event info 1122 resetEventManager mgr 1123 registerFd mgr ReadEvent wakeup 1124 buildEvents mgr reqs 1030 1125 1031 -- perform the select()1032 let do_ selectdelays = do1126 -- perform the poll 1127 let do_poll delays = do 1033 1128 -- check the current time and wake up any thread in 1034 1129 -- threadDelay whose timeout has expired. Also find the 1035 -- timeout value for the select() call.1130 -- timeout value for the poll. 1036 1131 now <- getUSecOfDay 1037 1132 (delays', timeout) <- getDelay now ptimeval delays 1038 1133 1039 res <- c_select (fromIntegral ((max wakeup maxfd)+1)) readfds writefds 1040 nullPtr timeout 1134 res <- pollForEvents mgr timeout 1041 1135 if (res == -1) 1042 1136 then do 1043 1137 err <- getErrno 1044 1138 case err of 1045 _ | err == eINTR -> do_ selectdelays'1046 -- EINTR: just redo the select()1139 _ | err == eINTR -> do_poll delays' 1140 -- EINTR: just redo the poll 1047 1141 _ | err == eBADF -> return (True, delays) 1048 1142 -- EBADF: one of the file descriptors is closed or bad, 1049 1143 -- we don't know which one, so wake everyone up. 1050 _ | otherwise -> throwErrno " select"1144 _ | otherwise -> throwErrno "poll" 1051 1145 -- otherwise (ENOMEM or EINVAL) something has gone 1052 1146 -- wrong; report the error. 1053 1147 else 1054 1148 return (False,delays') 1055 1149 1056 (wakeup_all,delays') <- do_ selectdelays01150 (wakeup_all,delays') <- do_poll delays0 1057 1151 1058 1152 exit <- 1059 1153 if wakeup_all then return False 1060 1154 else do 1061 b <- fdIsSet wakeup readfds1155 b <- isFdReady mgr ReadEvent wakeup 1062 1156 if b == 0 1063 1157 then return False 1064 1158 else alloca $ \p -> do … … 1087 1181 atomicModifyIORef prodding (\_ -> (False, ())) 1088 1182 1089 1183 reqs' <- if wakeup_all then do wakeupAll reqs; return [] 1090 else completeRequests reqs readfds writefds[]1184 else completeRequests reqs mgr [] 1091 1185 1092 service_loop wakeup readfds writefdsptimeval reqs' delays'1186 service_loop wakeup mgr ptimeval reqs' delays' 1093 1187 1094 1188 io_MANAGER_WAKEUP, io_MANAGER_DIE, io_MANAGER_SYNC :: Word8 1095 1189 io_MANAGER_WAKEUP = 0xff … … 1181 1275 -- ----------------------------------------------------------------------------- 1182 1276 -- IO requests 1183 1277 1184 buildFdSets :: Fd -> Ptr CFdSet -> Ptr CFdSet -> [IOReq] -> IO Fd 1185 buildFdSets maxfd _ _ [] = return maxfd 1186 buildFdSets maxfd readfds writefds (Read fd _ : reqs) 1187 | fd >= fD_SETSIZE = error "buildFdSets: file descriptor out of range" 1188 | otherwise = do 1189 fdSet fd readfds 1190 buildFdSets (max maxfd fd) readfds writefds reqs 1191 buildFdSets maxfd readfds writefds (Write fd _ : reqs) 1192 | fd >= fD_SETSIZE = error "buildFdSets: file descriptor out of range" 1193 | otherwise = do 1194 fdSet fd writefds 1195 buildFdSets (max maxfd fd) readfds writefds reqs 1278 buildEvents :: EventManager mgr => mgr -> [IOReq] -> IO () 1279 buildEvents _ [] = return () 1280 buildEvents mgr (Read fd _ : reqs) = do 1281 registerFd mgr ReadEvent fd 1282 buildEvents mgr reqs 1283 buildEvents mgr (Write fd _ : reqs) = do 1284 registerFd mgr WriteEvent fd 1285 buildEvents mgr reqs 1196 1286 1197 completeRequests :: [IOReq] -> Ptr CFdSet -> Ptr CFdSet-> [IOReq]1287 completeRequests :: EventManager mgr => [IOReq] -> mgr -> [IOReq] 1198 1288 -> IO [IOReq] 1199 completeRequests [] _ _reqs' = return reqs'1200 completeRequests (Read fd m : reqs) readfds writefdsreqs' = do1201 b <- fdIsSet fd readfds1289 completeRequests [] _ reqs' = return reqs' 1290 completeRequests (Read fd m : reqs) mgr reqs' = do 1291 b <- isFdReady mgr ReadEvent fd 1202 1292 if b /= 0 1203 then do putMVar m (); completeRequests reqs readfds writefdsreqs'1204 else completeRequests reqs readfds writefds(Read fd m : reqs')1205 completeRequests (Write fd m : reqs) readfds writefdsreqs' = do1206 b <- fdIsSet fd writefds1293 then do putMVar m (); completeRequests reqs mgr reqs' 1294 else completeRequests reqs mgr (Read fd m : reqs') 1295 completeRequests (Write fd m : reqs) mgr reqs' = do 1296 b <- isFdReady mgr WriteEvent fd 1207 1297 if b /= 0 1208 then do putMVar m (); completeRequests reqs readfds writefdsreqs'1209 else completeRequests reqs readfds writefds(Write fd m : reqs')1298 then do putMVar m (); completeRequests reqs mgr reqs' 1299 else completeRequests reqs mgr (Write fd m : reqs') 1210 1300 1211 1301 wakeupAll :: [IOReq] -> IO () 1212 1302 wakeupAll [] = return () … … 1262 1352 -} 1263 1353 1264 1354 -- ---------------------------------------------------------------------------- 1355 #if USE_POLL 1356 -- poll() interface 1357 1358 data CPollFd 1359 1360 foreign import ccall unsafe "__hscore_read_event" c_poll_read_event :: CInt 1361 foreign import ccall unsafe "__hscore_write_event" c_poll_write_event :: CInt 1362 foreign import ccall unsafe "__hscore_pollfd_resize" 1363 c_pollfd_resize :: Ptr CPollFd -> IO (Ptr CPollFd) 1364 foreign import ccall unsafe "__hscore_pollfd_add" 1365 c_pollfd_add :: Ptr CPollFd -> Fd -> CInt -> IO () 1366 foreign import ccall unsafe "__hscore_pollfd_test" 1367 c_pollfd_test :: Ptr CPollFd -> Fd -> CInt -> IO CInt 1368 foreign import ccall unsafe "__hscore_pollfd_reset" 1369 c_pollfd_reset :: Ptr CPollFd -> IO () 1370 foreign import ccall safe "__hscore_poll" 1371 c_poll :: Ptr CPollFd -> Ptr CTimeVal -> IO CInt 1372 1373 pollReadEvent, pollWriteEvent :: CInt 1374 pollReadEvent = c_poll_read_event 1375 pollWriteEvent = c_poll_write_event 1376 1377 #else 1265 1378 -- select() interface 1266 1379 1267 1380 -- ToDo: move to System.Posix.Internals? … … 1295 1408 1296 1409 foreign import ccall unsafe "sizeof_fd_set" 1297 1410 sizeofFdSet :: Int 1411 #endif 1298 1412 1299 1413 #endif 1300 1414 -
include/HsBase.h
diff -rN -u old-base/include/HsBase.h new-base/include/HsBase.h
old new 141 141 #include <share.h> 142 142 #endif 143 143 144 #if HAVE_POLL_H 145 #include <poll.h> 146 #endif 144 147 #if HAVE_SYS_SELECT_H 145 148 #include <sys/select.h> 146 149 #endif … … 626 629 627 630 INLINE int __hscore_select(int nfds, fd_set *readfds, fd_set *writefds, 628 631 fd_set *exceptfds, struct timeval *timeout) { 629 return (select(nfds,readfds,writefds,exceptfds,timeout)); 632 return select(nfds,readfds,writefds,exceptfds,timeout); 633 } 634 635 #if HAVE_POLL_H 636 /* Poll-related stuff. The data structures managed here are assumed 637 to be accessed only from the I/O manager thread. */ 638 639 typedef struct { 640 int numfds; /* number of array elements allocated */ 641 int lastidx; /* highest array slot currently in use */ 642 struct pollfd *fds; /* allocated contiguously at end of struct */ 643 } hscore_pollfd; 644 645 INLINE hscore_pollfd *__hscore_pollfd_resize(hscore_pollfd *o) 646 { 647 hscore_pollfd *p; 648 int numfds = o == NULL ? 32 : (o->numfds * 2); 649 p = realloc(o, sizeof(*p) + numfds * sizeof(p->fds[0])); 650 if (p == NULL) 651 abort(); 652 p->numfds = numfds; 653 p->fds = (struct pollfd *) ((char *)p) + sizeof(*p); 654 if (o == NULL) 655 p->lastidx = -1; 656 return p; 630 657 } 631 658 659 /* These may be ORed together into a bitmask. */ 660 INLINE int __hscore_read_event() { return 0x01; } 661 INLINE int __hscore_write_event() { return 0x02; } 662 663 INLINE void __hscore_pollfd_add(hscore_pollfd *p, int fd, int evt) 664 { 665 int i; 666 667 for (i = 0; i <= p->lastidx && p->fds[i].fd != fd; i++) 668 ; 669 670 if (i > p->lastidx) { 671 p->lastidx += 1; 672 if (p->lastidx == p->numfds) 673 p = __hscore_pollfd_resize(p); 674 p->fds[i].events = 0; 675 p->fds[i].fd = fd; 676 } 677 678 if (evt & __hscore_read_event()) { 679 p->fds[i].events |= POLLIN | POLLPRI; 680 #ifdef POLLRDHUP 681 p->fds[i].events |= POLLRDHUP; 682 #endif 683 } 684 if (evt & __hscore_write_event()) 685 p->fds[i].events |= POLLOUT; 686 } 687 688 INLINE int __hscore_pollfd_test(hscore_pollfd *p, int fd, int evt) 689 { 690 int i, r; 691 int top; 692 693 for (i = 0; i <= p->lastidx && p->fds[i].fd != fd; i++) 694 ; 695 696 if (i > p->lastidx) 697 return 0; 698 699 r = p->fds[i].revents & (POLLERR | POLLHUP | POLLNVAL); 700 if (evt & __hscore_read_event()) { 701 r |= p->fds[i].revents & (POLLIN | POLLPRI); 702 #ifdef POLLRDHUP 703 r |= p->fds[i].revents & POLLRDHUP; 704 #endif 705 } 706 if (evt & __hscore_write_event()) 707 r |= p->fds[i].revents & POLLOUT; 708 return r; 709 } 710 711 INLINE void __hscore_pollfd_reset(hscore_pollfd *p) 712 { 713 p->lastidx = -1; 714 } 715 716 INLINE int __hscore_poll(hscore_pollfd *p, struct timeval *timeout) 717 { 718 int timeo = timeout == NULL 719 ? -1 720 : (timeout->tv_sec * 1000 + timeout->tv_usec / 1000); 721 722 return poll(p->fds, p->lastidx + 1, timeo); 723 } 724 #endif 725 632 726 // gettimeofday()-related 633 727 634 728 #if !defined(__MINGW32__)
