3 years agonet: tcp: Advertise support for SACK
Barret Rhoden [Tue, 20 Jun 2017 19:58:40 +0000 (15:58 -0400)]
net: tcp: Advertise support for SACK

TCP Selective Acknowledgment.  We don't do anything with it yet.  We can
disable it at compile time (change SACK_SUPPORTED) if our support breaks
anything.  We can also add run-time support in the future.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: tcp: Remove the Syn_received state
Barret Rhoden [Tue, 20 Jun 2017 19:05:18 +0000 (15:05 -0400)]
net: tcp: Remove the Syn_received state

I think Presotto's note was right: you should send a reset.  The situation
is when we sent a SYN, then we receive a SYN without an ACK.  That was the
only time we'd set Syn_received, and a reset is safer.  I think.

It also removes a bunch of code that pretty much never runs, except during

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: tcp: Support TCP timestamps
Barret Rhoden [Mon, 19 Jun 2017 19:40:00 +0000 (15:40 -0400)]
net: tcp: Support TCP timestamps

We don't do anything with the info yet - we just add them and respond to
them.  This helps our distant end with various things.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: tcp: Refactor TCP6 and 4 common code
Barret Rhoden [Mon, 19 Jun 2017 19:22:36 +0000 (15:22 -0400)]
net: tcp: Refactor TCP6 and 4 common code

htontcp{4,6} and ntohtcp{4,6} have a lot of duplicate code.  This commit
pulls out the common option and block allocation code.  We might be able to
do something with checksum offload and other bits in the future.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: tcp: Fix memory leak with tcpackproc
Barret Rhoden [Mon, 19 Jun 2017 18:40:01 +0000 (14:40 -0400)]
net: tcp: Fix memory leak with tcpackproc

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: tcp: Account for TCP options when using MSS
Barret Rhoden [Mon, 19 Jun 2017 18:22:46 +0000 (14:22 -0400)]
net: tcp: Account for TCP options when using MSS

The advertised MSS reflects the MTU of the host.  It is the largest packet
we'll send out, not including MAC, default IP, and default TCP headers.  If
we have extra TCP options, like the timestamps or SACKs, then those bytes
count against the advertised MSS.

We have a couple uses of the MSS.  The typical_mss is used for cwnd
calculations - it's the amount of data (not options) we expect to send.
The payload_mss is the actual amount we send for a given packet.  This may
vary since some options are only added to some packets for a given stream.

This wasn't a problem before since we only sent TCP opts on SYN or SYN/ACK
packets, which weren't close to the MSS.  We don't use this feature in this
commit, but we will shortly.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: tcp: Always set the retrans timer
Barret Rhoden [Mon, 19 Jun 2017 18:06:53 +0000 (14:06 -0400)]
net: tcp: Always set the retrans timer

The check was for the largest possible packet.  With TSO, we send a lot of
different packet sizes, so the largest-packet check doesn't make as much

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: tcp: Adjust the transmit queue limit
Barret Rhoden [Mon, 19 Jun 2017 15:18:37 +0000 (11:18 -0400)]
net: tcp: Adjust the transmit queue limit

If we don't grow the queue limit as the cwnd grows, TCP blocks on waiting
for more data from the user.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: tcp: Fix cwnd and ssthresh for TSO and Reno
Barret Rhoden [Wed, 14 Jun 2017 19:22:21 +0000 (15:22 -0400)]
net: tcp: Fix cwnd and ssthresh for TSO and Reno

RFC 5681 suggests the ssthresh initially be arbitrarily high.  Older RFCs
suggested the old value of 64K.  This is the cutoff where slow-start stops
and we enter the congestion avoidance.

