3 years agoparlib: Tease out uth_sync_t from has_blocked()
Barret Rhoden [Fri, 28 Apr 2017 16:05:29 +0000 (12:05 -0400)]
parlib: Tease out uth_sync_t from has_blocked()

Some callers of uthread_has_blocked() might want to separate the blocking
on the sync from the notification to the 2LS - even though both of those
are 2LS ops.

The specific case is pthread_barriers (in an upcoming patch).  There, we
have an optimization where we don't hold the spinlock across
uthread_yield(), and instead reacquire it and double-check if we should
block.  In that case, we'd rather call the 2LS has_blocked *before*
grabbing the barrier's spinlock (> 25% performance improvement).  Other
sync primitives might want to do the same.

Overall, this is probably a better fit - it removes those has_blocked cases
that take NULL and provides a little more flexibility to the sync primitive
code.  It also gets rid of the slightly ugly __uth_default_sync_enqueue()
and provides a nicer sync object interface.  The downside is that the 2LS
gets its has_blocked info independent of the source of the blocking.
Probably doesn't matter.

Similar to the commit 'Make sync objects static', I considered rebasing
this change, but I didn't want to break git bisect or otherwise introduce
hard-to-debug problems, which I've already had a few of due to the
toolchain changes.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agopthread: Reimplement mutexes, CVs, and RW locks (XCC)
Barret Rhoden [Thu, 27 Apr 2017 19:19:13 +0000 (15:19 -0400)]
pthread: Reimplement mutexes, CVs, and RW locks (XCC)

Pthreads had its own older code.  Now, we just use the uthread code.  It's
mostly straightforward, except that pthread mutexes have a type that
determines whether or not they are recursive or not.

I also moved some of the older support code around, like spin_to_sleep().
That's still used by the barrier code.

If applications want to spin before sleeping on mutexes (adaptive mutex /
brewtexes), they can use their own primitives.  On a related note, if your
context switch overhead is lower, then lure of spinning isn't as strong,
and spinning deprives the 2LS of a scheduling opportunity.

Rebuild your toolchain.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Make uth mutex/CV initializers C++ safe (XCC)
Barret Rhoden [Thu, 27 Apr 2017 19:11:53 +0000 (15:11 -0400)]
parlib: Make uth mutex/CV initializers C++ safe (XCC)

GCC C++ can't handle { { .field = value } }.  It can handle one {}, but not
two.  C doesn't have this problem.  The issue comes up when someone does
something like:

