memory: Global page buffer pool

Currently, we maintain a percpu page buffer pool for page allocator.
When the pool is empty or full, the global mutex free_page_ranges_lock
is take to refill or unfill the pool.

This patch introduces a global page buffer pool in addition to the
percpu page buffer pool.

1) L1-pool (Percpu page buffer pool)

if nr < max * 1 / 4
   refill

if nr > max * 3 / 4
   unfill

2) L2-pool (Global page buffer pool)

if nr < max * 1 / 4
   refill

if nr > max * 3 / 4
   unfill

When L1-pool needs refill or unfill, it moves a batch of pages from or to
L2-pool.

When L2-pool needs refill or unfill, it move a batch of pages from or to
global free page list.

Some notes:

- On fast path, both L1 and L2 allocation/deallocation require no lock.

- Atomic operations amortized to a large number of pages.
  Pages are exchanged in batch (currently 32 pages) between L1 and L2
  and global pool.

- Percpu threads are added for L1-pool refill/unfill. This looks
  over-killing, but there seems no other better way to do it.
  One option is to use async::run_later interface, but the refill/unfill
  operation will block, thus blocking other tasks on the same cpu.
  Another option is to use core/percpu-worker.cc interface. Again, it
  will block other tasks. For now, I am using per-cpu thread approach.

- nr_cpus(L1 pool) + 1(L2 pool) additional threads are added compared to
  current allocator. These threads help filling the pool more
  aggressively: at 1/4 - 3/4 level, compared to 0 - 1 level.

Tests:

1) I used /tests/misc-malloc.so to stress memory allocation/deallocation.

   for i in `seq 100`; do
       sudo scripts/run.py -nv -c16 -m16g -e "/tests/misc-malloc.so";
   done

100 round of tests passed.

2) tomcat + wrk

Running 10s test @ http://192.168.122.89:8081/servlet/json
Running 1m test @ http://192.168.122.89:8081/servlet/json

20 round of tests passed

Signed-off-by: Asias He <asias@cloudius-systems.com>
Signed-off-by: Avi Kivity <avi@cloudius-systems.com>
page scanner changes too sharp

I am currently running redis, and top.py shows the page scanner eating up 4 %
of my CPU. For the record, I don't see that on EC2 at all. In there, it barely
touches 0.5 %. Maybe my local CPU is just slower ?

Back to the patch, redis does not use mmap at all. The only mappings we have,
are the initial mappings that happen when we load the ELF libraries, during
initialization. When tracing the access pattern, I could see that in two interwined
runs, one of them would have _cpu set to 0.1 % - the minimum, while the other would
have it set to 20 % - the maximum.

The sharp changes would definitely explain the 4 % figures. What this patch
tries to do, is to use _cpu instead of _max_cpu as a correction factor for the
next _cpu calculation.  This way, even if we have a burst of scans, we will
increase it slowly, rather than drastically. If the scan rate persists being high,
we will then increasing it until the maximum.

With this patch, the trace output looks a lot smoother:

0x0000000000df63f0 page-access-sca  0        25.381661111 access_scanner       scanned=1, cleared=0, %cpu=0.1
0x0000000000df63f0 page-access-sca  0        25.382729839 access_scanner       scanned=25, cleared=23, %cpu=0.46
0x0000000000df63f0 page-access-sca  0        25.383742419 access_scanner       scanned=35, cleared=11, %cpu=0.722857
0x0000000000df63f0 page-access-sca  0        25.384820323 access_scanner       scanned=61, cleared=10, %cpu=0.592506
0x0000000000df63f0 page-access-sca  0        25.385900359 access_scanner       scanned=99, cleared=8, %cpu=0.239396

And cpu usage, as shown by top.py, is usually averaging around 0.8 %.

Signed-off-by: Glauber Costa <glommer@cloudius-systems.com>
Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
tests: add benchmark for timeslice length

This patch adds a tests/misc-timeslice.cc, a simple benchmark running two
cpu-hog threads and seeing what time slice each one gets (i.e., how often
do we switch between the two threads).

The same test can run on both Linux and OSv, so we can use it to callibrate
our choice of thyst (or whatever other mechanism we'll use for controlling
the time slice).

Running this on my own Linux host, I see it is using a 10ms time slice.

When we run it on OSv, we see a 1ms time slice. Sadly, this has nothing to
do with our intentional choice of our scheduler (thyst is higher than 1ms).
Rather what causes switching every 1ms is the unrelated "page access scanner"
thread. This thread runs every 1ms for an extremely short duration, and when
it stops running, the scheduler again picks the thread with least runtime,
without letting the thread that was running earlier complete its time slice
(its thyst advantage was taken away from it when it stopped running for the
page access scanner).

If I disable the page access scanner, I see the average timeslice is 3.95ms,
which is thyst*2 (thyst=2_ms), as expected.

This benchmarks suggests we should:

1. change thyst from 2_ms to 5_ms, to callibrate the time slices of cpu hogs
   like Linux.

2. Rethink page access scanner's desire to run 1000 times a second. Why 1000?
   Alternatively, if we woke the scanner thread 1000 times a second but did
   *not* reschedule at that point, we could get it running 1000 times a second
   when there are already many context switches - but running fewer times
   when there are few context switches.

Signed-off-by: Nadav Har'El <nyh@cloudius-systems.com>
Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
x64/misc.bin: update to latest

It has libraries that are needed by OpenSSL.

Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com>
httpserver: tests: fix invalid use of assert_between()

The method takes 4 parameters, not 3. Causes run-time error.
httpserver: tests: fix assetion failure in testfile.py

Fixes assetion failure with message: u'666' != 666

The 'permission' field is a string not an integer
libc: implement __fread_chk()

It is needed by RAND_load_file() from OpenSSL.
modules: add libz module

It is needed by both java and openssl
modules: make java depend on libz
modules: add openssl module
httpserver: link against boost_program-options which matches the includes

We use includes from misc.bin but shared object from the host. When I
linked against boost_program-options.so which I have on the host I
got:

obj/main.o: In function `boost::program_options::basic_command_line_parser<char>::run()':
/home/tgrabiec/src/osv/mgmt/httpserver/../../external/x64/misc.bin/usr/include/boost/program_options/detail/parsers.hpp:107: undefined reference to `boost::program_options::detail::cmdline::get_canonical_option_prefix()'
collect2: error: ld returned 1 exit status
httpserver: make: make 'init' target phony
httpserver: make: simplify rules
httpserver: make: link against openssl
httpserver: make: do not use relative paths

They're evil, this is broken with relative paths:

 cd $(src) && SOME_PATH=$(src)
httpserver: template API docs on the protocol name
httpserver: remove unused field
httpserver: abstract away HTTP transport

This will allow to switch between HTTP/HTTPS at run time.
modules: introduce run_on_init() declaration

api.run_on_init(cmdline) means that cmdline should be executed at init
time as if a file was put inside /init directory with '30-'
prefix.

The order in which commands declared this way will run depends on the
order in which modules depend on each other. Dependant modules will
run before modules which depend on them which means automatic priority
assignment.

The motivation for this change is to allow "run on init" behavior to
be optional, depending on the chosen run configuration. For example
some times we want HTTP server to run as daemon and some times as
standalone app. It's simplest to reuse an already present run
configuration mechanism for that.
httpserver: introduce .fg run configuration

When image is built like this:

  make image=httpserver.fg

OSv will wait for it before exiting. "fg" is for "foreground". It can
be useful when we want to have a generic image with just the API
through which commands will be started externally.