@@ -119,6 +119,12 @@ typedef struct _epoll_fd_data {
119119 int wr_ref_cnt ;
120120 int ex_ref_cnt ;
121121 int revents ;
122+ /* The following members aren't touched after forking. */
123+ union {
124+ _st_pollq_t * pq ;
125+ _st_pollq_t * * pqs ;
126+ };
127+ int pq_cnt ;
122128} _epoll_fd_data_t ;
123129
124130static struct _st_epolldata {
@@ -1194,16 +1200,97 @@ ST_HIDDEN int _st_epoll_pollset_add(struct pollfd *pds, int npds)
11941200 return 0 ;
11951201}
11961202
1203+ ST_HIDDEN void _st_epoll_pollq_del (_st_pollq_t * pq )
1204+ {
1205+ struct pollfd * pd = pq -> pds ;
1206+ struct pollfd * pd_end = pd + pq -> npds ;
1207+ _epoll_fd_data_t * efd ;
1208+ int i ;
1209+
1210+ while (pd < pd_end ) {
1211+ efd = & _st_epoll_data -> fd_data [pd -> fd ];
1212+ if (efd -> pq_cnt == 1 ) {
1213+ if (efd -> pq == pq )
1214+ efd -> pq = NULL ;
1215+ } else if (efd -> pq_cnt > 0 ) {
1216+ for (i = 0 ; i < efd -> pq_cnt ; ++ i ) {
1217+ if (efd -> pqs [i ] == pq ) {
1218+ efd -> pqs [i ] = NULL ;
1219+ break ;
1220+ }
1221+ }
1222+ }
1223+ ++ pd ;
1224+ }
1225+ }
1226+
1227+ ST_HIDDEN int _st_epoll_pollq_add (_st_pollq_t * pq )
1228+ {
1229+ struct pollfd * pd = pq -> pds ;
1230+ struct pollfd * pd_end = pd + pq -> npds ;
1231+ _epoll_fd_data_t * efd ;
1232+ int i ;
1233+ _st_pollq_t * * pqs ;
1234+
1235+ while (pd < pd_end ) {
1236+ efd = & _st_epoll_data -> fd_data [pd -> fd ];
1237+ if (efd -> pq_cnt == 0 ) {
1238+ efd -> pq = pq ;
1239+ efd -> pq_cnt = 1 ;
1240+ } else if (efd -> pq_cnt == 1 ) {
1241+ if (efd -> pq == NULL ) {
1242+ efd -> pq = pq ;
1243+ } else {
1244+ assert (efd -> pq != pq );
1245+ pqs = malloc (sizeof (* pqs ) * 2 );
1246+ if (!pqs ) {
1247+ _st_epoll_pollq_del (pq );
1248+ errno = ENOMEM ;
1249+ return -1 ;
1250+ }
1251+ pqs [0 ] = efd -> pq ;
1252+ pqs [1 ] = pq ;
1253+ efd -> pqs = pqs ;
1254+ efd -> pq_cnt = 2 ;
1255+ }
1256+ } else {
1257+ for (i = 0 ; i < efd -> pq_cnt ; ++ i ) {
1258+ if (efd -> pqs [i ] == NULL ) {
1259+ efd -> pqs [i ] = pq ;
1260+ break ;
1261+ } else {
1262+ assert (efd -> pqs [i ] != pq );
1263+ }
1264+ }
1265+ if (i == efd -> pq_cnt ) {
1266+ pqs = realloc (efd -> pqs , sizeof (* pqs ) * (efd -> pq_cnt + 1 ));
1267+ if (!pqs ) {
1268+ _st_epoll_pollq_del (pq );
1269+ errno = ENOMEM ;
1270+ return -1 ;
1271+ }
1272+ efd -> pqs = pqs ;
1273+ efd -> pqs [efd -> pq_cnt ++ ] = pq ;
1274+ }
1275+ }
1276+ ++ pd ;
1277+ }
1278+
1279+ return 0 ;
1280+ }
1281+
11971282ST_HIDDEN void _st_epoll_dispatch (void )
11981283{
11991284 st_utime_t min_timeout ;
12001285 _st_clist_t * q ;
12011286 _st_pollq_t * pq ;
12021287 struct pollfd * pds , * epds ;
12031288 struct epoll_event ev ;
1204- int timeout , nfd , i , osfd , notify ;
1289+ int timeout , nfd , i , j , osfd , notify ;
12051290 int events , op ;
12061291 short revents ;
1292+ _epoll_fd_data_t * efd ;
1293+ _st_pollq_t * * pqs ;
12071294
12081295 if (_ST_SLEEPQ == NULL ) {
12091296 timeout = -1 ;
@@ -1224,7 +1311,10 @@ ST_HIDDEN void _st_epoll_dispatch(void)
12241311 _st_epoll_data -> pid = getpid ();
12251312
12261313 /* Put all descriptors on ioq into new epoll set */
1227- memset (_st_epoll_data -> fd_data , 0 , _st_epoll_data -> fd_data_size * sizeof (_epoll_fd_data_t ));
1314+ for (i = 0 ; i < _st_epoll_data -> fd_data_size ; ++ i ) {
1315+ memset (& _st_epoll_data -> fd_data [i ], 0 ,
1316+ offsetof(_epoll_fd_data_t , pq ));
1317+ }
12281318 _st_epoll_data -> evtlist_cnt = 0 ;
12291319 for (q = _ST_IOQ .next ; q != & _ST_IOQ ; q = q -> next ) {
12301320 pq = _ST_POLLQUEUE_PTR (q );
@@ -1245,48 +1335,63 @@ ST_HIDDEN void _st_epoll_dispatch(void)
12451335 }
12461336 }
12471337
1248- for (q = _ST_IOQ .next ; q != & _ST_IOQ ; q = q -> next ) {
1249- pq = _ST_POLLQUEUE_PTR (q );
1250- notify = 0 ;
1251- epds = pq -> pds + pq -> npds ;
1252-
1253- for (pds = pq -> pds ; pds < epds ; pds ++ ) {
1254- if (_ST_EPOLL_REVENTS (pds -> fd ) == 0 ) {
1255- pds -> revents = 0 ;
1338+ for (i = 0 ; i < nfd ; ++ i ) {
1339+ osfd = _st_epoll_data -> evtlist [i ].data .fd ;
1340+ efd = & _st_epoll_data -> fd_data [osfd ];
1341+ assert (efd -> pq_cnt > 0 );
1342+ if (efd -> pq_cnt == 1 )
1343+ pqs = & efd -> pq ;
1344+ else
1345+ pqs = efd -> pqs ;
1346+ for (j = 0 ; j < efd -> pq_cnt ; ++ j ) {
1347+ pq = pqs [j ];
1348+ if (!pq )
12561349 continue ;
1257- }
1258- osfd = pds -> fd ;
1259- events = pds -> events ;
1260- revents = 0 ;
1261- if ((events & POLLIN ) && (_ST_EPOLL_REVENTS (osfd ) & EPOLLIN ))
1262- revents |= POLLIN ;
1263- if ((events & POLLOUT ) && (_ST_EPOLL_REVENTS (osfd ) & EPOLLOUT ))
1264- revents |= POLLOUT ;
1265- if ((events & POLLPRI ) && (_ST_EPOLL_REVENTS (osfd ) & EPOLLPRI ))
1266- revents |= POLLPRI ;
1267- if (_ST_EPOLL_REVENTS (osfd ) & EPOLLERR )
1268- revents |= POLLERR ;
1269- if (_ST_EPOLL_REVENTS (osfd ) & EPOLLHUP )
1270- revents |= POLLHUP ;
1350+ notify = 0 ;
1351+ epds = pq -> pds + pq -> npds ;
12711352
1272- pds -> revents = revents ;
1273- if (revents ) {
1274- notify = 1 ;
1353+ for (pds = pq -> pds ; pds < epds ; pds ++ ) {
1354+ if (_ST_EPOLL_REVENTS (pds -> fd ) == 0 ) {
1355+ pds -> revents = 0 ;
1356+ continue ;
1357+ }
1358+ osfd = pds -> fd ;
1359+ events = pds -> events ;
1360+ revents = 0 ;
1361+ if ((events & POLLIN ) &&
1362+ (_ST_EPOLL_REVENTS (osfd ) & EPOLLIN ))
1363+ revents |= POLLIN ;
1364+ if ((events & POLLOUT ) &&
1365+ (_ST_EPOLL_REVENTS (osfd ) & EPOLLOUT ))
1366+ revents |= POLLOUT ;
1367+ if ((events & POLLPRI ) &&
1368+ (_ST_EPOLL_REVENTS (osfd ) & EPOLLPRI ))
1369+ revents |= POLLPRI ;
1370+ if (_ST_EPOLL_REVENTS (osfd ) & EPOLLERR )
1371+ revents |= POLLERR ;
1372+ if (_ST_EPOLL_REVENTS (osfd ) & EPOLLHUP )
1373+ revents |= POLLHUP ;
1374+
1375+ pds -> revents = revents ;
1376+ if (revents ) {
1377+ notify = 1 ;
1378+ }
12751379 }
1276- }
1277- if ( notify ) {
1278- ST_REMOVE_LINK (& pq -> links );
1279- pq -> on_ioq = 0 ;
1280- /*
1281- * Here we will only delete/modify descriptors that
1282- * didn't fire (see comments in _st_epoll_pollset_del()).
1283- */
1284- _st_epoll_pollset_del (pq -> pds , pq -> npds );
1380+ if ( notify ) {
1381+ _st_epoll_pollq_del ( pq );
1382+ ST_REMOVE_LINK (& pq -> links );
1383+ pq -> on_ioq = 0 ;
1384+ /*
1385+ * Here we will only delete/modify descriptors that
1386+ * didn't fire (see comments in _st_epoll_pollset_del()).
1387+ */
1388+ _st_epoll_pollset_del (pq -> pds , pq -> npds );
12851389
1286- if (pq -> thread -> flags & _ST_FL_ON_SLEEPQ )
1287- _ST_DEL_SLEEPQ (pq -> thread );
1288- pq -> thread -> state = _ST_ST_RUNNABLE ;
1289- _ST_ADD_RUNQ (pq -> thread );
1390+ if (pq -> thread -> flags & _ST_FL_ON_SLEEPQ )
1391+ _ST_DEL_SLEEPQ (pq -> thread );
1392+ pq -> thread -> state = _ST_ST_RUNNABLE ;
1393+ _ST_ADD_RUNQ (pq -> thread );
1394+ }
12901395 }
12911396 }
12921397
@@ -1353,7 +1458,9 @@ static _st_eventsys_t _st_epoll_eventsys = {
13531458 _st_epoll_pollset_del ,
13541459 _st_epoll_fd_new ,
13551460 _st_epoll_fd_close ,
1356- _st_epoll_fd_getlimit
1461+ _st_epoll_fd_getlimit ,
1462+ _st_epoll_pollq_add ,
1463+ _st_epoll_pollq_del
13571464};
13581465#endif /* MD_HAVE_EPOLL */
13591466
0 commit comments