Attempt to fix the issue 1147 does not seem to be working

8 views
Skip to first unread message

Waldek Kozaczuk

unread,
Jun 19, 2021, 1:45:38 AM6/19/21
to OSv Development
For whatever reason this patch does not work and tst-async.cc fails like below:

diff --git a/linux.cc b/linux.cc
index 522ed8ba..d91feb89 100644
--- a/linux.cc
+++ b/linux.cc
@@ -62,23 +62,37 @@ static mutex queues_mutex;
 enum {
     FUTEX_WAIT           = 0,
     FUTEX_WAKE           = 1,
+    FUTEX_WAIT_BITSET    = 9,
     FUTEX_PRIVATE_FLAG   = 128,
     FUTEX_CLOCK_REALTIME = 256,
     FUTEX_CMD_MASK       = ~(FUTEX_PRIVATE_FLAG|FUTEX_CLOCK_REALTIME),
 };
 
+#define FUTEX_BITSET_MATCH_ANY  0xffffffff
+
 int futex(int *uaddr, int op, int val, const struct timespec *timeout,
-        int *uaddr2, int val3)
+        int *uaddr2, uint32_t val3)
 {
     switch (op & FUTEX_CMD_MASK) {
+    case FUTEX_WAIT_BITSET:
+        if (val3 != FUTEX_BITSET_MATCH_ANY) {
+            abort("Unimplemented futex() operation %d\n", op);
+        }
+
     case FUTEX_WAIT:
         WITH_LOCK(queues_mutex) {
             if (*uaddr == val) {
                 waitqueue &q = queues[uaddr];
                 if (timeout) {
                     sched::timer tmr(*sched::thread::current());
-                    tmr.set(std::chrono::seconds(timeout->tv_sec) +
-                            std::chrono::nanoseconds(timeout->tv_nsec));
+                    if ((op & FUTEX_CMD_MASK) == FUTEX_WAIT_BITSET) {
+                        osv::clock::wall::time_point abs_time(std::chrono::seconds(timeout->tv_sec) +
+                                                              std::chrono::nanoseconds(timeout->tv_nsec));
+                        tmr.set(abs_time);
+                    } else {
+                        tmr.set(std::chrono::seconds(timeout->tv_sec) +
                                std::chrono::nanoseconds(timeout->tv_nsec));
+                    }
                     sched::thread::wait_for(queues_mutex, tmr, q);
                     // FIXME: testing if tmr was expired isn't quite right -
                     // we could have had both a wakeup and timer expiration
@@ -403,7 +417,7 @@ long syscall(long number, ...)
     SYSCALL0(gettid);
     SYSCALL2(clock_gettime, clockid_t, struct timespec *);
     SYSCALL2(clock_getres, clockid_t, struct timespec *);
-    SYSCALL6(futex, int *, int, int, const struct timespec *, int *, int);
+    SYSCALL6(futex, int *, int, int, const struct timespec *, int *, uint32_t);
     SYSCALL1(close, int);
     SYSCALL2(pipe2, int *, int);
     SYSCALL1(epoll_create1, int);

./scripts/run.py -e '/tests/tst-async.so'
OSv v0.55.0-285-g660345d5
eth0: 192.168.122.15
Booted up in 259.57 ms
Cmdline: /tests/tst-async.so
Running 18 test cases...
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_one_shot_task_fires_soon": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_async_task_fires": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_async_task_can_be_reprogrammed_while_armed": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_async_task_can_be_reprogrammed_after_cancelled": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_desctructor_does_not_block_when_called_after_task_is_done": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_destructor_waits_for_callback_to_finish": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_async_task_can_be_reprogrammed_after_done": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_async_task_can_be_reprogrammed_from_the_callback": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_destructor_waits_for_callbacks_which_have_rescheduled_themselves": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_a_task_which_is_set_far_in_future_does_not_block_new_task": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_task_which_is_scheduled_second_but_with_sooner_expiration_time_fires_first": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_timers_with_same_expiration_time_fire_separately": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
/git-repos/osv/tests/tst-async.cc(24): fatal error: in "test_serial_timer__cancel_sync_waits_for_callback": critical check promise.get_future().wait_for(duration) == std::future_status::ready has failed
Assertion failed: _n_scheduled == 0 (core/async.cc: ~serial_timer_task: 386)

[backtrace]
0x00000000402382a8 <__assert_fail+24>
0x000000004042736c <async::serial_timer_task::~serial_timer_task()+44>
0x000010000000c6f8 <???+50936>
0x0000100000019b26 <???+105254>
0x00000000408a278f <vtable for std::basic_streambuf<char, std::char_traits<char> >+15>

What is interesting if I set relative timer for FUTEX_WAIT_BITSET instead of the absolute one as the spec demands, the test passes.

What am I doing wrong?

Waldek

Waldek Kozaczuk

unread,
Jun 20, 2021, 11:40:33 AM6/20/21
to OSv Development
I think I have found the culprit. We have to check the futex operation flag that specify which clock to use. 

       FUTEX_CLOCK_REALTIME (since Linux 2.6.28)
              This option bit can be employed only with the
              FUTEX_WAIT_BITSET, FUTEX_WAIT_REQUEUE_PI, and (since Linux
              4.5) FUTEX_WAIT operations.

              If this option is set, the kernel measures the timeout
              against the CLOCK_REALTIME clock.

              If this option is not set, the kernel measures the timeout
              against the CLOCK_MONOTONIC clock.”

In our case the FUTEX_REAL_TIME is not set so if I change my code to use mono tonic clocks, all works. 

Waldek
--
You received this message because you are subscribed to a topic in the Google Groups "OSv Development" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/osv-dev/ktzFAJFxbs4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to osv-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/bb0272e8-0864-47d8-adc7-b43ada1af0f4n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages