Project

General

Profile

Feature #8788 ยป tt_efd_v2.patch

normalperson (Eric Wong), 07/08/2014 10:38 PM

View differences:

configure.in
1145 1145
  intrinsics.h \
1146 1146
  langinfo.h \
1147 1147
  locale.h \
1148
  sys/eventfd.h \
1148 1149
  sys/sendfile.h \
1149 1150
  time.h \
1150 1151
  net/socket.h \
......
1980 1981
AC_CHECK_FUNCS(dup3)
1981 1982
AC_CHECK_FUNCS(eaccess)
1982 1983
AC_CHECK_FUNCS(endgrent)
1984
AC_CHECK_FUNCS(eventfd)
1983 1985
AC_CHECK_FUNCS(fchmod)
1984 1986
AC_CHECK_FUNCS(fchown)
1985 1987
AC_CHECK_FUNCS(fcntl)
thread_pthread.c
1225 1225
#define TIME_QUANTUM_USEC (100 * 1000)
1226 1226

  
1227 1227
#if USE_SLEEPY_TIMER_THREAD
1228
static ssize_t
1229
tt_pipe_write(int fd)
1230
{
1231
    return write(fd, "!", 1);
1232
}
1233

  
1234
static ssize_t
1235
tt_pipe_read(int fd)
1236
{
1237
#define CCP_READ_BUFF_SIZE 1024
1238
    /* buffer can be shared because no one refers to them. */
1239
    static char buff[CCP_READ_BUFF_SIZE];
1240
    return read(fd, buff, sizeof(buff));
1241
}
1242

  
1243
struct tt_wakeup_impl {
1244
    ssize_t (*tt_write)(int fd);
1245
    ssize_t (*tt_read)(int fd);
1246
};
1247

  
1248
struct tt_wakeup_impl *ttwup;
1249
struct tt_wakeup_impl tt_pipe = { tt_pipe_write, tt_pipe_read };
1250

  
1228 1251
static struct {
1229 1252
    int normal[2];
1230 1253
    int low[2];
......
1242 1265

  
1243 1266
    /* already opened */
1244 1267
    if (timer_thread_pipe.owner_process == getpid()) {
1245
	const char *buff = "!";
1246 1268
      retry:
1247
	if ((result = write(fd, buff, 1)) <= 0) {
1269
	if ((result = ttwup->tt_write(fd)) <= 0) {
1248 1270
	    int e = errno;
1249 1271
	    switch (e) {
1250 1272
	      case EINTR: goto retry;
......
1280 1302
static void
1281 1303
consume_communication_pipe(int fd)
1282 1304
{
1283
#define CCP_READ_BUFF_SIZE 1024
1284
    /* buffer can be shared because no one refers to them. */
1285
    static char buff[CCP_READ_BUFF_SIZE];
1286 1305
    ssize_t result;
1287 1306

  
1288 1307
    while (1) {
1289
	result = read(fd, buff, sizeof(buff));
1308
	result = ttwup->tt_read(fd);
1290 1309
	if (result == 0) {
1291 1310
	    return;
1292 1311
	}
......
1313 1332
    if (close(pipes[0]) < 0) {
1314 1333
	rb_bug_errno("native_stop_timer_thread - close(ttp[0])", errno);
1315 1334
    }
1316
    if (close(pipes[1]) < 0) {
1335
    if ((pipes[0] != pipes[1]) && (close(pipes[1]) < 0)) {
1317 1336
	rb_bug_errno("native_stop_timer_thread - close(ttp[1])", errno);
1318 1337
    }
1319 1338
    pipes[0] = pipes[1] = -1;
......
1354 1373
    set_nonblock(pipes[1]);
1355 1374
}
1356 1375

  
1376
#if defined(HAVE_EVENTFD) && defined(HAVE_SYS_EVENTFD_H)
1377
#  include <sys/eventfd.h>
1378
static ssize_t tt_efd_write(int fd)
1379
{
1380
    static const uint64_t buf = 1;
1381

  
1382
    return write(fd, &buf, sizeof(buf));
1383
}
1384

  
1385
static ssize_t tt_efd_read(int fd)
1386
{
1387
    uint64_t buf;
1388

  
1389
    return read(fd, &buf, sizeof(buf));
1390
}
1391

  
1392
struct tt_wakeup_impl tt_efd = { tt_efd_write, tt_efd_read };
1393

  
1394
/*
1395
 * eventfd appeared in 2.6.22, but only gained EFD_CLOEXEC/NONBLOCK support
1396
 * in 2.6.27, so we must take care of systems having new headers but
1397
 * run on old kernels
1398
 */
1399
#  if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
1400
#    define TT_EFD_FLAGS (EFD_CLOEXEC|EFD_NONBLOCK)
1401
#  else
1402
#    define TT_EFD_FLAGS (0)
1403
#  endif
1404
static int
1405
efd_pair(int fds[2])
1406
{
1407
    static int efd_flags = TT_EFD_FLAGS;
1408
    int fd;
1409

  
1410
    /* close eventfd of parent process */
1411
    if (fds[0] >= 0)
1412
	close_communication_pipe(fds);
1413

  
1414
    fd = eventfd(0, efd_flags);
1415
    if (fd < 0) {
1416
	int err = errno;
1417
	if (err == EINVAL && efd_flags != 0) { /* Linux 2.6.22 - 2.6.26 */
1418
	    efd_flags = 0; /* need manual fixup later */
1419
	    fd = eventfd(0, efd_flags);
1420
	    if (fd < 0)
1421
		return errno;
1422
	}
1423
	else {
1424
	    return err; /* ENOSYS, EMFILE, ENFILE, ENODEV or ENOMEM */
1425
	}
1426
    }
1427
    rb_update_max_fd(fd);
1428
    if (efd_flags == 0) { /* fixup for old kernels */
1429
	set_nonblock(fd);
1430
	rb_maygvl_fd_fix_cloexec(fd);
1431
    }
1432
    fds[0] = fds[1] = fd;
1433
    return 0;
1434
}
1435

  
1436
static int
1437
efd_setup(void)
1438
{
1439
    int err = efd_pair(timer_thread_pipe.normal);
1440

  
1441
    if (err) return err;
1442

  
1443
    err = efd_pair(timer_thread_pipe.low);
1444
    if (!err)
1445
	ttwup = &tt_efd; /* success! */
1446
    else
1447
	close_communication_pipe(timer_thread_pipe.normal);
1448

  
1449
    return err;
1450
}
1451
# else /* !HAVE_EVENTFD */
1452
static int
1453
efd_setup(void)
1454
{
1455
    return ENOSYS;
1456
}
1457
# endif /* !HAVE_EVENTFD */
1458

  
1357 1459
/* communication pipe with timer thread and signal handler */
1358 1460
static void
1359 1461
setup_communication_pipe(void)
......
1362 1464
	/* already set up. */
1363 1465
	return;
1364 1466
    }
1365
    setup_communication_pipe_internal(timer_thread_pipe.normal);
1366
    setup_communication_pipe_internal(timer_thread_pipe.low);
1467

  
1468
    if (efd_setup() != 0) {
1469
	setup_communication_pipe_internal(timer_thread_pipe.normal);
1470
	setup_communication_pipe_internal(timer_thread_pipe.low);
1471
	ttwup = &tt_pipe;
1472
    }
1367 1473

  
1368 1474
    /* validate pipe on this process */
1369 1475
    timer_thread_pipe.owner_process = getpid();
1370
-