Browse Source

Futex bugfixes (may help #40), more enhancements to LTP framework.

Don Porter 7 years ago
parent
commit
872af4984c

+ 1 - 1
LibOS/buildglibc.py

@@ -135,9 +135,9 @@ link_binaries     = [ ( 'elf',    'ld-linux-x86-64.so.2' ),
                       ( 'csu',    'crt1.o' ),
                       ( 'csu',    'crti.o' ),
                       ( 'csu',    'crtn.o' ),
+                      ( 'rt',     'librt.so.1' ),
                       ( 'libos',  'liblibos.so.1' ) ]
 
-
 if not do_install:
 
     for (dir, bin) in link_binaries:

+ 7 - 4
LibOS/shim/include/shim_thread.h

@@ -206,18 +206,21 @@ static inline void thread_setwait (struct shim_thread ** queue,
         *queue = thread;
 }
 
-static inline void thread_sleep (void)
+static inline int thread_sleep (uint64_t timeout_us)
 {
     struct shim_thread * cur_thread = get_cur_thread();
 
     if (!cur_thread)
-        return;
+        return -EINVAL;
 
     PAL_HANDLE event = cur_thread->scheduler_event;
     if (!event)
-        return;
+        return -EINVAL;
+
+    if ( NULL == DkObjectsWaitAny(1, &event, timeout_us))
+        return -PAL_ERRNO;
 
-    DkObjectsWaitAny(1, &event, NO_TIMEOUT);
+    return 0;
 }
 
 static inline void thread_wakeup (struct shim_thread * thread)

+ 1 - 1
LibOS/shim/src/ipc/shim_ipc.c

@@ -460,7 +460,7 @@ int do_ipc_duplex (struct shim_ipc_msg_obj * msg,
         goto out;
 
     debug("wait for response (seq = %lu)\n", msg->msg.seq);
-    thread_sleep();
+    thread_sleep(NO_TIMEOUT);
 
     ret = msg->retval;
 out:

+ 1 - 1
LibOS/shim/src/ipc/shim_ipc_pid.c

@@ -777,7 +777,7 @@ int get_rpc_msg (IDTYPE * sender, void * buf, int len)
     thread_setwait(&r->thread, NULL);
     list_add_tail(&r->list, &rpc_reqs);
     unlock(rpc_queue_lock);
-    thread_sleep();
+    thread_sleep(NO_TIMEOUT);
     put_thread(r->thread);
     if (sender)
         *sender = r->sender;

+ 26 - 4
LibOS/shim/src/sys/shim_futex.c

@@ -128,8 +128,10 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
         case FUTEX_WAIT_BITSET: {
             uint32_t bitset = (futex_op == FUTEX_WAIT_BITSET) ? val3 :
                               0xffffffff;
-            debug("FUTEX_WAIT: %p (val = %d) vs %d mask = %08x\n",
-                  uaddr, *uaddr, val, bitset);
+            uint64_t timeout_us = NO_TIMEOUT;
+            
+            debug("FUTEX_WAIT: %p (val = %d) vs %d mask = %08x, timeout ptr %p\n",
+                  uaddr, *uaddr, val, bitset, utime);
 
             if (*uaddr != val) {
                 ret = -EAGAIN;
@@ -139,11 +141,31 @@ int shim_do_futex (unsigned int * uaddr, int op, int val, void * utime,
             struct futex_waiter waiter;
             thread_setwait(&waiter.thread, NULL);
             INIT_LIST_HEAD(&waiter.list);
-            waiter.bitset = (futex_op == FUTEX_WAIT_BITSET) ? val3 : 0xffffffff;
+            waiter.bitset = bitset;
             list_add_tail(&waiter.list, &futex->waiters);
 
             unlock(hdl->lock);
-            thread_sleep();
+            if (utime) {
+                struct timespec *ts = (struct timespec*) utime;
+                // Round to microsecs
+                timeout_us = (ts->tv_sec * 1000000) + (ts->tv_nsec / 1000);
+                // Check for the CLOCK_REALTIME flag
+                if (futex_op == FUTEX_WAIT_BITSET)  {
+                    // DEP 1/28/17: Should really differentiate clocks, but
+                    // Graphene only has one for now.
+                    //&& 0 != (op & FUTEX_CLOCK_REALTIME)) {
+                    uint64_t current_time = DkSystemTimeQuery();
+                    if (current_time == 0) {
+                        ret = -EINVAL;
+                        break;
+                    }
+                    timeout_us -= current_time;
+                }
+            }
+            ret = thread_sleep(timeout_us);
+            /* DEP 1/28/17: Should return ETIMEDOUT, not EAGAIN, on timeout. */
+            if (ret == -EAGAIN)
+                ret = -ETIMEDOUT;
             lock(hdl->lock);
             break;
         }

+ 1 - 1
LibOS/shim/src/sys/shim_sigaction.c

@@ -152,7 +152,7 @@ int shim_do_sigsuspend (const __sigset_t * mask)
     set_sig_mask(cur, mask);
     cur->suspend_on_signal = true;
     thread_setwait(NULL, NULL);
-    thread_sleep();
+    thread_sleep(NO_TIMEOUT);
 out:
     unlock(cur->lock);
     set_sig_mask(cur, old);

+ 1 - 1
LibOS/shim/test/Makefile

@@ -5,7 +5,7 @@ export SYS
 
 PALDIR  = $(level)../../../Pal/src
 SHIMDIR = $(level)../src
-LIBCDIR = $(level)../../glibc-build
+LIBCDIR = $(level)../../../Runtime
 
 CC = gcc
 CXX = g++

+ 58 - 2
LibOS/shim/test/apps/ltp/BLOCKED

@@ -1,3 +1,61 @@
+chdir01
+chdir04
+epoll_wait01
+fcntl15
+fcntl15_64
+flock03
+fork07
+fork08
+inotify06
+fanotify06
+linkat01
+lseek10
+mkdir01
+mkdir09
+mknod03
+mknod08
+mount05
+mremap01
+msgctl07
+msgrcv03
+msgrcv04
+msgrcv06
+open12
+open14
+openat01
+openat03
+pselect02
+pselect02_64
+pwrite02
+pwrite02_64
+readdir02
+readv02
+readv03
+rename04
+rename14
+rmdir05
+rt_sigaction02
+rt_sigprocmask02
+rt_sigqueueinfo01
+semctl03
+semctl06
+semop03
+sendfile04
+sendfile04_64
+sendmsg02
+setpgid03
+sighold02
+sigrelse01
+stat06
+stat06_64
+times03
+truncate02
+truncate02_64
+unlink07
+unlink08
+waitid02
+writev02
+writev05
 getresuid02
 getresuid03
 epoll-ltp
@@ -32,5 +90,3 @@ signal01
 trace05
 uname02
 waitpid04
-futex_wait01
-futex_wake02

+ 7 - 0
LibOS/shim/test/apps/ltp/PASSED

@@ -110,14 +110,21 @@ ftruncate02,1
 ftruncate02_64,1
 ftruncate03,3
 ftruncate03_64,3
+futex_wait01,1
+futex_wait01,2
+futex_wait01,3
+futex_wait01,4
 futex_wait03,1
 futex_wait04,1
+futex_wait05,1
 futex_wake01,1
 futex_wake01,2
 futex_wake01,3
 futex_wake01,4
 futex_wake01,5
 futex_wake01,6
+futex_wait_bitset01,1
+futex_wait_bitset02,1
 getcontext01,1
 getdents02,1
 getdents02,2

+ 2 - 3
LibOS/shim/test/apps/ltp/README

@@ -21,9 +21,8 @@ Results are of 4 types :
 [Broken] -> Either system call is not implemented in Graphene or test preparation failed
 
 To run one particular testcase, execute following :
-1) cd LibOS/shim/test/native
-2) ./pal <ltp-repo>/ltp/testcases/kernel/syscalls/alarm/alarm01
+ ~/Runtime/pal <ltp-repo>/opt/ltp/testcases/bin/<test>
 
-In this way, one can debug one particular syscall testcase, 'alarm01' in this case.
+In this way, one can debug one particular syscall testcase.
 
 As you fix bugs, keep updating PASSED BLOCKED lists.

+ 11 - 4
LibOS/shim/test/apps/ltp/fetch.py

@@ -38,6 +38,7 @@ class RunCmd(threading.Thread):
             del self.p
 
         if (finish):
+            reported = False
             name.seek(0)
             for output in name.readlines():
                 toks = output.split()
@@ -45,7 +46,7 @@ class RunCmd(threading.Thread):
                     continue
                 test_subtest = self.test + "," + toks[1]
                 self.test_subtest = test_subtest
-                if "TINFO" in output or test_subtest in current_passed or test_subtest in current_failed or self.test in current_hanged or test_subtest in current_blocked:
+                if "TINFO" in output or test_subtest in current_passed or test_subtest in current_failed or self.test in current_hanged or test_subtest in current_broken:
                     continue
                 if output:
                     output = output.strip()
@@ -54,17 +55,23 @@ class RunCmd(threading.Thread):
                     print >>failed_tests_fh, test_subtest
                     print CRED + "[Fail   ] " + test_subtest + CEND
                     current_failed[test_subtest] = 1
+                    reported = True
                 elif "TPASS" in output:
                     print >>passed_tests_fh, test_subtest
                     print CGREEN + "[Pass   ] " + test_subtest + CEND
                     current_passed[test_subtest] = 1
+                    reported = True
                 elif "TCONF" in output or "TBROK" in output or "error" in output:
                     print >>broken_tests_fh, test_subtest
                     print "[Broken ] " + test_subtest      #Syscall not implemented or test preparation failed
-                    current_blocked[test_subtest] = 1
+                    current_broken[test_subtest] = 1
+                    reported = True
             #else:
             #    print "[Broken ] " + self.test      #Syscall not implemented or test preparation failed
-
+            if (not reported):
+                print >>broken_tests_fh, self.test
+                print CRED + "[Broken ] " + self.test + CEND
+                current_broken[self.test] = 1
     def Run(self):
         self.start()
         self.join()
@@ -92,7 +99,7 @@ broken_tests_fh.write("Test,Subtest number,Status\n")
 
 current_passed = dict()
 current_failed = dict()
-current_blocked = dict()
+current_broken = dict()
 current_hanged = dict()
 timeouts_dict = dict()
 

+ 1 - 1
LibOS/shim/test/native/Makefile

@@ -9,7 +9,7 @@ target = $(exec_target) $(manifests) pal
 level = ../
 include ../Makefile
 
-CFLAGS-libos = -I$(SHIMDIR)/../include -L$(LIBCDIR)/libos
+CFLAGS-libos = -I$(SHIMDIR)/../include -L$(SHIMDIR)/../../glibc-build/libos
 
 ifeq ($(SYS),x86_64-linux-gnu)
 $(c_executables): %: %.c