The cwnd (congestion window, managed by the sender) has been suggested to
start at 10 * MSS, instead of 1.  (https://lwn.net/Articles/427104/).

Also, we weren't growing our cwnd properly.  For every ACK, we'd increase
it by MSS.  That assumes an ACK only consists of one MSS (or less).  We
were handling the 'or less' case, but if an ACK covered 10 MSS, we'd only
advance by 1 MSS.  This is possible when using TSO.

If 'expanded = acked' seems too simple, consider we'd want this:

expanded = (acked / MSS) * MSS + acked % MSS;

which is just

expanded = acked;

Similarly, we weren't accounting for large packets during the congestion
avoidance phase.

Finally, I used the Reno algorithm for adjusting ssthresh and cwnd when we
have a loss.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agokprof: Allow clearing the kptrace buffer
Barret Rhoden [Tue, 11 Jul 2017 15:10:26 +0000 (11:10 -0400)]
kprof: Allow clearing the kptrace buffer

This also adds a slimmed down version of dmesg, which also supports -c.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoqio: Allow changing limits dynamically
Barret Rhoden [Mon, 19 Jun 2017 15:03:33 +0000 (11:03 -0400)]
qio: Allow changing limits dynamically

The queue's limit is the point at which writers get blocked.  Specifically,
they block once the qlen crosses the limit - the actual write succeeds.

The tricky bit is that if you increase the limit, some writers may become
unblocked.  Similarly, the queue may become writable, which requires us to
fire a tap.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoRemove the #define exit() _exit() hack (XCC)
Barret Rhoden [Thu, 8 Jun 2017 21:14:49 +0000 (17:14 -0400)]
Remove the #define exit() _exit() hack (XCC)

The atexit handlers might do dangerous things that can't be done in vcore
context.  The old note mentioned yielding, which we could work around, but
other handlers can block too. (confirmed by testing).

So we retain the "exit -> _exit" behavior for vcore context, but not for
uthreads.  Importantly, the change is done in glibc, instead of macro
nastiness.  This popped up when someone wanted to call a function pointer
named 'exit.'

Fun tidbit, this hack might have predated threads.  It came in less than a
week after the first pthread scheduler commit.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agomlx4: Fix NAPI polling
Barret Rhoden [Mon, 26 Jun 2017 16:26:12 +0000 (12:26 -0400)]
mlx4: Fix NAPI polling

I triggered this by trying to send a lot of packets at once, specifically
by removing the kthread_yield() from tcp.c.  When we poll and exceed the
budget, in Linux the NAPI code will call the poll function again.  We
weren't, and we weren't rearming the NIC's TX IRQ.  Then we'd never be able
to send another packet, since the transmit ring would always be full.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agomlx4: Fix transmit flow control and concurrency
Barret Rhoden [Thu, 22 Jun 2017 20:16:31 +0000 (16:16 -0400)]
mlx4: Fix transmit flow control and concurrency

We had no way to put backpressure on the network stack, and if you sent
packets fast enough, you'd overflow the NIC's TX queues, and get a "CQ

Also, I noticed we had no protection for concurrency.  If we had two
concurrent transmitters, they would fight for slots in the ring.  The worst
I could come up with was one flow could get another's payload (consider
TSO'd packets, but someone else's packet replaces one of your frags).
That'd be another nightmare to debug.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoReplacing timer support for VM Guests (XCC)
Gan Shun [Tue, 11 Jul 2017 21:52:10 +0000 (14:52 -0700)]
Replacing timer support for VM Guests (XCC)

The old vm timer was a single thread that poked at all cores regardless
of the actual time the guest set the alarm for.

The new timers use the parlib alarm infrastructure, and actually sets up
independent timers for all cores so that we can properly emulate per-core
lapic timers.

Reinstall your kernel headers

Change-Id: I05bddbfb93b8ad62078e688175b54917b151cfaf
Signed-off-by: Gan Shun <ganshun@gmail.com>
[used gth_to_vmtf(), XCC warning]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoRemove MWAIT functionality from the VM guest.
Gan Shun [Tue, 11 Jul 2017 21:14:04 +0000 (14:14 -0700)]
Remove MWAIT functionality from the VM guest.

Turns out linux uses MONITOR/MWAIT to wake up AP cores when they have
work. We don't support proper MONITOR/MWAIT for VM guests so our only
solution right now is to turn it off.

Turns out this is the reason SMP VM guests were slow. The issue wasn't
the timer at all, but my old implementation of the timer covered up the
bug as I rammed every core with timer interrupts. That masked the fact
that guest cores were waiting on some address that we never actually

