@@ -119,6 +119,12 @@ typedef struct _epoll_fd_data {
119
119
int wr_ref_cnt ;
120
120
int ex_ref_cnt ;
121
121
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 ;
122
128
} _epoll_fd_data_t ;
123
129
124
130
static struct _st_epolldata {
@@ -1194,16 +1200,97 @@ ST_HIDDEN int _st_epoll_pollset_add(struct pollfd *pds, int npds)
1194
1200
return 0 ;
1195
1201
}
1196
1202
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
+
1197
1282
ST_HIDDEN void _st_epoll_dispatch (void )
1198
1283
{
1199
1284
st_utime_t min_timeout ;
1200
1285
_st_clist_t * q ;
1201
1286
_st_pollq_t * pq ;
1202
1287
struct pollfd * pds , * epds ;
1203
1288
struct epoll_event ev ;
1204
- int timeout , nfd , i , osfd , notify ;
1289
+ int timeout , nfd , i , j , osfd , notify ;
1205
1290
int events , op ;
1206
1291
short revents ;
1292
+ _epoll_fd_data_t * efd ;
1293
+ _st_pollq_t * * pqs ;
1207
1294
1208
1295
if (_ST_SLEEPQ == NULL ) {
1209
1296
timeout = -1 ;
@@ -1224,7 +1311,10 @@ ST_HIDDEN void _st_epoll_dispatch(void)
1224
1311
_st_epoll_data -> pid = getpid ();
1225
1312
1226
1313
/* 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
+ }
1228
1318
_st_epoll_data -> evtlist_cnt = 0 ;
1229
1319
for (q = _ST_IOQ .next ; q != & _ST_IOQ ; q = q -> next ) {
1230
1320
pq = _ST_POLLQUEUE_PTR (q );
@@ -1245,48 +1335,63 @@ ST_HIDDEN void _st_epoll_dispatch(void)
1245
1335
}
1246
1336
}
1247
1337
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 )
1256
1349
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 ;
1271
1352
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
+ }
1275
1379
}
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 );
1285
1389
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
+ }
1290
1395
}
1291
1396
}
1292
1397
@@ -1353,7 +1458,9 @@ static _st_eventsys_t _st_epoll_eventsys = {
1353
1458
_st_epoll_pollset_del ,
1354
1459
_st_epoll_fd_new ,
1355
1460
_st_epoll_fd_close ,
1356
- _st_epoll_fd_getlimit
1461
+ _st_epoll_fd_getlimit ,
1462
+ _st_epoll_pollq_add ,
1463
+ _st_epoll_pollq_del
1357
1464
};
1358
1465
#endif /* MD_HAVE_EPOLL */
1359
1466
0 commit comments