struct my_struct {
uth_mutex_t foo;

icu does this with their umutex.h implementation.  There it is for

For us, we can get away with the non-specific initializers, so long as we
put the parlib_once_t first.

Rebuild your toolchain.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add a rwlock test
Barret Rhoden [Thu, 27 Apr 2017 16:30:50 +0000 (12:30 -0400)]
parlib: Add a rwlock test

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoOverhaul glibc locking (XCC)
Barret Rhoden [Wed, 26 Apr 2017 19:18:49 +0000 (15:18 -0400)]
Overhaul glibc locking (XCC)

Previously, we were using the low-level locks (spin_pdr_locks) for almost
everything in glibc.  The libc_lock was a spinlock, etc.  It turns out, the
libc_lock is supposed to be a mutex.

I had a couple cases where the app would yield while holding a libc_lock,
which you cannot do if it is a spinlock.  Specifically, this happened when
calling fclose() on a FILE (holding the old libc_lock), which closed the
underlying FD, when we were using epoll.  The epoll close callback grabs a
uthread mutex.  The fix is to make the libc_lock a uthread mutex too.  No
problem, right?

The problem was malloc was also using those locks, and vcore context calls
malloc and free.  Vcore context code cannot use mutexes.  So our options
were either never to call malloc or free from vcore context, or to use a
different type of lock.  So far, we can get by with malloc using
spin_pdr_locks (the low-level lock (LLL)).

This all does mean that vcore context code cannot call some things from
glibc, such as close(), printf(), or anything using the libc_lock (a
mutex), including the _IO_lock (which is now explicitly a libc_lock (mutex)
and not a spinlock).  Currently, that includes interprocess signal
handlers, which are run from vcore context.  fprintf() to stderr and stdout
will work, but some other signal-safe functions might not.  close() doesn't
work, not because of the libc_lock (fclose() grabs that, not close()), but
because of the close callbacks, which *do* grab mutexes.  And you can't
grab a mutex from vcore context.

There are a few other implications.  malloc() (using a spinlock) relies on
sbrk(), which previously was a libc_lock.  That now needs to be a spinlock.
It is possible for the kernel to block the mmap() call.  If that happens,
userspace will spin until the call completes.  Oh well.

I also sorted out the rtld locks.  Previously, we were doing nothing for
the recursive locks.  If we had threads racing in dlopen(), then we could
corrupt the various data structures in ld.  Yikes!  There might be issues
with those locks still.  I made them spinlocks, since we can't access
parlib objects at all in that code.  (We can access headers).

Now that rtld isn't using the libc_locks, we no longer have anyone calling
into parlib-compat.c's spinlocks, and we can replace that thread-unsafe
code with asserts.

There's probably a few problems with all of this still.  For instance,
maybe we an do something different for ld.so compared to libdl.so.  Who
knows.  At least it's a little better than before.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Make parlib printfs safe
Barret Rhoden [Tue, 25 Apr 2017 17:40:38 +0000 (13:40 -0400)]
parlib: Make parlib printfs safe

You can't call glibc's printf from certain contexts: notably vcore context
or when a uthread disabled notifications.  If you do, you'll grab a mutex
in glibc (the IO lock, which is changing in an upcoming patch), and we'll
panic - you can't block in those contexts.

But there's no need to manually call __vc_ctx_fprintf() - we can catch it
with a macro.  Yes, it's nasty.  And it works for both printf() and
fprintf(), but only for stdout and stderr streams.

Also, for this to work, any code that could be called from vcore context
should include parlib/stdio.h, not stdio.h.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoHave all asserts call parlib's assert (XCC)
Barret Rhoden [Tue, 25 Apr 2017 17:20:17 +0000 (13:20 -0400)]
Have all asserts call parlib's assert (XCC)

Now all calls to assert() will print the same info and have a backtrace,
regardless of whether or not you included parlib/assert.h.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Improve panic() and assert()
Barret Rhoden [Tue, 25 Apr 2017 16:29:51 +0000 (12:29 -0400)]
parlib: Improve panic() and assert()

Two things:
- Don't use printf() in panic/assert.  It will soon be illegal to use
  glibc's IO functions (including printf()) from vcore context.
- Force a backtrace on assert/panic.  Note this does not replace glibc's
  assert, so you'd have to #include <parlib/assert.h> to get it.  For now.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Set line buffering for stdout
Barret Rhoden [Mon, 24 Apr 2017 23:50:21 +0000 (19:50 -0400)]
parlib: Set line buffering for stdout

I don't know why this is necessary and not already done by glibc
internally.  I've triggered this a lot with some later patches, but I don't
see why.  I also recall people having problems with this before - Gan and
Ron might have had it back with the early VM work.

Similarly, this might be related to commit c074a35e7f17 ("BB: manually
writes echo's buffer").  Line buffering helped back then, but we also still
didn't get the errno/errstr back (according to the commit message).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Catch broken uses of notif_disabled_depth
Barret Rhoden [Tue, 25 Apr 2017 18:25:02 +0000 (14:25 -0400)]
parlib: Catch broken uses of notif_disabled_depth

Uthreads can disable notifs, such as when grabbing PDR locks, and then
yield to vcore context.  However, they can only do so if their yield
callback lets go of the lock.  At that point, we'll reenable their notifs.
It's broken to have notifs disabled while yielding under any other

Note that the spin_pdr_unlock() call, often made in the yield callback,
will not reenable notifs, since it is being called by vcore context - not
the original uthread that grabbed the lock.  Vcore context is unlocking on
behalf of the uthread.  This is the "atomically block and unlock" that is
the basis for all of the higher-level blocking sync primitives (e.g.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Catch illegal block attempts
Barret Rhoden [Mon, 24 Apr 2017 15:50:29 +0000 (11:50 -0400)]
parlib: Catch illegal block attempts

Without the assert, we can have some code that shouldn't block grab mutexes
and whatnot.  They could have blocked, but they didn't, and then we only
catch the bug in the constested case - rarer and harder to debug.

Now, we'll immediately panic if we try to do something wrong.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoFix a couple warnings in glibc (XCC)
Barret Rhoden [Thu, 20 Apr 2017 22:14:38 +0000 (18:14 -0400)]
Fix a couple warnings in glibc (XCC)

Rebuild glibc at your leisure.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoUse weak __thread declarations in parlib-compat (XCC)
Barret Rhoden [Thu, 20 Apr 2017 17:48:01 +0000 (13:48 -0400)]
Use weak __thread declarations in parlib-compat (XCC)

The weak_alias() macro doesn't work well with the __thread keyword.  We can
just do the weak attribute manually.  This pops up as a bug if we ever
include a header that has the real __thread declaration in parlib-compat.c.

Rebuild glibc at your leisure.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Have exactly one specific 2LS
Barret Rhoden [Wed, 3 May 2017 14:08:45 +0000 (10:08 -0400)]
parlib: Have exactly one specific 2LS

Processes in Akaros are given control over their cores, but with this
control comes a bootstrapping problem.  For very early code, such as ld.so
and parts of glibc, the kernel takes care of a few things.  This time is
referred to as "early-SCP context."  Eventually, the process is capable of
handling itself, and it takes over.

Previously, we would make the transition from the early-SCP to the thread0
scheduler, and then if a "real" 2LS (e.g. pthreads or vmm) was linked in,
it's constructor would switch us from thread0 to the real 2LS.

There's a bunch of problems with this.
- What's to stop you from having multiple 2LSs linked in, and then only the
  'last ctor wins'?
- It's very tricky to transition from thread0 to another 2LS.  We've had a
  bunch of bugs and tricky code related to races, blocking calls, and other
things during the transition.  Going from early-SCP to a 2LS is fine.  But
once the process has taken control, switching out schedulers is very
- If glibc (or any code, like a ctor) makes a 2LS op after thread0 is
  running, but before the next 2LS takes over, the object we're operating
on will get confused.  For instance, consider a sync object initialized for
thread0, but then locked while pthreads is the 2LS.  Pthreads would see a
sync object that it didn't initialize.

For all these reasons, and especially the latter, it's time to go back to
the older style of 2LS ops: there's a weak version of the sched ops, which
is thread0s.  That will be the default 2LS unless another one is used.  If
you link in another 2LS (e.g. pthreads or vmm), then that will take over.
This will also catch issues of linking in multiple 2LSs.

Now that we know the specific 2LS statically, uthread_lib_init() can call
the 2LS's initialization function.  Previously we were forcing the 2LS
ctors to make sure uthread code ran first, but there was actually nothing
making sure the 2LSs ctor ran first.  Imagine a ctor in your application
that uses the 2LS via the GCC/C++ threading.  ld or whatever can figure out
that it needs parlib and run parlib's ctors first.  But it won't know that
e.g. pthread's ctor needs to run.  Now, that's not a problem.  The
dependency is on GCC/C++ threads -> uthreads, and the implied dependency
from uthreads to the real 2LS is sorted out by calling the 2LS's

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Make sync objects static (XCC)
Barret Rhoden [Thu, 20 Apr 2017 13:49:35 +0000 (09:49 -0400)]
parlib: Make sync objects static (XCC)

It turns out that sync objects need to be statically allocated and capable
of initialization without malloc.  We're going to need to use uthread
mutexes for Glibc's locks (libc-lock.h), which get used for malloc.  Thus
we can't call back into malloc. (recursion).

Rebuild the world (especially GCC).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoRemove old tests and mhello
Barret Rhoden [Wed, 19 Apr 2017 21:17:32 +0000 (17:17 -0400)]
Remove old tests and mhello

The venerable mhello (and its lesser buddy mcp_halt) need to be retired.
Given the changes in uthread code, it's harder to fake being a 2LS without
implementing a 2LS, and it's not worth maintaining those programs.

Goodnight sweet prince.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Trim some header includes
Barret Rhoden [Tue, 18 Apr 2017 20:08:57 +0000 (16:08 -0400)]
parlib: Trim some header includes

Including stdio.h and to a lesser extent assert.h is a problem if we ever
include them transitively in glibc.  This happens if we include something
like uthread.h, which we'll likely need to fix glibc's libc-lock.h

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add reader-writer sleeping locks
Barret Rhoden [Fri, 14 Apr 2017 20:54:09 +0000 (16:54 -0400)]
parlib: Add reader-writer sleeping locks

Glibc needs these internally.  Someone else might find them useful, too.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoAdd a shared_ptr sanity check
Barret Rhoden [Fri, 14 Apr 2017 16:13:47 +0000 (12:13 -0400)]
Add a shared_ptr sanity check

This was an example of the brutal bug that was due to the lack of GCC/C++
threads.  Now, if you look at the asm, you'll see a call to

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add cpu_relax_any()
Barret Rhoden [Fri, 14 Apr 2017 15:40:44 +0000 (11:40 -0400)]
parlib: Add cpu_relax_any()

A lot of uses of cpu_relax_vc() don't know the other vcore we are waiting
on.  Use this helper in those situations.

As a reminder, you can use the regular cpu_relax() if:
- you're waiting on something other than another vcore, such as the
kernel or a udelay loop
- you have notifs enabled.
- you have a call to ensure_vcore_runs() in the loop with cpu_relax()

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Allow cpu_relax_vc() calls from uthreads
Barret Rhoden [Fri, 14 Apr 2017 15:23:02 +0000 (11:23 -0400)]
parlib: Allow cpu_relax_vc() calls from uthreads

This goes a little farther than commit 2ee62d285f56 ("parlib: Fix assertion
in cpu_relax_vc()").  Not only is it OK for uthreads to call
cpu_relax_vc(), but they should be able to call it regardless of whether
notifs are disabled or not.

Basically, any uthread can always call this.  If they aren't responsible
for handling preemption issues, they just do the normal cpu_relax(), which
is just a compiler barrier and "pause" on x86.

Here's how to think about this.  If we're spinning in userspace and waiting
on another core in userspace, we need to consider that the other core has
been preempted.  Our current preemption code is set up so that we'll
receive a notif (software IPI) if another core is preempted.  So if we have
notifs enabled, then we don't need to do anything fancy.  If notifs are
disabled, then we might not see the preemption message.  In that case, we
need to call ensure_vcore_runs() and all that (polling the vcoremap).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoUse patches for existing toolchain files (XCC)
Barret Rhoden [Tue, 7 Mar 2017 17:12:29 +0000 (12:12 -0500)]
Use patches for existing toolchain files (XCC)

When building gcc and glibc, we use the same technique: extract the
tarball, copy over everything from the -akaros directory, apply a few
patches, and build.

The -akaros directory is nice since we can easily edit and maintain those
files, e.g. sysdeps/akaros/write.c.  Most of those files do not exist in
the tarball.  However, on occasion, we do need to change files in the
tarball, such as gcc-4.9.2/config.sub.  For those, we had been keeping a
copy in the -akaros directory, and that slightly modified copy would
replace the version from the tarball.

The problem with this approach is that it is hard to know what has changed
in those files without comparing to the native version in the tarball.
It'll also be harder to port those changes when we eventually upgrade to a
newer toolchain.

Now we'll have two sources of changes.  We'll still have the -akaros
directory for the files that only exist in our port.  Anything that is part
of the tarball that needs to be changed will be in the existing.patch.
Note that during development, you can still put files in the -akaros
directory and they will overwrite the tarball files.  Just be sure to not
commit those files, and instead apply the appropriate patch.  You can get
the guts of the patch from the hidden file generated during make (e.g.

Rebuild your toolchain.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoAdd the 'akaros' threading model to gcc (XCC)
Barret Rhoden [Mon, 6 Mar 2017 21:47:14 +0000 (16:47 -0500)]
Add the 'akaros' threading model to gcc (XCC)

Gcc has a bunch of callbacks for basic thread operations.  These are used
internally for C++ operations.  For instance, shared_ptrs use a reference
count.  Whether or not that refcount needs to be accessed atomically
depends on whether or not there are threads in the system.  There are a
bunch of these functions - see gthr-akaros.h for all of them.

Previously, we told gcc to use 'posix' threading, which means pthreads.
However, if we're using a different 2LS, then that would be incorrect.  The
correct threading model is to make our own.

Further, since our pthreads aren't really integrated into gcc/glibc, we
were returning 0 (false) when asked "are we multithreaded."  That led to a
brutal shared_ptr refcount bug.

This commit fixes the detection of threading and should also deal with any
other interactions between gcc/c++ and uthreads.

Rebuild your toolchain (gcc and glibc).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add uthread_self()
Barret Rhoden [Thu, 13 Apr 2017 19:30:16 +0000 (15:30 -0400)]
parlib: Add uthread_self()

Yes, this is just current_uthread, but having a layer of interposition is
useful for catching bugs.  Specifically, I'm worried about apps or
libraries calling one of the _self() functions from vcore context - they'd
get the ID of the thread running on that vcore, not the vcore itself.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: UTH_EXT_BLK_JUSTICE -> _MISC
Barret Rhoden [Thu, 13 Apr 2017 17:24:17 +0000 (13:24 -0400)]

And have pthreads track the appropriate state for threads blocking.  This
will only matter for diagnostics: we can look at a pthread and get a hint
as to what its doing or why it is blocked.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agofutex: Make futexes independent of pthreads
Barret Rhoden [Fri, 7 Apr 2017 17:59:51 +0000 (13:59 -0400)]
futex: Make futexes independent of pthreads

Unlike POSIX semaphores, the futex code can't be implemented 1:1 with
semaphores or CVs.  It manages its own wakeup conditions and whatnot.  We
probably could reimplement the whole thing with other uthread primitives.
For now, we just want to make it not depend on pthread code.

Similar to POSIX semaphores, futex.h is a common header for the Linux/POSIX
world, and is an API people will want to use regardless of their 2LS.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agopthread: Implement POSIX semaphores with uth sems (XCC)
Barret Rhoden [Fri, 7 Apr 2017 17:47:36 +0000 (13:47 -0400)]
pthread: Implement POSIX semaphores with uth sems (XCC)

We had these as part of pthreads, but now the POSIX sem interfaces work for
any 2LS.  We'll keep it in pthread.c for now, since it's basically the
POSIX interface to threads and synchronization.  Eventually everyone will
be able to use pthread-like functions (including these sems) regardless of
their 2LS.

Fully rebuild the toolchain, including reconfiguring.  (make clean will do
the trick).  The issue is libgomp determines the size of omp_locks during
config time.  Any changes to the size of a semaphore (which is a uthread
sem) triggers the need for a reconfig.  If you ever have builds dying
during libgomp (late in the toolchain build), this is probably why.  Scroll
back a dozen pages and you'll see the error.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoImplement sched_yield() with uthread_sched_yield() (XCC)
Barret Rhoden [Wed, 12 Apr 2017 18:20:56 +0000 (14:20 -0400)]
Implement sched_yield() with uthread_sched_yield() (XCC)

Rebuild glibc at your leisure.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add uthread_sched_yield()
Barret Rhoden [Wed, 12 Apr 2017 17:29:00 +0000 (13:29 -0400)]
parlib: Add uthread_sched_yield()

Like pthread_yield(), but it works for all 2LSs.  It can also handle if you
are a single-threaded process (no 2LS and also an SCP).  When you have
multiple threads, you yield in favor of those other threads.  Otherwise,
you yield in favor of other processes.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add uthread_create()
Barret Rhoden [Wed, 12 Apr 2017 16:35:30 +0000 (12:35 -0400)]
parlib: Add uthread_create()

And the corresponding 2LS op.  uthread_create() creates and runs a generic
thread that runs a function - similar to pthread_create(), but it works
regardless of the 2LS being used.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmm: Make all task functions return void *
Barret Rhoden [Tue, 11 Apr 2017 20:37:55 +0000 (16:37 -0400)]
vmm: Make all task functions return void *

I avoided this for a while, but it makes the upcoming changes to 2LSs
easier.  GCC wants to be able to spawn a thread that returns a void *, and
its simpler to have all VMM task threads do it than to special case it.

Besides, it's a matter of time until someone wants to spawn and join on a
task thread inside the VMM.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Implement join/detach() for all uthreads
Barret Rhoden [Tue, 11 Apr 2017 19:28:50 +0000 (15:28 -0400)]
parlib: Implement join/detach() for all uthreads

Previously, it was up to specific 2LSs, such as pthreads, to implement
join() and detach() if they wanted it.  GCC needs it for the C++ threads,
and it might be helpful for all 2LSs.  Now, join/detach() are handled at
the uthread layer.

These functions only kick in if a thread exits.  That is still controlled
by the 2LS.  Previously, exits were done with a yield callback.  Instead,
2LSs will call uth_2ls_thread_exit(), and the callback work is done in the
2LS->thread_exited() op.  If a thread never exits, such as certain types of
VM threads, then that op will not be called.  And, as one would expect, if
you join() a thread that never exits, you'll block forever.

The implementation of join/detach/exit differs from the original pthreads
implementation.  The pthread implementation had a race on the detach state,
where a bad combination of detacher/joiner/exiter could be corrupted.
CAS-ing on the state solved a lot of those problems.

The other major improvement was adding a parallel join.  Since this join
will work for all 2LSs, I'd like it to work for some of the more exotic
schedulers.  Parallel join is a common operation in some threading
libraries and frameworks (openmp, lithe, etc).  My implementation uses
krefs so that the joiner is only woken up once for all N threads, instead
of up to N times.  The kref also helps with races between concurrent joins
and exits.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add 'timed' functions for sems/mtxs/cvs
Barret Rhoden [Fri, 7 Apr 2017 15:23:58 +0000 (11:23 -0400)]
parlib: Add 'timed' functions for sems/mtxs/cvs

These allow waiters to timeout while waiting on their sync objects.  GCC's
threading interface needs them, and in general they are fairly common

One nice thing is that all of the waiting operations can use the same
mechanism.  Thanks to the generic sync_object, CVs and semaphores (and thus
mutexes) use the same alarm handler + callbacks.

We can use the timed versions to implement the untimed versions.  The
differences are very minor (e.g., just branches in the contended mutex
case).  GCC didn't need a CV-timed-recurse-wait function, but it was easy
to do, and stylistically the same as the others.

Note that the timeouts for CVs apply only to the CV, not the mutex.  If the
CV times out, you will still have the mutex locked when you return.  This
is also the expected pthread semantics:

When such timeouts occur, pthread_cond_timedwait() shall
nonetheless release and re-acquire the mutex referenced by mutex.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add an alarm helper
Barret Rhoden [Fri, 7 Apr 2017 15:20:02 +0000 (11:20 -0400)]
parlib: Add an alarm helper

Anyone working with timespecs and parlib/alarm.h will use this.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmm: Remove references to pthreads
Barret Rhoden [Fri, 7 Apr 2017 14:51:25 +0000 (10:51 -0400)]
vmm: Remove references to pthreads

We don't have a dependency from vmm on pthreads (in the top-level
Makefile), and we probably don't need one ever.  We don't need one now.

However, #including pthread.h can cause intermittent build failures, since
user/vmm and user/pthread can be built in parallel, and vmm could see a
corrupted pthread.h.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Move alarm/timer functions from benchutil
Barret Rhoden [Thu, 6 Apr 2017 20:43:37 +0000 (16:43 -0400)]
parlib: Move alarm/timer functions from benchutil

Certain functions are in benchutil because they couldn't be in parlib.  The
original function of this sort needed -libm (sqrt, IIRC).

These other timing functions were in benchutil since usec2tsc() was there,
which was back in 2013.  It turns out those didn't need to be in benchutil,
and they were moved about a year later in commit dd7547b8fc54 ("Moves some
timing func from benchutil to parlib").

Now that there's no reason to have those functions in benchutil, we can
move them to parlib.  I need to do this since I'd like to use alarms for
parlib's mutex.c functions.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agobenchutil: Clarify unset_alarm()'s semantics
Barret Rhoden [Thu, 6 Apr 2017 19:01:00 +0000 (15:01 -0400)]
benchutil: Clarify unset_alarm()'s semantics

Userspace alarm code is based off older versions of the kernel's alarms.
But they both have the same semantics for unset: when unset returns, the
alarm handler has either completed or will never fire.

If we want to support the "non-IRQ" style alarm handlers, we'll probably
want to report the guts of the kernel's tchain code (maybe with CVs).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add uth_cond_var_wait_recurse()
Barret Rhoden [Thu, 6 Apr 2017 18:00:01 +0000 (14:00 -0400)]
parlib: Add uth_cond_var_wait_recurse()

GCC needs this for its threading interface.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: sem/mtx/cv: Add init() and destroy()
Barret Rhoden [Fri, 7 Apr 2017 17:25:51 +0000 (13:25 -0400)]
parlib: sem/mtx/cv: Add init() and destroy()

POSIX semaphores want init() and destroy() methods.  Similarly, GCC's
threading interface needs init() and destroy() for mutexs and CVs.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Implement uthread mutexes with semaphores
Barret Rhoden [Thu, 6 Apr 2017 16:43:13 +0000 (12:43 -0400)]
parlib: Implement uthread mutexes with semaphores

Mutexes are now wrappers around semaphores of value 1.  For the most part,
this commit moves the old mutex logic into semaphore functions (renaming
mtx->sem), and then changes the locking logic from 'locked' to 'count'.
Note the mutexes and semaphores use different once_ctl functions, and the
semaphore static initializer sets count directly.

I probably should have done this from the start.  There's a good chance
we'll implement user/pthread/semaphore.h with uthread semaphores, in an
effort to not have a dozen different synchronization functions.  Though
that one might end up being a kernel #device if we need inter-process
semaphores.  (All the uthread sync is intra-process.)

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add a test for recursive mutexes
Barret Rhoden [Wed, 5 Apr 2017 19:17:27 +0000 (15:17 -0400)]
parlib: Add a test for recursive mutexes

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add static initializers for mutexes / CVs
Barret Rhoden [Wed, 5 Apr 2017 18:32:34 +0000 (14:32 -0400)]
parlib: Add static initializers for mutexes / CVs

We'll need these for GCC generic thread interface.  Note we don't have a
static destructor, so to speak.  Under the hood, the sync object and its
size is controlled by the 2LS, and there may be some amount of work the 2LS
needs to do to destroy the object.  For now, don't free statically
initialized mutexes/CV.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Change opaque mutex/cv types to be structs
Barret Rhoden [Wed, 5 Apr 2017 18:19:39 +0000 (14:19 -0400)]
parlib: Change opaque mutex/cv types to be structs

Instead of pointers to structs.  We'll need this for the static
initialization of mutexes and whatnot.  The opaque types used to be
pointers, instead of a structs, since we didn't know their size.  That used
to be determined by the 2LS in its mutex/cv overrides.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Always use the default mutex/cv interface
Barret Rhoden [Wed, 5 Apr 2017 16:21:01 +0000 (12:21 -0400)]
parlib: Always use the default mutex/cv interface

Previously, the 2LSs could override the mutex/CVs.  Now, the old default
implementation is the only implementation.  2LSs do their thing with the
sync objects.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add synchronization objects
Barret Rhoden [Wed, 5 Apr 2017 15:44:53 +0000 (11:44 -0400)]
parlib: Add synchronization objects

The way synchronization primitives worked before is that a 2LS could
override the default functions (e.g. mutex_lock()) if they don't want the
default scheduling policy (FIFO).

After thinking about it a bit, the 2LS-specific part is the scheduling
decision: given an object (e.g. mutex), which thread should run next?  The
rest of it: uthread_yield(), callbacks, etc, is the same for all 2LSs.  We
can see this to some extent already with how recursive mutexes aren't part
of the 2LS interface.  It will become more clear as we add timeouts to
mutexes and CVs; that work just need to be done at the uthread level.  The
2LS just picks the next uthread.

This work is part of the GCC generic threading interface.  One of the
things required from that is a static initializer for mutexes.  To deal
with that, we'll need some fields in a mutex that uthread.c can access (for
a once_ctl).  That's part of the reason why mutex allocation will be a
uthread job, and the 2LS just does the sync_obj.  That sync obj can be used
for all sorts of synchronization primitives - at least mutexes and CVs for
now, maybe more in the future.

I considered allowing static allocation (but not initialization) of 2LS
sync_objs.  If we want to do that in the future, we can do so if we set an
upper bound on the size of a 2LS sync obj, and use a uint8_t
sync_store[SOME_AMT] that all 2LSs cast to their object.  It's probably not
worth it at this point.

There's also a minor issue with whether or not get_next() and friends
returns a uthread or another object.  If we wanted to use this in event.c
(which we don't, for other reasons at the moment), we might want to get the
controller back, not the uthread.  It's a layer of indirection.  That would
require storing a pointer with the per-uthread part of the sync structure
(e.g. TAILQ_ENTRY).  Right now, the implied pointer is the uthread, which
we can easily access since the per-uthread part is embedded in the uthread
(or 2LS thread).  We could just store another pointer next to it, but so
far it's not worth it / necessary.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Use cpu_relax_vc() in parlib_run_once() (XCC)
Barret Rhoden [Tue, 4 Apr 2017 18:06:22 +0000 (14:06 -0400)]
parlib: Use cpu_relax_vc() in parlib_run_once() (XCC)

When you spin wait in userspace, there's a chance that whoever you are
spinning on is preempted.  In these cases, use cpu_relax_vc() instead of
cpu_relax().  That'll periodically check to make sure the other vcores are

Rebuild glibc.  The acrobatics with the weak symbol are needed since some
parts of glibc call parlib_run_once(), and glibc needs to be able to link
without parlib temporarily.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoConvert run_once() to parlib_run_once() (XCC)
Barret Rhoden [Tue, 4 Apr 2017 17:59:25 +0000 (13:59 -0400)]
Convert run_once() to parlib_run_once() (XCC)

The kernel still uses run_once(); that's now in the kernel-only header.
Userspace will now use parlib_run_once().  They can also use
pthread_once(), which differs in that you can't pass an argument to the
init function.  That's a POSIX limitation, but I'll need the void *arg for
another use case.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Move init_once_racy() to parlib (XCC)
Barret Rhoden [Mon, 3 Apr 2017 20:05:56 +0000 (16:05 -0400)]
parlib: Move init_once_racy() to parlib (XCC)

Reinstall your kernel headers.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoRemove kernel-specific parts of ros/common.h (XCC)
Barret Rhoden [Mon, 3 Apr 2017 19:59:57 +0000 (15:59 -0400)]
Remove kernel-specific parts of ros/common.h (XCC)

Parts of ros/common.h were accessed only by the kernel.  This developed
over time.  We can put those in k/i/common.h instead of having them
in the kernel interface file.

Reinstall your kernel headers.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agondblib: Remove dependency on pthreads
Barret Rhoden [Mon, 3 Apr 2017 18:24:45 +0000 (14:24 -0400)]
ndblib: Remove dependency on pthreads

This popped up during other changes.  If we need pthreads, then we can
include it and then also add the real dependency to the top level Makefile.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add a helper for multi-threaded-ness
Barret Rhoden [Mon, 6 Mar 2017 21:21:12 +0000 (16:21 -0500)]
parlib: Add a helper for multi-threaded-ness

GCC needs to know at runtime if we have multiple threads or not.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add recursive uthread mutexes
Barret Rhoden [Mon, 6 Mar 2017 20:44:08 +0000 (15:44 -0500)]
parlib: Add recursive uthread mutexes

I'm not a huge fan of recursive mutexes, but GCC needs them for C++.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add trylock to uthread mutexes
Barret Rhoden [Mon, 6 Mar 2017 20:14:50 +0000 (15:14 -0500)]
parlib: Add trylock to uthread mutexes

GCC needs this, and other people might too.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Use 'const' in the set_dtls() interface
Barret Rhoden [Mon, 6 Mar 2017 20:00:12 +0000 (15:00 -0500)]
parlib: Use 'const' in the set_dtls() interface

This keeps it in line with pthread_setspecific().

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmm: move biostables to the library
Ronald G. Minnich [Fri, 21 Apr 2017 18:18:13 +0000 (14:18 -0400)]
vmm: move biostables to the library

Put the bios tables in the user/vmm library.
vmrunkernel is becoming simpler and the library
is becoming more capable.

This is tested with a full prodkernel boot.

Change-Id: If29d6b5d8da4a3475e5fd26a3e1edeeb4d7614bc
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoMark 'user' as PHONY in the top-level Makefile
Barret Rhoden [Tue, 25 Apr 2017 19:23:25 +0000 (15:23 -0400)]
Mark 'user' as PHONY in the top-level Makefile

'user' is also a directory, so some make targets thought they didn't
need to be updated.  Specifically this included make tests, which
doesn't depend on install-libs anymore.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoSplit user-dirs into base and extra (XCC)
Barret Rhoden [Tue, 25 Apr 2017 14:28:30 +0000 (10:28 -0400)]
Split user-dirs into base and extra (XCC)

In commit 3035c3db676f ("user/vmm: add and use a load_elf function")
we established a dependency from VMM to elfutils.  However, vmm was
getting installed during the toolchain installation (through make
install-libs).  This was before elfutils was installed.

Breaking user-dirs into the base libraries that are expected to go with
the toolchain and 'extra' libraries that other code (e.g. vmrunkernel
and dune) needs does the trick.  Mostly - perfmon should also be an
'extra' library, but due to the way our apps-install works, it won't
work out.  The longer range solution is to make actual packages for
perfmon and vmm and have them get built and installed via a package
management system.

Rebuild your toolchain, if you want to make sure this works.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmm: move paging setup to the library
Ronald G. Minnich [Fri, 21 Apr 2017 15:45:00 +0000 (11:45 -0400)]
vmm: move paging setup to the library

We create a new function, setup_paging(start, size, debug)
which returns a pointer to the base of page tables (needed
for starting the VM). Since it is just manipulating values
in arrays, and it's almost impossible for it to go wrong,
we print a nice message and bail if anything goes wrong.

Change-Id: I1d5ef0ce1c2a7fed4e21a18bd48ffdac0b3ab0e9
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmrunkernel: get the page table setup right
Ronald G. Minnich [Fri, 21 Apr 2017 00:11:55 +0000 (20:11 -0400)]
vmrunkernel: get the page table setup right

I screwed this up so many times, maybe this time it's right.
Tested on 3 different memory sizes with weird alignments.

I've added a new check, checkmemaligned, which ensures
that memstart and memsize are 2m aligned.

This check needs to be separate from the memory
function as some environments may not call
memory() but still need to check alignment.

Change-Id: Ie7b8e324683f0415bd8d5d078fe3ff29a04a515e
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmrunkernel: cleanup
Ronald G. Minnich [Thu, 20 Apr 2017 19:41:19 +0000 (15:41 -0400)]
vmrunkernel: cleanup

Get rid of many unused globals, move as many used ones
to main() as possible. The vm stuff will be a bit more work.

Change-Id: I1e877b11c94b906cd013f3d2e0ba81152d974c28
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agouser/vmm: add and use a load_elf function
Ron Minnich [Thu, 20 Apr 2017 15:39:07 +0000 (11:39 -0400)]
user/vmm: add and use a load_elf function

load_elf loads an elf, not just a kernel.

I've tested vmrunkernel with this and it works fine.

Change-Id: Ib1d825746e0307565ecd44216bd739f9e6d30c54
Signed-off-by: Ron Minnich <rminnich@google.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmrunkernel: change timer frequency to 1Khz
GanShun [Tue, 18 Apr 2017 14:16:15 +0000 (10:16 -0400)]
vmrunkernel: change timer frequency to 1Khz

This is a temporary stopgap measure to make SMP not suck.
We should eventually calculate the frequency dynamically

Change-Id: Ie54e60bd631e2beb520661eecd70bed3a686d007
Signed-off-by: GanShun <ganshun@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmm: CPUID level 0x0B handling
Dan Cross [Wed, 12 Apr 2017 19:40:16 +0000 (15:40 -0400)]
vmm: CPUID level 0x0B handling

TODO: Figure out EAX (really, RAX in our world) values at SMT level.

When we get CPUID level 0x0b, reflect to userspace.  We
fake some information about the SMP topology of the machine:
basically, no hyperthreading and $n$ cores in a single

We'll probably have to hook this into the ACPI tables somehow
to get the full effect; in the meantime, this seems to work.

Change-Id: I9543066e74e592d381c11bcd76e7f9e0476c7cab
Signed-off-by: Dan Cross <crossd@gmail.com>
[removed WIP tag]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agox86: vmm: Fix number of CPU detection from cpuid
Barret Rhoden [Mon, 17 Apr 2017 19:04:58 +0000 (15:04 -0400)]
x86: vmm: Fix number of CPU detection from cpuid

Cpuid leaf 0x1, ebx, was reporting the number of logical processors from
the host OS.  We should be reporting the number of guest cores.

Similarly, I added a masking of the APIC core id to one byte, in the off
chance that would cause a problem.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agospatch away Linux spinlock functions.
Dan Cross [Wed, 12 Apr 2017 16:33:05 +0000 (12:33 -0400)]
spatch away Linux spinlock functions.

Instead of trying to paper over these with preprocessor macros,
spatch them to what they are supposed to be.

Change-Id: I7b9ed4d27e2e595020186dc435d9d41e37262ce9
Signed-off-by: Dan Cross <crossd@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agospin_lock -> spin_lock_irqsave and matching unlock
Dan Cross [Mon, 10 Apr 2017 18:47:46 +0000 (14:47 -0400)]
spin_lock -> spin_lock_irqsave and matching unlock

I discovered a kernel panic when the mlx driver tried
to spinlock an IRQ-saving lock.  This is the result of
a manual audit to look for such bugs and repair them.
Is it all correct?  Who knows.  These drivers are
behemoths and actively searching through all of them
and verifing actual correctness of all locking calls in
all contexts is a big job that, frankly, none of us
have adequate time for at the moment.

Spinlock debugging FTW for pointing the problem out in
the first place.  Arguably, we ought to have separate
structure types for the different kinds of locks so
that this could be a compile time error.

Change-Id: I314c285672d15a5b43e0c2b0cb70b9b259c6c437
Signed-off-by: Dan Cross <crossd@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmm: add helpers for making more memory
Ronald G. Minnich [Thu, 9 Mar 2017 18:42:45 +0000 (10:42 -0800)]
vmm: add helpers for making more memory

This is working and lets me add lots of memory.
It is only lightly tested at this point, however.

Change-Id: I892b7261d5220b59bb29f669a60e5f7774acc1cb
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
[checkpatch fixes, renamed e820map() and memory(), added a call to
mmap_memory() that was lost, used MAX() instead of ? : ]

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoAdd a `waserror` call to ipifcadd.
Dan Cross [Thu, 6 Apr 2017 19:17:49 +0000 (15:17 -0400)]
Add a `waserror` call to ipifcadd.

When `ipifcadd` acquires a write lock, make sure we have
a stanza to check for `waserror` and release the lock if
one of its called functions should `error`.

Change-Id: I1a2c96166249a562d92f27368e6993bb577588af
Signed-off-by: Dan Cross <crossd@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: Initialize rwlock in ipifc
Barret Rhoden [Thu, 6 Apr 2017 17:30:58 +0000 (13:30 -0400)]
net: Initialize rwlock in ipifc

There are other sync structures in the ipifc that we aren't using.  I opted
to keep them around for now (and to initialize them) in case we ever try to
use them for their stated purpose (unbind on the fly).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agosdiahci: Need to properly initialize spinlock.
Dan Cross [Wed, 5 Apr 2017 19:22:05 +0000 (15:22 -0400)]
sdiahci: Need to properly initialize spinlock.

The AHCI driver was using `spinlock_init` on locks it was trying
to `spin_lock_irqsave`.  Use `spinlock_init_irqsave` instead.

Similarly, we have to initialize the controller lock.

Change-Id: Ieeb87601c9d73d77f524c948500d50db68247484
Signed-off-by: Dan Cross <crossd@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agomlx4u: Initialize iboe->lock properly.
Dan Cross [Wed, 5 Apr 2017 19:09:08 +0000 (15:09 -0400)]
mlx4u: Initialize iboe->lock properly.

Use the Akaros `spinlock_init` function to initialize iboe->lock,
not Linux's `spin_lock_init` (which is #define'd to Akaros's

Change-Id: If55ecf25fcd59f7d1c2c01b96fc76f69c738f8c5
Signed-off-by: Dan Cross <crossd@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years ago9ns: Align struct dirtab to 64 bytes
Barret Rhoden [Fri, 31 Mar 2017 00:08:11 +0000 (20:08 -0400)]
9ns: Align struct dirtab to 64 bytes

devvars puts struct dirtabs into a linker table.  Those tables are all
64 byte aligned, and the objects within the table will be laid out with
64 byte alignment.

This was probably the cause of the intermittent startup assertion
failure in vars_init() (couldn't find ".").  "." is at the end of the
vars table, and any confusion regarding the length, size, or alignment
of the tables and objects could result in not memcpying that item.

I noticed this when changing the KNAMELEN, which increased the size of
the dirtab to 0x120 bytes.  That's 32-byte aligned, not 64.  However,
the objects within the table were laid out (by the linker) in 0x140 byte
strides: 0x120 rounded up to 64.  Additionally, before I fixed this
alignment, vars_init() had a hard time doing pointer arithmetic on the
struct dirtab *s, and would come up with a really large number.  Doing
the math manually worked.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years ago9ns: Catch errors thrown by devtab.{reset,init}
Barret Rhoden [Thu, 30 Mar 2017 21:01:24 +0000 (17:01 -0400)]
9ns: Catch errors thrown by devtab.{reset,init}

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years ago9ns: Use strlcpy() for various devices
Barret Rhoden [Thu, 30 Mar 2017 20:26:26 +0000 (16:26 -0400)]
9ns: Use strlcpy() for various devices

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years ago9ns: Use an int for perm and mode
Barret Rhoden [Thu, 30 Mar 2017 18:04:12 +0000 (14:04 -0400)]
9ns: Use an int for perm and mode

-1 means "don't change the mode."  That was 0x00000000ffffffff, which is
not ~0UL (0xffffffffffffffff).  Just use an int and don't play games with
the sizeof longs and whatnot.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agodevroot: Fix stat and clean up rootgen.
Barret Rhoden [Thu, 30 Mar 2017 18:01:28 +0000 (14:01 -0400)]
devroot: Fix stat and clean up rootgen.

Stat on directories didn't work.  It was doing the usual devstat() thing
where devstat() makes a fake entry.  But we can actually do better, by
implementing rootstat directly.  Since we're trying to be a filesystem, we
shouldn't be using the synthetic solutions (e.g. devstat), which get the
timestamps and usernames wrong.

Likewise, I cleaned up rootgen() a little.  We had been taking a dirtab
pointer, but not actually using it (except in one odd case), which was

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agodevroot: Use dirtab's length instead of rootdata's size
Barret Rhoden [Wed, 29 Mar 2017 18:38:29 +0000 (14:38 -0400)]
devroot: Use dirtab's length instead of rootdata's size

There were two mechanisms tracking the size of an object in #root - the
dirtab's length and the rootdata's size fields.  We didn't always keep them
in sync, and we really only need one.

I also removed the sizep field - it wasn't clear that it was used for
anything other than the rootinit() attempt to keep the length and size in

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoqio: Clean up q.*full()
Barret Rhoden [Wed, 29 Mar 2017 15:14:06 +0000 (11:14 -0400)]
qio: Clean up q.*full()

The old qfull() and qwritable() should be opposites.  qfull() was actually
wrong in that if we had set no limit, qfull() would always return TRUE
instead of always returning FALSE.  I guess in Plan 9 it was on the caller
to know if there was a limit or not.

qnotfull() was a rendez condition, not a generic function.  It also wasn't
just about being full or not, it included being closed.  Renaming the
function makes that more clear.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoqio: Remove q->len
Barret Rhoden [Wed, 29 Mar 2017 14:54:44 +0000 (10:54 -0400)]
qio: Remove q->len

q->dlen is the amount of data bytes in the queue: the bytes that our
clients are adding and removing.

q->len was the amount of total bytes in the queue, including metadata,
block structs, and anything else.  If you had a block with 0 data bytes in
the queue, the size of the block itself counted against q->len.

Note that the qlen() function actually returns q->dlen.  The only time we
really used q->len was for flow control, and that's where it caused
problems.  I had a pipe where the reader didn't wake a writer.  The reader
saw 'was_unwritable', then popped a block of length 0, and did a retry
(this was the Qcoalesce case).  However, popping that block made the queue
writable again, which was unexpected since the reader got nothing.

Instead of mucking around with q->len and q->dlen any further, I just
yanked q->len completely.  It's not clear that we even wanted q->len, and
it's been the source of bugs and confusion for a while now.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoucq: Fix print_ucq()
Barret Rhoden [Tue, 21 Mar 2017 18:25:19 +0000 (14:25 -0400)]
ucq: Fix print_ucq()

Two things: one was a u64 vs u32 (the slot is often > 4 GB), and the comma
operator in the for loop's check was wrong.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agorandom: Support epoll() and select()
Barret Rhoden [Tue, 21 Mar 2017 18:10:37 +0000 (14:10 -0400)]
random: Support epoll() and select()

The taps are for epoll().  select() doesn't actually need the taps, since
it will see (u)random as readable, always (fstat).  If we ever make Qrandom
block, then we can add edge detection to it (and thus a real tap function).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agocons: Support epolling /dev/null
Barret Rhoden [Mon, 20 Mar 2017 22:37:31 +0000 (18:37 -0400)]
cons: Support epolling /dev/null

Some apps want to epoll on their output streams.  If that's redirected to
/dev/null (#cons/null), then they will try to epoll/select/poll on it.

We don't have actual edges, but we can fake it.  And we'll also need to
support stat reporting writable.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agostrace: Handle variable-width timestamps
Barret Rhoden [Mon, 20 Mar 2017 22:19:10 +0000 (18:19 -0400)]
strace: Handle variable-width timestamps

If a machine has an uptime of over 10 million seconds (about 4 months),
then the timestamp field grows.  Strace couldn't handle this, since it
assumed the field was 40 bytes.

Incidentally, the machine wasn't up for 120 days, but it might have not
been turned off in that long.  Sometimes (often?) soft reboots don't reset
the TSC, which is where that timestamp comes from.  This occurence is the
same reason I found the bug from commit fd20de73987b ("Fixes TCP drops due
to ARP timeouts").

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: Allow local.d configs to specify HOST / FQDN
Barret Rhoden [Fri, 17 Mar 2017 20:28:22 +0000 (16:28 -0400)]
net: Allow local.d configs to specify HOST / FQDN

If you set HOST, ifconfig will create a line in /etc/hosts for the primary
NIC's IP (ipifc/0).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: slab: Fix ancient ctor off-by-one
Barret Rhoden [Thu, 16 Mar 2017 22:43:08 +0000 (18:43 -0400)]
parlib: slab: Fix ancient ctor off-by-one

The original purpose for that list was to build the chain of small slab
objects.  But we only ran the ctor on the first n - 1 of them.

This bug is ancient - it's from the kernel's original slab implementation.
We hadn't really used slab ctors a lot.  Same goes for userspace, until my
recent epoll changes.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Align the stack when saving FP state
Barret Rhoden [Thu, 16 Mar 2017 19:06:42 +0000 (15:06 -0400)]
parlib: Align the stack when saving FP state

We need the sigdata struct to be aligned properly for the FPU save/restore.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Fix potential races with DTLS
Barret Rhoden [Thu, 2 Mar 2017 17:56:21 +0000 (12:56 -0500)]
parlib: Fix potential races with DTLS

I didn't see these happen, but stumbled on them as possibilities during
other bug hunts.

The DTLS one sounds a lot like a problem with glibc's version.  For the
pthread code, I'm being a little paranoid.  pthread_cleanup_pop() will call
free(), which also might want to use the DTLS.  free() should be able to
handle things if the key is deleted, but who knows.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Fix assertion in cpu_relax_vc()
Barret Rhoden [Thu, 2 Mar 2017 17:45:47 +0000 (12:45 -0500)]
parlib: Fix assertion in cpu_relax_vc()

It's okay for a uthread to do this, but they must have notifications
disabled, such that the rest of the system (kernel and user code on other
cores) thinks this vcore is running in vcore context.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Remove get_user_ctx_stack()
Barret Rhoden [Mon, 27 Feb 2017 19:14:48 +0000 (14:14 -0500)]
parlib: Remove get_user_ctx_stack()

This was an older function whose functionality is now handled by

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: socket: Implement accept4() (XCC)
Barret Rhoden [Fri, 24 Feb 2017 21:44:58 +0000 (16:44 -0500)]
net: socket: Implement accept4() (XCC)

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: socket: Support SOCK_CLOEXEC (XCC)
Barret Rhoden [Fri, 24 Feb 2017 20:56:22 +0000 (15:56 -0500)]
net: socket: Support SOCK_CLOEXEC (XCC)

If a socket is marked SOCK_CLOEXEC, then the intention is that none of that
socket's FDs (the socket itself, any listen files, ctls, etc) will get
passed on to its child after exec().

Note that accept() does not pass on CLOEXEC, yet.  The NONBLOCK was for the
attempt, which was when we were the parent socket.  The actual ctl that we
get in return is the child socket, which is controlled by accept4() (TBD).

Although I want to get rid of exec(), in the meantime, we should attempt to
support it.

While I was here, I added a helper for opening a Rock's ctlfd (a common
pattern), and supported NONBLOCK for pipes.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: Report listen files with incalls as readable
Barret Rhoden [Fri, 24 Feb 2017 19:49:40 +0000 (14:49 -0500)]
net: Report listen files with incalls as readable

When a conversation has inbound calls, userspace can now see that by doing
a stat on the listen file (e.g. /net/tcp/1/listen).  This is necessary for
libraries that use stat() to detect the 'level' of an event.  select() and
epoll() both do this (select() for its own behavior, epoll() to synthesize

And you can now see whether or not there are incalls in 'pip.'  If you
happen to see it, either you got lucky or there's probably a bug.  Which is
probably why you're running 'pip' in the first place.  =)

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoceq: Add a dump function
Barret Rhoden [Fri, 24 Feb 2017 19:48:39 +0000 (14:48 -0500)]
ceq: Add a dump function

Call this from kfunc.  I used this in debugging the epoll problem.  It
turns out that the CEQ wasn't the problem, but I imagine I'll need this in
the future for another bug.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoepoll: Error out if someone asks for one-shot
Barret Rhoden [Thu, 2 Mar 2017 17:50:24 +0000 (12:50 -0500)]
epoll: Error out if someone asks for one-shot

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoepoll: Give every waiter their own event queue
Barret Rhoden [Fri, 24 Feb 2017 19:40:14 +0000 (14:40 -0500)]
epoll: Give every waiter their own event queue

This was a brutal bug.  Basically, multiple epoll_wait() calls with
timeouts could consume each other's events.  They had independent async
syscs, but the notifications all went to the same evq (the old

As a result, when uthreads blocked on the alarm evq, either for the main
blockon(ceq_evq, alarm_evq) or the dummy alarm_evq, they could wake up due
to another uthread's call.  Eventually, some uthread would get a real
event, then would try to cancel their alarm.  But someone else would get
the event_queue message (the one from the aborted syscall 'completing').
Then the original uthread would sleep for a long, undetermined amount of
time, based on when our uth happened to extract someone *else's* message,
since ours was gone.

The fix is to have separate event queues for each waiter (that has a
timeout), just like how they have their own syscall structures.

This is actually a nice opportunity to use a slab allocator, since we want
a bunch of constructed alarm objects sitting around.  Due to the INDIR/RCU
problem (can't safely reuse memory until all INDIRs are done), we don't
want to reuse the memory - keeping the objects around in a kmem_cache is
ideal.  The other benefit of the slab allocator is that we can use the same
pool of these for all epoll controllers, which means we'll never have more
of these than we have threads, instead of threads * nr_epoll_ctlrs.  (Round
up to the nearest slab size, btw).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoAllow filtering by PID for "db sem"
Barret Rhoden [Thu, 23 Feb 2017 16:21:47 +0000 (11:21 -0500)]
Allow filtering by PID for "db sem"

The PID argument to "db sem" is optional.  Without it, it shows all
semaphores.  With it, it will only show sems with kthreads of a particular
process.  Use PID == 0 for "no process" (e.g., ktasks).

bash-4.3$ m db sem 272
All sems with waiters:
Semaphore 0xffff8000096db630 has -1 signals (neg = waiters)
        Kthread 0xffff800007dfd620 (open /net/tcp/0/listen at fd -100),
            proc 272, sysc 0x00007f7fff9fe840,
            pc/frame 0xffffffffc201948a 0xfffffff000017ad8

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoFix FD leak in pipe (XCC)
Barret Rhoden [Thu, 23 Feb 2017 15:56:43 +0000 (10:56 -0500)]
Fix FD leak in pipe (XCC)

We weren't closing the dirfd.  You'd notice this after a lot of ssh
connections, since the pipes would build up.  They weren't closed and were
getting passed to dropbear's children.  After a dozen scps, if you looked
at the open files for a new ssh + shell connection, you'd see a dozen pipe

Rebuild glibc, eventually.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoUpdate bt-akaros.sh
Barret Rhoden [Wed, 22 Feb 2017 19:13:55 +0000 (14:13 -0500)]
Update bt-akaros.sh

Two changes:
- It uses nm with demangling, so we get better backtraces from C++ programs
- It caches symbol tables for binaries, such that we run nm only once per
  object.  Between that and grep, it speeds up the backtrace for large

You'll need Bash version 4 or later, though you probably have it already.
If not, use the old script on your own.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoepoll: Fire existing events during EPOLL_CTL_ADD
Barret Rhoden [Fri, 17 Feb 2017 19:08:38 +0000 (14:08 -0500)]
epoll: Fire existing events during EPOLL_CTL_ADD

On Linux, if you ask for an edge-triggered epoll, the kernel happens to
send you an event based on the current status when you sign up,

Specifically, this will return with an EPOLLOUT event:
- epoll_create()
- socket(SOCK_DGRAM)
- epoll_ctl_add(EPOLLOUT | EPOLLET)
- epoll_wait()

Even though you're only supposed to epoll_wait() on an edge-triggered event
*after* you've attempted I/O and got EAGAIN.

However, our epoll() tries to act like Linux's, and some buggy programs
may expect Linux's epoll's behavior.

Note that this change may result in spurious notifications.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoAdd sys_send_event() (XCC)
Barret Rhoden [Fri, 17 Feb 2017 19:04:53 +0000 (14:04 -0500)]
Add sys_send_event() (XCC)

This syscall sends an event message to a specific event queue.  Given that
it's all in the user's shared memory, I didn't make a version of this that
works between processes.  Without a way for the target process to specify
the ev_q pointer, (such as the the kernel_events array), it seems extremely
dangerous to do IPC with this.

It's actually possible for userspace to post messages to its mboxes, under
certain circumstances.  In the future, I might have a parlib function that
tries that and falls back to the kernel for the cases where the user could
not do it.

Reinstall your kernel headers.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>