Signed-off-by: Gan Shun <ganshun@gmail.com>
Change-Id: Ie21f8137aa2ec2312f907b8fd4b6c9685fdf5a9d
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmm: Modifed load_elf to allow an offset
Zach Zimmerman [Fri, 30 Jun 2017 22:36:36 +0000 (15:36 -0700)]
vmm: Modifed load_elf to allow an offset

Change-Id: I897abff7b8bcbcaf9743eeed51d67da9a09a0afc
Signed-off-by: Zach Zimmerman <zpzim@google.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agodune: gettimeofday fix
Zach Zimmerman [Fri, 30 Jun 2017 22:05:58 +0000 (15:05 -0700)]
dune: gettimeofday fix

Change-Id: I5c14e66d7055c05b4838c8e3b1b7815fef8350bc
Signed-off-by: Zach Zimmerman <zpzim@google.com>
[minor formatting]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agodune: working test with emulated syscalls
Ronald G. Minnich [Mon, 21 Nov 2016 22:09:46 +0000 (14:09 -0800)]
dune: working test with emulated syscalls

Dune is working with dune_test as a vm to test vmcall functionality

Change-Id: Iead546ccfb405519db525f4e5b81a1bb1e647517
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Zach Zimmerman <zpzim@google.com>
[minor formatting, removed redundant #defines for MiB and MinMemory]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoAdding .travis.yml
Gan Shun [Wed, 14 Jun 2017 17:22:08 +0000 (10:22 -0700)]
Adding .travis.yml

This allows us to test automated builds on travis, and the results are
sent to akaros-travis@googlegroups.com

Signed-off-by: Gan Shun <ganshun@gmail.com>
Change-Id: I87e216346da0d99e67e428c4f056c67a904f96be
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoReduce verbosity of some make commands
Gan Shun [Fri, 9 Jun 2017 20:32:18 +0000 (13:32 -0700)]
Reduce verbosity of some make commands

Redirect the outputs of the toolchain build to
tools/compilers/gcc-glibc/build_logs and the outputs of make
apps-install and apps-clean to $AKAROS_ROOT/build_logs

This change also fixes a bug in unsetting multiline environment

Signed-off-by: Gan Shun <ganshun@gmail.com>
Change-Id: Iac496c3e01853e6e97f31345a86256ce7b2c1284
[for apps-targets, changed 'info' -> 'echo']
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoModify adt to use symbolic-ref
Gan Shun [Thu, 8 Jun 2017 21:35:04 +0000 (14:35 -0700)]
Modify adt to use symbolic-ref

Signed-off-by: Gan Shun <ganshun@gmail.com>
Change-Id: I941e805029753bf543a0f75876f3bbe4e32de7de
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoefence: clang-format
Barret Rhoden [Tue, 6 Jun 2017 21:13:50 +0000 (17:13 -0400)]
efence: clang-format

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoefence: Fix it all and add a test
Barret Rhoden [Tue, 6 Jun 2017 20:54:01 +0000 (16:54 -0400)]
efence: Fix it all and add a test

To use it, link with -lelectric-fence.  You can do this from your top-level
Makelocal.  e.g. CFLAGS_USER or _TESTS += -lelectric-fence.

This doesn't support C++.  For that, we can look into libduma or something.

The biggest pain was that gcc was optimizing away internalUse and other
flag variables.  That's because it knows about malloc(), but doesn't know
that we are overriding it.  So we have to disable that optimization.

The other thing was locking: first off, our trylock returns a bool (TRUE or
FALSE), not an int (0 or 1).  Second, malloc and free are called from vcore
context, so we can't use a mutex.  Much like with Glibc's malloc lock, we
need to use spin_pdr locks.  Finally, we need to lock inside memalign, not
in the outer functions.  Specifically, someone could be calling memalign
directly and be unprotected.  There's nothing in malloc/calloc/valloc/etc
that needs to be protected.

I also added wrappers for functions like posix_memalign(), and removed the
obnoxious version printing.  I removed tstheap, put its guts in one of our
utests, and added a test for catching faults.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoelectric-fence: builds and boots
Ronald G. Minnich [Wed, 31 May 2017 17:00:14 +0000 (10:00 -0700)]
electric-fence: builds and boots

tstheap fails:

Unhandled user trap from early SCP

in uthread_yield, some other dumb mistake I'm making.

Change-Id: Ib1428dcb2a8c1984352e2adc4c8dea050d497e48
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoelectric-fence: changed Makefile to Akaros style
Ronald G. Minnich [Tue, 30 May 2017 15:19:23 +0000 (08:19 -0700)]
electric-fence: changed Makefile to Akaros style

Change-Id: I3a8e699c4aadd4e12f13efb0de06f3410e42bc53
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoelectric fence: initial checkin
Ronald G. Minnich [Tue, 30 May 2017 15:17:30 +0000 (08:17 -0700)]
electric fence: initial checkin

This is from git@github.com:CheggEng/electric-fence
commit 7199c87ec6df05cff6b0faa0b7114b02b53dffe1

I did not include the debian/ directory.

Change-Id: If8a24910791fc469f4c51734cfc98471829f78d3
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agovmm: Fix use-after-free in load_elf()
Barret Rhoden [Tue, 6 Jun 2017 19:45:57 +0000 (15:45 -0400)]
vmm: Fix use-after-free in load_elf()

elf_end() frees various structures, so you can't access ehdr anymore.  This
was caught by electric fence.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoRemove pthread_lib_init() declaration
Barret Rhoden [Tue, 6 Jun 2017 19:45:26 +0000 (15:45 -0400)]
Remove pthread_lib_init() declaration

The function went away a month or two ago.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoFix a deadlock in mprotect()
Barret Rhoden [Fri, 2 Jun 2017 00:19:48 +0000 (20:19 -0400)]
Fix a deadlock in mprotect()

We wouldn't make forward progress if you tried to mprotect() a region
that already had those protections.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agomlx4: Support TSO/GSO/LSO
Barret Rhoden [Tue, 6 Jun 2017 17:01:42 +0000 (13:01 -0400)]
mlx4: Support TSO/GSO/LSO

The changes were taken from the Linux transmit function.  I added back in
the 'linear' checks (meaning, is there data in the block main body),
ignored the 'inline' stuff, and turned on LSO (a.k.a. TSO/GSO).

Also, there was a bug with the xsum flags.  Bipck is never set by the
stack, so we weren't setting a flag that Linux always sets.  We do the IP
header xsum in software - it's just 20 bytes.  However, the Bipck flag is
used by drivers to tell the stack that the NIC did the IP header xsum.
That's just the way it works for Plan 9.  This all popped up because LSO'd
packets had incorrect header xsums.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: Add accounting to help TSO/LSO/GSO
Barret Rhoden [Fri, 2 Jun 2017 22:21:44 +0000 (18:21 -0400)]
net: Add accounting to help TSO/LSO/GSO

The NIC will need to know how big the transport headers are.  The easiest
way is to just have the protocol tell us.  I used the same style as the
checksum_start, where we track the relative value from bp->rp.

Note that although I track the transport_header_end in UDP, we don't have
UDP GSO support elsewhere in the stack.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Expand our printf hacks
Barret Rhoden [Fri, 26 May 2017 19:23:46 +0000 (15:23 -0400)]
parlib: Expand our printf hacks

The hacked versions of printf() now return values and have a vfprintf()
variant.  Dropbear needed these.

Unfortunately, anyone who tries to printf from signal handlers, which are
currently executed in vcore context for IPC, will need to manually #include
<parlib/stdio.h>.  We might be able to get the regular stdio.h to include
it, but my feeble attempts couldn't get the toolchain to build.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: Add a function to dump TCP's hash table
Barret Rhoden [Fri, 26 May 2017 19:22:00 +0000 (15:22 -0400)]
net: Add a function to dump TCP's hash table

Kfunc this from the monitor.  This was useful debugging failed TCP

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoAdd a test for partial writes
Barret Rhoden [Fri, 26 May 2017 18:26:58 +0000 (14:26 -0400)]
Add a test for partial writes

This will catch the qio and Inferno rwrite() bugs.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoqio: Track the amount of bytes read
Barret Rhoden [Fri, 26 May 2017 16:49:33 +0000 (12:49 -0400)]
qio: Track the amount of bytes read

This was useful for debugging.  You can see the amount of bytes via 'pip'.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoqio: Fix potential memory leak in __qbread()
Barret Rhoden [Fri, 26 May 2017 16:41:11 +0000 (12:41 -0400)]
qio: Fix potential memory leak in __qbread()

The race could happen where we __try_qbread(), see we need a spare to split
the first block, but when we go in the next time the queue is empty or some
other condition that triggers an error().

Like with __qwrite(), only some callers are allowed to use waserror and
throw, so we need to be careful about when we do the error unwinding.

Also, for whatever reason, we need these volatiles when dealing with
waserror().  I checked the ASM again, and the compiler will not realize
that 'spare' could have changed, despite the "returns twice" attribute
deeper in waserror().

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoqio: Report partial progress for NONBLOCK queues
Barret Rhoden [Thu, 25 May 2017 20:10:45 +0000 (16:10 -0400)]
qio: Report partial progress for NONBLOCK queues

__qbwrite() can throw for many reasons, including EPIPE (closed queue),
EAGAIN (full for now), and EINTR (syscall aborted).  However, large
qwrites, meaning greater than Maxatomic, get broken into several block
writes.  Some could succeed before we catch the error, and we need to
report those successes as a partial write.

To make things a little trickier, __qwrite() is only allowed to throw based
on its qio flags.  Other times waserror() might be dangerous, such as in
irq context.

This came up by writing large blocks to a non-blocking pipe.  The writer
thought that none of the write made it, so it kept writing the same blocks
over and over.  However, each time the first block (at least) was actually
written.  The reader received that first block over and over.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoFix Plan 9 partial write() return values
Barret Rhoden [Thu, 25 May 2017 20:07:33 +0000 (16:07 -0400)]
Fix Plan 9 partial write() return values

We were returning the value that the user attempted to write, not the
amount that actually made it.

Note that the proper way for a device to return -1 is to throw an error(),
which we catch in rwrite().  If a device's write method actually returns
-1, that'll screw things up.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: Improve a few netlogs
Barret Rhoden [Tue, 23 May 2017 18:09:53 +0000 (14:09 -0400)]
net: Improve a few netlogs

The ICMP and TCP log messages were a little sparse.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agonet: Support connects to
Barret Rhoden [Tue, 23 May 2017 18:07:48 +0000 (14:07 -0400)]
net: Support connects to

In Linux, is translated to mean "this machine."  We can do the

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agomlx4: Advertise that the NIC pads to mintu
Barret Rhoden [Tue, 23 May 2017 18:00:58 +0000 (14:00 -0400)]
mlx4: Advertise that the NIC pads to mintu

The minimum ethernet packet is 60 bytes.  A TCP/IP packet with no options
and no data is 40 bytes.  The ethernet MAC is 14 bytes.  The extra 6 bytes
need to come from somewhere.

Some NICs will pad those bits in hardware, including the mlx4.  If we pad
them in software, the NIC can get confused.  This showed itself as TCP ACKs
with bad checksums when we used checksum offload.  The NIC computed a value
that was off by 6 - the size of the padding.  Not sure why, exactly.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agox86: Get the boot time from CMOS
Barret Rhoden [Wed, 10 May 2017 19:46:57 +0000 (15:46 -0400)]
x86: Get the boot time from CMOS

We read this once at boot.  All future time checks should be based on the
walltime_ns_last.  One of these days, we'll update that field when we get
info from e.g. NTP.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoSet the hostname, if provided, from ifconfig
Barret Rhoden [Wed, 10 May 2017 18:01:05 +0000 (14:01 -0400)]
Set the hostname, if provided, from ifconfig

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agox86: Fix KERNBASE mapping for > 512 GB RAM
Barret Rhoden [Wed, 10 May 2017 15:36:46 +0000 (11:36 -0400)]
x86: Fix KERNBASE mapping for > 512 GB RAM

The mapping was setting PTE_W, but not PTE_P.  This would have caused
faults whenever we tried to access those pages, which would have been
really nasty to track down.  I found this because of the panic in
__pte_to_epte_perm() (wasn't expected PTE_W only).

To be more clear in the code, we should be setting PTE_KERN_RW, which is
PTE_W | PTE_P.  Same goes for the VPT/UVPT mapping.  Those latter changes
were just in the naming of the flags.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Write to FD 2 for akaros_printf()
Barret Rhoden [Thu, 4 May 2017 18:48:15 +0000 (14:48 -0400)]
parlib: Write to FD 2 for akaros_printf()

And be a little more careful with snprint().

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoFix getifaddrs (XCC)
Barret Rhoden [Thu, 4 May 2017 18:44:58 +0000 (14:44 -0400)]
Fix getifaddrs (XCC)

There were a bunch of problems.  First, there was a buffer overflow with
the etheraddr, which was being used for the pathname.  That always went
over.  Second, the for loop for freeing the ifaddrs was wrong, since it'd
access ifa->ifa_next after ifa was freed.

Next up, it wasn't reporting the ethernet address in a way that anyone knew
to look for, and it didn't support IP addresses.

All of that should work now, though I didn't test IPv6.

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoAdd syscall tracing support to 'path' calls
Barret Rhoden [Wed, 3 May 2017 17:24:42 +0000 (13:24 -0400)]
Add syscall tracing support to 'path' calls

Syscalls like openat() already had their path argument added to the data
blob, but others like stat() and access() didn't.  I added support for all
of the syscalls that take path arguments.  This required adding a couple
helpers for building the trace data payload.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoFix snprintf() overflow issues
Barret Rhoden [Wed, 3 May 2017 16:25:08 +0000 (12:25 -0400)]
Fix snprintf() overflow issues

snprintf() is a pain.  Taking a 'negative' number for consecutive calls
after an overflow is a common pattern: see netif.c (derived from Plan 9)
and mlx4/mcg.c (from Linux).  We had been taking an int for the size, but
ought to be taking a size_t - if for nothing else than to make the change
now *and* adding the check, instead of later without the check.

On a similar note seprintf() was using its return value incorrectly.  The
uses of seprintf() seemed ok, since no one used "buf + rc" for anything
other than 'start' for another seprintf() call.  We could have seprintf()
do the same thing as snprintf(), but it seems a little dangerous to return
a pointer outside the [start, end) range.

One thing to remember is that if seprintf()/snprintf() overflowed, we
probably don't have a null-terminated buffer.  Some of our call sites might
not like that.

Similarly, the logic in parlib for detecting overflow was just wrong.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agopthreads: Remove sched_policy and sched_priority
Barret Rhoden [Fri, 28 Apr 2017 19:19:10 +0000 (15:19 -0400)]
pthreads: Remove sched_policy and sched_priority

We never actually supported this - we just faked it.  We'll continue to
fake it, but won't track the faked values in the thread struct.

If it turns out that the pthreads interface is the best way for apps to
influence a 2LS, then we can hook these functions up to real 2LS ops.
Until then, we'll go with the "application-specific" nature of the 2LS,
where the 2LS itself is made to work with a particular app.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agopthread: Make pthread barriers 2LS-independent
Barret Rhoden [Fri, 28 Apr 2017 16:36:44 +0000 (12:36 -0400)]
pthread: Make pthread barriers 2LS-independent

This is one step towards making pthreads a generic API that can be used
when *any* 2LS is used.  Long term, we'll need that so library code can
make pthread calls (e.g. pthread_create(), pthread_mutex_lock(), etc.) and
access the real 2LS.  The alternative is porting every POSIX library that
wants to grab a thread.

Thanks to the previous commits, we're able to swap in uthreads for pthreads
and use sync object with bulk wakeups directly.  The first couple
implementations of this didn't have bulk wakeups or called
uthread_has_blocked() while holding the barrier's lock.  Both of those
noticeably hurt performance.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add a thread_bulk_runnable() 2LS op
Barret Rhoden [Fri, 28 Apr 2017 16:31:29 +0000 (12:31 -0400)]
parlib: Add a thread_bulk_runnable() 2LS op

If the 2LS knows it is waking up N threads, it can make better decisions or
otherwise perform better.  This gives us a 3x improvement on
pthread barriers.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
3 years agoparlib: Add __uth_sync_swap and __uth_sync_is_empty
Barret Rhoden [Fri, 28 Apr 2017 16:14:19 +0000 (12:14 -0400)]
parlib: Add __uth_sync_swap and __uth_sync_is_empty

These are helper methods, useful for bulk wakeups.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
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>