Skip to content
Snippets Groups Projects
  1. Jun 19, 2013
    • Nadav Har'El's avatar
      sched::thread: wake_with() to wake a wait_until() · f99c5ccc
      Nadav Har'El authored
      When we use wait_until(), e.g.,
      
              wait_until([&] { return *x == 0; })
      
      We used (in a bunch of places in the code, including condvar) the
      following "obvious" idiom to wake it up:
      
              *x = 0;
              t->wake();
      
      This does the right thing in *almost* all situations. But there's still
      one rare (but very possible) scenario where this is wrong. The problem is
      that the first line (*x = 0) may already cause the wait_until to return.
      This can happen when wait_until didn't yet check the condition, or if it
      was sleeping and by rare coincidence, got woken up by a spurious interrupt
      at the same time we did *x = 0. Now, consider the case that the waiting
      thread decides to exit after the wait_until... So the "*x = 0" causes the
      thread to exit, and when we want to do "t->wake()" the thread no longer
      exists, and the statement crashes.
      
      This patch adds two new thread methods: t->ref() increments a counter
      preventing a thread's destruction, until a matching t->unref().
      With these methods, the correct way to wake the above wait_until() is:
      
              t->ref();
              *x = 0;
              t->wake();
              t->unref();
      
      This patch also adds a one-line shortcut to the above 4 lines, with syntax
      mirroring that of wait_until:
      
              t->wake_with([&] { *x = 0; });
      
      The ref()/unref() methods are marked private, to encourage the use of
      wake_with(), and also to allow wake_with() in the future to be optimized
      to avoid calling ref()/unref() when not needed. For example, when the thread
      is on the same CPU as the current thread, merely disabling preemption (a
      very fast operation) prevents the thread from running - and exiting - and
      ref()/unref() are not necessary.
      
      Unfortunately, while this patch solves one bug, it does not solve two
      additional bugs that existed before, and continue to exist after this
      patch:
      
      1. When a thread completes (see thread::complete()) it wakes a thread
         waiting on join() (if there is one) and this join() deletes the thread
         and its stack. The problem is that if the timing is right (or wrong ;-)),
         the joiner thread may delete the stack while complete() is still
         running on this stack, and can cause a crash.
      
      2. If join() races with the thread's completion, it is possible that
         the thread thinks nobody is waiting for it so notifies nobody, but
         at the same time join() starts to wait, and will never be woken up.
      
      Added two "FIXME" about these remaining bugs.
      f99c5ccc
    • Nadav Har'El's avatar
      Don't crash on lseek() of non-regular file · 0c8ef37c
      Nadav Har'El authored
      lseek() crashes when used on pipes, sockets, and now also fd 0, 1 or 2
      (the console), because they don't have an underlying vnode. No reason
      to assert() in this case, should just return ESPIPE (like Linux does
      for pipes, sockets and ttys).
      
      Similarly, fsync, readdir and friends, fchdir and fstatfs shouldn't
      crash if given a fd without a vnode, and rather should return the
      expected error.
      0c8ef37c
    • Nadav Har'El's avatar
      Fix concurrent console read and write bug · 907e6336
      Nadav Har'El authored
      We had a bug where a read() on the console (fd 0) would block writes to
      the console (fd 1 or 2). This was most noticable when background threads
      in the CLI tried to write output, and were blocked until the next keypress
      because the blocking read() would lock the writes out.
      
      The bug happens because we opened the console using open("/dev/console")
      and dup()'ed the resulting fd, but this results, in the current code, in
      every read and write to these file descriptors to pass through vfs_read()/
      vfs_write(), which lock a single vnode lock for all three file descriptors -
      leading to write on fd 1 blocking while read is ongoing on fd 0.
      
      This patch doesn't fix this vnode lock issue, which remains - and should
      be fixed when the devfs or vfs layers are rewritten. Instead, this patch
      adds a *second API* for opening a console which doesn't go through the
      vnode or devfs layers:
      
      A new console::open() function returns a file descriptor which implements
      the correct file operations, and is not associated with any vnode.
      
      The new implementation works well with write() while read() is ongoing.
      
      Note that poll() support was missing from the old implementation (it
      seems it can't be done with the vnode abstraction?) and is still missing
      in the new implementation, although now shouldn't be hard to add
      (need to implement the poll fileops, and to use poll_wake() in the
      line-discipline function console_poll).
      907e6336
    • Avi Kivity's avatar
      cli: fix tab completion · 79a89f95
      Avi Kivity authored
      tab completion relies on a global 'ls' object, re-add it.
      
      Broken by 4bfe157b.
      79a89f95
    • Nadav Har'El's avatar
      Add unsupported_poll · 29652e61
      Nadav Har'El authored
      Sorry, missing unsupported_poll broke compilation after the previous patch
      29652e61
    • Nadav Har'El's avatar
      Temporary, inefficient, epoll implementation · ad26fb4b
      Nadav Har'El authored
      This is an epoll_*() implementation which calls poll() to do the real work.
      This is of course a terrible implementation, which makes epoll() less
      efficient, instead of more efficient, then poll(). However, it allows me
      to progress with running Jetty in parallel with perfecting epoll.
      ad26fb4b
    • Nadav Har'El's avatar
      Add todo/dns · 15386921
      Nadav Har'El authored
      It's not clear if our DNS resolver works or not - need to test and fix
      if needed.
      15386921
    • Nadav Har'El's avatar
      BSD porting: implement mtx_assert() · 1b9a3b5b
      Nadav Har'El authored
      Trivially implement mtx_assert(). This would catch the "ifconfig" bug
      fixed in the previous patch - where ifconfig called sofree() without
      the accept lock.
      1b9a3b5b
    • Nadav Har'El's avatar
      Fix "ifconfig" corrupting accept_mtx · 073d9ea7
      Nadav Har'El authored
      ifconfig used to call sofree(), which assumed accept_mtx was taken, which
      wasn't true, resulting in either an assertion failure (if we implement
      assert_mtx - see next patch) or a mutex corruption (if assert_mtx does
      nothing).
      
      Instead, we should call soclose(). This wasn't very hard to figure out,
      given the comment in socreate() saying "The socket should be closed with
      soclose()." :-)
      073d9ea7
  2. Jun 18, 2013
  3. Jun 17, 2013
    • Avi Kivity's avatar
      cli: don't import java.lang · e5e4e1b7
      Avi Kivity authored
      java.lang.Math will override JavaScript's Math object.
      e5e4e1b7
    • Avi Kivity's avatar
      java: add tracepoint interface class · 29a4b2dd
      Avi Kivity authored
      Exposes tracepoints and counters
      29a4b2dd
    • Avi Kivity's avatar
      trace: add probe functions · e58366ac
      Avi Kivity authored
      Add a facility to run functions when a tracepoint is hit.  This is independent
      of logging; you can add a probe function with logging disabled or enabled.
      e58366ac
    • Avi Kivity's avatar
      percpu: add allocatable per-cpu counters · 43ded08d
      Avi Kivity authored
      43ded08d
    • Avi Kivity's avatar
      kvmclock: make per-cpu · d0c2b805
      Avi Kivity authored
      The kvmclock ABI requires it to calculate system time using values for the cpu
      it is running on.
      
      Do this by:
        - changing the system time structure to be per-cpu
        - adding a cpu notifier so that per-cpu MSRs are initialized for each cpu
        - hacking around initialization order issues
      d0c2b805
    • Avi Kivity's avatar
      sched: add cpu notifiers · 26a9fd2f
      Avi Kivity authored
      cpu notifiers are called whenever a cpu is brought up (and one day, down), so
      that drivers that manage the cpu (for example, kvmclock) can initialize
      themselves.
      
      The callback is called on the cpu that is being brought up.
      26a9fd2f
    • Avi Kivity's avatar
      percpu: per-cpu variables · 63ab89b6
      Avi Kivity authored
      Per-cpu variables can be used from contexts where preemption is disabled
      (such as interrupts) or when migration is impossible (pinned threads) for
      managing data that is replicated for each cpu.
      
      The API is a smart pointer to a variable which resolves to the object's
      location on the current cpu.
      
      Define:
      
         #include <osv/percpu.hh>
      
         PERCPU(int, my_counter);
         PERCPU(foo, my_foo);
      
      Use:
      
         ++*my_counter;
         my_foo->member = 7;
      63ab89b6
    • Guy Zana's avatar
      msleep: switch debug messages to tracepoints · 401e14e5
      Guy Zana authored
      401e14e5
Loading