]> rtime.felk.cvut.cz Git - l4.git/commitdiff
update
authorl4check <l4check@d050ee49-bd90-4346-b210-929a50b99cfc>
Mon, 12 Jan 2015 21:57:36 +0000 (21:57 +0000)
committerl4check <l4check@d050ee49-bd90-4346-b210-929a50b99cfc>
Mon, 12 Jan 2015 21:57:36 +0000 (21:57 +0000)
git-svn-id: http://svn.tudos.org/repos/oc/tudos/trunk@67 d050ee49-bd90-4346-b210-929a50b99cfc

205 files changed:
l4/pkg/ferret/COPYING [new file with mode: 0644]
l4/pkg/ferret/Control [new file with mode: 0644]
l4/pkg/ferret/Makefile [new file with mode: 0644]
l4/pkg/ferret/README [new file with mode: 0644]
l4/pkg/ferret/TODO [new file with mode: 0644]
l4/pkg/ferret/examples/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/dp_test/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/dp_test/broken [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/dp_test/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/performance/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/performance/perf.c [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/performance/threads.c [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/pthread_test/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/pthread_test/broken [new file with mode: 0644]
l4/pkg/ferret/examples/benchmarks/pthread_test/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/demo/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/demo/gcc_instrument/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/demo/gcc_instrument/broken [new file with mode: 0644]
l4/pkg/ferret/examples/demo/gcc_instrument/gen.c [new file with mode: 0644]
l4/pkg/ferret/examples/demo/gcc_instrument/std.c [new file with mode: 0644]
l4/pkg/ferret/examples/demo/histo_demo/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/demo/histo_demo/broken [new file with mode: 0644]
l4/pkg/ferret/examples/demo/histo_demo/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/demo/l4linux_user/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/demo/l4linux_user/broken [new file with mode: 0644]
l4/pkg/ferret/examples/demo/l4linux_user/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/demo/list_demo/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/demo/list_demo/broken [new file with mode: 0644]
l4/pkg/ferret/examples/demo/list_demo/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/demo/list_demo_re/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/demo/list_demo_re/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/demo/scalar_demo/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/demo/scalar_demo/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/demo/test/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/demo/test/broken [new file with mode: 0644]
l4/pkg/ferret/examples/demo/test/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/demo/ulist_demo/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/demo/ulist_demo/broken [new file with mode: 0644]
l4/pkg/ferret/examples/demo/ulist_demo/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/l4lx_arping/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/l4lx_arping/arping.c [new file with mode: 0644]
l4/pkg/ferret/examples/l4lx_arping/broken [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/common/uu.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/common/uu.h [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/dope_control/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/dope_control/README [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/dope_control/broken [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/dope_control/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/dope_control/main_window.dpe [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/idle_switch_mon/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/idle_switch_mon/broken [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/idle_switch_mon/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_control/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_control/README [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_control/broken [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_control/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_histo_mon/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_histo_mon/broken [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_histo_mon/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_verify_tamed_mon/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_verify_tamed_mon/broken [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/l4lx_verify_tamed_mon/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/TODO [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/buffer.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/buffer.h [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/gui.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/gui.h [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/main.h [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/main_window.dpe [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/net.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/net.h [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/poll.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/merge_mon/poll.h [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/simple_mon/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/simple_mon/broken [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/simple_mon/main.c [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/simple_mon_re/Makefile [new file with mode: 0644]
l4/pkg/ferret/examples/monitors/simple_mon_re/main.c [new file with mode: 0644]
l4/pkg/ferret/include/Makefile [new file with mode: 0644]
l4/pkg/ferret/include/client.h [new file with mode: 0644]
l4/pkg/ferret/include/clock.h [new file with mode: 0644]
l4/pkg/ferret/include/comm.h [new file with mode: 0644]
l4/pkg/ferret/include/fpages.h [new file with mode: 0644]
l4/pkg/ferret/include/gcc_instrument.h [new file with mode: 0644]
l4/pkg/ferret/include/l4lx_client.h [new file with mode: 0644]
l4/pkg/ferret/include/local_names.h [new file with mode: 0644]
l4/pkg/ferret/include/maj_min.h [new file with mode: 0644]
l4/pkg/ferret/include/monitor.h [new file with mode: 0644]
l4/pkg/ferret/include/monitor_list.h [new file with mode: 0644]
l4/pkg/ferret/include/sensordir.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/__dplist_magic.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/__llist.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/__llist_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/__llist_init.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/__llist_producer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/__llist_producer_local.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/__slist_magic.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/__ulist_magic.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/alist.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/alist_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/alist_init.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/alist_producer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/common.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/dplist.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/dplist_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/dplist_init.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/dplist_producer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/histogram.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/histogram_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/histogram_init.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/histogram_producer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/list.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/list_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/list_init.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/list_producer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/list_producer_wrap.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/llist.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/scalar.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/scalar_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/scalar_init.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/scalar_producer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/slist.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/slist_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/slist_init.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/slist_producer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/tbuf.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/tbuf_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/ulist.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/ulist_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/ulist_init.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/ulist_producer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/vlist.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/vlist_consumer.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/vlist_init.h [new file with mode: 0644]
l4/pkg/ferret/include/sensors/vlist_producer.h [new file with mode: 0644]
l4/pkg/ferret/include/types.h [new file with mode: 0644]
l4/pkg/ferret/include/util.h [new file with mode: 0644]
l4/pkg/ferret/lib/Makefile [new file with mode: 0644]
l4/pkg/ferret/lib/common/Makefile [new file with mode: 0644]
l4/pkg/ferret/lib/common/comm.cc [new file with mode: 0644]
l4/pkg/ferret/lib/common/convert.cc [new file with mode: 0644]
l4/pkg/ferret/lib/common/pack.cc [new file with mode: 0644]
l4/pkg/ferret/lib/common/unpack.cc [new file with mode: 0644]
l4/pkg/ferret/lib/common/util.cc [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/Makefile [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/__llist_consumer.c [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/alist_consumer.c [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/dplist_consumer.c [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/histogram_consumer.c [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/list_consumer.c [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/monitor.cc [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/scalar_consumer.c [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/slist_consumer.c [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/tbuf_consumer.c [new file with mode: 0644]
l4/pkg/ferret/lib/consumer/ulist_consumer.c [new file with mode: 0644]
l4/pkg/ferret/lib/fpages/Makefile [new file with mode: 0644]
l4/pkg/ferret/lib/fpages/broken [new file with mode: 0644]
l4/pkg/ferret/lib/fpages/fpages.c [new file with mode: 0644]
l4/pkg/ferret/lib/gcc_instrument/Makefile [new file with mode: 0644]
l4/pkg/ferret/lib/gcc_instrument/broken [new file with mode: 0644]
l4/pkg/ferret/lib/gcc_instrument/instrument.c [new file with mode: 0644]
l4/pkg/ferret/lib/gcc_instrument/std_instrument.c [new file with mode: 0644]
l4/pkg/ferret/lib/local_names/Makefile [new file with mode: 0644]
l4/pkg/ferret/lib/local_names/broken [new file with mode: 0644]
l4/pkg/ferret/lib/local_names/local_names.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/Makefile [new file with mode: 0644]
l4/pkg/ferret/lib/producer/__llist_init.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/__llist_producer.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/alist_init.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/alist_producer.S [new file with mode: 0644]
l4/pkg/ferret/lib/producer/common.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/create.cc [new file with mode: 0644]
l4/pkg/ferret/lib/producer/create_dir.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/dplist_init.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/free.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/histogram_init.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/instance.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/l4lx_client.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/list_init.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/list_producer.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/scalar_init.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/slist_init.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/ulist_init.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/ulist_producer.c [new file with mode: 0644]
l4/pkg/ferret/lib/producer/vlist_init.c [new file with mode: 0644]
l4/pkg/ferret/server/Makefile [new file with mode: 0644]
l4/pkg/ferret/server/re/Makefile [new file with mode: 0644]
l4/pkg/ferret/server/re/main.cc [new file with mode: 0644]
l4/pkg/ferret/server/re/sensor.cc [new file with mode: 0644]
l4/pkg/ferret/server/re/sensor.h [new file with mode: 0644]
l4/pkg/ferret/server/re/sensordir.cc [new file with mode: 0644]
l4/pkg/ferret/server/sensor_directory/Makefile [new file with mode: 0644]
l4/pkg/ferret/server/sensor_directory/README [new file with mode: 0644]
l4/pkg/ferret/server/sensor_directory/clients.c [new file with mode: 0644]
l4/pkg/ferret/server/sensor_directory/clients.h [new file with mode: 0644]
l4/pkg/ferret/server/sensor_directory/dir.c [new file with mode: 0644]
l4/pkg/ferret/server/sensor_directory/dir.h [new file with mode: 0644]
l4/pkg/ferret/server/sensor_directory/sensors.c [new file with mode: 0644]
l4/pkg/ferret/server/sensor_directory/sensors.h [new file with mode: 0644]
l4/pkg/ferret/server/sensor_directory/server.c [new file with mode: 0644]
repomgr

diff --git a/l4/pkg/ferret/COPYING b/l4/pkg/ferret/COPYING
new file mode 100644 (file)
index 0000000..2199452
--- /dev/null
@@ -0,0 +1,6 @@
+The files in this package are for INTERNAL USE at the Operating
+Systems Research Group of the Technische Universität Dresden only!
+
+Please do not distribute this package or parts to other parties.
+
+Copyright (C) 2005  Martin Pohlack
diff --git a/l4/pkg/ferret/Control b/l4/pkg/ferret/Control
new file mode 100644 (file)
index 0000000..9334217
--- /dev/null
@@ -0,0 +1,4 @@
+provides: ferret-common ferret-producer ferret-consumer
+requires: l4sys log l4util libc l4re_c libboost-lite zlib stdlibs
+          dope libstdc++ libpthread
+Maintainer: doebel@os.inf.tu-dresden.de
diff --git a/l4/pkg/ferret/Makefile b/l4/pkg/ferret/Makefile
new file mode 100644 (file)
index 0000000..108f22b
--- /dev/null
@@ -0,0 +1,7 @@
+PKGDIR ?= .
+L4DIR  ?= $(PKGDIR)/../..
+
+include $(L4DIR)/mk/subdir.mk
+
+examples: lib
+server: lib
diff --git a/l4/pkg/ferret/README b/l4/pkg/ferret/README
new file mode 100644 (file)
index 0000000..3af9598
--- /dev/null
@@ -0,0 +1,16 @@
+This package is aimed at being the successor of rt_mon while
+incorporating my MS Research Cambridge experiences and some of
+grtmon's features.
+
+It is not fully working yet and will be an experimental testbed for my
+runtime monitoring stuff.
+
+Martin Pohlack
+
+
+FAQ:
+====
+
+Q: What does this package name 'ferret' mean?
+
+A: ferret - a very curious animal, investigating everything ...
diff --git a/l4/pkg/ferret/TODO b/l4/pkg/ferret/TODO
new file mode 100644 (file)
index 0000000..947d658
--- /dev/null
@@ -0,0 +1,83 @@
+L4Re
+====
+* sensors: list, histo
+* libs
+        client
+        comm
+        fpages
+        gcc_instrument
+        local_names
+        Makefile
+        monitor
+        sensors
+  [x]   util
+* demos
+        gcc_instrument
+        histo_demo
+        l4linux_user
+        list_demo
+        list_demo_re
+        Makefile
+        scalar_demo
+   [x]  scalar_demo_re
+        test
+        ulist_demo
+* monitors
+        common
+        dope_control
+        idle_switch_mon
+        l4lx_control
+        l4lx_histo_mon
+        l4lx_verify_tamed_mon
+        Makefile
+        merge_mon
+        simple_mon
+* server
+
+
+Ferret
+======
+ - try to optimize commit even more by using power of 2 sizes for
+   sensor buffers
+ - Remote Control:
+    - start now + send in x seconds to xyz.dat
+ - maybe use a cyclic buffer?
+ - support merging of several events to a larger one
+ - restructure client libs to use structs of function pointers for
+   common stuff
+ - define some error constants for the return cases
+ - check whether kernel buffer memory could be forwarded using a
+   dataspace, if so, do it this way, as clients do not depend so much
+   on the kernel debugger and monitor libs get simpler
+ - instrument something (e.g., DOpE)
+ - all list functions need a method to set their 'read_next' to now
+   and their lost count to 0
+ - map different thread / task ID schemes
+ - Merge_mon:
+    - Fix: update transfer progress after stopping receiving data
+    - Fix: Init. network transfer of data after STOP
+    - add support for stopping and starting tracing certain events in jdb
+ - Change all memory allocation in ferret client libs to something
+   else, which does not use the same heap as the other code (prevent
+   influencing the system by monitoring it)
+
+DONE:
+ - We need a conversion function to transform kernel events to a
+   common event format, or change the layout of kernel events to a
+   common format
+ - support reopen
+ - support super-pages to speed up performance (fewer TLB misses)
+ - We need a monitor which can merge several event streams and forward
+   them over network, serial cable, or dump them to disk  [-> MergeMon]
+ - provide L4VFS interface for sensor_directory
+ - care for malloc problem (different environments may not have a
+   malloc impl.)
+ - exchange position of index and element area for lists
+ - support instance in directory
+ - Support non-L4Env Tasks via dm_* clientlibs (function map_ds),
+   there should be no dependency on other L4Env stuff
+ - verify algorithms' correctnes using Spin or similar model checker
+   tools
+ - Remote Control:
+    - dump stats
+    - dump
diff --git a/l4/pkg/ferret/examples/Makefile b/l4/pkg/ferret/examples/Makefile
new file mode 100644 (file)
index 0000000..d5067cc
--- /dev/null
@@ -0,0 +1,6 @@
+PKGDIR ?= ..
+L4DIR  ?= $(PKGDIR)/../..
+
+TARGET = benchmarks demo monitors
+
+include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/ferret/examples/benchmarks/Makefile b/l4/pkg/ferret/examples/benchmarks/Makefile
new file mode 100644 (file)
index 0000000..8afc559
--- /dev/null
@@ -0,0 +1,6 @@
+PKGDIR ?= ../..
+L4DIR  ?= $(PKGDIR)/../..
+
+TARGET = dp_test pthread_test #performance
+
+include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/ferret/examples/benchmarks/dp_test/Makefile b/l4/pkg/ferret/examples/benchmarks/dp_test/Makefile
new file mode 100644 (file)
index 0000000..dd2808f
--- /dev/null
@@ -0,0 +1,19 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+DEFAULT_RELOC   = 0x00680000
+TARGET          = fer_dp_test
+
+MODE            = l4env_minimal
+
+LIBS           += -lferret_monitor -lferret_client -lferret_producer        \
+                  -lferret_consumer -lferret_util -lferret_comm             \
+                  -lferret_fpages -lferret_fpages -lferret_local_names
+
+#OPTS = -O3 -fomit-frame-pointer
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/benchmarks/dp_test/broken b/l4/pkg/ferret/examples/benchmarks/dp_test/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/benchmarks/dp_test/main.c b/l4/pkg/ferret/examples/benchmarks/dp_test/main.c
new file mode 100644 (file)
index 0000000..6c4a44e
--- /dev/null
@@ -0,0 +1,202 @@
+/**
+ * \file   ferret/examples/dp_test/main.c
+ * \brief  Testcase for delayed preemption lists.
+ *
+ * \date   2007-05-21
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <l4/log/l4log.h>
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/sys/syscalls.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/clock.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/monitor.h>
+#include <l4/ferret/sensors/list.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/list_producer_wrap.h>
+#include <l4/ferret/sensors/list_consumer.h>
+#include <l4/ferret/sensors/dplist.h>
+#include <l4/ferret/sensors/dplist_producer.h>
+#include <l4/ferret/sensors/dplist_consumer.h>
+
+#define LOOPS       (128 * 1024 * 1024)
+#define LOOPS_INNER 1024
+
+char LOG_tag[9] = "FerDPTest";
+
+int main(int argc, char* argv[])
+{
+    int i, j, ret;
+    long long ts[2];
+
+    // -=# monitoring code start #=-
+    ferret_dplist_t * dpl1 = NULL;
+    ferret_list_local_t * l1 = NULL;
+
+    ferret_list_moni_t * ml1 = NULL;
+    ferret_dplist_moni_t * mdpl1 = NULL;
+
+    ferret_list_entry_t * el = malloc(64);
+
+    l4_sleep(1000);
+    // create sensor and configure it to an element size of 64 with
+    // 1024 list entries
+    ret = ferret_create(2, 3, 4, FERRET_DPLIST, 0, "64:1024", dpl1, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+    //LOG("DPList created with the following properties:"
+    //    " count = %d, element_size = %d", dpl1->count, dpl1->element_size);
+
+    // create sensor and configure it to an element size of 64 with
+    // 1024 list entries
+    ret = ferret_create(3, 3, 4, FERRET_LIST, 0, "64:1024", l1, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+
+    // self attach to sensors to read stuff from them again
+    ret = ferret_att(2, 3, 4, mdpl1);
+    if (ret)
+    {
+        LOG("Could not attach to sensor 2:3:4");
+        exit(1);
+    }
+    ret = ferret_att(3, 3, 4, ml1);
+    if (ret)
+    {
+        LOG("Could not attach to sensor 3:3:4");
+        exit(1);
+    }
+    // -=# monitoring code end #=-
+
+    printf("Beginning tests, stay tuned ...\n");
+    printf("Doing %d writes:\n", LOOPS);
+    ts[0] = l4_rdtsc();
+    for (i = 0; i < LOOPS; i++)
+    {
+        ferret_dplist_post_1w(dpl1, 2, 3, 4, i);
+    }
+    ts[1] = l4_rdtsc();
+    printf("DPList: cycles per event = %g\n", (ts[1] - ts[0]) / (double)LOOPS);
+
+    ts[0] = l4_rdtsc();
+    for (i = 0; i < LOOPS; i++)
+    {
+        ferret_list_post_1w(l1, 2, 3, 4, i);
+    }
+    ts[1] = l4_rdtsc();
+    printf("List:   cycles per event = %g\n", (ts[1] - ts[0]) / (double)LOOPS);
+
+    printf("Doing %d write--read pairs %d times:\n",
+           LOOPS_INNER, LOOPS / LOOPS_INNER);
+    ts[0] = l4_rdtsc();
+    for (j = 0; j < LOOPS / LOOPS_INNER; j++)
+    {
+        //printf("b lost %lld events\n", mdpl1->lost);
+        for (i = 0; i < LOOPS_INNER; i++)
+        {
+            ferret_dplist_post_1w(dpl1, 2, 3, 4, i);
+        }
+        for (i = 0; i < LOOPS_INNER; i++)
+        {
+            ret = ferret_dplist_get(mdpl1, el);
+            if (ret != 0)
+            {
+                printf("Error code from ferret_dplist_get(): %d\n", ret);
+                printf("head = %lld, next_read = %lld, i = %d\n",
+                       mdpl1->glob->head.value, mdpl1->next_read.value, i);
+                exit(1);
+            }
+        }
+        //printf("a lost %lld events\n", mdpl1->lost);
+    }
+    ts[1] = l4_rdtsc();
+    printf("DPList: lost %lld events\n", mdpl1->lost);
+    printf("DPList: cycles per event (write + read) = %g\n",
+           (ts[1] - ts[0]) / (double)LOOPS);
+
+    ts[0] = l4_rdtsc();
+    for (j = 0; j < LOOPS / LOOPS_INNER; j++)
+    {
+        for (i = 0; i < LOOPS_INNER; i++)
+        {
+            ferret_list_post_1w(l1, 2, 3, 4, i);
+        }
+        for (i = 0; i < LOOPS_INNER; i++)
+        {
+            ret = ferret_list_get(ml1, el);
+            if (ret != 0)
+            {
+                printf("Error code from ferret_dplist_get(): %d\n", ret);
+                exit(1);
+            }
+        }
+    }
+    ts[1] = l4_rdtsc();
+    printf("List:   lost %lld events\n", ml1->lost);
+    printf("List:   cycles per event (write + read) = %g\n",
+           (ts[1] - ts[0]) / (double)LOOPS);
+
+
+#if 0
+    j = 0;
+    while (1)
+    {
+        // -=# monitoring code start #=-
+        ferret_dplist_post_2w(dpl1, 2, 3, 4, j, 0);
+        // -=# monitoring code end #=-
+
+        // do some work
+        loops = 10000 + l4util_rand();
+        for (i = 0; i < loops; i++)
+            asm volatile ("": : : "memory");  // memory barrier
+
+        // -=# monitoring code start #=-
+        ferret_dplist_post_2w(dpl1, 2, 3, 4, j, 1);
+        // -=# monitoring code end #=-
+
+        l4_sleep(100);
+        j++;
+        if (j % 10 == 0)
+        {
+            LOG(".");
+        }
+    }
+#endif
+
+    // -=# monitoring code start #=-
+    /* Demonstrates cleanup.
+     *
+     * The sensor will be freed after all parties released it, that
+     * is, the creator and all monitors.
+     */
+    ret = ferret_free_sensor(2, 3, 4, dpl1, &free);
+    if (ret)
+    {
+        LOG("Error freeing sensor: ret = %d", ret);
+        exit(1);
+    }
+    // -=# monitoring code end #=-
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/benchmarks/performance/Makefile b/l4/pkg/ferret/examples/benchmarks/performance/Makefile
new file mode 100644 (file)
index 0000000..227bf11
--- /dev/null
@@ -0,0 +1,16 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C_fer_perf_test   = perf.c
+#SRC_C_fer_thread_test = threads.c
+
+TARGET          = fer_perf_test #fer_thread_test
+
+REQUIRES_LIBS+= ferret-producer ferret-common libstdc++
+
+OPTS = -O3 -fno-strict-aliasing $(CARCHFLAGS_$(ARCH)) $(CARCHFLAGS_$(ARCH)_$(CPU)) -fomit-frame-pointer
+
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/benchmarks/performance/perf.c b/l4/pkg/ferret/examples/benchmarks/performance/perf.c
new file mode 100644 (file)
index 0000000..3216a93
--- /dev/null
@@ -0,0 +1,169 @@
+/**
+ * \file   ferret/examples/performance/perf.c
+ * \brief  Measure some performance numbers on events
+ *
+ * \date   2006-04-25
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/clock.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/sensors/list_producer.h>
+
+int main(void)
+{
+    ferret_list_local_t * l1 = NULL, * l2 = NULL, * l3 = NULL;
+       l4_cap_idx_t srv = lookup_sensordir();
+    int ret;
+    int i, j;
+    int index;
+    ferret_time_t t1, t2;
+
+    ferret_list_entry_common_t * elc;
+
+    l4_sleep(1000);
+    // create sensor and configure it to an element size of 8 with
+    // 100 list entries
+    ret = ferret_create(srv, 12, 1, 0, FERRET_LIST,
+                        0, "8:128", l1, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    // create sensor and configure it to an element size of 64 with
+    // 1000 list entries
+    ret = ferret_create(srv, 12, 2, 0, FERRET_LIST,
+                        FERRET_SUPERPAGES, "64:1024", l2, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    // create sensor and configure it to an element size of 64 with
+    // 65000 list entries
+    ret = ferret_create(srv, 12, 3, 0, FERRET_LIST,
+                        FERRET_SUPERPAGES, "64:65000", l3, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    printf("---------- 1,000,000 loops\n");
+
+    for (j = 0; j < 10; j++)
+    {
+        t1 = l4_rdtsc();
+        for (i = 0; i < 1000000; i++)
+        {
+            index = ferret_list_dequeue(l1);
+            ferret_list_commit(l1, index);
+        }
+        t2 = l4_rdtsc();
+        printf("l1: %lld cycles per loop!\n",
+                       
+            (t2 - t1) / 1000000);
+        l4_sleep(1000);
+    }
+
+    printf("---------- 1,000,000 loops\n");
+
+    for (j = 0; j < 10; j++)
+    {
+        t1 = l4_rdtsc();
+        for (i = 0; i < 1000000; i++)
+        {
+            index = ferret_list_dequeue(l2);
+            ferret_list_commit(l2, index);
+        }
+        t2 = l4_rdtsc();
+        printf("l2: %lld cycles per loop!\n",
+            (t2 - t1) / 1000000);
+        l4_sleep(1000);
+    }
+
+    printf("---------- 1,000,000 loops\n");
+
+    for (j = 0; j < 10; j++)
+    {
+        t1 = l4_rdtsc();
+        for (i = 0; i < 1000000; i++)
+        {
+            index = ferret_list_dequeue(l2);
+            elc = (ferret_list_entry_common_t *)
+                ferret_list_e4i(l2->glob, index);
+            elc->major     = 12;
+            elc->minor     = 2;
+            elc->instance  = 0;
+            elc->cpu       = 0;
+            elc->data32[2] = 1;  // start
+            elc->data32[3] = j;
+            ferret_list_commit(l2, index);
+        }
+        t2 = l4_rdtsc();
+        printf("l2 (+ payload): %lld cycles per loop!\n",
+            (t2 - t1) / 1000000);
+        l4_sleep(1000);
+    }
+
+    printf("---------- 1,000,000 loops\n");
+
+    for (j = 0; j < 10; j++)
+    {
+        t1 = l4_rdtsc();
+        for (i = 0; i < 1000000; i++)
+        {
+            index = ferret_list_dequeue(l3);
+            ferret_list_commit(l3, index);
+        }
+        t2 = l4_rdtsc();
+        printf("l3: %lld cycles per loop!\n",
+            (t2 - t1) / 1000000);
+        l4_sleep(1000);
+    }
+
+    printf("---------- 1,000,000 loops\n");
+
+    for (j = 0; j < 10; j++)
+    {
+        t1 = l4_rdtsc();
+        for (i = 0; i < 1000000; i++)
+        {
+            index = ferret_list_dequeue(l3);
+            elc = (ferret_list_entry_common_t *)
+                ferret_list_e4i(l3->glob, index);
+            elc->major     = 12;
+            elc->minor     = 2;
+            elc->instance  = 0;
+            elc->cpu       = 0;
+            elc->data32[2] = 1;  // start
+            elc->data32[3] = j;
+            ferret_list_commit(l3, index);
+        }
+        t2 = l4_rdtsc();
+        printf("l3 (+ payload): %lld cycles per loop!\n",
+            (t2 - t1) / 1000000);
+        l4_sleep(1000);
+    }
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/benchmarks/performance/threads.c b/l4/pkg/ferret/examples/benchmarks/performance/threads.c
new file mode 100644 (file)
index 0000000..f2d39a6
--- /dev/null
@@ -0,0 +1,529 @@
+/**
+ * \file   ferret/examples/performance/threads.c
+ * \brief  Measure some performance numbers on events
+ *
+ * \date   2006-04-25
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <limits.h>
+
+#include <l4/log/l4log.h>
+#include <l4/thread/thread.h>
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/semaphore/semaphore.h>
+#include <l4/sys/syscalls.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/clock.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/list_producer_wrap.h>
+#include <l4/ferret/sensors/ulist_producer.h>
+#include <l4/ferret/sensors/slist_producer.h>
+#include <l4/ferret/sensors/alist_producer.h>
+
+char LOG_tag[9] = "FerPerf";
+
+#define THREADS 5
+#define FAST_POST 1
+#define THROUGHPUT_LOOPS 10000000
+
+typedef struct stats_s
+{
+    l4thread_t    t;
+    unsigned int  count;        // overall thread loop counter
+    unsigned int  last;         // previous thread loop counter
+    unsigned int  current;      // current loop counter
+    ferret_time_t start;        // start timestamp
+    unsigned int  min;          // minimal time
+    unsigned int  max;          // maximal time
+    unsigned int  avg;          // sliding average time * 4096
+    l4semaphore_t sem;          // semaphore to block threads
+    int           should_exit;  // thread should terminate itself
+} stats_t;
+
+stats_t stats[THREADS];
+ferret_list_local_t * list = NULL;
+ferret_alist_t * alist = NULL;
+ferret_ulist_local_t * ulist = NULL;
+ferret_slist_t * slist = NULL;
+
+const int l4thread_max_threads = 90;
+
+static void thread_fn_list(void *arg)
+{
+    int me = (int)arg;
+    int index;
+    ferret_list_entry_common_t * elc;
+    unsigned int diff;
+
+    for (stats[me].count = 0; 1; stats[me].count++)
+    {
+        if ((stats[me].count & 1024) == 0)  // check if we should be running
+        {
+            l4semaphore_down(&stats[me].sem);
+            l4semaphore_up(&stats[me].sem);
+            if (stats[me].should_exit)
+            {
+                l4thread_exit();
+            }
+        }
+        stats[me].start = l4_rdtsc();
+        index = ferret_list_dequeue(list);
+        elc = (ferret_list_entry_common_t *)ferret_list_e4i(list->glob, index);
+#ifdef FAST_POST
+        elc->maj_min   = MAJ_MIN(12, 2);
+#else
+        elc->major     = 12;
+        elc->minor     = 2;
+#endif
+        elc->instance  = 0;
+        elc->cpu       = 0;
+        elc->data32[2] = 1;  // some constant
+        elc->data32[3] = stats[me].count;
+        ferret_list_commit(list, index);
+        diff = l4_rdtsc() - stats[me].start;
+        if (diff < stats[me].min)
+            stats[me].min = diff;
+        else if (diff > stats[me].max)
+            stats[me].max = diff;
+        // sliding average fixpoint (12 bit shifted)
+        stats[me].avg = (31 * stats[me].avg + (diff << 12)) >> 5;
+    }
+}
+
+static void thread_fn_list2(void *arg)
+{
+    int me = (int)arg;
+    unsigned int diff;
+
+    for (stats[me].count = 0; 1; stats[me].count++)
+    {
+        if ((stats[me].count & 1024) == 0)  // check if we should be running
+        {
+            l4semaphore_down(&stats[me].sem);
+            l4semaphore_up(&stats[me].sem);
+            if (stats[me].should_exit)
+            {
+                l4thread_exit();
+            }
+        }
+        stats[me].start = l4_rdtsc();
+#ifdef FAST_POST
+        ferret_list_postX_2w(list, MAJ_MIN(12, 2), 0, 1, stats[me].count);
+#else
+        ferret_list_post_2w(list, 12, 2, 0, 1, stats[me].count);
+#endif
+        diff = l4_rdtsc() - stats[me].start;
+        if (diff < stats[me].min)
+            stats[me].min = diff;
+        else if (diff > stats[me].max)
+            stats[me].max = diff;
+        // sliding average fixpoint (12 bit shifted)
+        stats[me].avg = (31 * stats[me].avg + (diff << 12)) >> 5;
+    }
+}
+
+static void thread_fn_ulist(void *arg)
+{
+    int me = (int)arg;
+    unsigned int diff;
+
+    for (stats[me].count = 0; 1; stats[me].count++)
+    {
+        if ((stats[me].count & 1024) == 0)  // check if we should be running
+        {
+            l4semaphore_down(&stats[me].sem);
+            l4semaphore_up(&stats[me].sem);
+            if (stats[me].should_exit)
+            {
+                l4thread_exit();
+            }
+        }
+        stats[me].start = l4_rdtsc();
+#ifdef FAST_POST
+        ferret_ulist_postX_2w(ulist, MAJ_MIN(12, 2), 0, 1, stats[me].count);
+#else
+        ferret_ulist_post_2w(ulist, 12, 2, 0, 1, stats[me].count);
+#endif
+        diff = l4_rdtsc() - stats[me].start;
+        if (diff < stats[me].min)
+            stats[me].min = diff;
+        else if (diff > stats[me].max)
+            stats[me].max = diff;
+        // sliding average fixpoint (12 bit shifted)
+        stats[me].avg = (31 * stats[me].avg + (diff << 12)) >> 5;
+    }
+}
+
+static void thread_fn_slist(void *arg)
+{
+    int me = (int)arg;
+    unsigned int diff;
+
+    for (stats[me].count = 0; 1; stats[me].count++)
+    {
+        if ((stats[me].count & 1024) == 0)  // check if we should be running
+        {
+            l4semaphore_down(&stats[me].sem);
+            l4semaphore_up(&stats[me].sem);
+            if (stats[me].should_exit)
+            {
+                l4thread_exit();
+            }
+        }
+        stats[me].start = l4_rdtsc();
+#ifdef FAST_POST
+        ferret_slist_postX_2w(slist, MAJ_MIN(12, 2), 0, 1, stats[me].count);
+#else
+        ferret_slist_post_2w(slist, 12, 2, 0, 1, stats[me].count);
+#endif
+        diff = l4_rdtsc() - stats[me].start;
+        if (diff < stats[me].min)
+            stats[me].min = diff;
+        else if (diff > stats[me].max)
+            stats[me].max = diff;
+        // sliding average fixpoint (12 bit shifted)
+        stats[me].avg = (31 * stats[me].avg + (diff << 12)) >> 5;
+    }
+}
+
+static void thread_fn_alist(void *arg)
+{
+    int me = (int)arg;
+    unsigned int diff;
+
+    for (stats[me].count = 0; 1; stats[me].count++)
+    {
+        if ((stats[me].count & 1024) == 0)  // check if we should be running
+        {
+            l4semaphore_down(&stats[me].sem);
+            l4semaphore_up(&stats[me].sem);
+            if (stats[me].should_exit)
+            {
+                l4thread_exit();
+            }
+        }
+        stats[me].start = l4_rdtsc();
+#ifdef FAST_POST
+        ferret_alist_postX_2w(alist, MAJ_MIN(12, 2), 0, 1, stats[me].count);
+#else
+        ferret_alist_post_2w(alist, 12, 2, 0, 1, stats[me].count);
+#endif
+        diff = l4_rdtsc() - stats[me].start;
+        if (diff < stats[me].min)
+            stats[me].min = diff;
+        else if (diff > stats[me].max)
+            stats[me].max = diff;
+        // sliding average fixpoint (12 bit shifted)
+        stats[me].avg = (31 * stats[me].avg + (diff << 12)) >> 5;
+    }
+}
+
+
+static void reset_stats(int i)
+{
+    stats[i].min = UINT_MAX;
+    stats[i].avg = 200 << 12;
+    stats[i].max = 0;
+}
+
+static void poll_for_stats(void)
+{
+    int i, j, threads_active;
+
+    for (threads_active = 1; threads_active <= THREADS; threads_active++)
+    {
+        LOG("%d threads running now ...", threads_active);
+        for (j = 0; j < 2; j++)
+        {
+            // start some threads and let them run for a little
+            for (i = 0; i < threads_active; i++)
+            {
+                l4semaphore_up(&stats[i].sem);
+            }
+            l4_sleep(5000);
+            for (i = 0; i < threads_active; i++)
+            {
+                l4semaphore_down(&stats[i].sem);
+            }
+
+            // now collect the numbers
+            for (i = 0; i < threads_active; i++)
+            {
+                stats[i].current = stats[i].count;
+            }
+            for (i = 0; i < threads_active; i++)
+            {
+                LOG_printf("Thread %d: Cycles/event <%u:%u:%u>, events %u\n",
+                           i, stats[i].min, stats[i].avg >> 12, stats[i].max,
+                           stats[i].current - stats[i].last);
+            }
+            for (i = 0; i < threads_active; i++)
+            {
+                stats[i].last = stats[i].current;
+                reset_stats(i);
+            }
+        }
+    }
+}
+
+static void test_throughput(void)
+{
+    unsigned long long start, stop;
+    int i;
+
+    start = l4_rdtsc();
+    for (i = 0; i < THROUGHPUT_LOOPS; i++)
+    {
+#ifdef FAST_POST
+        ferret_list_postX_2w(list, MAJ_MIN(12, 2), 0, 1, i);
+#else
+        ferret_list_post_2w(list, 12, 2, 0, 1, i);
+#endif
+    }
+    stop = l4_rdtsc();
+    LOG_printf("List throughput: %d loops, %llu cycles, %llu cyc/event\n",
+               THROUGHPUT_LOOPS, stop - start,
+               (stop - start) / THROUGHPUT_LOOPS);
+
+
+    start = l4_rdtsc();
+    for (i = 0; i < THROUGHPUT_LOOPS; i++)
+    {
+#ifdef FAST_POST
+        ferret_ulist_postX_2w(ulist, MAJ_MIN(12, 2), 0, 1, i);
+#else
+        ferret_ulist_post_2w(ulist, 12, 2, 0, 1, i);
+#endif
+    }
+    stop = l4_rdtsc();
+    LOG_printf("UList throughput: %d loops, %llu cycles, %llu cyc/event\n",
+               THROUGHPUT_LOOPS, stop - start,
+               (stop - start) / THROUGHPUT_LOOPS);
+
+
+    start = l4_rdtsc();
+    for (i = 0; i < THROUGHPUT_LOOPS; i++)
+    {
+#ifdef FAST_POST
+        ferret_slist_postX_2w(slist, MAJ_MIN(12, 2), 0, 1, i);
+#else
+        ferret_slist_post_2w(slist, 12, 2, 0, 1, i);
+#endif
+    }
+    stop = l4_rdtsc();
+    LOG_printf("SList throughput: %d loops, %llu cycles, %llu cyc/event\n",
+               THROUGHPUT_LOOPS, stop - start,
+               (stop - start) / THROUGHPUT_LOOPS);
+
+
+    start = l4_rdtsc();
+    for (i = 0; i < THROUGHPUT_LOOPS; i++)
+    {
+#ifdef FAST_POST
+        ferret_alist_postX_2w(alist, MAJ_MIN(12, 2), 0, 1, i);
+#else
+        ferret_alist_post_2w(alist, 12, 2, 0, 1, i);
+#endif
+    }
+    stop = l4_rdtsc();
+    LOG_printf("AList throughput: %d loops, %llu cycles, %llu cyc/event\n",
+               THROUGHPUT_LOOPS, stop - start,
+               (stop - start) / THROUGHPUT_LOOPS);
+}
+
+
+int main(int argc, char* argv[])
+{
+    int ret, i;
+
+    l4_sleep(1000);
+    // create sensor and configure it to an element size of 64 with
+    // 1000 list entries
+    ret = ferret_create(12, 2, 0, FERRET_LIST,
+                        FERRET_SUPERPAGES, "64:1024", list, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor list: ret = %d", ret);
+        exit(1);
+    }
+
+    ret = ferret_create(12, 3, 0, FERRET_ULIST,
+                        FERRET_SUPERPAGES, "64:1024", ulist, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor ulist: ret = %d", ret);
+        exit(1);
+    }
+
+    ret = ferret_create(12, 4, 0, FERRET_SLIST,
+                        FERRET_SUPERPAGES, "64:1024", slist, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor slist: ret = %d", ret);
+        exit(1);
+    }
+
+    ret = ferret_create(12, 5, 0, FERRET_ALIST,
+                        FERRET_SUPERPAGES, "1024", alist, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor alist: ret = %d", ret);
+        exit(1);
+    }
+
+    test_throughput();
+
+    // list
+    // create threads
+    for (i = 0; i < THREADS; i++)
+    {
+        reset_stats(i);
+        stats[i].last        = 0;
+        stats[i].current     = 0;
+        stats[i].sem         = L4SEMAPHORE_LOCKED;
+        stats[i].should_exit = 0;
+        stats[i].t = l4thread_create(thread_fn_list, (void *)i,
+                                     L4THREAD_CREATE_ASYNC);
+        if (stats[i].t < 0)
+        {
+            LOG("Error creating thread %d, ret = %d", i, stats[i].t);
+            exit(1);
+        }
+    }
+    LOG("Created %d threads for list benchmark.", i);
+
+    poll_for_stats();
+
+    for (i = 0; i < THREADS; i++)
+    {
+        stats[i].should_exit = 1;
+    }
+    l4_sleep(1000);
+
+    // list2
+    // create threads
+    for (i = 0; i < THREADS; i++)
+    {
+        reset_stats(i);
+        stats[i].last        = 0;
+        stats[i].current     = 0;
+        stats[i].sem         = L4SEMAPHORE_LOCKED;
+        stats[i].should_exit = 0;
+        stats[i].t = l4thread_create(thread_fn_list2, (void *)i,
+                                     L4THREAD_CREATE_ASYNC);
+        if (stats[i].t < 0)
+        {
+            LOG("Error creating thread %d, ret = %d", i, stats[i].t);
+            exit(1);
+        }
+    }
+    LOG("Created %d threads for list2 benchmark.", i);
+
+    poll_for_stats();
+
+    for (i = 0; i < THREADS; i++)
+    {
+        stats[i].should_exit = 1;
+    }
+    l4_sleep(1000);
+
+
+    // ulist
+    // create threads
+    for (i = 0; i < THREADS; i++)
+    {
+        reset_stats(i);
+        stats[i].last        = 0;
+        stats[i].current     = 0;
+        stats[i].sem         = L4SEMAPHORE_LOCKED;
+        stats[i].should_exit = 0;
+        stats[i].t = l4thread_create(thread_fn_ulist, (void *)i,
+                                     L4THREAD_CREATE_ASYNC);
+        if (stats[i].t < 0)
+        {
+            LOG("Error creating thread %d, ret = %d", i, stats[i].t);
+            exit(1);
+        }
+    }
+    LOG("Created %d threads for ulist benchmark.", i);
+
+    poll_for_stats();
+
+    for (i = 0; i < THREADS; i++)
+    {
+        stats[i].should_exit = 1;
+    }
+    l4_sleep(1000);
+
+    // slist
+    // create threads
+    for (i = 0; i < THREADS; i++)
+    {
+        reset_stats(i);
+        stats[i].last        = 0;
+        stats[i].current     = 0;
+        stats[i].sem         = L4SEMAPHORE_LOCKED;
+        stats[i].should_exit = 0;
+        stats[i].t = l4thread_create(thread_fn_slist, (void *)i,
+                                     L4THREAD_CREATE_ASYNC);
+        if (stats[i].t < 0)
+        {
+            LOG("Error creating thread %d, ret = %d", i, stats[i].t);
+            exit(1);
+        }
+    }
+    LOG("Created %d threads for slist benchmark.", i);
+
+    poll_for_stats();
+
+    for (i = 0; i < THREADS; i++)
+    {
+        stats[i].should_exit = 1;
+    }
+
+    l4_sleep(1000);
+
+    // alist
+    // create threads
+    for (i = 0; i < THREADS; i++)
+    {
+        reset_stats(i);
+        stats[i].last        = 0;
+        stats[i].current     = 0;
+        stats[i].sem         = L4SEMAPHORE_LOCKED;
+        stats[i].should_exit = 0;
+        stats[i].t = l4thread_create(thread_fn_alist, (void *)i,
+                                     L4THREAD_CREATE_ASYNC);
+        if (stats[i].t < 0)
+        {
+            LOG("Error creating thread %d, ret = %d", i, stats[i].t);
+            exit(1);
+        }
+    }
+    LOG("Created %d threads for alist benchmark.", i);
+
+    poll_for_stats();
+
+    for (i = 0; i < THREADS; i++)
+    {
+        stats[i].should_exit = 1;
+    }
+
+    l4_sleep(1000);
+
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/benchmarks/pthread_test/Makefile b/l4/pkg/ferret/examples/benchmarks/pthread_test/Makefile
new file mode 100644 (file)
index 0000000..9882cb3
--- /dev/null
@@ -0,0 +1,18 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+#DEFAULT_RELOC   = 0x00680000
+TARGET          = ferret_pthread_test
+
+MODE            = l4linux
+
+OPTS = -O3 -fno-strict-aliasing $(CARCHFLAGS_$(ARCH)) $(CARCHFLAGS_$(ARCH)_$(CPU)) -fomit-frame-pointer
+
+LIBS            = -lpthread -lferret_init -lferret_producer
+LIBCLIBS        =
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/benchmarks/pthread_test/broken b/l4/pkg/ferret/examples/benchmarks/pthread_test/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/benchmarks/pthread_test/main.c b/l4/pkg/ferret/examples/benchmarks/pthread_test/main.c
new file mode 100644 (file)
index 0000000..7f8a9a8
--- /dev/null
@@ -0,0 +1,121 @@
+/**
+ * \file   ferret/examples/pthread_test/main.c
+ * \brief  Test for measuring sensor overhead in multithreaded environment.
+ *
+ * \date   2007-05-14
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/times.h>
+#include <sys/time.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/list_producer_wrap.h>
+#include <l4/ferret/sensors/list_init.h>
+/*
+#include <l4/ferret/l4lx_client.h>
+#include <l4/ferret/util.h>
+*/
+
+#define MAX_THREADS 16
+#define LIST_CONFIG "64:10000"
+
+int threads;
+pthread_t thread_ids[MAX_THREADS];
+ferret_list_t * list;
+ferret_list_local_t * llist;
+
+static void * do_work(void * p)
+{
+    int i;
+    for (i = 0; i < 2000000; i++)
+    {
+        ferret_list_post_1wc(1, llist, 1, 2, 3, 0x12345678);
+    }
+    return NULL;
+}
+
+int main(int argc, char* argv[])
+{
+    int ret, i;
+    struct timeval tv1, tv2;
+    long long temp;
+
+    threads = 16;
+
+    /* 1. setup sensors in local memory
+     * 2. setup some local threads
+     * 3. let threads work in local sensor, measuring overhead
+     * 4. join threads
+     */
+
+
+    // 1.
+    {
+        ssize_t size;
+        size = ferret_list_size_config(LIST_CONFIG);
+        if (size <= 0)
+        {
+            fprintf(stderr, "Error getting size for list.\n");
+            exit(1);
+        }
+        ret = posix_memalign((void **)&list, 4096, size);
+        if (list == NULL || ret != 0)
+        {
+            fprintf(stderr, "Error getting memory for list.\n");
+            exit(1);
+        }
+        ret = ferret_list_init(list, LIST_CONFIG);
+        if (ret != 0)
+        {
+            fprintf(stderr, "Something wrong in list_init: %d, %s.\n",
+                    ret, LIST_CONFIG);
+            exit(1);
+        }
+        llist = (ferret_list_local_t *)list;
+        ferret_list_init_producer((void **)&llist, &malloc);
+    }
+
+    ret = gettimeofday(&tv1, NULL);
+
+    // 2.
+    for (i = 0; i < threads; i++)
+    {
+        ret = pthread_create(&thread_ids[i], NULL, do_work, (void *)i);
+        if (ret != 0)
+        {
+            perror("pthread_create");
+            exit(1);
+        }
+    }
+
+    // 3.
+    // empty
+
+    // 4.
+    for (i = 0; i < threads; i++)
+    {
+        ret = pthread_join(thread_ids[i], NULL);
+        if (ret != 0)
+        {
+            perror("pthread_join");
+            exit(1);
+        }
+    }
+    ret = gettimeofday(&tv2, NULL);
+    temp = tv2.tv_sec * 1000000LL + tv2.tv_usec -
+           tv1.tv_sec * 1000000LL + tv1.tv_usec;
+    printf("Time [s]: %f\n", temp / 1000000.0);
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/demo/Makefile b/l4/pkg/ferret/examples/demo/Makefile
new file mode 100644 (file)
index 0000000..a106892
--- /dev/null
@@ -0,0 +1,7 @@
+PKGDIR ?= ../..
+L4DIR  ?= $(PKGDIR)/../..
+
+TARGET = histo_demo list_demo_re ulist_demo scalar_demo test l4linux_user \
+         gcc_instrument
+
+include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/ferret/examples/demo/gcc_instrument/Makefile b/l4/pkg/ferret/examples/demo/gcc_instrument/Makefile
new file mode 100644 (file)
index 0000000..eb38d95
--- /dev/null
@@ -0,0 +1,24 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C_fer_gcc_inst_gen = gen.c
+SRC_C_fer_gcc_inst_std = std.c
+
+DEFAULT_RELOC   = 0x00680000
+TARGET          = fer_gcc_inst_gen fer_gcc_inst_std
+
+MODE            = l4env_minimal
+
+CFLAGS         += -finstrument-functions
+
+LIBS_fer_gcc_inst_gen += -lferret_gcc_instrument -lferret_client          \
+                         -lferret_producer -lferret_util -lferret_comm    \
+                         -lferret_fpages -lferret_local_names
+
+LIBS_fer_gcc_inst_std += -lferret_gcc_instrument_std -lferret_client      \
+                         -lferret_producer -lferret_util -lferret_comm    \
+                         -lferret_fpages -lferret_local_names
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/demo/gcc_instrument/broken b/l4/pkg/ferret/examples/demo/gcc_instrument/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/demo/gcc_instrument/gen.c b/l4/pkg/ferret/examples/demo/gcc_instrument/gen.c
new file mode 100644 (file)
index 0000000..bc1f72e
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <l4/util/util.h>
+
+#include <l4/ferret/gcc_instrument.h>
+
+static void test1(void)
+{
+    printf("test1\n");
+}
+
+static void test2(void)
+{
+    printf("test2\n");
+    test1();
+}
+
+int main(void)
+{
+    ferret_gcc_instrument_init(&malloc, NULL);
+
+    l4_sleep(6000);
+
+    test1();
+    test2();
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/demo/gcc_instrument/std.c b/l4/pkg/ferret/examples/demo/gcc_instrument/std.c
new file mode 100644 (file)
index 0000000..6d8e199
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <l4/util/util.h>
+
+static void test1(void)
+{
+    printf("test1\n");
+}
+
+static void test2(void)
+{
+    printf("test2\n");
+    test1();
+}
+
+int main(void)
+{
+    l4_sleep(6000);
+
+    test1();
+    test2();
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/demo/histo_demo/Makefile b/l4/pkg/ferret/examples/demo/histo_demo/Makefile
new file mode 100644 (file)
index 0000000..26b161b
--- /dev/null
@@ -0,0 +1,16 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+DEFAULT_RELOC   = 0x00630000
+TARGET          = fer_histo_demo
+
+MODE            = l4env_minimal
+
+LIBS           += -lferret_client -lferret_producer -lferret_comm           \
+                  -lferret_fpages -lferret_local_names
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/demo/histo_demo/broken b/l4/pkg/ferret/examples/demo/histo_demo/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/demo/histo_demo/main.c b/l4/pkg/ferret/examples/demo/histo_demo/main.c
new file mode 100644 (file)
index 0000000..61add29
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+ * \file   ferret/examples/histo_demo/main.c
+ * \brief  Example demonstrating the usage of histograms.
+ *
+ * \date   21/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/log/l4log.h>
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/sys/syscalls.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/clock.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/histogram_producer.h>
+
+char LOG_tag[9] = "FerHiDe";
+
+int main(int argc, char* argv[])
+{
+    int i, j, loops;
+
+    // -=# monitor code start #=-
+    ferret_histo_t * h1 = NULL;
+    int ret;
+    ferret_utime_t start, end;
+
+    l4_sleep(1000);
+    // create histogram and configure it to a value range of 0 --
+    // 200000 with 10 bins
+    ret = ferret_create(11, 1, 0, FERRET_HISTO,
+                        0, "0:200000:10", h1, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+    // -=# monitor code end #=-
+
+    for (j = 0;; ++j)
+    {
+        // -=# monitoring code start #=-
+        FERRET_GET_TIME(FERRET_TIME_REL_TSC_FAST, start);
+        // -=# monitoring code end #=-
+
+        // do some work
+        loops = 10000 + l4util_rand();
+        for (i = 0; i < loops; i++)
+            asm volatile ("": : : "memory");
+
+        // -=# monitoring code start #=-
+        FERRET_GET_TIME(FERRET_TIME_REL_TSC_FAST, end);
+        ferret_histo_inc(h1, end - start);
+        // -=# monitoring code end #=-
+
+        // be nice to the system
+        if (j % 100 == 0)
+            l4_sleep(10);
+    }
+
+    // -=# monitoring code start #=-
+    /* will never be reached due to the infinite loop above, but
+     * demonstrates cleanup.
+     */
+    ret = ferret_free_sensor(11, 1, 0, h1, &free);
+    if (ret)
+    {
+        LOG("Error freeing sensor: ret = %d", ret);
+        exit(1);
+    }
+    // -=# monitoring code end #=-
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/demo/l4linux_user/Makefile b/l4/pkg/ferret/examples/demo/l4linux_user/Makefile
new file mode 100644 (file)
index 0000000..5cfc677
--- /dev/null
@@ -0,0 +1,16 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+#DEFAULT_RELOC   = 0x00680000
+TARGET          = ferret_l4lx_list
+
+MODE            = l4linux
+
+LIBS            = -lferret_l4lx_client -lferret_util
+LIBCLIBS        =
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/demo/l4linux_user/broken b/l4/pkg/ferret/examples/demo/l4linux_user/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/demo/l4linux_user/main.c b/l4/pkg/ferret/examples/demo/l4linux_user/main.c
new file mode 100644 (file)
index 0000000..e17d59a
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * \file   ferret/examples/l4linux_user/main.c
+ * \brief  Example demonstrating the usage of lists inside of L4Linux.
+ *
+ * \date   2006-03-28
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <l4/ferret/l4lx_client.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/util.h>
+
+int main(int argc, char* argv[])
+{
+    int i, j, loops, ret;
+
+    // -=# monitoring code start #=-
+    ferret_list_entry_common_t * elc;
+    ferret_list_entry_t * el;
+    int index;
+
+    ferret_list_l4lx_user_init();
+    // -=# monitoring code end #=-
+
+    /*
+    printf("Sensor @: %p\n", ferret_l4lx_user);
+    printf("Global sensor @: %p, mmi: %hd:%hd:%hd\n",
+           ferret_l4lx_user->glob,
+           ferret_l4lx_user->glob->header.major,
+           ferret_l4lx_user->glob->header.minor,
+           ferret_l4lx_user->glob->header.instance);
+    */
+
+    j = 0;
+    while (1)
+    {
+        //fprintf(stderr, ".");
+
+        // -=# monitoring code start #=-
+        // this demonstrates to cast the received pointer to a certain
+        // struct and fill it
+        index = ferret_list_dequeue(ferret_l4lx_user);
+        elc = (ferret_list_entry_common_t *)
+            ferret_list_e4i(ferret_l4lx_user->glob, index);
+        elc->major     = 100;
+        elc->minor     = 10;
+        elc->instance  = 0;
+        elc->cpu       = 0;
+        elc->data32[0] = 1;  // start
+        elc->data32[1] = j;
+        ferret_list_commit(ferret_l4lx_user, index);
+        // -=# monitoring code end #=-
+
+        // do some work
+        loops = 10000 + ((double)rand() * 65536 / RAND_MAX);
+        for (i = 0; i < loops; i++)
+            asm volatile ("": : : "memory");
+
+        // -=# monitoring code start #=-
+        // here, dynamic marshaling is demonstrated
+        index = ferret_list_dequeue(ferret_l4lx_user);
+        el = ferret_list_e4i(ferret_l4lx_user->glob, index);
+        ret = ferret_util_pack("hhhbxlll", el->data, 100, 10, 0, 0, 2, j, i);
+        ferret_list_commit(ferret_l4lx_user, index);
+        // -=# monitoring code end #=-
+
+        usleep(10000);
+        j++;
+    }
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/demo/list_demo/Makefile b/l4/pkg/ferret/examples/demo/list_demo/Makefile
new file mode 100644 (file)
index 0000000..44e13e0
--- /dev/null
@@ -0,0 +1,12 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+TARGET          = fer_list_demo
+
+REQUIRED_LIBS += libstdc++ libboost ferret-client ferret-common
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/demo/list_demo/broken b/l4/pkg/ferret/examples/demo/list_demo/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/demo/list_demo/main.c b/l4/pkg/ferret/examples/demo/list_demo/main.c
new file mode 100644 (file)
index 0000000..33e5ad1
--- /dev/null
@@ -0,0 +1,175 @@
+/**
+ * \file   ferret/examples/list_demo/main.c
+ * \brief  Example demonstrating the usage of lists.
+ *
+ * \date   25/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/clock.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/list_producer_wrap.h>
+
+char LOG_tag[9] = "FerLiDe";
+
+int main(int argc, char* argv[])
+{
+    int i, j, loops;
+
+    // -=# monitoring code start #=-
+    ferret_list_local_t * l1 = NULL, * l2 = NULL, * l3 = NULL, * l4 = NULL;
+    int ret;
+    int index;
+    ferret_utime_t t;
+
+    ferret_list_entry_common_t * elc;
+    ferret_list_entry_t * el;
+
+    l4_sleep(1000);
+    // create sensor and configure it to an element size of 8 bytes with
+    // 100 list entries
+    ret = ferret_create(12, 1, 0, FERRET_LIST,
+                        0, "8:100", l1, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+
+    // create sensor and configure it to an element size of 64 bytes with
+    // 1000 list entries
+    ret = ferret_create(12, 2, 0, FERRET_LIST,
+                        FERRET_SUPERPAGES, "64:1000", l2, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+
+
+    // testing reopen here
+    ret = ferret_create(12, 2, 0, FERRET_LIST,
+                        FERRET_SUPERPAGES, "64:1000", l3, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+    else
+    {
+        LOG("Reopen worked.");
+    }
+    ret = ferret_create(12, 2, 0, FERRET_LIST,
+                        FERRET_SUPERPAGES, "64:999", l4, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d (as expected)", ret);
+    }
+    else
+    {
+        LOG("Reopen worked (should not).");
+//        exit(1);
+    }
+
+
+    // -=# monitoring code end #=-
+
+    j = 0;
+    while (1)
+    {
+        // -=# monitoring code start #=-
+        // this sensor has empty events, just timestamps are inserted
+        // on commiting, so we don't have to insert other data
+        //LOG("X1: %p, %p, %p, %p", l1, l1->glob, l1->ind_buf, l1->out_buf);
+        index = ferret_list_dequeue(l1);
+        ferret_list_commit(l1, index);
+        index = ferret_list_dequeue(l1);
+        ferret_list_commit(l1, index);
+        index = ferret_list_dequeue(l1);
+        ferret_list_commit(l1, index);
+        index = ferret_list_dequeue(l1);
+        ferret_list_commit(l1, index);
+        // -=# monitoring code end #=-
+
+        // -=# monitoring code start #=-
+        // this demonstrates to cast the received pointer to a certain
+        // struct and fill it
+        index = ferret_list_dequeue(l2);
+        elc = (ferret_list_entry_common_t *)ferret_list_e4i(l2->glob, index);
+        FERRET_GET_TIME(FERRET_TIME_REL_TSC_FAST, elc->data64[0]);
+        elc->major     = 12;
+        elc->minor     = 2;
+        elc->instance  = 0;
+        elc->cpu       = 0;
+        elc->data32[2] = 1;  // start
+        elc->data32[3] = j;
+        ferret_list_commit(l2, index);
+        // -=# monitoring code end #=-
+
+        // do some work
+        loops = 10000 + l4util_rand();
+        for (i = 0; i < loops; i++)
+            asm volatile ("": : : "memory");
+
+        // -=# monitoring code start #=-
+        // here, dynamic marshaling is demonstrated
+        index = ferret_list_dequeue(l2);
+        el = ferret_list_e4i(l2->glob, index);
+        FERRET_GET_TIME(FERRET_TIME_REL_TSC_FAST, t);
+        //LOG("%lld, %p, %p", t, el, l2->glob);
+        ret = ferret_util_pack("hhhbxqll", el->data, 12, 2, 0, 0, t, 2, j);
+        ferret_list_commit(l2, index);
+        // -=# monitoring code end #=-
+
+        // -=# monitoring code start #=-
+        // demonstrate use of convenience wrappers here
+        ferret_list_post_c  (1, l3, 12, 2, 0);
+        ferret_list_post_1wc(1, l3, 12, 2, 0, 1);
+        ferret_list_post_2wc(1, l3, 12, 2, 0, 1, 2);
+        ferret_list_post_3wc(1, l3, 12, 2, 0, 1, 2, 3);
+        ferret_list_post_4wc(1, l3, 12, 2, 0, 1, 2, 3, 4);
+        // -=# monitoring code end #=-
+
+        l4_sleep(100);
+        j++;
+    }
+
+    // -=# monitoring code start #=-
+    /* will never be reached due to the infinite loop above, but
+     * demonstrates cleanup.
+     *
+     * The sensor will be freed after all parties released it, that
+     * is, the creator and all monitors.
+     */
+    ret = ferret_free_sensor(10, 1, 0, l1, &free);
+    if (ret)
+    {
+        LOG("Error freeing sensor: ret = %d", ret);
+        exit(1);
+    }
+
+    ret = ferret_free_sensor(10, 2, 0, l2, &free);
+    if (ret)
+    {
+        LOG("Error freeing sensor: ret = %d", ret);
+        exit(1);
+    }
+    // -=# monitoring code end #=-
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/demo/list_demo_re/Makefile b/l4/pkg/ferret/examples/demo/list_demo_re/Makefile
new file mode 100644 (file)
index 0000000..be2e47b
--- /dev/null
@@ -0,0 +1,14 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+DEFAULT_RELOC   = 0x00680000
+TARGET          = fer_list_demo
+
+
+REQUIRES_LIBS+= ferret-producer ferret-common libstdc++
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/demo/list_demo_re/main.c b/l4/pkg/ferret/examples/demo/list_demo_re/main.c
new file mode 100644 (file)
index 0000000..3b0d187
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * \file   ferret/examples/list_demo/main.c
+ * \brief  Example demonstrating the usage of lists.
+ *
+ * \date   25/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ * \author Bjoern Doebel   <doebel@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/client.h>
+#include <l4/ferret/clock.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/list_producer_wrap.h>
+#include <l4/util/util.h>
+#include <l4/util/rand.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <l4/sys/vcon.h>
+
+int main(void)
+{
+       l4_cap_idx_t srv = lookup_sensordir();
+    int i, j, loops;
+
+
+    // -=# monitoring code start #=-
+    ferret_list_local_t * l1 = NULL, * l2 = NULL, * l3 = NULL, * l4 = NULL;
+    int ret;
+    int index;
+    ferret_utime_t t;
+
+    ferret_list_entry_common_t * elc;
+    ferret_list_entry_t * el;
+
+    l4_sleep(1000);
+    // create sensor and configure it to an element size of 8 bytes with
+    // 100 list entries
+    ret = ferret_create(srv, 12, 1, 0, FERRET_LIST,
+                        0, "8:100", l1, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    // create sensor and configure it to an element size of 64 bytes with
+    // 1000 list entries
+    ret = ferret_create(srv, 12, 2, 0, FERRET_LIST,
+                        FERRET_SUPERPAGES, "64:1000", l2, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+
+    // testing reopen here
+    ret = ferret_create(srv, 12, 2, 0, FERRET_LIST,
+                        FERRET_SUPERPAGES, "64:1000", l3, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+    else
+    {
+        printf("Reopen worked.\n");
+    }
+
+    ret = ferret_create(srv, 12, 2, 0, FERRET_LIST,
+                        FERRET_SUPERPAGES, "64:999", l4, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d (as expected)\n", ret);
+    }
+    else
+    {
+        printf("Reopen worked (should not).\n");
+        exit(1);
+    }
+
+    // -=# monitoring code end #=-
+
+    j = 0;
+    while (1)
+    {
+        // -=# monitoring code start #=-
+        // this sensor has empty events, just timestamps are inserted
+        // on commiting, so we don't have to insert other data
+        //printf("X1: %p, %p, %p, %p\n", l1, l1->glob, l1->ind_buf, l1->out_buf);
+        index = ferret_list_dequeue(l1);
+        ferret_list_commit(l1, index);
+        index = ferret_list_dequeue(l1);
+        ferret_list_commit(l1, index);
+        index = ferret_list_dequeue(l1);
+        ferret_list_commit(l1, index);
+        index = ferret_list_dequeue(l1);
+        ferret_list_commit(l1, index);
+        // -=# monitoring code end #=-
+
+        // -=# monitoring code start #=-
+        // this demonstrates to cast the received pointer to a certain
+        // struct and fill it
+        index = ferret_list_dequeue(l2);
+        elc = (ferret_list_entry_common_t *)ferret_list_e4i(l2->glob, index);
+        FERRET_GET_TIME(FERRET_TIME_REL_US, elc->data64[0]);
+        elc->major     = 12;
+        elc->minor     = 2;
+        elc->instance  = 0;
+        elc->cpu       = 0;
+        elc->data32[2] = 1;  // start
+        elc->data32[3] = j;
+        ferret_list_commit(l2, index);
+        // -=# monitoring code end #=-
+
+        // do some work
+        loops = 10000 + l4util_rand();
+        for (i = 0; i < loops; i++)
+            asm volatile ("": : : "memory");
+
+        // -=# monitoring code start #=-
+        // here, dynamic marshaling is demonstrated
+        index = ferret_list_dequeue(l2);
+        el = ferret_list_e4i(l2->glob, index);
+        FERRET_GET_TIME(FERRET_TIME_REL_US, t);
+        //printf("%lld, %p, %p\n", t, el, l2->glob);
+        ret = ferret_util_pack("hhhbxqll", el->data, 12, 2, 0, 0, t, 2, j);
+        ferret_list_commit(l2, index);
+        // -=# monitoring code end #=-
+
+        // -=# monitoring code start #=-
+        // demonstrate use of convenience wrappers here
+        ferret_list_post_c  (1, l3, 12, 2, 0);
+        ferret_list_post_1wc(1, l3, 12, 2, 0, 1);
+        ferret_list_post_2wc(1, l3, 12, 2, 0, 1, 2);
+        ferret_list_post_3wc(1, l3, 12, 2, 0, 1, 2, 3);
+        ferret_list_post_4wc(1, l3, 12, 2, 0, 1, 2, 3, 4);
+        // -=# monitoring code end #=-
+
+        l4_sleep(100);
+        j++;
+    }
+
+    // -=# monitoring code start #=-
+    /* will never be reached due to the infinite loop above, but
+     * demonstrates cleanup.
+     *
+     * The sensor will be freed after all parties released it, that
+     * is, the creator and all monitors.
+     */
+    ret = ferret_free_sensor(10, 1, 0, l1, &free);
+    if (ret)
+    {
+        printf("Error freeing sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    ret = ferret_free_sensor(10, 2, 0, l2, &free);
+    if (ret)
+    {
+        printf("Error freeing sensor: ret = %d\n", ret);
+        exit(1);
+    }
+    // -=# monitoring code end #=-
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/demo/scalar_demo/Makefile b/l4/pkg/ferret/examples/demo/scalar_demo/Makefile
new file mode 100644 (file)
index 0000000..e82a677
--- /dev/null
@@ -0,0 +1,11 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+TARGET          = fer_scalar_demo
+SRC_C           = main.c
+SYSTEMS                = x86-l4f
+
+REQUIRES_LIBS+= ferret-common ferret-producer libstdc++
+
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/demo/scalar_demo/main.c b/l4/pkg/ferret/examples/demo/scalar_demo/main.c
new file mode 100644 (file)
index 0000000..4b8299b
--- /dev/null
@@ -0,0 +1,169 @@
+/**
+ * \file   ferret/examples/scalar_demo/main.c
+ * \brief  Example demonstrating the usage of scalar sensors with Ferret/RE.
+ *         Based on Martin Pohlack's original Ferret package for L4Env.
+ *
+ * \date   03/04/2009
+ * \author Martin Pohlack <mp26@os.inf.tu-dresden.de>
+ * \author Bjoern Doebel <doebel@tudos.org>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <l4/re/c/util/cap_alloc.h>
+#include <l4/re/c/namespace.h>
+#include <l4/util/util.h>
+#include <l4/util/rand.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/sensors/scalar.h>
+#include <l4/ferret/sensors/scalar_producer.h>
+#include <l4/ferret/sensors/scalar_consumer.h>
+
+#include <l4/ferret/clock.h>
+#include <l4/ferret/types.h>
+
+int main(void)
+{
+       printf("Hello from the scalar demo.\n");
+
+       l4_cap_idx_t srv = lookup_sensordir();
+
+    // -=# monitoring code start #=-
+    ferret_scalar_t * s1 = NULL, * s2 = NULL, * s3 = NULL, * s4 = NULL;
+    int ret, i, j, loops, pm;
+    ferret_utime_t start, end;
+
+    l4_sleep(1000);
+    // create sensor and configure it to a value range of 0 -- 100 and
+    // the unit '%'
+    ret = ferret_create(srv, 10, 1, 0, FERRET_SCALAR,
+                        0, "0:100:%", s1, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    // create sensor and configure it to a value range of 0 -- 1000 and
+    // the unit 'time [us]'
+    ret = ferret_create(srv, 10, 2, 0, FERRET_SCALAR,
+                        0, "0:1000:time [us]", s2, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    // create sensor and configure it to a value range of 0 -- 100000 and
+    // the unit 'progress'
+    ret = ferret_create(srv, 10, 3, 0, FERRET_SCALAR,
+                        0, "0:1000:progress", s3, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    // create sensor and configure it to a value range of 0 -- 100000 and
+    // the unit 'Bandwidth [MB/s]'
+    ret = ferret_create(srv, 10, 4, 0, FERRET_SCALAR,
+                        0, "0:67:Bandwidth [MB/s]", s4, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d\n", ret);
+        exit(1);
+    }
+    // -=# monitoring code end #=-
+
+    pm = 0;
+    j = 0;
+
+       printf("-= Done creating sensors. Starting to produce data.=-\n");
+
+    while (1)
+    {
+        pm = (pm + 1) % 1000;
+        // -=# monitoring code start #=-
+        // simply insert a local value to transport it to a monitor
+        ferret_scalar_put(s1, pm / 10);
+        // -=# monitoring code end #=-
+
+        // -=# monitoring code start #=-
+        FERRET_GET_TIME(FERRET_TIME_REL_US, start);
+        // -=# monitoring code end #=-
+
+        // do some work
+        loops = 10000 + l4util_rand();
+        for (i = 0; i < loops; i++)
+            asm volatile ("": : : "memory");
+
+        // -=# monitoring code start #=-
+        // measure some duration and transport it to a monitor
+        //FERRET_GET_TIME(FERRET_TIME_REL_US_FAST, end); // does not work
+                                                           // with fiasco-ux
+        FERRET_GET_TIME(FERRET_TIME_REL_US, end);
+        ferret_scalar_put(s2, end - start);
+        // -=# monitoring code end #=-
+
+        // -=# monitoring code start #=-
+        // another simple value transported
+        ferret_scalar_put(s3, j);
+        // -=# monitoring code end #=-
+
+        // -=# monitoring code start #=-
+        // make some internal statistic available externally
+        // bandwidth will be between 30 and 65 MB/s
+        ferret_scalar_put(s4, 30  + l4util_rand() % 35);
+        // -=# monitoring code end #=-
+
+        l4_sleep(10);
+        j++;
+    }
+
+    // -=# monitoring code start #=-
+    /* will never be reached due to the infinite loop above, but
+     * demonstrates cleanup.
+     *
+     * The sensor will be freed after all parties released it, that
+     * is, the creator and all monitors.
+     */
+    ret = ferret_free_sensor(10, 1, 0, s1, &free);
+    if (ret)
+    {
+        printf("Error freeing sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    ret = ferret_free_sensor(10, 2, 0, s2, &free);
+    if (ret)
+    {
+        printf("Error freeing sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    ret = ferret_free_sensor(10, 3, 0, s3, &free);
+    if (ret)
+    {
+        printf("Error freeing sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    ret = ferret_free_sensor(10, 4, 0, s4, &free);
+    if (ret)
+    {
+        printf("Error freeing sensor: ret = %d\n", ret);
+        exit(1);
+    }
+
+    // -=# monitoring code end #=-
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/demo/test/Makefile b/l4/pkg/ferret/examples/demo/test/Makefile
new file mode 100644 (file)
index 0000000..223d789
--- /dev/null
@@ -0,0 +1,15 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+DEFAULT_RELOC   = 0x00730000
+TARGET          = fer_test
+
+MODE            = l4env_minimal
+
+LIBS           += -lferret_util
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/demo/test/broken b/l4/pkg/ferret/examples/demo/test/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/demo/test/main.c b/l4/pkg/ferret/examples/demo/test/main.c
new file mode 100644 (file)
index 0000000..86a0471
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * \file   ferret/examples/test/main.c
+ * \brief  Tests some functions
+ *
+ * \date   29/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdio.h>
+
+//#include <l4/log/l4log.h>
+//#include <l4/util/l4_macros.h>
+//#include <l4/util/util.h>
+//#include <l4/sys/syscalls.h>
+//#include <l4/sys/kdebug.h>
+#include <l4/sys/ktrace.h>
+#include <l4/sys/ktrace_events.h>
+
+#include <l4/ferret/util.h>
+
+char LOG_tag[9] = "FerTest";
+
+int main(int argc, char* argv[])
+{
+    char buf[1000];
+    int ret, i;
+
+    l4_tracebuffer_status_t * tbuf;
+    l4_tracebuffer_entry_t test;
+
+    tbuf = fiasco_tbuf_get_status();
+    printf("%p, 0:(%p, %lu, %llu), 1:(%p, %lu, %llu)\n", tbuf,
+           (void *)tbuf->tracebuffer0, tbuf->size0, tbuf->version0,
+           (void *)tbuf->tracebuffer1, tbuf->size1, tbuf->version1);
+
+    printf("%s test\n", "testing");
+
+    ret = ferret_util_pack("LLLLxxhxbQ00010s10p", buf, 1, 2, 3, 4, 5, 6, 7LL,
+                            "abcd", "xyzqw");
+    printf("ret = %d\n", ret);
+
+    for (i = 0; i < ret; ++i)
+    {
+        printf("%hhu, ", buf[i]);
+    }
+    puts("\n");
+
+    printf("sizeof %d\n", sizeof(l4_tracebuffer_entry_t));
+    printf("type offset %d\n", ((char *)&test.type) - ((char *)&test));
+    printf("sizeof %d\n", sizeof(test.m.pf));
+    printf("sizeof %d\n", sizeof(test.m.ipc));
+    printf("sizeof %d\n", sizeof(test.m.ipc_res));
+    printf("sizeof %d\n", sizeof(test.m.ipc_trace));
+    printf("sizeof %d\n", sizeof(test.m.ke));
+    printf("sizeof %d\n", sizeof(test.m.ke_reg));
+    printf("sizeof %d\n", sizeof(test.m.unmap));
+    printf("sizeof %d\n", sizeof(test.m.shortcut_failed));
+    printf("sizeof %d\n", sizeof(test.m.shortcut_succeeded));
+    printf("sizeof %d\n", sizeof(test.m.context_switch));
+    printf("sizeof %d\n", sizeof(test.m.exregs));
+    printf("sizeof %d\n", sizeof(test.m.breakpoint));
+    printf("sizeof %d\n", sizeof(test.m.trap));
+    printf("sizeof %d\n", sizeof(test.m.pf_res));
+    printf("sizeof %d\n", sizeof(test.m.sched));
+    printf("sizeof %d\n", sizeof(test.m.preemption));
+    printf("sizeof %d\n", sizeof(test.m.id_nearest));
+    printf("sizeof %d\n", sizeof(test.m.jean1));
+    printf("sizeof %d\n", sizeof(test.m.task_new));
+    printf("sizeof %d\n", sizeof(test.m.fit));
+    for (i = 0;
+         i < (tbuf->size0 + tbuf->size1) / sizeof(l4_tracebuffer_entry_t) &&
+             i < 100;
+         ++i)
+    {
+        printf("i = %d, %d, type = %hhd, %p\n", i,
+               tbuf->tracebuffer0[i].number,
+               tbuf->tracebuffer0[i].type,
+               &tbuf->tracebuffer0[i]);
+    }
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/demo/ulist_demo/Makefile b/l4/pkg/ferret/examples/demo/ulist_demo/Makefile
new file mode 100644 (file)
index 0000000..8616c33
--- /dev/null
@@ -0,0 +1,17 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+DEFAULT_RELOC   = 0x00680000
+TARGET          = fer_ulist_demo
+
+MODE            = l4env_minimal
+
+LIBS           += -lferret_client -lferret_producer -lferret_util           \
+                  -lferret_comm -lferret_fpages -lferret_fpages             \
+                  -lferret_local_names
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/demo/ulist_demo/broken b/l4/pkg/ferret/examples/demo/ulist_demo/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/demo/ulist_demo/main.c b/l4/pkg/ferret/examples/demo/ulist_demo/main.c
new file mode 100644 (file)
index 0000000..7cc8949
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * \file   ferret/examples/ulist_demo/main.c
+ * \brief  Example demonstrating the usage of ulists.
+ *
+ * \date   2007-06-21
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/log/l4log.h>
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/sys/syscalls.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/clock.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/sensors/ulist_producer.h>
+
+char LOG_tag[9] = "FerULiDe";
+
+int main(int argc, char* argv[])
+{
+    int i, j, loops;
+
+    // -=# monitoring code start #=-
+    ferret_ulist_local_t * l1 = NULL;
+    int ret;
+
+    l4_sleep(1000);
+    // create sensor and configure it to an element size of 64 with
+    // 1000 list entries
+    ret = ferret_create(12, 2, 0, FERRET_ULIST,
+                        FERRET_SUPERPAGES, "64:1000", l1, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+    // -=# monitoring code end #=-
+
+    j = 0;
+    while (1)
+    {
+        // -=# monitoring code start #=-
+        ferret_ulist_post_1w(l1, 1, 2, 3, 0xabcd1234);
+        // -=# monitoring code end #=-
+
+        // do some work
+        loops = 10000 + l4util_rand();
+        for (i = 0; i < loops; i++)
+            asm volatile ("": : : "memory");
+
+        // -=# monitoring code start #=-
+        ferret_ulist_post_1w(l1, 1, 2, 3, 0xabcd5678);
+        // -=# monitoring code end #=-
+
+        l4_sleep(100);
+        j++;
+    }
+
+    // -=# monitoring code start #=-
+    /* will never be reached due to the infinite loop above, but
+     * demonstrates cleanup.
+     *
+     * The sensor will be freed after all parties released it, that
+     * is, the creator and all monitors.
+     */
+    ret = ferret_free_sensor(12, 2, 0, l1, &free);
+    if (ret)
+    {
+        LOG("Error freeing sensor: ret = %d", ret);
+        exit(1);
+    }
+    // -=# monitoring code end #=-
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/l4lx_arping/Makefile b/l4/pkg/ferret/examples/l4lx_arping/Makefile
new file mode 100644 (file)
index 0000000..7c4720b
--- /dev/null
@@ -0,0 +1,16 @@
+PKGDIR         ?= ../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = arping.c
+
+#DEFAULT_RELOC   = 0x00680000
+TARGET          = l4lx_arping
+
+MODE            = l4linux
+
+LIBS            = -lferret_l4lx_client -lferret_util -lnet -lpcap
+LIBCLIBS        =
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/l4lx_arping/arping.c b/l4/pkg/ferret/examples/l4lx_arping/arping.c
new file mode 100644 (file)
index 0000000..5704fee
--- /dev/null
@@ -0,0 +1,1280 @@
+/*
+ * (c) 2000-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+/*
+ * arping
+ *
+ * By Thomas Habets <thomas@habets.pp.se>
+ *
+ * ARP 'ping' utility
+ *
+ * Broadcasts a who-has ARP packet on the network and prints answers.
+ * *VERY* useful when you are trying to pick an unused IP for a net that
+ * you don't yet have routing to. Then again, if you have no idea what I'm
+ * talking about then you prolly don't need it.
+ *
+ * Also finds out IP of specified MAC
+ *
+ * $Id$
+ */
+/*
+ *  Copyright (C) 2000-2002 Thomas Habets <thomas@habets.pp.se>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+//#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef WIN32
+#include <unistd.h>
+// NOTE: try un-commenting this
+//#include <stdint.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libnet.h>
+#endif
+
+#ifdef WIN32
+#include <win32/libnet.h>
+#endif
+#include <pcap.h>
+
+#if defined(WIN32)
+#define HAVE_ESIZE_TYPES 1
+#include "win32.h"
+#include "win32/getopt.h"
+#endif
+#if defined(linux)
+#define HAVE_ESIZE_TYPES 1
+#define FINDIF 1
+#endif
+
+#ifdef HAVE_NET_BPF_H
+#include <net/bpf.h>
+#endif
+
+#include <l4/ferret/l4lx_client.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/util.h>
+
+#ifndef HAVE_ESIZE_TYPES
+/*
+ * let's hope we at least have these
+ * FIXME: bleh, this is not auto-detected, so fix it with os-dependent stuff
+ * like we have above for linux
+ * But this broken thing compiled on my solaris, openbsd and linux-boxes so
+ * it kinda works.
+ */
+#define u_int8_t uint8_t
+#define u_int16_t uint16_t
+#define u_int32_t uint32_t
+#endif
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+#ifndef IP_ALEN
+#define IP_ALEN 4
+#endif
+
+const float version = 2.05f;
+
+static libnet_t *libnet = 0;
+
+static struct timeval lastpacketsent;
+
+static u_int32_t srcip,dstip;
+
+static int beep = 0;
+static int verbose = 0;
+static int alsototal = 0;
+/*static int pingmac = 0; */
+static int finddup = 0;
+static unsigned int numsent = 0;
+static unsigned int numrecvd = 0;
+static int addr_must_be_same = 0;
+// RAWRAW is RAW|RRAW
+static enum { NORMAL,QUIET,RAW,RRAW,RAWRAW } display = NORMAL;
+static char *target = "huh? bug in arping?";
+static u_int8_t ethnull[ETH_ALEN];
+static u_int8_t ethxmas[ETH_ALEN];
+static char srcmac[ETH_ALEN];
+static char dstmac[ETH_ALEN];
+
+volatile int time_to_die = 0;
+
+
+/*
+ *
+ */    
+static void do_libnet_init(const char *ifname)
+{
+       char ebuf[LIBNET_ERRBUF_SIZE];
+       if (verbose > 1) {
+               printf("libnet_init(%s)\n", ifname);
+       }
+       if (libnet) {
+               /* prolly going to switch interface from temp to real */
+               libnet_destroy(libnet);
+               libnet = 0;
+       }
+       if (getuid() && geteuid()) {
+               fprintf(stderr, "arping: must run as root\n");
+               exit(1);
+       }
+
+       if (!(libnet = libnet_init(LIBNET_LINK,
+                                  (char*)ifname,
+                                  ebuf))) {
+               fprintf(stderr, "arping: libnet_init(): %s\n", ebuf);
+               exit(1);
+       }
+}
+
+/*
+ *
+ */
+static const char *arping_lookupdev_default(u_int32_t srcip, u_int32_t dstip,
+                                    char *ebuf)
+{
+#ifdef WIN32
+       WCHAR buf[LIBNET_ERRBUF_SIZE + PCAP_ERRBUF_SIZE];
+       WCHAR* ret = (WCHAR*)pcap_lookupdev((char*)buf);
+       if (ret != NULL) {
+               wcstombs(ebuf, ret, LIBNET_ERRBUF_SIZE + PCAP_ERRBUF_SIZE);
+               return ebuf;
+       }
+       return NULL;
+#else
+       return pcap_lookupdev(ebuf);
+#endif
+}
+
+#if defined(FINDIF) && defined(linux)
+/*
+ *
+ */
+static const char *arping_lookupdev(u_int32_t srcip, u_int32_t dstip,
+                                   char *ebuf)
+{
+       FILE *f;
+       static char buf[1024];
+       char buf1[1024];
+       char buf2[1024];
+       char *p,*p2;
+       int n;
+
+       do_libnet_init(NULL);
+       libnet_addr2name4_r(dstip,0,buf2);
+       libnet_addr2name4_r(srcip,0,buf1);
+
+       /*
+        * Construct and run command
+        */
+       snprintf(buf, 1023, "/sbin/ip route get %s from %s 2>&1",
+                buf2,buf1);
+       if (!(f = popen(buf, "r"))) {
+               goto failed;
+       }
+       if (0>(n = fread(buf, 1, sizeof(buf)-1, f))) {
+               pclose(f);
+               goto failed;
+       }
+       buf[n] = 0;
+       if (-1 == pclose(f)) {
+               perror("arping: pclose()");
+               goto failed;
+       }
+
+       /*
+        * Parse out device
+        */
+       p = strstr(buf, "dev ");
+       if (!p) {
+               goto failed;
+       }
+
+       p+=4;
+
+       p2 = strchr(p, ' ');
+       if (!p2) {
+               goto failed;
+       }
+       *p2 = 0;
+       return p;
+ failed:
+       return arping_lookupdev_default(srcip,dstip,ebuf);
+}
+#else
+/*
+ *
+ */
+static const char *arping_lookupdev(u_int32_t srcip, u_int32_t dstip,
+                                   char *ebuf)
+{
+       return arping_lookupdev_default(srcip,dstip,ebuf);
+}
+#endif
+
+
+#ifdef WIN32
+static BOOL WINAPI arping_console_ctrl_handler(DWORD dwCtrlType )
+{
+       if(verbose) {
+               printf("arping_console_ctrl_handler( %d )\n", dwCtrlType );
+       }
+       time_to_die = 1;
+
+#if 0
+       /* if SetConsoleCtrlHandler() does what I think, this isn't needed */
+       if (display == NORMAL) {
+               printf("\n--- %s statistics ---\n"
+                      "%d packets transmitted, %d packets received, %3.0f%% "
+                      "unanswered\n",target,numsent,numrecvd,
+                      100.0 - 100.0 * (float)(numrecvd)/(float)numsent);
+                      }
+#endif
+       return TRUE;
+}
+#endif
+
+
+/*
+ *
+ */
+static void sigint(int i)
+{
+       time_to_die = 1;
+}
+
+/*
+ *
+ */
+static void usage(int ret)
+{
+       printf("ARPing %1.2f, by Thomas Habets <thomas@habets.pp.se>\n",
+              version);
+       printf("usage: arping [ -0aAbdFpqrRuv ] [ -w <us> ] [ -S <host/ip> ] "
+              "[ -T <host/ip ]\n"
+              "              [ -s <MAC> ] [ -t <MAC> ] [ -c <count> ] "
+              "[ -i <interface> ]\n"
+              "              <host/ip/MAC | -B>\n");
+       exit(ret);
+}
+
+/*
+ * It was unclear from msdn.microsoft.com if their scanf() supported
+ * [0-9a-fA-F], so I'll stay away from it.
+ */
+static int is_mac_addr(const char *p)
+{
+       /* cisco-style */
+       if (3*5-1 == strlen(p)) {
+               int c;
+               for (c = 0; c < strlen(p); c++) {
+                       if ((c % 5) == 4) {
+                               if ('.' != p[c]) {
+                                       goto checkcolon;
+                               }
+                       } else {
+                               if (!isxdigit(p[c])) {
+                                       goto checkcolon;
+                               }
+                       }
+               }
+               return 1;
+       }
+       /* windows-style */
+       if (6*3-1 == strlen(p)) {
+               int c;
+               for (c = 0; c < strlen(p); c++) {
+                       if ((c % 3) == 2) {
+                               if ('-' != p[c]) {
+                                       goto checkcolon;
+                               }
+                       } else {
+                               if (!isxdigit(p[c])) {
+                                       goto checkcolon;
+                               }
+                       }
+               }
+               return 1;
+       }
+
+ checkcolon:
+       /* unix */
+       return strchr(p, ':') ? 1 : 0;
+}
+
+/*
+ * lots of parms since C arrays suck
+ */
+static int get_mac_addr(const char *in,
+                       unsigned int *n0,
+                       unsigned int *n1,
+                       unsigned int *n2,
+                       unsigned int *n3,
+                       unsigned int *n4,
+                       unsigned int *n5)
+{
+       if (6 == sscanf(in, "%x:%x:%x:%x:%x:%x",n0,n1,n2,n3,n4,n5)) {
+               return 1;
+       } else if(6 == sscanf(in, "%2x%x.%2x%x.%2x%x",n0,n1,n2,n3,n4,n5)) {
+               return 1;
+       } else if(6 == sscanf(in, "%x-%x-%x-%x-%x-%x",n0,n1,n2,n3,n4,n5)) {
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * as always, the answer is 42
+ *
+ * in this case the question is how many bytes buf needs to be.
+ * Assuming a 33 byte max %d
+ *
+ * Still, I'm using at least 128bytes below
+ *
+ * (because snprintf() sadly isn't as portable, that's why)
+ */
+static char *tv2str(const struct timeval *tv, const struct timeval *tv2,
+                   char *buf)
+{
+       double f,f2;
+       int exp = 0;
+
+       f = tv->tv_sec + (double)tv->tv_usec / 1000000;
+       f2 = tv2->tv_sec + (double)tv2->tv_usec / 1000000;
+       f = (f2 - f) * 1000000;
+       while (f > 1000) {
+               exp+= 3;
+               f /= 1000;
+       }
+       switch (exp) {
+       case 0:
+               sprintf(buf, "%.3f usec", f);
+               break;
+       case 3:
+               sprintf(buf, "%.3f msec", f);
+               break;
+       case 6:
+               sprintf(buf, "%.3f sec", f);
+               break;
+       case 9:
+               sprintf(buf, "%.3f sec", f*1000);
+               break;
+        default:
+               // huh, uh, huhuh
+               sprintf(buf, "%.3fe%d sec", f, exp-6);
+       }
+       return buf;
+}
+
+
+
+/*
+ *
+ */
+static void pingmac_send(u_int8_t *srcmac, u_int8_t *dstmac,
+                        u_int32_t srcip, u_int32_t dstip,
+                        u_int16_t id, u_int16_t seq)
+{
+       static libnet_ptag_t icmp = 0, ipv4 = 0,eth=0;
+       int c;
+
+       if (-1 == (icmp = libnet_build_icmpv4_echo(ICMP_ECHO, // type
+                                                  0, // code
+                                                  0, // checksum
+                                                  id, // id
+                                                  seq, // seq
+                                                  NULL, // payload
+                                                  0, // payload len
+                                                  libnet,
+                                                  icmp))) {
+               fprintf(stderr, "libnet_build_icmpv4_echo(): %s\n",
+                       libnet_geterror(libnet));
+               sigint(0);
+       }
+
+       if (-1==(ipv4 = libnet_build_ipv4(LIBNET_IPV4_H
+                                         + LIBNET_ICMPV4_ECHO_H + 0,
+                                         0, // ToS
+                                         id, // id
+                                         0, // frag
+                                         64, // ttl
+                                         IPPROTO_ICMP,
+                                         0, // checksum
+                                         srcip,
+                                         dstip,
+                                         NULL, // payload
+                                         0,
+                                         libnet,
+                                         ipv4))) {
+               fprintf(stderr, "libnet_build_ipv4(): %s\n",
+                       libnet_geterror(libnet));
+               sigint(0);
+       }
+       if (-1 == (eth = libnet_build_ethernet(dstmac,
+                                              srcmac,
+                                              ETHERTYPE_IP,
+                                              NULL,
+                                              0,
+                                              libnet,
+                                              eth))) {
+               fprintf(stderr, "libnet_build_ethernet(): %s\n",
+                       libnet_geterror(libnet));
+               sigint(0);
+       }
+       if(verbose>1) {
+               printf("arping: sending packet\n");
+       }
+       if (-1 == (c = libnet_write(libnet))) {
+               fprintf(stderr, "arping: libnet_write(): %s\n",
+                       libnet_geterror(libnet));
+               sigint(0);
+       }
+       if (-1 == gettimeofday(&lastpacketsent, NULL)) {
+               fprintf(stderr, "arping: gettimeofday(): %s\n",
+                       strerror(errno));
+               sigint(0);
+       }
+       numsent++;
+}
+
+/*
+ *
+ */
+static void pingip_send(u_int8_t *srcmac, u_int8_t *dstmac,
+                       u_int32_t srcip, u_int32_t dstip)
+{
+       static libnet_ptag_t arp=0,eth=0;
+       if (-1 == (arp = libnet_build_arp(ARPHRD_ETHER,
+                                         ETHERTYPE_IP,
+                                         ETH_ALEN,
+                                         IP_ALEN,
+                                         ARPOP_REQUEST,
+                                         srcmac,
+                                         (u_int8_t*)&srcip,
+                                         ethnull,
+                                         (u_int8_t*)&dstip,
+                                         NULL,
+                                         0,
+                                         libnet,
+                                         arp))) {
+               fprintf(stderr, "arping: libnet_build_arp(): %s\n",
+                       libnet_geterror(libnet));
+               sigint(0);
+       }
+       if (-1 == (eth = libnet_build_ethernet(dstmac,
+                                              srcmac,
+                                              ETHERTYPE_ARP,
+                                              NULL,
+                                              0,
+                                              libnet,
+                                              eth))) {
+               fprintf(stderr, "arping: libnet_build_ethernet(): %s\n",
+                       libnet_geterror(libnet));
+               sigint(0);
+       }
+       if(verbose>1) {
+               printf("arping: sending packet\n");
+       }
+       if (-1 == libnet_write(libnet)) {
+               fprintf(stderr, "arping: libnet_write(): %s\n", 
+                       libnet_geterror(libnet));
+               sigint(0);
+       }
+       if (-1 == gettimeofday(&lastpacketsent, NULL)) {
+               fprintf(stderr, "arping: gettimeofday(): %s\n",
+                       strerror(errno));
+               sigint(0);
+       }
+       numsent++;
+}
+
+/*
+ *
+ */
+static void pingip_recv(const char *unused, struct pcap_pkthdr *h,
+                       u_int8_t *packet)
+{
+       struct libnet_802_3_hdr *heth;
+       struct libnet_arp_hdr *harp;
+       struct timeval arrival;
+       int c;
+
+       if(verbose>2) {
+               printf("arping: received response for ip ping\n");
+       }
+
+       if (-1 == gettimeofday(&arrival, NULL)) {
+               fprintf(stderr, "arping: gettimeofday(): %s\n",
+                       strerror(errno));
+               sigint(0);
+       }
+       heth = (void*)packet;
+       harp = (void*)((char*)heth + LIBNET_ETH_H);
+
+       if ((htons(harp->ar_op) == ARPOP_REPLY)
+           && (htons(harp->ar_pro) == ETHERTYPE_IP)
+           && (htons(harp->ar_hrd) == ARPHRD_ETHER)) {
+               u_int32_t ip;
+               memcpy(&ip, (char*)harp + harp->ar_hln
+                      + LIBNET_ARP_H,4);
+               if (addr_must_be_same
+                   && (memcmp((u_char*)harp+sizeof(struct libnet_arp_hdr),
+                              dstmac, ETH_ALEN))) {
+                       return;
+               }
+               if (dstip == ip) {
+                       switch(display) {
+                       case NORMAL: {
+                               char buf[128];
+                               printf("%d bytes from ", h->len);
+                               for (c = 0; c < 6; c++) {
+                                       printf("%.2x%c", heth->_802_3_shost[c],
+                                              (c<5)?':':' ');
+                               }
+                               
+                               printf("(%s): index=%d",
+                                      libnet_addr2name4(ip,0),
+                                      numrecvd);
+                               if (alsototal) {
+                                       printf("/%u", numsent-1);
+                               }
+                               printf(" time=%s",
+                                      tv2str(&lastpacketsent,
+                                             &arrival,buf));
+                               break; }
+                       case QUIET:
+                               break;
+                       case RAWRAW:
+                               for (c = 0; c < 6; c++) {
+                                       printf("%.2x%c", heth->_802_3_shost[c],
+                                              (c<5)?':':' ');
+                               }
+                               printf("%s", libnet_addr2name4(ip,0));
+                               break;
+                       case RRAW:
+                               printf("%s", libnet_addr2name4(ip,0));
+                               break;
+                       case RAW:
+                               for (c = 0; c < 6; c++) {
+                                       printf("%.2x%s", heth->_802_3_shost[c],
+                                              (c<5)?":":"");
+                               }
+                               break;
+                       default:
+                               fprintf(stderr, "arping: can't happen!\n");
+                       }
+                       if (display != QUIET) {
+                               printf(beep?"\a\n":"\n");
+                       }
+                       numrecvd++;
+               }
+       }
+}
+
+/*
+ * 
+ */
+static void pingmac_recv(const char *unused, struct pcap_pkthdr *h,
+                       u_int8_t *packet)
+{
+       struct libnet_802_3_hdr *heth;
+       struct libnet_ipv4_hdr *hip;
+       struct libnet_icmpv4_hdr *hicmp;
+       struct timeval arrival;
+       int c;
+
+       if(verbose>2) {
+               printf("arping: received response for mac ping\n");
+       }
+
+       if (-1 == gettimeofday(&arrival, NULL)) {
+               fprintf(stderr, "arping: gettimeofday(): %s\n",
+                       strerror(errno));
+               sigint(0);
+       }
+
+       heth = (void*)packet;
+       hip = (void*)((char*)heth + LIBNET_ETH_H);
+       hicmp = (void*)((char*)hip + LIBNET_IPV4_H);
+
+       if ((htons(hicmp->icmp_type) == ICMP_ECHOREPLY)
+           && ((!memcmp(heth->_802_3_shost, dstmac,ETH_ALEN)
+                || !memcmp(dstmac, ethxmas, ETH_ALEN)))
+           && !memcmp(heth->_802_3_dhost, srcmac, ETH_ALEN)) {
+/*             u_int8_t *cp = heth->_802_3_shost; */
+               if (addr_must_be_same) {
+                       u_int32_t tmp;
+                       memcpy(&tmp, &hip->ip_src, 4);
+                       if (dstip != tmp) {
+                               return;
+                       }
+               }
+               switch(display) {
+               case QUIET:
+                       break;
+               case NORMAL: {
+                       char buf[128];
+                       printf("%d bytes from %s (",h->len,
+                              libnet_addr2name4(*(int*)&hip->ip_src, 0));
+                       for (c = 0; c < 6; c++) {
+                               printf("%.2x%c", heth->_802_3_shost[c],
+                                      (c<5)?':':')');
+                       }
+                       printf(": icmp_seq=%d time=%s",
+                              htons(hicmp->icmp_seq),tv2str(&lastpacketsent,
+                                                     &arrival,buf));
+                       break; }
+               case RAW:
+                       printf("%s",
+                              libnet_addr2name4(hip->ip_src.s_addr, 0));
+                       break;
+               case RRAW:
+                       for (c = 0; c < 6; c++) {
+                               printf("%.2x%s", heth->_802_3_shost[c],
+                                      (c<5)?":":"");
+                       }
+                       break;
+               case RAWRAW:
+                       for (c = 0; c < 6; c++) {
+                               printf("%.2x%c", heth->_802_3_shost[c],
+                                      (c<5)?':':' ');
+                       }
+                       printf("%s",
+                              libnet_addr2name4(hip->ip_src.s_addr, 0));
+                       break;
+               default:
+                       fprintf(stderr, "arping: can't-happen-bug\n");
+                       sigint(0);
+               }
+               if (display != QUIET) {
+                       printf(beep?"\a\n":"\n");
+               }
+               numrecvd++;
+       }
+}
+
+
+/*
+ * 
+ */
+static void ping_recv(pcap_t *pcap,u_int32_t packetwait, pcap_handler func)
+{
+       struct timeval tv,tv2;
+       char done = 0;
+#ifndef WIN32
+       fd_set fds;
+#endif
+
+       if(verbose>3) {
+               printf("arping: receiving packets...\n");
+       }
+
+#ifdef WIN32
+       /* windows won't let us do select() */
+       if (-1 == gettimeofday(&tv2,NULL)) {
+              fprintf(stderr, "arping: gettimeofday(): %s\n",
+                      strerror(errno));
+               sigint(0);
+       }
+       while (!done && !time_to_die) {
+              struct pcap_pkthdr *pkt_header;
+              u_char *pkt_data;
+              if (pcap_next_ex(pcap, &pkt_header, &pkt_data) == 1) {
+                      func(pcap, pkt_header, pkt_data);
+              }
+              if (-1 == gettimeofday(&tv,NULL)) {
+                      fprintf(stderr, "arping: "
+                              "gettimeofday(): %s\n",
+                              strerror(errno));
+                      sigint(0);
+              }
+               /*
+                * setup next timeval, not very exact
+                */
+               tv.tv_sec  = (packetwait / 1000000)
+                      - (tv.tv_sec - tv2.tv_sec);
+              tv.tv_usec = (packetwait % 1000000)
+                      - (tv.tv_usec - tv2.tv_usec);
+              while (tv.tv_usec < 0) {
+                      tv.tv_sec--;
+                      tv.tv_usec += 1000000;
+              }
+              usleep(10);
+              if (tv.tv_sec < 0) {
+                      done=1;
+              }
+       }
+#else
+       tv.tv_sec = packetwait / 1000000;
+       tv.tv_usec = packetwait % 1000000;
+
+       for (;!done;) {
+               int sr;
+               FD_ZERO(&fds);
+               FD_SET(pcap_fileno(pcap), &fds);
+               
+               if (-1 == gettimeofday(&tv2,NULL)) {
+                       fprintf(stderr, "arping: "
+                               "gettimeofday(): %s\n",
+                               strerror(errno));
+                       sigint(0);
+               }
+//             printf("running select()\n");
+
+               switch(sr = select(pcap_fileno(pcap)+1,
+                                  &fds,
+                                  NULL,NULL,&tv)) {
+               case -1:
+                       if (errno == EINTR) {
+                               return;
+                       }
+                       fprintf(stderr, "arping: select(): "
+                               "%s\n", strerror(errno));
+                       sigint(0);
+               case 0:
+                       done = 1;
+                       break;
+               default: {
+                       int ret;
+                       if (1 != (ret = pcap_dispatch(pcap, 1,
+                                                     func,
+                                                     NULL))) {
+                               // rest, so we don't take 100% CPU... mostly
+                               // hmm... does usleep() exist everywhere?
+                               usleep(10);
+#ifndef HAVE_WEIRD_BSD
+                               // weird is normal on bsd :)
+                               if (verbose) {
+                                       fprintf(stderr, "arping: select=%d "
+                                               "pcap_dispatch=%d!\n",
+                                               sr, ret);
+                               }
+#endif
+                       }
+                       break; }
+               }
+               
+               if (-1 == gettimeofday(&tv,NULL)) {
+                       fprintf(stderr, "arping: "
+                               "gettimeofday(): %s\n",
+                               strerror(errno));
+                       sigint(0);
+               }
+               /*
+                * setup next timeval, not very exact
+                */
+               tv.tv_sec  = (packetwait / 1000000)
+                       - (tv.tv_sec - tv2.tv_sec);
+               tv.tv_usec = (packetwait % 1000000)
+                       - (tv.tv_usec - tv2.tv_usec);
+               while (tv.tv_usec < 0) {
+                       tv.tv_sec--;
+                       tv.tv_usec += 1000000;
+               }
+               if (tv.tv_sec < 0) {
+                       tv.tv_sec = tv.tv_usec = 0;
+               }
+               
+       }
+//     if (tv.tv_usec == 0) {
+//             tv.tv_usec = 1;
+//     }
+       if (-1 == select(0, NULL,NULL,NULL, &tv)) {
+               if (errno == EINTR) {
+                       return;
+               }
+               fprintf(stderr, "arping: select(delay): %s\n",strerror(errno));
+               sigint(0);
+       }
+#endif
+}
+
+/*
+ *
+ */
+int main(int argc, char **argv)
+{
+       char ebuf[LIBNET_ERRBUF_SIZE + PCAP_ERRBUF_SIZE];
+       char *cp;
+/*     int nullip = 0;*/
+       int promisc = 0;
+       int srcip_given = 0;
+       int srcmac_given = 0;
+       int dstip_given = 0;
+       const char *ifname = NULL;
+       char *parm;
+       int c;
+       unsigned int maxcount = -1;
+       int dont_use_arping_lookupdev=0;
+       struct bpf_program bp;
+       pcap_t *pcap;
+       static enum { NONE, PINGMAC, PINGIP } mode = NONE;
+       unsigned int packetwait = 1000000;
+
+    ferret_list_l4lx_user_init();
+    printf("Initialized Ferret sensor.\n");
+
+       memset(ethnull, 0, ETH_ALEN);
+
+       srcip = 0;
+       dstip = 0xffffffff;
+       memset(dstmac, 0xff, ETH_ALEN);
+       memset(ethxmas, 0xff, ETH_ALEN);
+
+       while (EOF!=(c=getopt(argc, argv, "0aAbBc:dFhi:I:pqrRs:S:t:T:uvw:"))) {
+               switch(c) {
+               case '0':
+                       srcip = 0;
+                       srcip_given = 1;
+                       break;
+               case 'a':
+                       beep = 1;
+                       break;
+               case 'A':
+                       addr_must_be_same = 1;
+                       break;
+               case 'b':
+                       srcip = 0xffffffff;
+                       srcip_given = 1;
+                       break;
+               case 'B':
+                       dstip = 0xffffffff;
+                       dstip_given = 1;
+                       break;
+               case 'c':
+                       maxcount = atoi(optarg);
+                       break;
+               case 'd':
+                       finddup = 1;
+                       break;
+               case 'F':
+                       dont_use_arping_lookupdev=1;
+                       break;
+               case 'h':
+                       usage(0);
+               case 'i':
+                       if (strchr(optarg, ':')) {
+                               fprintf(stderr, "arping: If you're trying to "
+                                       "feed me an interface alias then you "
+                                       "don't really\nknow what this programs"
+                                       " does, do you?\nUse -I if you really"
+                                       " mean it (undocumented on "
+                                       "purpose)\n");
+                               exit(1);
+                       }
+               case 'I': /* FALL THROUGH */
+                       ifname = optarg;
+                       break;
+               case 'p':
+                       promisc = 1;
+                       break;
+               case 'q':
+                       display = QUIET;
+                       break;
+               case 'r':
+                       display = (display==RRAW)?RAWRAW:RAW;
+                       break;
+               case 'R':
+                       display = (display==RAW)?RAWRAW:RRAW;
+                       break;
+               case 's': {// spoof source MAC
+                       unsigned int n[6];
+                       if (!get_mac_addr(optarg,
+                                         &n[0],&n[1],&n[2],
+                                         &n[3],&n[4],&n[5])){
+                               fprintf(stderr, "arping: Weird MAC addr %s\n",
+                                       optarg);
+                               exit(1);
+                       }
+                       for (c = 0; c < 6; c++) {
+                               srcmac[c] = n[c] & 0xff;
+                       }
+                       srcmac_given = 1;
+                       break;
+               }
+               case 'S': // set source IP, may be null for don't-know
+                       do_libnet_init(NULL);
+                       if (-1 == (srcip = libnet_name2addr4(libnet,
+                                                            optarg,
+                                                            LIBNET_RESOLVE))){
+                               fprintf(stderr, "arping: Can't resolve %s, or "
+                                       "%s is broadcast. If it is, use -b"
+                                       " instead of -S\n", optarg,optarg);
+                               exit(1);
+                       }
+                       srcip_given = 1;
+                       break;
+               case 't': { // set taget mac
+                       unsigned int n[6];
+                       if (mode == PINGMAC) {
+                               fprintf(stderr, "arping: -t can only be used "
+                                       "in IP ping mode\n");
+                               exit(1);
+                       }
+                       if (!get_mac_addr(optarg,
+                                         &n[0],&n[1],&n[2],
+                                         &n[3],&n[4],&n[5])){
+                               fprintf(stderr, "Illegal MAC addr %s\n",
+                                       optarg);
+                               exit(1);
+                       }
+                       for (c = 0; c < 6; c++) {
+                               dstmac[c] = n[c] & 0xff;
+                       }
+                       mode = PINGIP;
+                       break;
+               }
+               case 'T': // set destination IP
+                       if (mode == PINGIP) {
+                               fprintf(stderr, "arping: -T can only be used "
+                                       "in MAC ping mode\n");
+                               exit(1);
+                       }
+                       do_libnet_init(NULL);
+                       if (-1 == (dstip = libnet_name2addr4(libnet,
+                                                            optarg,
+                                                            LIBNET_RESOLVE))){
+                               fprintf(stderr,"arping: Can't resolve %s, or "
+                                       "%s is broadcast. If it is, use -B "
+                                       "instead of -T\n",optarg,optarg);
+                               exit(1);
+                       }
+                       mode = PINGMAC;
+                       break;
+               case 'u':
+                       alsototal = 1;
+                       break;
+               case 'v':
+                       verbose++;
+                       break;
+               case 'w':
+                       packetwait = (unsigned)atoi(optarg);
+                       break;
+               default:
+                       usage(1);
+               }
+       }
+
+       parm = (optind < argc) ? argv[optind] : NULL;
+
+       /*
+        * Handle dstip_given instead of ip address after parms (-B really)
+        */
+       if (mode == NONE) {
+               if (optind + 1 == argc) {
+                       mode = is_mac_addr(parm)?PINGMAC:PINGIP;
+               } else if (dstip_given) {
+                       mode = PINGIP;
+                       do_libnet_init(NULL);
+                       parm = strdup(libnet_addr2name4(dstip,0));
+                       if (!parm) {
+                               fprintf(stderr, "arping: out of mem\n");
+                               exit(1);
+                       }
+               }
+       }
+
+       if (!parm) {
+               usage(1);
+       }
+
+       /*
+        *
+        */
+       if (mode == NONE) {
+               usage(1);
+       }
+
+       /*
+        * libnet init (may be done already for resolving)
+        */
+       do_libnet_init(ifname);
+       
+       /*
+        * Make sure dstip and parm like eachother
+        */
+       if (mode == PINGIP && (!dstip_given)) {
+               if (is_mac_addr(parm)) {
+                       fprintf(stderr, "arping: Options given only apply to "
+                               "IP ping, but MAC address given as argument"
+                               "\n");
+                       exit(1);
+               }
+               if (-1 == (dstip = libnet_name2addr4(libnet,
+                                                    parm,
+                                                    LIBNET_RESOLVE))) {
+                       fprintf(stderr, "arping: Can't resolve %s\n", parm);
+                       exit(1);
+               }
+               parm = strdup(libnet_addr2name4(dstip,0));
+       }
+
+       /*
+        * parse parm into dstmac
+        */
+       if (mode == PINGMAC) {
+               unsigned int n[6];
+               if (optind + 1 != argc) {
+                       usage(1);
+               }
+               if (!is_mac_addr(parm)) {
+                       fprintf(stderr, "arping: Options given only apply to "
+                               "MAC ping, but no MAC address given as "
+                               "argument\n");
+                       exit(1);
+               }
+               if (!get_mac_addr(argv[optind],
+                                 &n[0],&n[1],&n[2],
+                                 &n[3],&n[4],&n[5])) {
+                       fprintf(stderr, "arping: Illegal mac addr %s\n",
+                               argv[optind]);
+                       return 1;
+               }
+               for (c = 0; c < 6; c++) {
+                       dstmac[c] = n[c] & 0xff;
+               }
+       }       
+
+       target = parm;
+       /*
+        * Argument processing done, parameters considered sane below
+        */
+
+       /*
+        * Get some good iface.
+        */
+       if (!ifname) {
+               if (dont_use_arping_lookupdev) {
+                       ifname = arping_lookupdev_default(srcip,dstip,ebuf);
+               } else {
+                       ifname = arping_lookupdev(srcip,dstip,ebuf);
+               }
+               if (!ifname) {
+                       fprintf(stderr, "arping: arping_lookupdev(): %s\n",
+                               ebuf);
+                       exit(1);
+               }
+               // FIXME: check for other probably-not interfaces
+               if (!strcmp(ifname, "ipsec")
+                   || !strcmp(ifname,"lo")) {
+                       fprintf(stderr, "arping: Um.. %s looks like the wrong "
+                               "interface to use. Is it? "
+                               "(-i switch)\n", ifname);
+                       fprintf(stderr, "arping: using it anyway this time\n");
+               }
+       }
+
+       /*
+        * Init libnet again, because we now know the interface name.
+        * We should know it by know at least
+        */
+       do_libnet_init(ifname);
+
+       /*
+        * pcap init
+        */
+       if (!(pcap = pcap_open_live((char*)ifname, 100, promisc, 10, ebuf))) {
+               fprintf(stderr, "arping: pcap_open_live(): %s\n",ebuf);
+               exit(1);
+       }
+#ifdef HAVE_NET_BPF_H
+       {
+               u_int32_t on = 1;
+               if (0 < (ioctl(pcap_fileno(pcap), BIOCIMMEDIATE,
+                              &on))) {
+                       fprintf(stderr, "arping: ioctl(fd,BIOCIMMEDIATE, 1) "
+                               "failed, continuing anyway, YMMV: %s\n",
+                               strerror(errno));
+               }
+       }
+#endif
+
+       if (mode == PINGIP) {
+               // FIXME: better filter with addresses?
+               if (-1 == pcap_compile(pcap, &bp, "arp", 0,-1)) {
+                       fprintf(stderr, "arping: pcap_compile(): error\n");
+                       exit(1);
+               }
+       } else { // ping mac
+               // FIXME: better filter with addresses?
+               if (-1 == pcap_compile(pcap, &bp, "icmp", 0,-1)) {
+                       fprintf(stderr, "arping: pcap_compile(): error\n");
+                       exit(1);
+               }
+       }
+       if (-1 == pcap_setfilter(pcap, &bp)) {
+               fprintf(stderr, "arping: pcap_setfilter(): error\n");
+               exit(1);
+       }
+
+       /*
+        * final init
+        */
+       if (!srcmac_given) {
+               if (!(cp = (char*)libnet_get_hwaddr(libnet))) {
+                       fprintf(stderr, "arping: libnet_get_hwaddr(): %s\n",
+                               libnet_geterror(libnet));
+                       exit(1);
+               }
+               memcpy(srcmac, cp, ETH_ALEN);
+       }
+       if (!srcip_given) {
+               if (-1 == (srcip = libnet_get_ipaddr4(libnet))) {
+                       fprintf(stderr, "arping: libnet_get_ipaddr4(libnet): "
+                               "%s\n", libnet_geterror(libnet));
+                       exit(1);
+               }
+       }
+#ifdef WIN32
+       SetConsoleCtrlHandler(NULL, TRUE);
+       SetConsoleCtrlHandler(arping_console_ctrl_handler, TRUE);
+#else
+       signal(SIGINT, sigint);
+#endif
+
+       if (verbose) {
+               printf("This box:   Interface: %s  IP: %s   MAC address: ",
+                      ifname, libnet_addr2name4(libnet_get_ipaddr4(libnet),
+                                                0));
+               for (c = 0; c < ETH_ALEN - 1; c++) {
+                       printf("%.2x:", (u_int8_t)srcmac[c]);
+               }
+               printf("%.2x\n", (u_int8_t)srcmac[ETH_ALEN - 1]);
+       }
+
+
+       if (display == NORMAL) {
+               printf("ARPING %s\n", parm);
+       }
+
+       /*
+        * let's roll
+        */
+       if (mode == PINGIP) {
+               unsigned int c;
+               pid_t pid = getpid();
+               for (c = 0; c < maxcount && !time_to_die; c++) {
+            ferret_list_entry_common_t *le;
+            int idx;
+            idx = ferret_list_dequeue(ferret_l4lx_user);
+            le = (ferret_list_entry_common_t *)
+                ferret_list_e4i(ferret_l4lx_user->glob, idx);
+            le->major = 2;
+            le->minor = 2;  // L4LXUser_arping
+            le->instance = 0;
+            le->cpu   = 0;
+            le->data32[0]   = 0;    // type == start
+            le->data32[1]   = pid;
+            ferret_list_commit(ferret_l4lx_user, idx);
+
+            pingip_send((u_int8_t *)srcmac, (u_int8_t *)dstmac, srcip, dstip);
+            // XXX: EVENT: sent a packet
+
+                       idx = ferret_list_dequeue(ferret_l4lx_user);
+            le = (ferret_list_entry_common_t *)
+                ferret_list_e4i(ferret_l4lx_user->glob, idx);
+            le->major = 2;
+            le->minor = 2;  // L4LXUser_arping
+            le->instance = 0;
+            le->cpu   = 0;
+            le->data32[0]   = 1;    // type == sent
+                       le->data32[1]   = pid;
+            ferret_list_commit(ferret_l4lx_user, idx);
+
+            ping_recv(pcap,packetwait,
+                      (pcap_handler)pingip_recv);
+
+            idx = ferret_list_dequeue(ferret_l4lx_user);
+            le = (ferret_list_entry_common_t *)
+                ferret_list_e4i(ferret_l4lx_user->glob, idx);
+            le->major = 2;
+            le->minor = 2;  // L4LXUser_arping
+            le->instance = 0;
+            le->cpu   = 0;
+            le->data32[0]   = 2;    // type == recv
+                       le->data32[1]   = pid;
+            ferret_list_commit(ferret_l4lx_user, idx);
+               }
+       } else { // PINGMAC
+               unsigned int c;
+               pid_t pid = getpid();
+               for (c = 0; c < maxcount && !time_to_die; c++) {
+            ferret_list_entry_common_t *le;
+            int idx;
+
+                       idx = ferret_list_dequeue(ferret_l4lx_user);
+            le = (ferret_list_entry_common_t *)
+                ferret_list_e4i(ferret_l4lx_user->glob, idx);
+            le->major = 2;
+            le->minor = 2;  // L4LXUser_arping
+            le->instance = 0;
+            le->cpu   = 0;
+            le->data32[0]   = 0;    // type == start
+                       le->data32[1]   = pid;
+            ferret_list_commit(ferret_l4lx_user, idx);
+
+            pingmac_send((u_int8_t *)srcmac, (u_int8_t *)dstmac, srcip, dstip,
+                         rand(), c);
+
+            idx = ferret_list_dequeue(ferret_l4lx_user);
+            le = (ferret_list_entry_common_t *)
+                ferret_list_e4i(ferret_l4lx_user->glob, idx);
+            le->major = 2;
+            le->minor = 2;  // L4LXUser_arping
+            le->instance = 0;
+            le->cpu   = 0;
+            le->data32[0]   = 1;    // type == sent
+                       le->data32[1]   = pid;
+            ferret_list_commit(ferret_l4lx_user, idx);
+                       
+                       ping_recv(pcap,packetwait,
+                                 (pcap_handler)pingmac_recv);
+            
+                       idx = ferret_list_dequeue(ferret_l4lx_user);
+            le = (ferret_list_entry_common_t *)
+                ferret_list_e4i(ferret_l4lx_user->glob, idx);
+            le->major = 2;
+            le->minor = 2;  // L4LXUser_arping
+            le->instance = 0;
+            le->cpu   = 0;
+            le->data32[0]   = 2;    // type == recv
+                       le->data32[1]   = pid;
+            ferret_list_commit(ferret_l4lx_user, idx);
+               }
+       }
+       if (display == NORMAL) {
+               printf("\n--- %s statistics ---\n"
+                      "%d packets transmitted, %d packets received, %3.0f%% "
+                      "unanswered\n",target,numsent,numrecvd,
+                      100.0 - 100.0 * (float)(numrecvd)/(float)numsent); 
+       }
+       exit(!numrecvd);
+
+       return 0;
+}
diff --git a/l4/pkg/ferret/examples/l4lx_arping/broken b/l4/pkg/ferret/examples/l4lx_arping/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/monitors/Makefile b/l4/pkg/ferret/examples/monitors/Makefile
new file mode 100644 (file)
index 0000000..4f2d680
--- /dev/null
@@ -0,0 +1,7 @@
+PKGDIR ?= ../..
+L4DIR  ?= $(PKGDIR)/../..
+
+TARGET = dope_control l4lx_control l4lx_verify_cli_mon merge_mon            \
+         idle_switch_mon l4lx_histo_mon l4lx_verify_tamed_mon simple_mon
+
+include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/ferret/examples/monitors/common/uu.c b/l4/pkg/ferret/examples/monitors/common/uu.c
new file mode 100644 (file)
index 0000000..3839501
--- /dev/null
@@ -0,0 +1,271 @@
+/**
+ * \file   ferret/examples/merge_mon/uu.c
+ * \brief  UUencoding functions, mostly from jdb
+ *
+ * \date   14/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+/* ENC is the basic 1 character encoding function to make a char printing */
+#define        ENC(c) ((c) ? ((c) & 077) + ' ': '`')
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <zlib.h>
+
+#include "uu.h"
+
+#define MIN(a, b) ((a)<(b)?(a):(b))
+
+#define LINE_IN 45
+
+static z_stream strm;
+
+/* Init. zlib data structures, available input data and start address
+ */
+static void init_z(size_t len, const void *start)
+{
+    int ret;
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    ret = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 + 16, 9,
+                       Z_DEFAULT_STRATEGY);
+    assert(ret == Z_OK);
+
+    strm.avail_in = len;
+    strm.next_in  = (void *)start;  // oh why ...
+}
+
+static int get_next_chunk(void *dest, ssize_t n, int flush)
+{
+    int ret;
+
+    strm.avail_out = n;
+    strm.next_out = dest;
+    ret = deflate(&strm, flush);
+    assert(ret != Z_STREAM_ERROR);
+    return n - strm.avail_out;
+}
+
+static void update_in_data(const unsigned char * buf, size_t * len)
+{
+    if (strm.avail_in == 0 && *len != 0)
+    {
+        strm.avail_in = *len;
+        strm.next_in  = (void *)buf;  // oh why ...
+        *len = 0;
+    }
+}
+
+void uu_dumpz(const char * filename, const unsigned char * s_buf, size_t len)
+{
+    unsigned int ch;
+    int n, ret;
+    const unsigned char *p_buf;
+    int out_i;
+    static unsigned char in[LINE_IN + 3];  // some spare zeros for uuencode
+    static unsigned char out[70];
+    int flush = Z_NO_FLUSH;
+
+    init_z(len, s_buf);
+
+    // uuencode header
+    printf("begin 644 %s.gz\n", filename);
+
+    while (1)
+    {
+        // get next line of data
+        n = get_next_chunk(in, LINE_IN, flush);
+        if (n < LINE_IN && flush == Z_NO_FLUSH)
+        {
+            flush = Z_FINISH;  // time to clean up now
+            n += get_next_chunk(in + n, LINE_IN - n, flush);
+        }
+        else if (n == 0 && flush == Z_FINISH)
+            break;  // no more data available, leave loop
+        memset(in + n, 0, sizeof(in) - n);
+
+        // fill output buffer
+        out_i = 0;
+        // line length prefix
+        ch = ENC(n);
+        out[out_i++] = ch;
+        for (p_buf = in; n > 0; n -= 3, p_buf += 3)
+       {
+            ch = *p_buf >> 2;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((*p_buf << 4) & 060) | ((p_buf[1] >> 4) & 017);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((p_buf[1] << 2) & 074) | ((p_buf[2] >> 6) & 03);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = p_buf[2] & 077;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+       }
+        // skip this newline for log output
+        //out[out_i++] = '\n';
+        out[out_i] = '\0';
+        puts((char const*)out);  // write it
+    }
+
+    ret = deflateEnd(&strm);
+    assert(ret == Z_OK);
+
+    // uuencode footer
+    printf("`\nend\n");
+}
+
+/* Also works in ring buffers with wrap-around
+ */
+void uu_dumpz_ringbuffer(const char * filename,
+                         const void * _buffer, size_t buffer_len,
+                         off_t start_offset, size_t transfer_size)
+{
+    int ret;
+    unsigned char * buffer = (unsigned char *)_buffer;
+    static unsigned char in[LINE_IN + 3];  // some spare zeros for uuencode
+    static unsigned char out[70];
+    int flush = Z_NO_FLUSH;
+    size_t first_len = MIN(transfer_size, buffer_len - start_offset);
+
+    assert((unsigned)start_offset < buffer_len);
+    assert(transfer_size <= buffer_len);
+
+    // init. zlib stream for first chunk
+    init_z(first_len, buffer + start_offset);
+    transfer_size -= first_len;
+
+    // uuencode header
+    printf("begin 644 %s.gz\n", filename);
+
+    while (1)
+    {
+        int out_i, n;
+        unsigned int ch;
+        const unsigned char * p_buf;
+
+        // get next line of data
+        n = get_next_chunk(in, LINE_IN, flush);
+        update_in_data(buffer, &transfer_size);
+        if (n < LINE_IN && flush == Z_NO_FLUSH)
+        {
+            flush = Z_FINISH;  // time to clean up now
+            n += get_next_chunk(in + n, LINE_IN - n, flush);
+            update_in_data(buffer, &transfer_size);
+        }
+        else if (n == 0 && flush == Z_FINISH)
+            break;  // no more data available, leave loop
+        memset(in + n, 0, sizeof(in) - n);
+
+        // fill output buffer
+        out_i = 0;
+        // line length prefix
+        ch = ENC(n);
+        out[out_i++] = ch;
+        for (p_buf = in; n > 0; n -= 3, p_buf += 3)
+       {
+            ch = *p_buf >> 2;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((*p_buf << 4) & 060) | ((p_buf[1] >> 4) & 017);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((p_buf[1] << 2) & 074) | ((p_buf[2] >> 6) & 03);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = p_buf[2] & 077;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+       }
+        // skip this newline for log output
+        //out[out_i++] = '\n';
+        out[out_i] = '\0';
+        puts((char const *)out);  // write it
+    }
+
+    ret = deflateEnd(&strm);
+    assert(ret == Z_OK);
+
+    // uuencode footer
+    printf("`\nend\n");
+}
+
+#if 0
+void uu_dump(const char * filename, const buf_t * buf)
+{
+    unsigned int ch;
+    int n;
+    const unsigned char *p_buf;
+    unsigned char *s_buf = buf->start;
+    int out_i;
+    static unsigned char in[48];
+    static unsigned char out[70];
+    size_t len = buf->write_pos - buf->start;
+
+    // debug
+    //printf("%hhx %hhx %hhx %hhx\n", ENC(8), ENC(64), ENC(4), ENC(2));
+
+    // uuencode header
+    printf("begin 644 %s\n", filename);
+
+    while (len > 0)
+    {
+        // get next line of data
+        if (len >= LINE_IN)
+       {
+            n = LINE_IN;
+       }
+        else
+       {
+            n = len;
+       }
+        memcpy(in, s_buf, n);
+        memset(in + n, 0, sizeof(in) - n);
+        len -= n;
+        s_buf += n;
+
+        // fill output buffer
+        out_i = 0;
+        // line length prefix
+        ch = ENC(n);
+        out[out_i++] = ch;
+        for (p_buf = in; n > 0; n -= 3, p_buf += 3)
+       {
+            ch = *p_buf >> 2;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((*p_buf << 4) & 060) | ((p_buf[1] >> 4) & 017);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = ((p_buf[1] << 2) & 074) | ((p_buf[2] >> 6) & 03);
+            ch = ENC(ch);
+            out[out_i++] = ch;
+            ch = p_buf[2] & 077;
+            ch = ENC(ch);
+            out[out_i++] = ch;
+       }
+        // skip this newline for log output
+        //out[out_i++] = '\n';
+        out[out_i] = '\0';
+
+        // write it
+        puts(out);
+    }
+
+    // uuencode footer
+    printf("`\nend\n");
+}
+#endif
diff --git a/l4/pkg/ferret/examples/monitors/common/uu.h b/l4/pkg/ferret/examples/monitors/common/uu.h
new file mode 100644 (file)
index 0000000..b376012
--- /dev/null
@@ -0,0 +1,25 @@
+/**
+ * \file   ferret/examples/merge_mon/uu.h
+ * \brief  UUencoding functions, mostly from jdb
+ *
+ * \date   14/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_EXAMPLES_MERGE_MON_UU_H_
+#define __FERRET_EXAMPLES_MERGE_MON_UU_H_
+
+#include <stddef.h>
+
+//void uu_dump(const char * filename, const buf_t *buf);
+void uu_dumpz(const char * filename, const unsigned char * s_buf, size_t len);
+void uu_dumpz_ringbuffer(const char * filename,
+                         const void * buffer, size_t buffer_len,
+                         off_t start_offset, size_t transfer_size);
+
+#endif
diff --git a/l4/pkg/ferret/examples/monitors/dope_control/Makefile b/l4/pkg/ferret/examples/monitors/dope_control/Makefile
new file mode 100644 (file)
index 0000000..e4afb6a
--- /dev/null
@@ -0,0 +1,26 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+PRIVATE_INCDIR  =+ $(PKGDIR_ABS)/examples/monitors/dope_control .
+
+SRC_C           = main.c
+
+DEFAULT_RELOC   = 0x00344000
+TARGET          = fer_dope_ctrl
+
+MODE            = l4env_minimal
+
+LIBS            = -lferret_client -lferret_producer -lferret_util -ll4dope  \
+                  -lferret_comm -lferret_fpages -lferret_local_names
+
+include $(L4DIR)/mk/prog.mk
+
+vpath main_window.dpe $(PKGDIR_ABS)/examples/monitors/dope_control
+vpath main_window.dpe $(PKGDIR_OBJ)/examples/monitors/dope_control/OBJ-$(SYSTEM)
+
+main_window.i: main_window.dpe
+       $(L4DIR)/tool/gen_dopecode/gen_dopecode $^ > $@
+
+main.o: main_window.i
diff --git a/l4/pkg/ferret/examples/monitors/dope_control/README b/l4/pkg/ferret/examples/monitors/dope_control/README
new file mode 100644 (file)
index 0000000..dd923c3
--- /dev/null
@@ -0,0 +1,4 @@
+This is a small GUI application for DOPE which can insert special
+control events (start/stop recording, dump, clear buffers, ping etc.) 
+into a dedicated control sensor.  Monitors can listen to these control
+events and react accordingly.
diff --git a/l4/pkg/ferret/examples/monitors/dope_control/broken b/l4/pkg/ferret/examples/monitors/dope_control/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/monitors/dope_control/main.c b/l4/pkg/ferret/examples/monitors/dope_control/main.c
new file mode 100644 (file)
index 0000000..ecd8e8b
--- /dev/null
@@ -0,0 +1,131 @@
+/**
+ * \file   ferret/examples/dope_control/main.c
+ * \brief  Remote control from DOpE by inserting special control events
+ *
+ * \date   2006-07-24
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <l4/dope/dopelib.h>
+#include <l4/ferret/client.h>
+#include <l4/ferret/maj_min.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/util.h>
+#include <l4/util/util.h>
+
+
+#define BUTTON_START  1
+#define BUTTON_STOP   2
+#define BUTTON_CLEAR  3
+#define BUTTON_SERIAL 4
+#define BUTTON_DUMP   5
+#define BUTTON_PING   6
+
+long app_id;
+ferret_list_local_t * list = NULL;
+
+
+static void press_callback(dope_event *e, void *arg)
+{
+    int id = (int)arg;
+    int idx;
+    ferret_list_entry_common_t * elc;
+
+    printf("Callback %d\n", id);
+
+    switch (id)
+    {
+    case BUTTON_START:
+        idx = ferret_list_dequeue(list);
+        elc = (ferret_list_entry_common_t *)ferret_list_e4i(list->glob, idx);
+        elc->major = FERRET_MONCON_MAJOR;
+        elc->minor = FERRET_MONCON_START;
+        ferret_list_commit(list, idx);
+        break;
+    case BUTTON_STOP:
+        idx = ferret_list_dequeue(list);
+        elc = (ferret_list_entry_common_t *)ferret_list_e4i(list->glob, idx);
+        elc->major = FERRET_MONCON_MAJOR;
+        elc->minor = FERRET_MONCON_STOP;
+        ferret_list_commit(list, idx);
+        break;
+    case BUTTON_CLEAR:
+        idx = ferret_list_dequeue(list);
+        elc = (ferret_list_entry_common_t *)ferret_list_e4i(list->glob, idx);
+        elc->major = FERRET_MONCON_MAJOR;
+        elc->minor = FERRET_MONCON_CLEAR;
+        ferret_list_commit(list, idx);
+        break;
+    case BUTTON_SERIAL:
+        idx = ferret_list_dequeue(list);
+        elc = (ferret_list_entry_common_t *)ferret_list_e4i(list->glob, idx);
+        elc->major = FERRET_MONCON_MAJOR;
+        elc->minor = FERRET_MONCON_SERSEND;
+        strcpy(elc->data8, "Test.dat");
+        ferret_list_commit(list, idx);
+        break;
+    case BUTTON_DUMP:
+        idx = ferret_list_dequeue(list);
+        elc = (ferret_list_entry_common_t *)ferret_list_e4i(list->glob, idx);
+        elc->major = FERRET_MONCON_MAJOR;
+        elc->minor = FERRET_MONCON_STATS;
+        ferret_list_commit(list, idx);
+        break;
+    case BUTTON_PING:
+        idx = ferret_list_dequeue(list);
+        elc = (ferret_list_entry_common_t *)ferret_list_e4i(list->glob, idx);
+        elc->major = FERRET_MONCON_MAJOR;
+        elc->minor = FERRET_MONCON_PING;
+        ferret_list_commit(list, idx);
+        break;
+    }
+}
+
+
+int main(int argc, char* argv[])
+{
+    int ret;
+
+    ret = ferret_create(FERRET_MONCON_MAJOR, FERRET_MONCON_MINOR, 0,
+                        FERRET_LIST, 0, "64:100", list, &malloc);
+    if (ret)
+    {
+        printf("Error creating sensor: ret = %d, giving up.", ret);
+        exit(1);
+    }
+
+    while ((ret = dope_init()))
+    {
+        printf("Waiting for DOpE ...\n");
+        l4_sleep(200);
+    }
+    app_id = dope_init_app("Ferret Merge Monitor");
+
+    #include "main_window.i"
+
+    dope_bind(app_id, "b_start", "clack", press_callback,
+              (void *)BUTTON_START);
+    dope_bind(app_id, "b_stop", "clack", press_callback,
+              (void *)BUTTON_STOP);
+    dope_bind(app_id, "b_clear", "clack", press_callback,
+              (void *)BUTTON_CLEAR);
+    dope_bind(app_id, "b_serial", "clack", press_callback,
+              (void *)BUTTON_SERIAL);
+    dope_bind(app_id, "b_dump", "clack", press_callback,
+              (void *)BUTTON_DUMP);
+    dope_bind(app_id, "b_ping", "clack", press_callback,
+              (void *)BUTTON_PING);
+
+    dope_eventloop(app_id);
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/monitors/dope_control/main_window.dpe b/l4/pkg/ferret/examples/monitors/dope_control/main_window.dpe
new file mode 100644 (file)
index 0000000..0a5c9ba
--- /dev/null
@@ -0,0 +1,36 @@
+# main window
+win = new Window()
+g1 = new Grid()
+win.set(-content g1 -x 0 -y 50)
+
+# labels
+temp = new Label()
+temp.set(-text "Send control events")
+g1.place(temp, -column 0 -row 0)
+
+# control buttons
+b_start = new Button()
+b_start.set(-text "Start")
+g1.place(b_start, -column 0 -row 1)
+
+b_stop = new Button()
+b_stop.set(-text "Stop")
+g1.place(b_stop, -column 0 -row 2)
+
+b_clear = new Button()
+b_clear.set(-text "Clear")
+g1.place(b_clear, -column 0 -row 3)
+
+b_serial = new Button()
+b_serial.set(-text "Send over serial")
+g1.place(b_serial, -column 0 -row 4)
+
+b_dump = new Button()
+b_dump.set(-text "Dump stats")
+g1.place(b_dump, -column 0 -row 5)
+
+b_ping = new Button()
+b_ping.set(-text "Ping")
+g1.place(b_ping, -column 0 -row 6)
+
+win.open()
diff --git a/l4/pkg/ferret/examples/monitors/idle_switch_mon/Makefile b/l4/pkg/ferret/examples/monitors/idle_switch_mon/Makefile
new file mode 100644 (file)
index 0000000..37aa213
--- /dev/null
@@ -0,0 +1,17 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+DEFAULT_RELOC   = 0x006f0000
+TARGET          = fer_idle_mon
+
+MODE            = l4env_minimal
+
+LIBS           += -lferret_monitor -lferret_consumer -lferret_util          \
+                  -lferret_client -lferret_producer -lferret_comm           \
+                  -lferret_fpages -lferret_local_names
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/monitors/idle_switch_mon/broken b/l4/pkg/ferret/examples/monitors/idle_switch_mon/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/monitors/idle_switch_mon/main.c b/l4/pkg/ferret/examples/monitors/idle_switch_mon/main.c
new file mode 100644 (file)
index 0000000..9b47d18
--- /dev/null
@@ -0,0 +1,322 @@
+/**
+ * \file   ferret/examples/idle_switch_mon/main.c
+ * \brief  Consumes kernel tracebuffer context switch events and
+ *         computes statistics about idle times,
+ *         [x -> idle -> x] vs. [x -> idle -> y] context switches
+ *         sequences etc.
+ *
+ * \date   2007-06-04
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <getopt.h>
+
+#include <l4/log/l4log.h>
+#include <l4/thread/thread.h>
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/util/rdtsc.h>
+#include <l4/sys/syscalls.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/monitor.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/maj_min.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/sensors/tbuf_consumer.h>
+#include <l4/ferret/sensors/histogram.h>
+#include <l4/ferret/sensors/histogram_producer.h>
+#include <l4/ferret/sensors/histogram_consumer.h>
+
+// states for state machine
+#define STATE_IN_IDLE  0
+#define STATE_IN_OTHER 1
+
+char LOG_tag[9] = "FerIdMo";
+
+/* Some magic for converting context pointers to thread_ids
+ * We cannot use l4sys' stuff here, because it does not handle 4k TCBs
+ */
+#define MY_TCB_MAGIC 0xC0000000
+
+static unsigned task_shift   = 18;
+static unsigned thread_shift = 11;
+static unsigned thread_mask  = (1 << 7) - 1;
+
+static inline l4_threadid_t __get_l4_threadid(Context *context)
+{
+    l4_threadid_t id;
+    id.raw        = 0;
+    id.id.task    = (((unsigned) context) - MY_TCB_MAGIC) >> task_shift;
+    id.id.lthread = ((((unsigned) context) - MY_TCB_MAGIC) >> thread_shift) &
+                    thread_mask;
+    return id;
+}
+
+long long switch_count = 0, thread_switch_equal = 0, task_switch_equal = 0;
+unsigned long long initial_lost, current_lost;
+ferret_histo_t * idle_histo = NULL;
+int start_demo_thread = 0;
+int loop_count = 10000;
+char * histo_setup = NULL;
+
+static void working(void *arg)
+{
+    int i;
+
+    while (1)
+    {
+        for (i = 0; i < 1000000; i++)
+        {
+        }
+        l4_sleep(10);
+    }
+}
+
+
+static void
+update_statistics(int equal_thread, int equal_task, ferret_time_t idle,
+                  unsigned long long current_lost)
+{
+    static int call_count = 0;
+    static ferret_time_t idle_us;
+    static unsigned long long last_lost = 0;
+
+    call_count++;
+
+    if (equal_thread)
+    {
+        thread_switch_equal++;
+    }
+    if (equal_task)
+    {
+        task_switch_equal++;
+    }
+    switch_count++;
+
+    // fixme: update timing histogram etc.
+    idle_us = l4_tsc_to_us(idle);
+    ferret_histo_inc(idle_histo, idle_us);
+
+    if (call_count >= loop_count)
+    {
+        call_count = 0;
+        printf("Idle thread switches (all, thread, task): "
+               "%llu, %llu  (%llu%%), %llu  (%llu%%)\n",
+               switch_count,
+               thread_switch_equal,
+               (thread_switch_equal * 100) / switch_count,
+               task_switch_equal,
+               (task_switch_equal * 100) / switch_count);
+        printf("Lost %llu events in this period.\n", current_lost - last_lost);
+        last_lost = current_lost;
+        /*printf("Idle time (min, avg, max): (%llu, %llu, %llu)\n",
+               idle_histo->head.val_min,
+               idle_histo->head.val_sum / idle_histo->head.val_count,
+               idle_histo->head.val_max);*/
+        ferret_histo_dump_smart(idle_histo);
+    }
+}
+
+static void usage(void)
+{
+    printf(
+    "usage: fer_idle_mon [options]\n"
+    "\n"
+    "  -4,--4k .......... Adapt context pointer computation to to 4K kernel\n"
+    "                     stacks.\n"
+    "  -d,--demo ........ Start a dummy thread in the background to cause\n"
+    "                     some context switches.\n"
+    "  -s,--histo_size .. Override histogram setup for idle times.\n"
+    "  -l,--loop ........ Print stats every nth update (default 10000).\n"
+    "  -h,--help ........ Print this help screen and exit.\n"
+    "\n"
+    "Example: fer_idle_mon -4 -d -s \"0:1000000:10000\"\n"
+    "This will collection information about the running system regarding idle"
+    " thread context switch patterns and idle thread activity times and startup"
+    " a demo thread.  The histogram will be configured for times between 0 and"
+    " 1000000 usecs with 10000 bins, i.e., a resolution of 100 usecs.\n"
+    "\n"
+    "Note: For this to make sense you should activate context switch trace"
+    " buffer events in JDB (O0+).\n"
+    );
+}
+
+static void parse_cmdline(int argc, char* argv[])
+{
+    int optionid;
+    int option = 0;
+    const struct option long_options[] =
+        {
+            { "4k",         0, NULL, '4'},
+            { "help",       0, NULL, 'h'},
+            { "demo",       0, NULL, 'd'},
+            { "histo_size", 1, NULL, 's'},
+            { "loop",       1, NULL, 'l'},
+            { 0, 0, 0, 0}
+        };
+
+    do
+    {
+        option = getopt_long(argc, argv, "4hds:l:", long_options, &optionid);
+        switch (option)
+        {
+        case '4':  // adapt layout of context address to 4K kernel stacks
+            task_shift   = 19;
+            thread_shift = 12;
+            break;
+        case 'd':
+            start_demo_thread = 1;
+            break;
+        case 'l':
+            loop_count = atoi(optarg);
+            if (loop_count < 1 || loop_count > 1000000)
+            {
+                printf("error  - bad value for loop_count %c, should "
+                       "be 1..1000000\n", loop_count);
+                exit(1);
+            }
+            break;
+        case 's':
+            histo_setup = strdup(optarg);
+            break;
+        case 'h':
+            usage();
+            exit(1);
+            break;
+        case -1:  // exit case
+            break;
+        default:
+            printf("error  - unknown option %c\n", option);
+            usage();
+            exit(2);
+        }
+    } while (option != -1);
+}
+
+int main(int argc, char* argv[])
+{
+    int ret;
+    ferret_tbuf_moni_t * tbuf;
+    l4_tracebuffer_entry_t te;
+
+    // histogram from 0 sec to 1 sec with a bin count of 1000000 ->
+    // bin size is 1 usec
+    histo_setup = "0:1000000:1000000";
+    parse_cmdline(argc, argv);
+
+    // attach to tracebuffer
+    ret = ferret_att(FERRET_TBUF_MAJOR, FERRET_TBUF_MINOR,
+                     FERRET_TBUF_INSTANCE, tbuf);
+    if (ret)
+    {
+        LOG("Could not attach to tracebuffer, fatal!");
+        exit(1);
+    }
+    initial_lost = tbuf->lost;
+    LOG("Initial lost count for tracebuffer is %llu.", initial_lost);
+
+    // create a histogram for idle times
+    ret = ferret_create(30, 1, 0, FERRET_HISTO, 0, histo_setup,
+                        idle_histo, &malloc);
+    if (ret)
+    {
+        LOG("Could not create idle time histogram, fatal!");
+        exit(1);
+    }
+
+    // create other thread to cause some context switches
+    if (start_demo_thread)
+    {
+        l4thread_create_named(working, ".worker", 0,
+                              L4THREAD_CREATE_ASYNC);
+    }
+
+    /* 1.   get tbuf event
+     * 1.1  if none available -> sleep a little bit -> 1.
+     * 2.   if not context switch event -> 1.
+     * 3.   if state == IN_OTHER && e.dest == IDLE
+     * 3.1     save e.from
+     * 3.2     save e.ts
+     * 4.   if state == IN_IDLE &&  e.dest != IDLE
+     * 4.1     save e.dest
+     * 4.2     save e.ts
+     * 4.3     update_stats()
+     * 5.   -> 1.
+     */
+
+    int state = STATE_IN_OTHER;  // init. with unknown state
+    ferret_time_t ts_to_idle, ts_from_idle;
+    l4_threadid_t tid_to_idle, tid_from_idle, temp;
+
+    // periodically read from sensor
+    while (1)
+    {
+        ret = ferret_tbuf_get(tbuf, &te);              // 1.
+        current_lost = tbuf->lost;
+        if (ret == -1)
+        {
+            l4_sleep(1000);
+            continue;
+        }
+        else if (ret < -1)
+        {
+            LOG("Something wrong with trace buffer: %d", ret);
+            exit(1);
+        }
+
+        if (te.type != l4_ktrace_tbuf_context_switch)  // 2.
+        {
+            LOG("Got other event type: %hhu", te.type);
+            continue;
+        }
+
+        //temp = __get_l4_threadid(te.context);
+        //LOG("From: %u.%u", temp.id.task, temp.id.lthread);
+        switch (state)
+        {
+        case STATE_IN_OTHER:                           // 3.
+            temp = __get_l4_threadid(te.m.context_switch.dest);
+            if (temp.raw != 0)  // idle thread
+            {
+                //LOG("From: %u.%u", temp.id.task, temp.id.lthread);
+                continue;
+            }
+            //LOG("O+");
+            ts_to_idle  = te.tsc;
+            tid_to_idle = __get_l4_threadid(te.context);
+            state = STATE_IN_IDLE;
+            break;
+        case STATE_IN_IDLE:                            // 4.
+            temp = __get_l4_threadid(te.m.context_switch.dest);
+            if (temp.raw == 0)  // idle thread
+            {
+                continue;
+            }
+            //LOG("I+");
+            ts_from_idle  = te.tsc;
+            tid_from_idle = temp;
+            state = STATE_IN_OTHER;
+            update_statistics(tid_to_idle.raw == tid_from_idle.raw,
+                              tid_to_idle.id.task == tid_from_idle.id.task,
+                              ts_from_idle - ts_to_idle, current_lost);
+            break;
+        default:
+            LOG("Eww.");
+            exit(1);
+        }
+
+    }
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_control/Makefile b/l4/pkg/ferret/examples/monitors/l4lx_control/Makefile
new file mode 100644 (file)
index 0000000..074005f
--- /dev/null
@@ -0,0 +1,16 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+#DEFAULT_RELOC   = 0x00680000
+TARGET          = fer_l4lx_ctrl
+
+MODE            = l4linux
+
+LIBS            = -lferret_l4lx_client -lferret_util -lferret_comm
+LIBCLIBS        =
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_control/README b/l4/pkg/ferret/examples/monitors/l4lx_control/README
new file mode 100644 (file)
index 0000000..cb4fc68
--- /dev/null
@@ -0,0 +1,4 @@
+This is a small L4Linux command line tool which can insert special
+control events (start/stop recording, dump, clear buffers, ping etc.) 
+into the L4Linux userland sensor.  Monitors can listen to these control
+events and react accordingly.
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_control/broken b/l4/pkg/ferret/examples/monitors/l4lx_control/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_control/main.c b/l4/pkg/ferret/examples/monitors/l4lx_control/main.c
new file mode 100644 (file)
index 0000000..8097bc9
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * \file   ferret/examples/l4lx_control/main.c
+ * \brief  Remote control from L4Linux by inserting special control events
+ *
+ * \date   2006-06-14
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <l4/ferret/l4lx_client.h>
+#include <l4/ferret/maj_min.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/util.h>
+
+static void usage(void)
+{
+    printf("usage: fer_l4lx_ctrl [exactly one option]\n"
+           "  -b,--begin ......... Start recording now\n"
+           "  -e,--end ........... Stop recording now\n"
+           "  -c,--clear ......... Clear recording buffer now\n"
+           "  -d,--dump .......... Dump some statistics in the monitor\n"
+           "  -p,--ping .......... Tell the monitor to give a sign of life\n"
+           "  -n,--net <ip:port> . Transfer recording buffer now to <ip:port>\n"
+           "  -s,--serial <name> . Dump recording buffer now (uuencoded) over serial line\n"
+           "example: fer_l4lx_ctrl -b\n"
+           "example: fer_l4lx_ctrl -n 1.2.3.4:1234\n"
+           "example: fer_l4lx_ctrl -s testing.dat\n"
+        );
+}
+
+int main(int argc, char* argv[])
+{
+    int idx;
+    ferret_list_entry_common_t * elc;
+    ferret_list_l4lx_user_init();
+
+    // parse parameters
+    {
+        int optionid;
+        int option = 0;
+        const struct option long_options[] =
+            {
+                { "begin",     0, NULL, 'b'},
+                { "end",       0, NULL, 'e'},
+                { "clear",     0, NULL, 'c'},
+                { "net",       1, NULL, 'n'},
+                { "serial",    1, NULL, 's'},
+                { "dump",      0, NULL, 'd'},
+                { "ping",      0, NULL, 'p'},
+                { "help",      0, NULL, 'h'},
+                { 0, 0, 0, 0}
+            };
+
+       if (argc < 2)
+       {
+            usage();
+            exit(1);
+       }
+
+        do
+        {
+            option = getopt_long(argc, argv, "becn:s:hdp",
+                                 long_options, &optionid);
+            switch (option)
+            {
+            case 'h':
+                usage();
+                exit(0);
+            case 'b':
+                idx = ferret_list_dequeue(ferret_l4lx_user);
+                elc = (ferret_list_entry_common_t *)
+                    ferret_list_e4i(ferret_l4lx_user->glob, idx);
+                elc->major     = FERRET_MONCON_MAJOR;
+                elc->minor     = FERRET_MONCON_START;
+                ferret_list_commit(ferret_l4lx_user, idx);
+                break;
+            case 'e':
+                idx = ferret_list_dequeue(ferret_l4lx_user);
+                elc = (ferret_list_entry_common_t *)
+                    ferret_list_e4i(ferret_l4lx_user->glob, idx);
+                elc->major     = FERRET_MONCON_MAJOR;
+                elc->minor     = FERRET_MONCON_STOP;
+                ferret_list_commit(ferret_l4lx_user, idx);
+                break;
+            case 'c':
+                idx = ferret_list_dequeue(ferret_l4lx_user);
+                elc = (ferret_list_entry_common_t *)
+                    ferret_list_e4i(ferret_l4lx_user->glob, idx);
+                elc->major     = FERRET_MONCON_MAJOR;
+                elc->minor     = FERRET_MONCON_CLEAR;
+                ferret_list_commit(ferret_l4lx_user, idx);
+                break;
+            case 's':
+                idx = ferret_list_dequeue(ferret_l4lx_user);
+                elc = (ferret_list_entry_common_t *)
+                    ferret_list_e4i(ferret_l4lx_user->glob, idx);
+                elc->major     = FERRET_MONCON_MAJOR;
+                elc->minor     = FERRET_MONCON_SERSEND;
+                strncpy(elc->data8, optarg, 48);
+                printf("Sending name: %s\n", optarg);
+                elc->data8[47] = '\0';
+                ferret_list_commit(ferret_l4lx_user, idx);
+                break;
+            case 'n':
+            {
+                uint16_t port;
+                struct in_addr ip;
+                char * sep;
+                char * aip;
+
+                idx = ferret_list_dequeue(ferret_l4lx_user);
+                elc = (ferret_list_entry_common_t *)
+                    ferret_list_e4i(ferret_l4lx_user->glob, idx);
+                elc->major     = FERRET_MONCON_MAJOR;
+                elc->minor     = FERRET_MONCON_NETSEND;
+                sep = index(optarg, ':');
+                if (sep == NULL)
+                {
+                    printf("Error parsing <ip:port>: '%s'\n", optarg);
+                    exit(2);
+                }
+                port = atoi(sep + 1);
+                aip = strndupa(optarg, sep - optarg);
+                if (inet_aton(aip, &ip) == 0)
+                {
+                    printf("Error parsing <ip>: '%s'\n", aip);
+                    exit(3);
+                }
+                printf("Parsed address: '%s:%hu'\n", aip, port);
+                elc->data16[0] = port;
+                memcpy(&(elc->data16[1]), &ip, sizeof(ip));
+                ferret_list_commit(ferret_l4lx_user, idx);
+                break;
+            }
+            case 'd':
+                idx = ferret_list_dequeue(ferret_l4lx_user);
+                elc = (ferret_list_entry_common_t *)
+                    ferret_list_e4i(ferret_l4lx_user->glob, idx);
+                elc->major     = FERRET_MONCON_MAJOR;
+                elc->minor     = FERRET_MONCON_STATS;
+                ferret_list_commit(ferret_l4lx_user, idx);
+                break;
+            case 'p':
+                idx = ferret_list_dequeue(ferret_l4lx_user);
+                elc = (ferret_list_entry_common_t *)
+                    ferret_list_e4i(ferret_l4lx_user->glob, idx);
+                elc->major     = FERRET_MONCON_MAJOR;
+                elc->minor     = FERRET_MONCON_PING;
+                ferret_list_commit(ferret_l4lx_user, idx);
+                break;
+
+            case -1:  // exit case
+                break;
+            default:
+                printf("error  - unknown option %c\n", option);
+                usage();
+                exit(1);
+            }
+        } while (option != -1);
+    }
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_histo_mon/Makefile b/l4/pkg/ferret/examples/monitors/l4lx_histo_mon/Makefile
new file mode 100644 (file)
index 0000000..e4cfc66
--- /dev/null
@@ -0,0 +1,16 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c
+
+#DEFAULT_RELOC   = 0x00680000
+TARGET          = ferret_histo_mon
+
+MODE            = l4linux
+
+LIBS            = -lferret_consumer -lferret_comm -lferret_fpages
+LIBCLIBS        =
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_histo_mon/broken b/l4/pkg/ferret/examples/monitors/l4lx_histo_mon/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_histo_mon/main.c b/l4/pkg/ferret/examples/monitors/l4lx_histo_mon/main.c
new file mode 100644 (file)
index 0000000..971aec5
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#include <l4/ferret/sensors/histogram_consumer.h>
+
+#define FIFO_NAME "histo_ctrl.fifo"
+
+struct stat sbuf;
+
+int length;
+ferret_histo_t * histo[2];
+void * addr;
+
+FILE *f1, *f2;
+
+char temp[3];
+
+int main(void)
+{
+    unsigned u;
+    int fd, fifo, ret;
+
+    // setup
+    ret = mkfifo(FIFO_NAME, 00666);
+    perror("mkfifo: ");
+
+    fd = open("/proc/ferret/syscall_histo", O_RDONLY);
+    perror("open: ");
+    if (fd < 0)
+        exit(1);
+    ret = fstat(fd, &sbuf);
+    perror("fstat: ");
+    if (ret < 0)
+        exit(1);
+    length = sbuf.st_size;
+    fprintf(stderr, "size: %d\n", length);
+    addr = mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);
+    perror("mmap: ");
+    if (addr == MAP_FAILED)
+        exit(1);
+    fprintf(stderr, "fd: %d, addr %p, errno %d\n", fd, addr, errno);
+    histo[0] = malloc(length);
+    histo[1] = malloc(length);
+    if (histo[0] == NULL || histo[1] == NULL)
+    {
+        fprintf(stderr, "Malloc failed.\n");
+        exit(1);
+    }
+
+    // getting the data
+    do
+    {
+        fifo = open(FIFO_NAME, O_RDONLY);
+        if (fifo < 0)
+            exit(1);
+        while ((ret = read(fifo, temp, 1)) == -1)
+            ;
+        if (ret == 0)
+        {
+            close(fifo);
+            continue;
+        }
+    } while (ret != 1);
+    fprintf(stderr, "Copying for the first time ...\n");
+    memcpy(histo[0], addr, length);
+    fprintf(stderr, "Waiting for next signal ...\n");
+
+    do
+    {
+        while ((ret = read(fifo, temp, 1)) == -1)
+            ;
+        if (ret == 0)
+        {
+            close(fifo);
+            fifo = open(FIFO_NAME, O_RDONLY);
+            if (fifo < 0)
+                exit(1);
+            continue;
+        }
+    } while (ret != 1);
+    memcpy(histo[1], addr, length);
+    fprintf(stderr, "... done.  Postprocessing data.\n");
+
+#if 0
+    histo[0] = malloc(length);
+    histo[1] = malloc(length);
+
+    f1 = fopen("ferret_syscall_hist1", "r");
+    fread(histo[0], length, 1, f1);
+    f2 = fopen("ferret_syscall_hist2", "r");
+    fread(histo[1], length, 1, f2);
+
+#endif
+
+    for (u = 0; u < histo[0]->head.bins; u++)
+    {
+        if (histo[1]->data[u] - histo[0]->data[u] != 0)
+            printf("%u:\t%u\n", u, histo[1]->data[u] - histo[0]->data[u]);
+    }
+
+    //ferret_histo_dump(histo[0]);
+    //ferret_histo_dump(histo[1]);
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_verify_tamed_mon/Makefile b/l4/pkg/ferret/examples/monitors/l4lx_verify_tamed_mon/Makefile
new file mode 100644 (file)
index 0000000..50437d2
--- /dev/null
@@ -0,0 +1,19 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+SRC_C           = main.c uu.c
+
+DEFAULT_RELOC   = 0x006f0000
+TARGET          = fer_l4lx_vtm
+
+MODE            = l4env_minimal
+
+LIBS           += -lferret_monitor -lferret_consumer -lferret_util -ll4z    \
+                  -lferret_comm -lferret_fpages -lferret_local_names
+
+PRIVATE_INCDIR += $(PKGDIR_ABS)/examples/monitors/common
+vpath uu.c $(PKGDIR_ABS)/examples/monitors/common
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_verify_tamed_mon/broken b/l4/pkg/ferret/examples/monitors/l4lx_verify_tamed_mon/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/monitors/l4lx_verify_tamed_mon/main.c b/l4/pkg/ferret/examples/monitors/l4lx_verify_tamed_mon/main.c
new file mode 100644 (file)
index 0000000..ec23aa9
--- /dev/null
@@ -0,0 +1,375 @@
+/**
+ * \file   ferret/examples/l4lx_verify_tamed_mon/main.c
+ * \brief  Monitor showing atomicity bug in L4Linux' tamer thread
+ *
+ * \date   2006-08-08
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+
+#include <l4/log/l4log.h>
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/sys/syscalls.h>
+#include <l4/sys/kdebug.h>
+#include <l4/sys/ktrace_events.h>
+
+#include <l4/ferret/monitor.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/sensors/list_consumer.h>
+#include <l4/ferret/sensors/tbuf_consumer.h>
+#include <l4/ferret/maj_min.h>
+
+#include "uu.h"
+
+char LOG_tag[9] = "FerLVTM";
+
+#define HISTORY_SIZE 10000
+#define LINE_SIZE    100
+
+typedef struct __attribute__ ((__packed__)) history_entry_s
+{
+    int                        size;
+    ferret_list_entry_common_t event;
+} history_entry_t;
+
+history_entry_t history[HISTORY_SIZE];
+int history_count    = 0;
+int history_position = 0;
+int quiet = 0;
+
+static void append_history(ferret_list_entry_common_t * e)
+{
+    history[history_position].size  = sizeof(ferret_list_entry_common_t);
+    history[history_position].event = *e;
+    history_position++;
+    if (history_position >= HISTORY_SIZE)
+        history_position = 0;
+    history_count++;
+}
+
+static void __attribute__((unused)) append_count(int c)
+{
+    static int counts[LINE_SIZE];
+    static int count = 0;
+
+    counts[count++] = c;
+    if (count >= LINE_SIZE)
+    {
+        for (count = 0; count < LINE_SIZE; count++)
+            printf("%d, ", counts[count]);
+        printf("\n");
+        count = 0;
+    }
+}
+
+static void eval_event(ferret_list_entry_common_t * e)
+{
+    //static unsigned short last = -1;
+    //static int count_atomic  = 0;
+    //static int count_context = 0;
+
+    ferret_list_entry_kernel_t * k = (ferret_list_entry_kernel_t *)e;
+
+    static ferret_utime_t t_start_atomic = 0;
+    static ferret_utime_t t_stop_atomic  = 0;
+    static ferret_utime_t t_last_context = 0;
+    static int l4lx_task_id         = -1;
+    static int l4lx_tamer_thread_id = -1;
+    static int dump_count = -1;
+
+    switch (e->major)
+    {
+    case FERRET_L4LX_MAJOR:
+        /* debug stuff ...
+        if (last != FERRET_L4LX_MAJOR)
+        {
+            append_count(count_context);
+            count_context = 0;
+        }
+        count_atomic++;
+        last = FERRET_L4LX_MAJOR;
+        ... debug stuff */
+        switch (e->minor)
+        {
+        case FERRET_L4LX_ATOMIC_BEGIN:
+            t_start_atomic = e->timestamp;
+            t_stop_atomic  = 0;
+            if (l4lx_task_id == -1)  // L4Linux kernel's task id
+            {
+                l4lx_task_id = ((l4_threadid_t)(e->data32[0])).id.task;
+                l4lx_tamer_thread_id =
+                    ((l4_threadid_t)(e->data32[0])).id.lthread;
+                printf("Tamer TID: %x.%x\n",
+                       l4lx_task_id, l4lx_tamer_thread_id);
+            }
+            break;
+        case FERRET_L4LX_ATOMIC_END1:
+        case FERRET_L4LX_ATOMIC_END2:
+            t_stop_atomic = e->timestamp;
+            //printf("%llu:%llu, %llu\n",
+            //       t_start_atomic, t_stop_atomic, t_last_context);
+            break;
+        default:
+            //printf("Got other event %hd:%hd:%hd, ignored.\n",
+            //       e->major, e->minor, e->instance);
+            break;
+        }
+        break;
+    case FERRET_TBUF_MAJOR:
+        /* debug stuff ...
+        if (last != FERRET_TBUF_MAJOR)
+        {
+            append_count(count_atomic);
+            //printf("Atomic: %d\n", count_atomic);
+            count_atomic = 0;
+        }
+        count_context++;
+        last = FERRET_TBUF_MAJOR;
+        ... debug stuff */
+        switch (e->minor)
+        {
+        case l4_ktrace_tbuf_context_switch:
+            t_last_context = e->timestamp;
+            if (t_last_context > t_start_atomic &&
+                t_stop_atomic == 0 && t_start_atomic != 0)
+            {
+                if (l4lx_task_id ==
+                    l4_ktrace_get_l4_taskid((void * )k->data32[1]) &&
+                    l4lx_tamer_thread_id !=
+                    l4_ktrace_get_l4_lthreadid((void * )k->data32[1]))
+
+                {
+                    if (quiet < 2 )
+                    {
+                        printf(
+                            l4util_idfmt" -> "l4util_idfmt": " ,
+                            l4util_idstr(l4_ktrace_get_l4_threadid(k->context)),
+                            l4util_idstr(l4_ktrace_get_l4_threadid(
+                                             (void * )k->data32[1]))
+                            );
+                        printf("Atomicity violation: %llu < %llu\n",
+                               t_start_atomic, t_last_context);
+                    }
+                    dump_count = 100;  // start count down for dump
+                }
+            }
+            break;
+        default:
+            //printf("Got other event %hd:%hd:%hd, ignored.\n",
+            //       e->major, e->minor, e->instance);
+            break;
+        }
+        break;
+    default:
+        //printf("Got other event %hd:%hd:%hd, ignored.\n",
+        //       e->major, e->minor, e->instance);
+        break;
+    }
+    append_history(e);
+
+    if (dump_count > 0)
+    {
+        dump_count--;
+    }
+    if (dump_count == 0)
+    {
+        if (quiet < 1)
+        {
+            uu_dumpz_ringbuffer("atomicity.dump", &history,
+                                HISTORY_SIZE * sizeof(history_entry_t),
+                                history_position * sizeof(history_entry_t),
+                                HISTORY_SIZE * sizeof(history_entry_t));
+        }
+        dump_count = -1;
+    }
+}
+
+static void usage(void)
+{
+    LOG_printf(
+        "usage: fer_l4lx_vtm [-q|-Q]"
+        " [-d val]\n"
+        "\n"
+        "  -q,--quiet ... Be quiet and do not disturb the system with\n"
+        "                 long output (also no trace output).  Useful\n"
+        "                 for longer running overhead measurements.\n"
+        "  -Q,--Quiet ... Be really QUIET and do not disturb the system with\n"
+        "                 any output at runtime (also no trace output).  \n"
+        "                 Useful for longer running overhead measurements.\n"
+        );
+}
+
+static int parse_args(int argc, char* argv[])
+{
+    int optionid;
+    int option = 0;
+    const struct option long_options[] =
+        {
+            { "quiet", 0, NULL, 'q'},
+            { "Quiet", 0, NULL, 'Q'},
+            { 0, 0, 0, 0}
+        };
+
+    do
+    {
+        option = getopt_long(argc, argv, "qQ",
+                             long_options, &optionid);
+        switch (option)
+        {
+        case 'q':
+            quiet = 1;
+            break;
+        case 'Q':
+            quiet = 2;
+            break;
+        case -1:  // exit case
+            break;
+        default:
+            printf("error  - unknown option %c\n", option);
+            usage();
+            return 2;
+        }
+    } while (option != -1);
+
+    return 0;
+}
+
+int main(int argc, char* argv[])
+{
+    /* 1. startup
+     * 2. poll to open all relevant sensors (0:0:0, 1:0:0)
+     * 3. in loop get new events and reorder according to time
+     * 4. if between atomic begin and atomic end other scheduling
+     *    event in same task -> flag error
+     */
+
+    int ret;
+    ferret_list_moni_t * list = NULL;
+    ferret_tbuf_moni_t * tbuf = NULL;
+    l4_tracebuffer_entry_t     tbuf_e;   // native tracebuffer entry
+    ferret_list_entry_common_t list_e;   // list entry for other sensors
+    ferret_list_entry_kernel_t list_te;  // list entry for converted tbuf entry
+
+    printf("History buffer and position addresses: %p, %p\n",
+           &history, &history_position);
+
+    if (parse_args(argc, argv))
+        return 1;
+
+    // open relevant sensors
+    while ((ret = ferret_att(FERRET_TBUF_MAJOR, FERRET_TBUF_MINOR,
+                             FERRET_TBUF_INSTANCE, tbuf)))
+    {
+        printf("Could not attach to %hd:%hd:%hd, retrying soon ...\n",
+            FERRET_TBUF_MAJOR, FERRET_TBUF_MINOR, FERRET_TBUF_INSTANCE);
+        l4_sleep(1000);
+    }
+    printf("Attached to %hd:%hd:%hd.\n",
+        FERRET_TBUF_MAJOR, FERRET_TBUF_MINOR, FERRET_TBUF_INSTANCE);
+
+    while ((ret = ferret_att(FERRET_L4LX_MAJOR, FERRET_L4LX_LIST_MINOR,
+                             1, list)))
+    {
+        printf("Could not attach to %hd:%hd:%hd, retrying soon ...\n",
+            FERRET_L4LX_MAJOR, FERRET_L4LX_LIST_MINOR, 1);
+        l4_sleep(1000);
+    }
+    printf("Attached to %hd:%hd:%hd.\n",
+        FERRET_L4LX_MAJOR, FERRET_L4LX_LIST_MINOR, 1);
+
+    // at first, fill the reorder buffers with one element from each sensor
+    while (1)
+    {
+        ret = ferret_tbuf_get(tbuf, &tbuf_e);
+        if (ret == -1)
+        {
+            //LOG("Waiting for element in tbuf ...");
+            l4_sleep(1000);
+            continue;
+        }
+        else if (ret < -1)
+        {
+            printf("Something wrong with tbuf: %d\n", ret);
+            exit(1);
+        }
+        ferret_util_convert_k2c(&tbuf_e, &list_te);
+        break;
+    }
+
+
+    while (1)
+    {
+        ret = ferret_list_get(list, (ferret_list_entry_t *)&list_e);
+        if (ret == -1)
+        {
+            //LOG("Waiting for element in list ...");
+            l4_sleep(1000);
+            continue;
+        }
+        else if (ret < -1)
+        {
+            printf("Something wrong with list: %d\n", ret);
+            exit(1);
+        }
+        break;
+    }
+
+    // periodically read from sensors
+    while (1)
+    {
+        if (list_e.timestamp < list_te.timestamp)
+        {  // list_e is older, we work with it and get a new one
+            eval_event(&list_e);
+            while (1)
+            {
+                ret = ferret_list_get(list, (ferret_list_entry_t *)&list_e);
+                if (ret == -1)
+                {
+                    //LOG("Waiting for element in list ...");
+                    l4_sleep(10);
+                    continue;
+                }
+                else if (ret < -1)
+                {
+                    printf("Something wrong with list: %d\n", ret);
+                    exit(1);
+                }
+                break;
+            }
+        }
+        else
+        {  // list_et is older, we work with it and get a new one
+            eval_event((ferret_list_entry_common_t *)&list_te);
+            while (1)
+            {
+                ret = ferret_tbuf_get(tbuf, &tbuf_e);
+                if (ret == -1)
+                {
+                    //LOG("Waiting for element in tbuf ...");
+                    l4_sleep(10);
+                    continue;
+                }
+                else if (ret < -1)
+                {
+                    printf("Something wrong with tbuf: %d\n", ret);
+                    exit(1);
+                }
+                ferret_util_convert_k2c(&tbuf_e, &list_te);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/Makefile b/l4/pkg/ferret/examples/monitors/merge_mon/Makefile
new file mode 100644 (file)
index 0000000..8d4efc6
--- /dev/null
@@ -0,0 +1,20 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+
+PRIVATE_INCDIR += $(PKGDIR_ABS)/examples/merge_mon .
+
+SRC_C           = main.c buffer.c uu.c gui.c\
+#gui.c buffer.c uu.c net.c poll.c
+DPE_gui.c       = main_window.dpe
+#TARGET          = fer_merge_mon
+
+REQUIRES_LIBS= ferret-consumer ferret-common dope zlib libstdc++ l4re_c-util
+
+
+include $(L4DIR)/mk/prog.mk
+
+PRIVATE_INCDIR += $(PKGDIR_ABS)/examples/monitors/common
+vpath uu.c $(PKGDIR_ABS)/examples/monitors/common
+
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/TODO b/l4/pkg/ferret/examples/monitors/merge_mon/TODO
new file mode 100644 (file)
index 0000000..8a315c4
--- /dev/null
@@ -0,0 +1,2 @@
+ - open sensors also later if they become available
+ - allow time triggered mode for start, stop, and dump
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/buffer.c b/l4/pkg/ferret/examples/monitors/merge_mon/buffer.c
new file mode 100644 (file)
index 0000000..7bdc2e9
--- /dev/null
@@ -0,0 +1,436 @@
+/**
+ * \file   ferret/examples/merge_mon/buffer.c
+ * \brief  Buffer management stuff.
+ *
+ * \date   13/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <alloca.h> // alloca
+#include <stdlib.h> 
+#include <stdint.h> 
+#include <stdio.h>  // printf
+#include <string.h> // strncpy
+
+//#include <l4/lock/lock.h>
+//#include <l4/ore/uip-ore.h>
+#include <l4/util/util.h>
+#include <l4/util/rdtsc.h>
+//#include <l4/semaphore/semaphore.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/maj_min.h>
+#include <l4/ferret/monitor.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/sensors/list_consumer.h>
+//#include <l4/ferret/sensors/tbuf_consumer.h>
+
+#include "buffer.h"
+#include "gui.h"
+#include "main.h"
+//#include "net.h"
+#include "uu.h"
+
+extern int dump_after;
+
+/*
+ * This function must be called with the buffer lock already held.
+ */
+void buf_set_start_ts(buf_t * buf)
+{
+    buf->start_ts = l4_rdtsc();  // open a new recording window
+    buf->stop_ts  = 0;
+}
+
+/*
+ * This function must be called with the buffer lock already held.
+ */
+void buf_set_stop_ts(buf_t * buf)
+{
+    buf->stop_ts = l4_rdtsc();   // close recording window
+}
+
+/*
+ * This function must be called with the buffer lock already held.
+ */
+void buf_set_offline(buf_t * buf)
+{
+    buf->start_ts = 2;
+    buf->stop_ts = 1;
+}
+
+/*
+ * This function must be called with the buffer lock already held.
+ */
+void buf_set_online(buf_t * buf)
+{
+    buf->start_ts = 0;
+    buf->stop_ts = 0;
+}
+
+/*
+ * This function must be called with the buffer lock already held.
+ */
+void buf_set_cyclic(buf_t * buf)
+{
+    buf->cyclic = 1;
+}
+
+/*
+ * This function must be called with the buffer lock already held.
+ */
+void buf_clear(buf_t * buf)
+{
+    int i;
+
+    buf->write_pos = buf->start;
+    buf->dump_pos  = buf->start;
+    buf->full      = 0;
+    for (i = 0; i < sensor_count; i++)
+    {
+        sensors[i].copied = 0;
+    }
+}
+
+
+static void buf_dumpz(buf_t *buf, char const *filename)
+{
+    char name[48];
+    strncpy(name, filename, 48);
+    name[47] = 0;
+    uu_dumpz(name, buf->start, buf->write_pos - buf->start);
+}
+
+/*
+ * This function must be called with the buffer lock already held.
+ */
+static int buf_is_valid_ts(const buf_t * buf, ferret_utime_t ts)
+{
+    if ((buf->start_ts <= ts) && (buf->stop_ts > ts || buf->stop_ts == 0))
+        return 1;  // no restriction
+    else
+        return 0;  // out of interval
+}
+
+/*
+ * Check whether an event is a control event.
+ *
+ * This function must be called with the buffer lock already held.
+ */
+static void buf_check_control_events(buf_t * buf,
+                                     ferret_list_entry_t * list_e_pu,
+                                     unsigned int size)
+{
+    ferret_list_entry_common_t * e = (ferret_list_entry_common_t *)list_e_pu;
+
+    if (size < sizeof(ferret_list_entry_common_t))
+        return;
+
+    if (e->major == FERRET_MONCON_MAJOR)
+    {
+        switch (e->minor)
+        {
+        case FERRET_MONCON_START:
+            buf_set_start_ts(buf);
+            break;
+        case FERRET_MONCON_STOP:
+            buf_set_stop_ts(buf);
+            break;
+#if 0
+        case FERRET_MONCON_NETSEND:
+            if (local_ip[0] != '\0')
+            {
+                int ret;
+                struct in_addr ip;
+                unsigned short port;
+
+                ret = l4semaphore_try_down(&net_sem);
+                if (ret == 0)
+                {
+                    printf("Network transfer already in progress!\n");
+                    return;
+                }
+
+                port = e->data16[0];
+                memcpy(&ip, &(e->data16[1]), sizeof(ip));
+                printf("Destination address: '%s:%d'\n", inet_ntoa(ip) , port);
+                ret = uip_ore_connect(ip, port);
+                if (ret)
+                {
+                    printf("Error connecting: %d!\n", ret);
+                    l4semaphore_up(&net_sem);
+                    return;
+                }
+            }
+            else
+            {
+                printf("No local IP address given, not doing anything!\n");
+            }
+            break;
+#endif
+        case FERRET_MONCON_SERSEND:
+            buf_dumpz(buf, (char const*)e->data8);
+            break;
+        case FERRET_MONCON_CLEAR:
+            buf_clear(buf);
+            break;
+        case FERRET_MONCON_STATS:
+        {
+            int i;
+            printf("Stats:\n");
+            printf("  Buffer (start, size, write_pos): %p, %zd, %p\n",
+                   buf->start, buf->size, buf->write_pos);
+            printf("  Times (start, stop): %llu, %llu\n",
+                   buf->start_ts, buf->stop_ts);
+            printf("Sensors:\n");
+            for (i = 0; i < sensor_count; ++i)
+            {
+                if (sensors[i].open == 0)
+                    continue;
+                printf("  %s <%hu, %hu, %hu>\n", sensors[i].name,
+                           sensors[i].major, sensors[i].minor,
+                           sensors[i].instance);
+            }
+            break;
+        }
+        case FERRET_MONCON_PING:
+            printf("Yes, I'm here up and running!\n");
+            break;
+        }
+    }
+}
+
+/* retval: -1 -> continue
+ * retval: -2 -> break out
+ *
+ * This function must be called with the buffer lock already held.
+ */
+static int
+buf_copy_event(buf_t * buf, ferret_list_entry_t * ev, int size, int sensor)
+{
+    // continue if we already know the buffer is full
+    if (buf->full)
+        return -1;
+
+    if (! buf_is_valid_ts(buf, ev->timestamp))
+    {  // skip this event as it is out of our time range
+        return -1;
+    }
+
+    // check if buffer memory is full
+    if (buf->write_pos + size + sizeof(int) >=
+        buf->start + buf->size)
+    {
+        if (buf->cyclic)
+        {
+            buf_clear(buf);
+        }
+        else
+        {
+            buf->full = 1;
+            return -2;
+        }
+    }
+
+    // we have some space left, so save event data
+    *((int *)(buf->write_pos)) = size;
+    buf->write_pos += sizeof(int);
+    memcpy(buf->write_pos, ev, size);
+    buf->write_pos += size;
+    sensors[sensor].copied++;
+    sensors[sensor].last_ts = ev->timestamp;
+
+    return 0;
+}
+
+
+int buf_fill(buf_t * buf, int max_size, int interval, int verbose __attribute__((unused)))
+{
+    int i, ret;
+    ferret_list_entry_kernel_t * list_e_pk;
+    list_e_pk = alloca(max_size);
+    // make an alias to same memory region
+    ferret_list_entry_t * list_e_pu = (ferret_list_entry_t *)list_e_pk;
+    ferret_list_entry_common_t loss_event;
+    int count = 0;
+
+    // copy elements
+    while (1)
+    {
+        uint16_t type;
+        int size = 0;
+
+        pthread_mutex_lock(&buf->lock);
+
+        if ((dump_after != 0) &&
+            (count == dump_after)) {
+            buf_dumpz(buf, "dump.log");
+            count = 0;
+        }
+        count++;
+
+        for (i = 0; i < sensor_count; ++i)
+        {
+            /* 1. test sensor type
+             * 2. execute getter function according to type and store
+             *    events, prefix-size coded into memory buffer
+             * 3. stop if buffer full
+             */
+            if (sensors[i].open == 0)
+                continue;
+
+            type = ((ferret_common_t *)(sensors[i].sensor))->type;
+
+            while (1)
+            {
+                if (type == FERRET_LIST)
+                {
+                    ret = ferret_list_get(
+                        (ferret_list_moni_t *)(sensors[i].sensor), list_e_pu);
+                    if (ret == -1)
+                    {
+                        break;
+                    }
+                    else if (ret < -1)
+                    {
+                        printf(
+                            "Something wrong with sensor %s (%hu:%hu:%hu):"
+                            " %d\n", sensors[i].name,
+                            sensors[i].major, sensors[i].minor,
+                            sensors[i].instance, ret);
+                    }
+                    size = ((ferret_list_moni_t *)
+                            (sensors[i].sensor))->glob->element_size;
+                    buf_check_control_events(buf, list_e_pu, size);
+
+                    // check lost count here
+                    if (((ferret_list_moni_t *)(sensors[i].sensor))->lost >
+                        sensors[i].last_lost)
+                    {
+                        uint64_t count =
+                            ((ferret_list_moni_t *)(sensors[i].sensor))->lost -
+                            sensors[i].last_lost;
+                        // setup loss event
+                        loss_event.timestamp = sensors[i].last_ts + 1;
+                        loss_event.major     = FERRET_EVLOSS_MAJOR;
+                        loss_event.minor     = FERRET_EVLOSS_MINOR;
+                        loss_event.instance  = 0;
+                        loss_event.cpu       = 0;
+                        loss_event.data16[0] = sensors[i].major;
+                        loss_event.data16[1] = sensors[i].minor;
+                        loss_event.data16[2] = sensors[i].instance;
+                        loss_event.data64[1] = count;
+                        loss_event.data64[2] = list_e_pu->timestamp;
+
+                        ret = buf_copy_event(
+                            buf, (ferret_list_entry_t *)&loss_event,
+                            sizeof(loss_event), i);
+
+                        // update our copy of the lost_count
+                        sensors[i].last_lost =
+                            ((ferret_list_moni_t *)(sensors[i].sensor))->lost;
+
+                        if (ret == -1)
+                            continue;
+                        if (ret == -2)
+                        {
+                            i = sensor_count;  // leave outer loop
+                            break;             // leave inner loop
+                        }
+                    }
+                }
+#if 0
+                else if (type == FERRET_TBUF)
+                {
+                    l4_tracebuffer_entry_t tbuf_e;
+                    //printf("TBUF:\n");
+                    //puts("T");
+
+                    ret = ferret_tbuf_get(
+                        (ferret_tbuf_moni_t *)sensors[i].sensor, &tbuf_e);
+                    if (ret == -1)
+                    {
+                        break;
+                    }
+                    else if (ret < -1)
+                    {
+                        printf("Something wrong with trace buffer: %d\n", ret);
+                    }
+                    ferret_util_convert_k2c(&tbuf_e, list_e_pk);
+                    size = sizeof(l4_tracebuffer_entry_t);
+
+                    // check lost count here
+                    if (((ferret_list_moni_t *)(sensors[i].sensor))->lost >
+                        sensors[i].last_lost)
+                    {
+                        uint64_t count =
+                            ((ferret_list_moni_t *)(sensors[i].sensor))->lost -
+                            sensors[i].last_lost;
+                        // setup loss event
+                        loss_event.timestamp = sensors[i].last_ts + 1;
+                        loss_event.major     = FERRET_EVLOSS_MAJOR;
+                        loss_event.minor     = FERRET_EVLOSS_MINOR;
+                        loss_event.instance  = 0;
+                        loss_event.cpu       = 0;
+                        loss_event.data16[0] = sensors[i].major;
+                        loss_event.data16[1] = sensors[i].minor;
+                        loss_event.data16[2] = sensors[i].instance;
+                        loss_event.data64[1] = count;
+                        loss_event.data64[2] = list_e_pk->timestamp;
+
+                        ret = buf_copy_event(
+                            buf, (ferret_list_entry_t *)&loss_event,
+                            sizeof(loss_event), i);
+
+                        // update our copy of the lost_count
+                        sensors[i].last_lost =
+                            ((ferret_list_moni_t *)(sensors[i].sensor))->lost;
+
+                        if (ret == -1)
+                            continue;
+                        if (ret == -2)
+                        {
+                            i = sensor_count;  // leave outer loop
+                            break;             // leave inner loop
+                        }
+                    }
+                }
+#endif
+                else
+                {
+                    printf("Found wrong sensor type (%d): %hu!\n", i, type);
+                    return 1;
+                }
+
+                ret = buf_copy_event(buf, (ferret_list_entry_t *)list_e_pk,
+                                     size, i);
+
+                if (ret == -2)
+                {
+                    i = sensor_count;  // leave outer loop
+                    break;             // leave inner loop
+                }
+            }
+        }
+//        if (verbose)
+//            puts("S");
+        gui_update(buf);
+        pthread_mutex_unlock(&buf->lock);
+
+        if (global_exit)
+        {
+            return 0;
+        }
+        l4_sleep(interval);
+    };
+
+    printf("Should not happen!\n");
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/buffer.h b/l4/pkg/ferret/examples/monitors/merge_mon/buffer.h
new file mode 100644 (file)
index 0000000..ce8c495
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * \file   ferret/examples/merge_mon/buffer.h
+ * \brief  Buffer data structures
+ *
+ * \date   13/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_EXAMPLES_MERGE_MON_BUFFER_H_
+#define __FERRET_EXAMPLES_MERGE_MON_BUFFER_H_
+
+#include <sys/types.h>
+
+#include <l4/ferret/types.h>
+#include <pthread-l4.h>
+
+typedef struct
+{
+    unsigned char * start;      // buffer's starting address
+    ssize_t         size;       // full size of the buffer
+    unsigned char * write_pos;  // current buffer position for writing
+    unsigned char * dump_pos;   // current buffer position for dumping
+    pthread_mutex_t lock;       // lock protecting buffer access
+    ferret_utime_t  start_ts;   // for filtering events, start timestamp
+    ferret_utime_t  stop_ts;    // for filtering events, stop timestamp
+    int             full;       // flag whether buffer is full
+    int             cyclic;     // auto-clear buffer if it is full
+} buf_t;
+
+int buf_fill(buf_t * buf, int max_size, int interval, int verbose);
+void buf_set_start_ts(buf_t * buf);
+void buf_set_stop_ts(buf_t * buf);
+void buf_clear(buf_t * buf);
+void buf_set_offline(buf_t * buf);
+void buf_set_online(buf_t * buf);
+void buf_set_cyclic(buf_t * buf);
+
+
+#endif
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/gui.c b/l4/pkg/ferret/examples/monitors/merge_mon/gui.c
new file mode 100644 (file)
index 0000000..b00c81d
--- /dev/null
@@ -0,0 +1,228 @@
+/**
+ * \file   ferret/examples/merge_mon/gui.c
+ * \brief  Some GUI related functions
+ *
+ * \date   13/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <l4/dope/dopelib.h>
+#include <l4/util/util.h>
+
+#include <l4/ferret/sensors/list_consumer.h>
+
+#include "buffer.h"
+#include "gui.h"
+#include "main.h"
+//#include "net.h"
+#include "uu.h"
+
+#define MERGE_MON_B_START 0
+#define MERGE_MON_B_STOP  1
+#define MERGE_MON_B_CLEAR 2
+#define MERGE_MON_B_EXIT  3
+#define MERGE_MON_B_IP    4
+#define MERGE_MON_B_LOG   5
+int global_exit = 0;
+
+pthread_t gui_thread_id;
+extern int verbose;
+
+static void *gui_thread(void * arg)
+{
+       (void)arg;
+    dope_eventloop();
+       return NULL;
+}
+
+static void press_callback(dope_event  *e, void *arg)
+{
+    int id = (int)arg;
+       (void)e;
+
+    printf("press_callback: %d\n", id);
+
+    switch (id)
+    {
+    case MERGE_MON_B_START:
+        pthread_mutex_lock(&buf.lock);
+        buf_set_start_ts(&buf);
+        pthread_mutex_unlock(&buf.lock);
+        break;
+    case MERGE_MON_B_STOP:
+        pthread_mutex_lock(&buf.lock);
+        buf_set_stop_ts(&buf);
+        pthread_mutex_unlock(&buf.lock);
+        break;
+    case MERGE_MON_B_CLEAR:
+        pthread_mutex_lock(&buf.lock);
+        buf_clear(&buf);
+        pthread_mutex_unlock(&buf.lock);
+        break;
+    case MERGE_MON_B_EXIT:
+        global_exit = 1;
+        exit(0);
+#if 0
+    case MERGE_MON_B_IP:
+        pthread_mutex_lock(&buf.lock);
+        if (local_ip[0] != '\0')
+        {
+            char c_ip[16];
+            char c_port[6];
+            int ret;
+            struct in_addr ip;
+            unsigned short port;
+
+            ret = l4semaphore_try_down(&net_sem);
+            if (ret == 0)
+            {
+                printf("Network transfer already in progress!\n");
+                pthread_mutex_unlock(&buf.lock);
+                return;
+            }
+
+            dope_req(c_ip, sizeof(c_ip), "e_ip.text");
+            dope_req(c_port, sizeof(c_port), "e_port.text");
+
+            printf("Got: '%s':'%s'\n", c_ip, c_port);
+            ret = inet_aton(c_ip, &ip);
+            if (ret == 0)
+            {
+                printf("Error parsing IP address: '%s'!\n", c_ip);
+                l4semaphore_up(&net_sem);
+                pthread_mutex_unlock(&buf.lock);
+                return;
+            }
+            port = atoi(c_port);
+            ret = uip_ore_connect(ip, port);
+            if (ret)
+            {
+                printf("Error connecting: %d!\n", ret);
+                l4semaphore_up(&net_sem);
+                pthread_mutex_unlock(&buf.lock);
+                return;
+            }
+        }
+        else
+        {
+            printf("No local IP address given, not doing anything!\n");
+        }
+        pthread_mutex_unlock(&buf.lock);
+        break;
+#endif
+    case MERGE_MON_B_LOG:
+    {
+        static char filename[100];
+        pthread_mutex_lock(&buf.lock);
+        dope_req(filename, sizeof(filename), "e_log.text");
+        printf("Dumping from %p: %hhx %hhx %hhx %hhx...\n", buf.start,
+               buf.start[0], buf.start[1], buf.start[2], buf.start[3]);
+        uu_dumpz(filename, buf.start, buf.write_pos - buf.start);
+        pthread_mutex_unlock(&buf.lock);
+        break;
+    }
+    }
+}
+
+int gui_init()
+{
+    int ret, cnt = 0;
+
+    while ((ret = dope_init()) && cnt++ < 5)
+    {
+               if (verbose)
+                       printf("Waiting for DOpE ...\n");
+        l4_sleep(200);
+    }
+
+    if (ret)
+        return -1;
+
+#if 0
+    app_id = dope_init_app("Ferret Merge Monitor");
+    // fixme: check ret
+#endif
+
+    #include "main_window.dpi"
+
+    dope_bind("b_start", "press", press_callback,
+              (void *)MERGE_MON_B_START);
+    dope_bind("b_stop", "press", press_callback,
+              (void *)MERGE_MON_B_STOP);
+    dope_bind("b_clear", "press", press_callback,
+              (void *)MERGE_MON_B_CLEAR);
+    dope_bind("b_exit", "press", press_callback,
+              (void *)MERGE_MON_B_EXIT);
+
+    dope_bind("b_tran_ip", "press", press_callback,
+              (void *)MERGE_MON_B_IP);
+    dope_bind("b_tran_log", "press", press_callback,
+              (void *)MERGE_MON_B_LOG);
+
+#if 0
+    l4thread_create_named(gui_thread, ".dope", 0,
+                          L4THREAD_CREATE_ASYNC);
+#else
+       ret = pthread_create(&gui_thread_id, NULL, gui_thread, NULL);
+       if (ret < 0) {
+               printf("Error creating DOpE GUI thread: %d\n", ret);
+               return -1;
+       }
+#endif
+
+    return 0;
+}
+
+void gui_update(const buf_t * buf)
+{
+    int i;
+    int min         = 0;
+    int max         = buf->size;
+    int fill        = buf->write_pos - buf->start;
+    int transferred = buf->dump_pos - buf->start;
+
+    if (! use_gui)
+        return;
+
+    dope_cmdf("l_fill.set(-from %d -to %d)", min, max);
+    dope_cmdf("l_fill.barconfig(transfer, -value %d)", transferred);
+    dope_cmdf("l_fill.barconfig(fill, -value %d)", fill - transferred);
+
+    for (i = 0; i < sensor_count; i++)
+    {
+        if (sensors[i].open)
+        {
+            dope_cmd("temp = new Label()");
+            if (sensors[i].name)
+            {
+                dope_cmdf(
+                    "temp.set(-text \"%s [%hu:%hu:%hu] %llu %llu %u\")",
+                    sensors[i].name, sensors[i].major, sensors[i].minor,
+                    sensors[i].instance,
+                    ((ferret_list_moni_t *)(sensors[i].sensor))->lost,
+                    ((ferret_list_moni_t *)(sensors[i].sensor))->next_read,
+                    sensors[i].copied);
+            }
+            else
+            {
+                dope_cmdf(
+                    "temp.set(-text \"[%hu:%hu:%hu] %llu %llu %u\")",
+                    sensors[i].major, sensors[i].minor,
+                    sensors[i].instance,
+                    ((ferret_list_moni_t *)(sensors[i].sensor))->lost,
+                    ((ferret_list_moni_t *)(sensors[i].sensor))->next_read,
+                    sensors[i].copied);
+            }
+            dope_cmdf("g_sen.place(temp, -column 0 -row %d)", i);
+        }
+    }
+}
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/gui.h b/l4/pkg/ferret/examples/monitors/merge_mon/gui.h
new file mode 100644 (file)
index 0000000..54b9db7
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/examples/merge_mon/gui.h
+ * \brief  Some GUI related functions
+ *
+ * \date   13/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_EXAMPLES_MERGE_MON_GUI_H_
+#define __FERRET_EXAMPLES_MERGE_MON_GUI_H_
+
+extern long app_id;
+extern int global_exit;
+
+int gui_init(void);
+void gui_update(const buf_t * buf);
+
+#endif
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/main.c b/l4/pkg/ferret/examples/monitors/merge_mon/main.c
new file mode 100644 (file)
index 0000000..68a959c
--- /dev/null
@@ -0,0 +1,392 @@
+/**
+ * \file   ferret/examples/merge_mon/main.c
+ * \brief  This monitor consumes events from several lists and merges
+ *         them into a large buffer, which later can be transfered and
+ *         evaluated offline.
+ *
+ * \date   11/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <alloca.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/monitor.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/sensors/list_consumer.h>
+//#include <l4/ferret/sensors/tbuf_consumer.h>
+
+#include "buffer.h"
+#include "gui.h"
+#include "main.h"
+//#include "net.h"
+#include "poll.h"
+
+char LOG_tag[9] = "FerMeMo";
+
+sensor_entry_t sensors[MAX_SENSORS];
+int sensor_count = 0;
+char local_ip[16] = "";    // local IP address in text form
+//unsigned short local_port = 9000;   // local IP port
+
+static int interval = 1000;
+//static char * sensor_dir_basepath = NULL;
+int verbose = 0;
+static int delay = 0;
+int use_gui = 1;
+int dump_after = 0;
+
+// buffer data structures
+buf_t buf = {NULL, 10000 * 1024, NULL, NULL, PTHREAD_MUTEX_INITIALIZER,
+             0ULL, 0ULL, 0, 0};
+
+static void usage(void)
+{
+    printf(
+        "usage: fer_merge_mon [-b val] [-s val]* [-m val] [-i val] [-v]"
+        " [-d val]\n"
+        "\n"
+#if 0
+        "  -b,--base ....... Base path name to the sensor directory.\n"
+#endif
+        "  -s,--sensor ..... Sensor to open:\n"
+        "                    This can be either a major:minor:instance \n"
+        "                    triple of numbers or a filename denoting string\n"
+        "                    representing the sensor.\n"
+        "                    This option can be given several times if your\n"
+        "                    want to listen to several sensors..\n"
+        "  -m,--memory ..... Amount of memory to use for sensor data buf.\n"
+        "                    (in KBytes), defaults to 10 MBytes\n"
+        "  -i,--interval ... Internal polling interval (in msec), defaults\n"
+        "                    to 1000ms\n"
+        "  -a,--dump-after...UU-Dump the event buffer after N iterations of the\n"
+        "                    polling loop\n"
+        "  -d,--delay ...... Waiting delay after program start until sensor\n"
+        "                    directory is asked (in msec), defaults to 0 msec\n"
+#if 0
+        "  -l,--local_ip ... Local IP address to use (n.n.n.n where n are \n"
+        "                    independent decimals 0...255)\n"
+        "  -p,--local_port . Local IP port to use (default 9000)\n"
+#endif
+        "  -v,--verbose .... Be verbose\n"
+        "  -g,--nogui ...... Don't use DOpE Gui, only work in background,\n"
+        "                    controlling works via special control events\n"
+        "  -o,--offline .... Start offline (not recording events)\n"
+        "  -c,--cyclic ..... Autoclear buffer if full (pseudo ring buffer)\n"
+        "                    and record from the start again.\n"
+        "example: fer_merge_mon -b /servers/ferret/ -s 0:0:0 -s 10:2:1\n"
+        " --sensor 10:2:3 -s verner/decoder/cpu -m 20000 -i 100\n"
+        "This will open four sensors relative to '/servers/ferret/' and use 20\n"
+        " MBytes of memory for storage.  The polling interval is 100 msec.");
+}
+
+
+int main(int argc, char* argv[])
+{
+    /* 1. parse command line for:
+     *   - list of sensors to open,
+     *   - polling interval,
+     *   - memory buffer size
+     * 2. have a GUI with: start, stop, destination ip:port, transfer
+     *    button, visual fill level indicator, visual 'lost counter' for
+     *    each sensor
+     * 3. loop over all sensors and merge event into prefix-length
+     *    encoded memory region (convert kernel event to common format)
+     * 4. transfer data on request
+     */
+
+    int i;
+    int ret;
+    unsigned int max_size = 0;
+#if 0
+    int outstanding_sensors = 0;
+#endif
+    l4_cap_idx_t srv = lookup_sensordir();
+
+    if (l4_is_invalid_cap(srv)) {
+        printf("Could not find sensor directory. Exiting.\n");
+        exit(1);
+    }
+
+    // parse parameters
+    {
+        int optionid;
+        int option = 0;
+        const struct option long_options[] =
+            {
+                { "sensor",     1, NULL, 's'},
+                { "memory",     1, NULL, 'm'},
+                { "base",       1, NULL, 'b'},
+                { "interval",   1, NULL, 'i'},
+                { "dump-after", 1, NULL, 'a'},
+                { "delay",      1, NULL, 'd'},
+                { "verbose",    0, NULL, 'v'},
+                { "local_ip",   1, NULL, 'l'},
+                { "local_port", 1, NULL, 'p'},
+                { "nogui",      0, NULL, 'g'},
+                { "offline",    0, NULL, 'o'},
+                { "cyclic",     0, NULL, 'c'},
+                { 0, 0, 0, 0}
+            };
+
+        do
+        {
+            option = getopt_long(argc, argv, "s:m:b:i:vd:l:goc",
+                                 long_options, &optionid);
+            switch (option)
+            {
+            case 's':
+                if (optarg[0] >= '0' && optarg[0] <= '9')  // mmi tripple
+                {
+                    ret = sscanf(optarg, "%hu:%hu:%hu",
+                                 &sensors[sensor_count].major,
+                                 &sensors[sensor_count].minor,
+                                 &sensors[sensor_count].instance);
+                    if (ret != 3)
+                    {
+                        printf("Error parsing string '%s' for tripple\n",
+                               optarg);
+                        exit(3);
+                    }
+                }
+                else                                       // filename
+                {
+                    sensors[sensor_count].name = strdup(optarg);
+                }
+                // debug
+                sensor_count++;
+                break;
+            case 'm':
+                buf.size = atoi(optarg) * 1024;
+                if (buf.size < 1024)
+                {
+                    printf("Wrong memory size specified: '%s', should be an"
+                           " integer greater than 0!", optarg);
+                    exit(1);
+                }
+                break;
+#if 0
+            case 'b':
+                sensor_dir_basepath = strdup(optarg);
+                if (strlen(sensor_dir_basepath) == 0 ||
+                    sensor_dir_basepath[0] != L4VFS_PATH_SEPARATOR)
+                {
+                    printf("Wrong base path name specified: '%s', should be an"
+                           " absolute path (starting with %c)!",
+                           optarg, L4VFS_PATH_SEPARATOR);
+                    exit(1);
+                }
+                break;
+#endif
+            case 'i':
+                interval = atoi(optarg);
+                if (interval < 1)
+                {
+                    printf("Wrong interval specified: '%s', should be an"
+                           " integer greater than 0!", optarg);
+                    exit(1);
+                }
+                break;
+            case 'a':
+                dump_after = atoi(optarg);
+                printf("dumping buffer after %d iterations.\n", dump_after);
+                break;
+            case 'd':
+                delay = atoi(optarg);
+                if (delay < 1)
+                {
+                    printf("Wrong delay specified: '%s', should be an"
+                           " integer greater than 0!", optarg);
+                    exit(1);
+                }
+                break;
+#if 0
+            case 'p':
+                local_port = atoi(optarg);
+                break;
+            case 'l':
+            {
+                unsigned char a, b, c, d;
+                ret = sscanf(optarg, "%hhu.%hhu.%hhu.%hhu", &a, &b, &c, &d);
+                if (ret != 4)
+                {
+                    printf("Error parsing IP address: '%s', should be like"
+                           " '1.2.3.4'!", optarg);
+                    exit(1);
+                }
+                strcpy(local_ip, optarg);
+                break;
+            }
+#endif
+            case 'v':
+                verbose = 1;
+                break;
+            case 'g':
+                use_gui = 0;
+                break;
+            case 'o':
+                buf_set_offline(&buf);
+                break;
+            case 'c':
+                buf_set_cyclic(&buf);
+                break;
+            case -1:  // exit case
+                break;
+            default:
+                printf("error  - unknown option %c\n", option);
+                usage();
+                return 2;
+            }
+        } while (option != -1);
+    }
+
+    // dump what we got
+    if (verbose)
+    {
+        printf("Sensors requested (%d):\n", sensor_count);
+        for (i = 0; i < sensor_count; ++i)
+        {
+            printf("  %s: %hu, %hu, %hu\n", sensors[i].name,
+                   sensors[i].major, sensors[i].minor, sensors[i].instance);
+        }
+    }
+
+    // delay
+    if (verbose)
+    {
+        printf("Sleeping for %d msec\n", delay);
+    }
+    l4_sleep(delay);
+
+    // allocate required memory
+#if 0
+    buf.start = (unsigned char *)l4dm_mem_allocate(
+        buf.size, L4RM_MAP + L4DM_PINNED + L4DM_CONTIGUOUS);
+#else
+    // shouldn't plain malloc() suffice?
+    buf.start = malloc(buf.size);
+    pthread_mutex_init(&buf.lock, NULL);
+#endif
+    if (buf.start == NULL)
+    {
+        printf("Error allocating memory: %zd!\n", buf.size);
+        exit(2);
+    }
+    if (verbose)
+    {
+        printf("Allocated %zd Bytes for sensor data at %p.\n",
+               buf.size, buf.start);
+    }
+
+    // open stuff
+    for (i = 0; i < sensor_count; ++i)
+    {
+        if (sensors[i].name)
+        {
+            printf("Found name entry: '%s', not yet supported, ignored!\n",
+                   sensors[i].name);
+        }
+        else
+        {
+            ret = ferret_att(srv, sensors[i].major, sensors[i].minor,
+                             sensors[i].instance, sensors[i].sensor);
+            if (ret)
+            {
+                printf("Could not attach to %hu:%hu:%hu, trying again later!\n",
+                       sensors[i].major, sensors[i].minor,
+                       sensors[i].instance);
+#if 0
+                outstanding_sensors = 1;
+#endif
+            }
+            else
+            {
+                uint16_t type;
+
+                sensors[i].open      = 1;
+                sensors[i].copied    = 0;
+                sensors[i].last_lost = 0;
+                sensors[i].last_ts   = 0;
+
+                type = ((ferret_common_t *)(sensors[i].sensor))->type;
+                if (type == FERRET_LIST)
+                {
+                    max_size = MAX(max_size,
+                                   ((ferret_list_moni_t *)
+                                    (sensors[i].sensor))->glob->element_size);
+                }
+#if 0
+                else if (type == FERRET_TBUF)
+                {
+                    max_size = MAX(max_size, sizeof(l4_tracebuffer_entry_t));
+                }
+#endif
+                else
+                {
+                    printf("Found wrong sensor type (%d): %hu!\n", i, type);
+                }
+
+                if (verbose)
+                {
+                    printf("Attached to %hu:%hu:%hu.\n",
+                           sensors[i].major, sensors[i].minor,
+                           sensors[i].instance);
+                    printf("New maximal element size is %d\n", max_size);
+                }
+            }
+        }
+    }
+    buf_clear(&buf);
+
+    if (verbose)
+    {
+        printf("Maximal element size is %d\n", max_size);
+    }
+
+#if 0
+    // from here on we run multithreaded
+    // startup uip helper thread
+    if (local_ip[0] != '\0')
+    {
+        net_init(local_ip);
+    }
+#endif
+
+    // startup gui stuff with helper thread
+    if (use_gui) {
+        if ((ret = gui_init()))
+            printf("Could not initialize GUI: %d, continuing without it.\n", ret);
+    }
+
+#if 0
+    // If we have sensors that could not be opened use a polling
+    // thread to check for them periodically.
+    if (outstanding_sensors)
+    {
+        poll_sensors();
+        // so, we don't know how sensor size will be later on, so we
+        // use a safe bet here
+        max_size = MAX_EVENT_SIZE;
+    }
+#endif
+
+    ret = buf_fill(&buf, max_size, interval, verbose);
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/main.h b/l4/pkg/ferret/examples/monitors/merge_mon/main.h
new file mode 100644 (file)
index 0000000..42749f6
--- /dev/null
@@ -0,0 +1,48 @@
+/**
+ * \file   ferret/examples/merge_mon/main.h
+ * \brief  Global data structures
+ *
+ * \date   13/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_EXAMPLES_MERGE_MON_MAIN_H_
+#define __FERRET_EXAMPLES_MERGE_MON_MAIN_H_
+
+#include <l4/ferret/types.h>
+
+#include "main.h"
+#include "buffer.h"
+
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MAX_SENSORS 256
+#define MAX_EVENT_SIZE 4096
+
+typedef struct sensor_entry_s
+{
+    char         * name;
+    uint16_t       major;
+    uint16_t       minor;
+    uint16_t       instance;
+    void         * sensor;
+    int            open;
+    unsigned int   copied;
+    uint64_t       last_lost;  // lost count last time we checked
+    ferret_utime_t last_ts;
+} sensor_entry_t;
+
+extern sensor_entry_t sensors[MAX_SENSORS];
+extern int sensor_count;
+extern char local_ip[16];
+extern unsigned short local_port;
+extern int verbose;
+extern int use_gui;
+extern buf_t buf;
+
+#endif
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/main_window.dpe b/l4/pkg/ferret/examples/monitors/merge_mon/main_window.dpe
new file mode 100644 (file)
index 0000000..fb68900
--- /dev/null
@@ -0,0 +1,84 @@
+# main window
+win = new Window()
+g1 = new Grid()
+win.set(-content g1 -x 0 -y 360)
+
+# labels
+temp = new Label()
+temp.set(-text "Control:")
+g1.place(temp, -column 0 -row 0)
+
+temp = new Label()
+temp.set(-text "Transfer:")
+g1.place(temp, -column 0 -row 3)
+
+temp = new Label()
+temp.set(-text "Sensors: (ID lost current copied)")
+g1.place(temp, -column 0 -row 6)
+
+# sensor grid
+g_sen = new Grid()
+g1.place(g_sen, -column 0 -row 7)
+
+# control buttons
+g_con = new Grid()
+g1.place(g_con, -column 0 -row 1)
+
+b_start = new Button()
+b_start.set(-text "Start")
+g_con.place(b_start, -column 0 -row 0)
+
+b_stop = new Button()
+b_stop.set(-text "Stop")
+g_con.place(b_stop, -column 1 -row 0)
+
+b_clear = new Button()
+b_clear.set(-text "Clear")
+g_con.place(b_clear, -column 2 -row 0)
+
+b_exit = new Button()
+b_exit.set(-text "Exit")
+g_con.place(b_exit, -column 3 -row 0)
+
+# fill level indicator
+l_fill = new LoadDisplay()
+l_fill.set(-orient horizontal)
+g1.place(l_fill, -column 0 -row 2)
+
+# transfer ip stuff
+g_tran_ip = new Grid()
+g1.place(g_tran_ip, -column 0 -row 4)
+
+temp = new Label()
+temp.set(-text "IP Address:")
+g_tran_ip.place(temp, -column 0 -row 0)
+
+e_ip = new Entry()
+e_ip.set(-text "141.76.48.62")
+g_tran_ip.place(e_ip, -column 0 -row 1)
+
+temp = new Label()
+temp.set(-text "Port:")
+g_tran_ip.place(temp, -column 1 -row 0)
+
+e_port = new Entry()
+e_port.set(-text "9000")
+g_tran_ip.place(e_port, -column 1 -row 1)
+
+b_tran_ip = new Button()
+b_tran_ip.set(-text "Transfer")
+g_tran_ip.place(b_tran_ip, -column 2 -row 1)
+
+# transfer log stuff
+g_tran_log = new Grid()
+g1.place(g_tran_log, -column 0 -row 5)
+
+e_log = new Entry()
+e_log.set(-text "drops.dump")
+g_tran_log.place(e_log, -column 0 -row 0)
+
+b_tran_log = new Button()
+b_tran_log.set(-text "Dump uuencoded to log")
+g_tran_log.place(b_tran_log, -column 1 -row 0)
+
+win.open()
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/net.c b/l4/pkg/ferret/examples/monitors/merge_mon/net.c
new file mode 100644 (file)
index 0000000..aa6f7c7
--- /dev/null
@@ -0,0 +1,151 @@
+/**
+ * \file   ferret/examples/merge_mon/net.c
+ * \brief  Network transfer stuff
+ *
+ * \date   17/01/2006
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <l4/ore/uip-ore.h>
+#include <l4/semaphore/semaphore.h>
+#include <l4/lock/lock.h>
+
+#include "net.h"
+#include "main.h"
+#include "buffer.h"
+
+int net_connected = 0;
+int conn_port;
+l4semaphore_t net_sem = L4SEMAPHORE_UNLOCKED;
+
+static int send_one_packet(int port)
+{
+    unsigned int len;
+
+    if (buf.dump_pos >= buf.start + buf.size)  // end of whole buffer
+        return 1;
+    if (buf.dump_pos >= buf.write_pos)         // end of filled buffer
+        return 2;
+
+    // fixme: protect with buf_lock, not so easy right now, as buf->lock
+    //        is also used to stop filling thread, so we would probably
+    //        deadlock here ...
+    //l4lock_down(&buf->lock);
+    if (buf.write_pos - buf.dump_pos < 1400)
+    {
+        len = buf.write_pos - buf.dump_pos;
+    }
+    else
+    {
+        len = 1400;
+    }
+    //l4lock_up(&buf->lock);
+    uip_ore_send(buf.dump_pos, len, port);
+    buf.dump_pos += len;
+
+    return 0;
+}
+
+void receive_cb(const void *buf_start, const unsigned size, unsigned port);
+void ack_cb(void *addr, unsigned port);
+void rexmit_cb(void *addr, unsigned size, unsigned port);
+void connected_cb(const struct in_addr ip, unsigned port);
+void timeout_cb(unsigned port);
+void abrt_cb(unsigned port);
+void close_cb(unsigned port);
+
+void receive_cb(const void *buf_start, const unsigned size, unsigned port)
+{
+    printf("net: received something!\n");
+}
+
+void ack_cb(void *addr, unsigned port)
+{
+    int ret;
+
+    printf("net: ack!\n");
+
+    ret = send_one_packet(port);
+    if (ret)
+    {
+        uip_ore_close(port);
+    }
+}
+
+void rexmit_cb(void *addr, unsigned size, unsigned port)
+{
+    printf("net: retransmit!\n");
+    uip_ore_send(addr, size, port);
+}
+
+void connected_cb(const struct in_addr ip, unsigned port)
+{
+    int ret;
+    printf("net: connected!\n");
+
+    net_connected = 1;
+    conn_port = port;
+    buf.dump_pos = buf.start;
+
+    ret = send_one_packet(port);
+    if (ret)
+    {
+        uip_ore_close(port);
+    }
+}
+
+void timeout_cb(unsigned port)
+{
+    printf("net: timeout!\n");
+    net_connected = 0;
+
+    l4semaphore_up(&net_sem);
+}
+
+void abrt_cb(unsigned port)
+{
+    printf("net: abort!\n");
+    net_connected = 0;
+
+    l4semaphore_up(&net_sem);
+}
+
+void close_cb(unsigned port)
+{
+    printf("net: closed!\n");
+    net_connected = 0;
+
+    l4semaphore_up(&net_sem);
+}
+
+int net_init(const char * ip)
+{
+    uip_ore_config c;
+
+    memset(&c, 0, sizeof(c));
+
+    strcpy(c.ip, ip);
+//    c.port_nr = port;
+
+    c.recv_callback    = receive_cb;
+    c.ack_callback     = ack_cb;
+    c.rexmit_callback  = rexmit_cb;
+    c.connect_callback = connected_cb;
+    c.abort_callback   = abrt_cb;
+    c.timeout_callback = timeout_cb;
+    c.close_callback   = close_cb;
+
+    uip_ore_initialize(&c);
+    uip_thread = l4thread_create(uip_ore_thread, NULL, L4THREAD_CREATE_SYNC);
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/net.h b/l4/pkg/ferret/examples/monitors/merge_mon/net.h
new file mode 100644 (file)
index 0000000..d7d4177
--- /dev/null
@@ -0,0 +1,22 @@
+/**
+ * \file   ferret/examples/merge_mon/net.h
+ * \brief  Network transfer stuff
+ *
+ * \date   17/01/2006
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_EXAMPLES_MERGE_MON_NET_H_
+#define __FERRET_EXAMPLES_MERGE_MON_NET_H_
+
+extern l4semaphore_t net_sem;
+extern int net_connected;
+
+int net_init(const char * ip);
+
+#endif
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/poll.c b/l4/pkg/ferret/examples/monitors/merge_mon/poll.c
new file mode 100644 (file)
index 0000000..b3c443a
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * \file   ferret/examples/merge_mon/poll.c
+ * \brief  polls for outstanding sensors
+ *
+ * \date   2007-11-27
+ * \author Ronald Aigner  <ra3@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <stdio.h>
+
+#include <l4/sys/cache.h>
+#include <l4/util/util.h>
+
+#include <l4/ferret/monitor.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/sensors/list_consumer.h>
+//#include <l4/ferret/sensors/tbuf_consumer.h>
+
+#include "poll.h"
+#include "main.h"
+
+static void polling_thread(void* arg)
+{
+    int searching = 1;
+    int i, ret;
+    uint16_t type;
+
+    while (searching)
+    {
+        l4_sleep(1000);
+        searching = 0;
+
+        for (i = 0; i < sensor_count; i++)
+        {
+            if (sensors[i].open)
+                continue;
+
+                       l4_cap_idx_t srv = lookup_sensordir();
+
+            searching = 1;
+            ret = ferret_att(srv, sensors[i].major, sensors[i].minor,
+                             sensors[i].instance, sensors[i].sensor);
+            if (ret)
+            {
+                if (verbose)
+                {
+                    printf("Still could not attach to %hu:%hu:%hu, retrying!\n",
+                           sensors[i].major, sensors[i].minor,
+                           sensors[i].instance);
+                }
+                continue;
+            }
+
+            // this looks a bit racy ...
+            sensors[i].copied    = 0;
+            sensors[i].last_lost = 0;
+            sensors[i].last_ts   = 0;
+
+            type = ((ferret_common_t *)(sensors[i].sensor))->type;
+            if (type != FERRET_LIST && type != FERRET_TBUF)
+            {
+                printf("Found wrong sensor type (%d): %hu!\n", i, type);
+            }
+
+            if (verbose)
+            {
+                printf("Attached to %hu:%hu:%hu.\n",
+                       sensors[i].major, sensors[i].minor,
+                       sensors[i].instance);
+            }
+
+            __asm__ __volatile__("": : :"memory");  // barrier
+            sensors[i].open = 1;
+        }
+    }
+}
+
+void poll_sensors(void)
+{
+    l4thread_create_named(polling_thread, ".poll", 0, L4THREAD_CREATE_ASYNC);
+}
diff --git a/l4/pkg/ferret/examples/monitors/merge_mon/poll.h b/l4/pkg/ferret/examples/monitors/merge_mon/poll.h
new file mode 100644 (file)
index 0000000..f91f9df
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * \file   ferret/examples/merge_mon/poll.h
+ * \brief  Polling thread for internal sensor directory
+ *
+ * \date   2007-11-27
+ * \author Ronald Aigner  <ra3@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_EXAMPLES_MERGE_MON_POLL_H_
+#define __FERRET_EXAMPLES_MERGE_MON_POLL_H_
+
+void poll_sensors(void);
+
+#endif
diff --git a/l4/pkg/ferret/examples/monitors/simple_mon/Makefile b/l4/pkg/ferret/examples/monitors/simple_mon/Makefile
new file mode 100644 (file)
index 0000000..b25d231
--- /dev/null
@@ -0,0 +1,10 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+SRC_C           = main.c
+TARGET          = fer_simple_mon
+LIBS           += -lferret_monitor -lferret_consumer -lferret_util          \
+                  -lferret_comm -lferret_fpages -lferret_local_names
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/monitors/simple_mon/broken b/l4/pkg/ferret/examples/monitors/simple_mon/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/examples/monitors/simple_mon/main.c b/l4/pkg/ferret/examples/monitors/simple_mon/main.c
new file mode 100644 (file)
index 0000000..827c196
--- /dev/null
@@ -0,0 +1,254 @@
+/**
+ * \file   ferret/examples/simple_mon/main.c
+ * \brief  Example demonstrating the usage of monitoring functions.
+ *
+ * \date   11/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <l4/log/l4log.h>
+#include <l4/util/l4_macros.h>
+#include <l4/util/rand.h>
+#include <l4/util/util.h>
+#include <l4/sys/syscalls.h>
+#include <l4/sys/kdebug.h>
+
+#include <l4/ferret/monitor.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/sensors/scalar_consumer.h>
+#include <l4/ferret/sensors/histogram_consumer.h>
+#include <l4/ferret/sensors/list_consumer.h>
+#include <l4/ferret/sensors/tbuf_consumer.h>
+
+char LOG_tag[9] = "FerSiMo";
+
+int main(int argc, char* argv[])
+{
+    int c, i, ret;
+    const int max_count = 100;
+    ferret_scalar_t * s1, * s2, * s3, * s4;
+    ferret_histo_t * h1;
+    ferret_list_moni_t * l1, * l2;
+    ferret_tbuf_moni_t * t1;
+    ferret_monitor_list_entry_t entries[max_count];
+    ferret_monitor_list_entry_t *e = entries;
+    l4_tracebuffer_entry_t te[100];
+    int te_count;
+    ferret_time_t told;
+
+    ferret_list_entry_t * le = malloc(sizeof(ferret_list_entry_t) +
+                                       sizeof(ferret_list_entry_common_t));
+    ferret_list_entry_common_t * lec;
+
+
+    l4_sleep(2000);
+
+    // listing the directories content
+    c = ferret_list(&e, max_count, 0);
+    for (i = 0; i < c; i++)
+    {
+        LOG("%hu, %hu, %hu, %hu, %u", entries[i].major, entries[i].minor,
+            entries[i].instance, entries[i].type, entries[i].id);
+    }
+
+    c = ferret_list(&e, 2, 0);
+    for (i = 0; i < c; i++)
+    {
+        LOG("%hu, %hu, %hu, %hu, %u", entries[i].major, entries[i].minor,
+            entries[i].instance, entries[i].type, entries[i].id);
+    }
+    c = ferret_list(&e, 2, 2);
+    for (i = 0; i < c; i++)
+    {
+        LOG("%hu, %hu, %hu, %hu, %u", entries[i].major, entries[i].minor,
+            entries[i].instance, entries[i].type, entries[i].id);
+    }
+
+    // attaching to some sensors
+
+    // scalars ...
+    ret = ferret_att(10, 1, 0, s1);
+    if (ret)
+    {
+        LOG("Could not attach to 10:1, ignored");
+    }
+    ret = ferret_att(10, 2, 0, s2);
+    if (ret)
+    {
+        LOG("Could not attach to 10:2, ignored");
+    }
+    ret = ferret_att(10, 3, 0, s3);
+    if (ret)
+    {
+        LOG("Could not attach to 10:3, ignored");
+    }
+    ret = ferret_att(10, 4, 0, s4);
+    if (ret)
+    {
+        LOG("Could not attach to 10:4, ignored");
+    }
+
+    // histograms ...
+    ret = ferret_att(11, 1, 0, h1);
+    if (ret)
+    {
+        LOG("Could not attach to 11:1, ignored");
+    }
+
+    // lists ...
+    ret = ferret_att(12, 1, 0, l1);
+    if (ret)
+    {
+        LOG("Could not attach to 12:1, ignored");
+    }
+
+    ret = ferret_att(12, 2, 0, l2);
+    if (ret)
+    {
+        LOG("Could not attach to 12:2, ignored");
+    }
+
+    // tracebuffer
+    ret = ferret_att(0, 0, 0, t1);
+    if (ret)
+    {
+        LOG("Could not attach to 0:0, ignored");
+    }
+
+    // periodically read from sensors and dump their values
+    while (1)
+    {
+        puts("************************************************************\n");
+        if (s1)
+            printf("s1: %lld, ", ferret_scalar_get(s1));
+        if (s2)
+            printf("s2: %lld, ", ferret_scalar_get(s2));
+        if (s3)
+            printf("s3: %lld, ", ferret_scalar_get(s3));
+        if (s4)
+            printf("s4: %lld, ", ferret_scalar_get(s4));
+        if (s1 || s2 || s3 || s4)
+            puts("\n");
+
+        if (h1)
+        {
+            printf("h1: (U: %u, O: %u, Min: %lld, Max: %lld, S: %lld, C: %u) ",
+                   h1->head.underflow, h1->head.overflow, h1->head.val_min, 
+                   h1->head.val_max, h1->head.val_sum, h1->head.val_count);
+            for (i = 0; i < h1->head.bins; ++i)
+            {
+                printf("%u, ", h1->data[i]);
+            }
+            puts("\n");
+        }
+
+        told = 0;
+        if (l1)
+        {
+            while (1)
+            {
+                ret = ferret_list_get(l1, le);
+                if (ret == -1)
+                    break;
+                else if (ret < -1)
+                {
+                    LOG("l1: Something wrong with list: %d", ret);
+                    exit(1);
+                }
+                printf("l1: time: %lld, diff: %lld\n", le->timestamp,
+                       le->timestamp - told);
+                told = le->timestamp;
+            }
+        }
+
+        told = 0;
+        if (l2)
+        {
+            while (1)
+            {
+                ret = ferret_list_get(l2, le);
+                if (ret == -1)
+                    break;
+                else if (ret < -1)
+                {
+                    LOG("l2: Something wrong with list: %d", ret);
+                    exit(1);
+                }
+                lec = (ferret_list_entry_common_t *)le;
+                printf("l2: time: %lld, %hd.%hd, type: %d, seq.:"
+                       " %d, ttime: %lld",
+                       lec->timestamp, lec->major, lec->minor,
+                       lec->data32[2], lec->data32[3], lec->data64[0]);
+                if (lec->data32[2] == 2)  // stop type event
+                {
+                    printf(", ttdiff: %lld\n", lec->data64[0] - told);
+                }
+                else
+                {
+                    told = lec->data64[0];
+                    puts("\n");
+                }
+                // testing unpack stuff here
+                {
+                    ferret_time_t t1, t2;
+                    uint16_t major, minor, instance;
+                    uint8_t cpu;
+                    uint32_t seq, type;
+
+                    ret = ferret_util_unpack("qhhhbxqll", le,
+                                             &t1, &major, &minor, &instance,
+                                             &cpu, &t2, &type, &seq);
+                    printf("u2: time: %lld, %hd.%hd, type: %d, seq.:"
+                           " %d, ttime: %lld\n",
+                           t1, major, minor, type, seq, t2);
+                }
+            }
+        }
+
+        if (t1)
+        {
+            te_count = 0;
+            while (1)
+            {
+                for (i = 0; i < 100; ++i)
+                {
+                    ret = ferret_tbuf_get(t1, &te[i]);
+                    if (ret == -1)
+                    {
+                        break;
+                    }
+                    else if (ret < -1)
+                    {
+                        LOG("t1: Something wrong with trace buffer: %d", ret);
+                        exit(1);
+                    }
+                }
+
+                printf("t1: count: %d\n", i);
+                /*
+                for (j = 0; j < i; ++j)
+                {
+                    printf("t1: number: %d, eip %p, tsc %lld, type %hhd\n",
+                           te[j].number, (void * )te[j].eip, te[j].tsc,
+                           te[j].type);
+                }
+                */
+                if (i != 100)
+                    break;
+            }
+        }
+
+        l4_sleep(1000);
+    }
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/examples/monitors/simple_mon_re/Makefile b/l4/pkg/ferret/examples/monitors/simple_mon_re/Makefile
new file mode 100644 (file)
index 0000000..afdccfd
--- /dev/null
@@ -0,0 +1,9 @@
+PKGDIR         ?= ../../..
+L4DIR          ?= $(PKGDIR)/../..
+
+SYSTEMS         = x86-l4f
+SRC_C           = main.c
+TARGET          = fer_simple_mon
+REQUIRES_LIBS   = ferret-common ferret-consumer libstdc++
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/examples/monitors/simple_mon_re/main.c b/l4/pkg/ferret/examples/monitors/simple_mon_re/main.c
new file mode 100644 (file)
index 0000000..93bbcf6
--- /dev/null
@@ -0,0 +1,166 @@
+/**
+ * \file   ferret/examples/simple_mon_re/main.c
+ * \brief  SimpleMon exampe for L4Re
+ *
+ * \date   10/03/2009
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ * \author Bjoern Doebel   <doebel@tudos.org>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <l4/util/util.h>
+
+#include <l4/ferret/monitor.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/sensors/scalar_consumer.h>
+//#include <l4/ferret/sensors/histogram_consumer.h>
+#include <l4/ferret/sensors/list_consumer.h>
+//#include <l4/ferret/sensors/tbuf_consumer.h>
+
+char LOG_tag[9] = "FerSiMo";
+
+int main(void)
+{
+       ferret_scalar_t *s1, *s2, *s3, *s4;
+       ferret_list_moni_t * l1, * l2;
+       ferret_list_entry_t * le = malloc(sizeof(ferret_list_entry_t) +
+                                         sizeof(ferret_list_entry_common_t));
+       ferret_list_entry_common_t * lec;
+       ferret_time_t told;
+
+       int ret;
+
+       l4_cap_idx_t srv = lookup_sensordir();
+
+       l4_sleep(3000);
+
+       // attaching to some sensors
+
+       // scalars ...
+       ret = ferret_att(srv, 10, 1, 0, s1);
+       if (ret)
+       {
+               printf("Could not attach to 10:1, ignored\n");
+       }
+       ret = ferret_att(srv, 10, 2, 0, s2);
+    if (ret)
+    {
+        printf("Could not attach to 10:2, ignored\n");
+    }
+    ret = ferret_att(srv, 10, 3, 0, s3);
+    if (ret)
+    {
+        printf("Could not attach to 10:3, ignored\n");
+    }
+    ret = ferret_att(srv, 10, 4, 0, s4);
+    if (ret)
+    {
+        printf("Could not attach to 10:4, ignored\n");
+    }
+
+    // lists ...
+    ret = ferret_att(srv, 12, 1, 0, l1);
+    if (ret)
+    {
+        printf("Could not attach to 12:1, ignored\n");
+    }
+
+    ret = ferret_att(srv, 12, 2, 0, l2);
+    if (ret)
+    {
+        printf("Could not attach to 12:2, ignored\n");
+    }
+
+    // periodically read from sensors and dump their values
+    while (1)
+    {
+        puts("************************************************************\n");
+        if (s1)
+            printf("s1: %lld, ", ferret_scalar_get(s1));
+        if (s2)
+            printf("s2: %lld, ", ferret_scalar_get(s2));
+        if (s3)
+            printf("s3: %lld, ", ferret_scalar_get(s3));
+        if (s4)
+            printf("s4: %lld, ", ferret_scalar_get(s4));
+        if (s1 || s2 || s3 || s4)
+            puts("\n");
+
+        told = 0;
+        if (l1)
+        {
+            while (1)
+            {
+                ret = ferret_list_get(l1, le);
+                if (ret == -1)
+                    break;
+                else if (ret < -1)
+                {
+                    printf("l1: Something wrong with list: %d\n", ret);
+                    exit(1);
+                }
+                printf("l1: time: %lld, diff: %lld\n", le->timestamp,
+                       le->timestamp - told);
+                told = le->timestamp;
+            }
+        }
+
+        told = 0;
+        if (l2)
+        {
+            while (1)
+            {
+                ret = ferret_list_get(l2, le);
+                if (ret == -1)
+                    break;
+                else if (ret < -1)
+                {
+                    printf("l2: Something wrong with list: %d\n", ret);
+                    exit(1);
+                }
+                lec = (ferret_list_entry_common_t *)le;
+                printf("l2: time: %lld, %hd.%hd, type: %d, seq.:"
+                       " %d, ttime: %lld",
+                       lec->timestamp, lec->major, lec->minor,
+                       lec->data32[2], lec->data32[3], lec->data64[0]);
+                if (lec->data32[2] == 2)  // stop type event
+                {
+                    printf(", ttdiff: %lld\n", lec->data64[0] - told);
+                }
+                else
+                {
+                    told = lec->data64[0];
+                    puts("\n");
+                }
+                // testing unpack stuff here
+                {
+                    ferret_time_t t1, t2;
+                    uint16_t major, minor, instance;
+                    uint8_t cpu;
+                    uint32_t seq, type;
+
+                    ret = ferret_util_unpack("qhhhbxqll", le,
+                                             &t1, &major, &minor, &instance,
+                                             &cpu, &t2, &type, &seq);
+                    printf("u2: time: %lld, %hd.%hd, type: %d, seq.:"
+                           " %d, ttime: %lld\n",
+                           t1, major, minor, type, seq, t2);
+                }
+            }
+        }
+
+
+               l4_sleep(1000);
+       }
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/include/Makefile b/l4/pkg/ferret/include/Makefile
new file mode 100644 (file)
index 0000000..1df01b1
--- /dev/null
@@ -0,0 +1,4 @@
+PKGDIR ?= ..
+L4DIR  ?= $(PKGDIR)/../..
+
+include $(L4DIR)/mk/include.mk
diff --git a/l4/pkg/ferret/include/client.h b/l4/pkg/ferret/include/client.h
new file mode 100644 (file)
index 0000000..0506643
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * \file   ferret/include/client.h
+ * \brief  Interface for client applications to sensor directory
+ *
+ * \date   2005-11-07
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_CLIENT_H_
+#define __FERRET_INCLUDE_CLIENT_H_
+
+#include <l4/sys/compiler.h>
+
+#include <l4/ferret/types.h>
+
+EXTERN_C_BEGIN
+
+// macro to hide the casting to void ** of addr
+#define \
+    ferret_create(cap, major, minor, instance, type, flags, config, addr, alloc) \
+    ferret_create_sensor((cap), (major), (minor), (instance), (type), (flags),     \
+                         (config), (void **)&(addr), (alloc))
+
+// macro to hide the casting to void ** of addr
+#define \
+    ferret_create_dir(major, minor, instance, type, flags,                  \
+                      config, addr, alloc, dir)                             \
+    ferret_create_sensor_dir((major), (minor), (instance), (type), (flags), \
+                             (config), (void **)&(addr), (alloc), dir)
+
+/**
+ * @brief Allocate a new sensor
+ *
+ * @param  dir_cap  cap to sensor dir
+ * @param  major    major identifier for sensor
+ * @param  minor    minor identifier for sensor
+ * @param  instance instance identifier for sensor
+ * @param  type     type of sensor (as defined in ferret/include/types.h)
+ * @param  flags    special flags to use for this sensor (as defined in
+ *                  ferret/include/types.h)
+ * @param  config   sensor specific flags to parameterize this sensor
+ * @param  addr     address to map sensor memory to (NULL -> l4rm chooses)
+ * @retval addr     address of mapped sensor memory
+ * @param  alloc    function pointer to memory allocation function
+ *                  (malloc() signature)
+ *
+ * @return 0 on succes, != 0 otherwise
+ */
+L4_CV int ferret_create_sensor(l4_cap_idx_t dir_cap,
+                               uint16_t major, uint16_t minor,
+                               uint16_t instance, uint16_t type,
+                               uint32_t flags, const char * config,
+                               void ** addr, void *(*alloc)(size_t size));
+
+/**
+ * @brief Allocate a new sensor with given thread id for sensor
+ *        directory for non-L4Env task
+ *
+ * @param  major    major identifier for sensor
+ * @param  minor    minor identifier for sensor
+ * @param  instance instance identifier for sensor
+ * @param  type     type of sensor (as defined in ferret/include/types.h)
+ * @param  flags    special flags to use for this sensor (as defined in
+ *                  ferret/include/types.h)
+ * @param  config   sensor specific flags to parameterize this sensor
+ * @param  addr     address to map sensor memory to (must be != NULL)
+ * @retval addr     address of mapped sensor memory
+ * @param  alloc    function pointer to memory allocation function
+ *                  (malloc() signature)
+ * @param  dir      explicitly given thread id for sensor directory
+ *
+ * @return 0 on succes, != 0 otherwise
+ *
+ * Use this function if you cannot ask names (e.g., because you are
+ * names) but otherwise know the thread id of the sensor directory.
+ * Also this functions does not use l4rm_* to attach the dataspace
+ * locally, but l4dm_attache_ds, i.e., you must choose the destination
+ * address yourself.
+ *
+ */
+L4_CV int ferret_create_sensor_dir(uint16_t major, uint16_t minor,
+                                   uint16_t instance, uint16_t type,
+                                   uint32_t flags, const char * config,
+                                   void ** addr, void *(*alloc)(size_t size),
+                                   l4_cap_idx_t dir);
+
+L4_CV int ferret_free_sensor(uint16_t major, uint16_t minor,
+                             uint16_t instance, void * addr,
+                             void (*free)(void *));
+L4_CV int ferret_create_instance(void);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/clock.h b/l4/pkg/ferret/include/clock.h
new file mode 100644 (file)
index 0000000..62d266c
--- /dev/null
@@ -0,0 +1,112 @@
+/**
+ * \file   ferret/include/clock.h
+ * \brief  macros and defines for getting time values
+ *
+ * \date   04/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_CLOCK_H_
+#define __FERRET_INCLUDE_CLOCK_H_
+
+#include <l4/ferret/types.h>
+#include <l4/re/env.h>
+
+#if defined(ARCH_x86) || defined(ARCH_amd64)
+#include <l4/util/rdtsc.h>
+#endif
+
+#include <l4/sys/compiler.h>
+#include <l4/sys/thread.h>
+
+/*********************************************************************
+ * Time sources
+ *********************************************************************/
+
+// reserve 0 as illegal value !
+
+enum TimeSource
+{
+       /*
+        * Reserved
+        */
+       FERRET_ILLEGAL_TIME = 0,
+       /*
+        * Directly use CPU ticks. Absolute time since bootup.
+        */
+       FERRET_TIME_ABS_TSC = 1,
+       /*
+        * Same as FERRET_TIME_ABS_TSC, but convert ticks to Âµs via l4_tsc_to_us().
+        * Absolute time since booutp.
+        */
+       FERRET_TIME_ABS_US  = 2,
+       /*
+        * Accumulated time in Âµs, relatvie to thread.
+        * THIS IS SLOW!
+        */
+       FERRET_TIME_REL_US  = 3,
+#if 0
+       /*
+        * Accumulated time in ticks, relatvie to thread.
+        * THIS IS NOT FAST IN RE!
+        */
+       FERRET_TIME_REL_TSC_FAST = 4,
+       /*
+        * Accumulated time in Âµs, relatvie to thread.
+        * THIS IS NOT FAST IN RE!
+        */
+       FERRET_TIME_REL_US_FAST = 5,
+#endif
+};
+
+
+
+/*********************************************************************
+ * Time macros
+ *********************************************************************/
+
+// fixme: sort case block according to common cases
+
+EXTERN_C ferret_time_t ferret_rel_utime(void);
+
+#define FERRET_GET_TIME(clock_type, time_val)                             \
+do                                                                        \
+{                                                                         \
+       switch (clock_type)                                                   \
+       {                                                                     \
+       case FERRET_TIME_REL_US:                                              \
+               (time_val) = ferret_rel_utime();                                  \
+               break;                                                            \
+       case FERRET_TIME_ABS_TSC:                                             \
+               (time_val) = l4_rdtsc();                                          \
+               break;                                                            \
+       case FERRET_TIME_ABS_US:                                              \
+               (time_val) = l4_tsc_to_us(l4_rdtsc());                            \
+               break;                                                            \
+       default:                                                              \
+               printf("corrupted CLOCKTYPE\n");                                  \
+       }                                                                     \
+} while (0)
+
+
+/**
+ * @brief Calibrates scalers etc. for the use of the corresponding clock
+ *
+ * @param clock clock type to calibrate for
+ */
+L4_INLINE L4_CV void ferret_calibrate_clock(int clock_type);
+L4_INLINE L4_CV void ferret_calibrate_clock(int clock_type)
+{
+#if defined(ARCH_x86) || defined(ARCH_amd64)
+       if (clock_type == FERRET_TIME_REL_US)
+               if (l4_scaler_tsc_to_us == 0)  // calibrate on demand
+                       l4_calibrate_tsc(l4re_kip());
+#endif
+}
+
+#endif
diff --git a/l4/pkg/ferret/include/comm.h b/l4/pkg/ferret/include/comm.h
new file mode 100644 (file)
index 0000000..f685c36
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * \file   ferret/include/comm.h
+ * \brief  Helper stuff for finding the sensor directory.
+ *
+ * \date   2007-06-21
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ * \author Bjoern Doebel   <doebel@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_COMM_H_
+#define __FERRET_INCLUDE_COMM_H_
+
+#include <l4/re/c/util/cap_alloc.h>
+
+EXTERN_C_BEGIN
+
+l4_cap_idx_t lookup_sensordir(void);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/fpages.h b/l4/pkg/ferret/include/fpages.h
new file mode 100644 (file)
index 0000000..40b8dc4
--- /dev/null
@@ -0,0 +1,20 @@
+/**
+ * \file   ferret/include/fpages.h
+ * \brief  IDL wrapper for fpages interface
+ *
+ * \date   2007-06-21
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_FPAGES_H_
+#define __FERRET_INCLUDE_FPAGES_H_
+
+L4_CV int ferret_fpages_request(int ksem, uint16_t major, uint16_t minor,
+                                uint16_t instance);
+
+#endif
diff --git a/l4/pkg/ferret/include/gcc_instrument.h b/l4/pkg/ferret/include/gcc_instrument.h
new file mode 100644 (file)
index 0000000..55082f2
--- /dev/null
@@ -0,0 +1,25 @@
+/**
+ * \file   ferret/include/gcc_instrument.h
+ * \brief  Support functions for gcc-function-level instrumentation
+ *
+ * \date   2007-10-09
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_GCC_INSTRUMENT_H
+#define __FERRET_INCLUDE_GCC_INSTRUMENT_H
+
+#include <l4/sys/types.h>
+
+/* Set function pointer for get_threadid-function and create sensor.
+ */
+L4_CV void ferret_gcc_instrument_init(void *(*alloc)(size_t s),
+                                      l4_threadid_t (*myself)(void))
+    __attribute__ ((no_instrument_function));
+
+#endif
diff --git a/l4/pkg/ferret/include/l4lx_client.h b/l4/pkg/ferret/include/l4lx_client.h
new file mode 100644 (file)
index 0000000..e9d0136
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * \file   ferret/include/l4lx_client.h
+ * \brief  Helper function for L4Linux user mode clients.
+ *
+ * \date   2006-04-03
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_L4LX_CLIENT_H_
+#define __FERRET_INCLUDE_L4LX_CLIENT_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/list_producer.h>
+
+EXTERN_C_BEGIN
+
+/**< process-global pointer to l4Linux user land sensor, init */
+extern ferret_list_local_t * ferret_l4lx_user;
+
+/**
+ * @brief Setup the global userland list ferret_l4lx_user for L4Linux
+ *        clients.
+ *
+ * @param  alloc function pointer to memory allocating function
+ */
+L4_CV void ferret_list_l4lx_user_init(void);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/local_names.h b/l4/pkg/ferret/include/local_names.h
new file mode 100644 (file)
index 0000000..00ce7bb
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * \file   ferret/include/local_names.h
+ * \brief  Manage local names for kernel objects.
+ *
+ * \date   2007-06-20
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_LOCAL_NAMES_H_
+#define __FERRET_INCLUDE_LOCAL_NAMES_H_
+
+#include <l4/sys/linkage.h>
+
+/**
+ * @brief Reserve one name entry for a new kernel object
+ *
+ * @return index of local name assigned (1 .. MAX_LOCAL_NAMES)
+ *         - 0 on failure
+ */
+L4_CV int ferret_local_names_reserve(void);
+
+/**
+ * @brief Free one entry in local name table for kernel objects
+ *
+ * @param index index to free
+ */
+L4_CV void ferret_local_names_dispose(int index);
+
+#endif
diff --git a/l4/pkg/ferret/include/maj_min.h b/l4/pkg/ferret/include/maj_min.h
new file mode 100644 (file)
index 0000000..c2b2d80
--- /dev/null
@@ -0,0 +1,103 @@
+/**
+ * \file   ferret/include/maj_min.h
+ * \brief  Collection of well known major / minor numbers for sensors.
+ *
+ * \date   2006-04-04
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_MAJ_MIN_H_
+#define __FERRET_INCLUDE_MAJ_MIN_H_
+
+// Fiasco's tracebuffer
+#define FERRET_TBUF_MAJOR    0
+#define FERRET_TBUF_MINOR    0
+#define FERRET_TBUF_INSTANCE 0
+
+// L4Linux kernel sensors
+#define FERRET_L4LX_MAJOR    1
+// in-kernel minors
+#define FERRET_L4LX_LIST_MINOR          0       // the global event list
+#define FERRET_L4LX_SYSCALLCOUNT_MINOR  2       // system call histogram
+#define FERRET_L4LX_SYSCALLPROF_MINOR   3       // profiling histogram
+// minors for kprobe modules
+#define FERRET_L4LX_FORKINST_MINOR      1000
+#define FERRET_L4LX_FORKINST_MINOR2     1001
+#define FERRET_L4LX_NETINST_MINOR       1004
+// minors for atomic sequences (e.g., in tamer thread)
+#define FERRET_L4LX_ATOMIC_BEGIN        2000
+#define FERRET_L4LX_ATOMIC_END1         2001
+#define FERRET_L4LX_ATOMIC_END2         2002
+// minors for CLI / STI debugging in L4Linux
+#define FERRET_L4LX_CLI_BEGIN           2010
+#define FERRET_L4LX_CLI_END1            2011
+#define FERRET_L4LX_CLI_END2            2012
+#define FERRET_L4LX_STI_BEGIN           2013
+#define FERRET_L4LX_STI_END             2014
+// minors for tcp debugging
+#define FERRET_L4LX_TCP_RETRANSMIT      3000
+#define FERRET_L4LX_TCP_RETRANS_BUG     3001
+
+// L4Linux userland sensor
+#define FERRET_L4LXU_MAJOR   2
+#define FERRET_L4LXU_MINOR   0
+
+// Names
+#define FERRET_NAMES_MAJOR  20
+
+// dice_trace sensor
+#define FERRET_DICE_MAJOR  100
+#define FERRET_DICE_MINOR    0
+
+// L4env sensor
+#define FERRET_L4ENV_MAJOR 102
+#define FERRET_L4ENV_MINOR   0
+
+// dope experiments
+#define FERRET_DOPE_MAJOR  104
+#define FERRET_DOPE_MINOR    0
+
+// input experiments
+#define FERRET_INPUT_MAJOR 105
+#define FERRET_INPUT_MINOR   0
+
+// l4io experiments
+#define FERRET_L4IO_MAJOR 106
+#define FERRET_L4IO_MINOR   0
+
+// function call trace
+#define FERRET_FUNC_TRACE_MAJOR       200
+#define FERRET_FUNC_TRACE_MINOR_ENTER   1
+#define FERRET_FUNC_TRACE_MINOR_EXIT    2
+
+/********************************************************************/
+
+// some special events for controlling monitors
+
+#define FERRET_MONCON_MAJOR   50000  // for events and sensors
+#define FERRET_MONCON_MINOR   50001  // minor for sensor
+
+// minor for events, avoid collisions for easy debugging
+#define FERRET_MONCON_START   50010  // start recording now
+#define FERRET_MONCON_STOP    50011  // stop recording now
+#define FERRET_MONCON_NETSEND 50012  // send data now over tcp, details are
+                                     // defined in the event
+#define FERRET_MONCON_SERSEND 50013  // send data now over serial line,
+                                     // uuencoded
+#define FERRET_MONCON_CLEAR   50014  // clear buffer from recorded data
+#define FERRET_MONCON_STATS   50015  // dump some stats in the monitor
+#define FERRET_MONCON_PING    50016  // encourage the monitor to show a sign
+                                     // of life, maybe by log output to check
+                                     // connection
+
+// special events for signaling loss of events from source
+
+#define FERRET_EVLOSS_MAJOR   51000
+#define FERRET_EVLOSS_MINOR   51000
+
+#endif
diff --git a/l4/pkg/ferret/include/monitor.h b/l4/pkg/ferret/include/monitor.h
new file mode 100644 (file)
index 0000000..66023af
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * \file   ferret/include/monitor.h
+ * \brief  Interface for client applications to sensor directory
+ *
+ * \date   07/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ * \author Bjoern Doebel   <doebel@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_MONITOR_H_
+#define __FERRET_INCLUDE_MONITOR_H_
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/monitor_list.h>
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+// macro to hide the casting to void ** of addr
+#define ferret_att(srv, major, minor, instance, addr)                  \
+    ferret_attach((srv), (major), (minor), (instance), (void **)&(addr))
+
+L4_CV int ferret_attach(l4_cap_idx_t srv,
+                        uint16_t major, uint16_t minor,
+                        uint16_t instance, void ** addr);
+L4_CV int ferret_detach(l4_cap_idx_t srv,
+                        uint16_t major, uint16_t minor,
+                        uint16_t instance, void ** addr);
+L4_CV int ferret_list(l4_cap_idx_t srv,
+                      ferret_monitor_list_entry_t ** entries, int count,
+                      int offset);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/monitor_list.h b/l4/pkg/ferret/include/monitor_list.h
new file mode 100644 (file)
index 0000000..0e1caa4
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * \file   ferret/include/monitor_list.h
+ * \brief  Transfer type for IDL to directory
+ *
+ * \date   15/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_MONITOR_LIST_H_
+#define __FERRET_INCLUDE_MONITOR_LIST_H_
+
+#include <l4/ferret/types.h>
+
+typedef struct
+{
+    uint16_t major;
+    uint16_t minor;
+    uint16_t instance;
+    uint16_t type;
+    uint32_t id;
+} ferret_monitor_list_entry_t;
+
+#endif
diff --git a/l4/pkg/ferret/include/sensordir.h b/l4/pkg/ferret/include/sensordir.h
new file mode 100644 (file)
index 0000000..42c99be
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#pragma once
+
+enum Protocols
+{
+       Client  = 0x10,
+       Monitor = 0x20
+};
+
+
+enum ClientOperations
+{
+       Create = 0x10,
+       Free   = 0x20,
+       NewInstance = 0x30,
+};
+
+
+enum MonitorOperations
+{
+       Attach = 0x10,
+       Detach = 0x20,
+       List   = 0x30,
+};
diff --git a/l4/pkg/ferret/include/sensors/__dplist_magic.h b/l4/pkg/ferret/include/sensors/__dplist_magic.h
new file mode 100644 (file)
index 0000000..8821fa7
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * \file   ferret/include/sensors/__dplist_magic.h
+ * \brief  Template magic for dplists
+ *
+ * \date   2007-06-11
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#undef  FERRET_LLIST_LOCK
+#undef  FERRET_LLIST_UNLOCK
+#undef  FERRET_LLIST_LOCAL_LOCK
+#undef  FERRET_LLIST_LOCAL_UNLOCK
+#undef  FERRET_LLIST_INIT
+#undef  FERRET_LLIST_DEINIT
+
+#ifdef L4_SUPPORT_DP
+#  define FERRET_LLIST_LOCK(a) l4_utcb_delay_preemption_set()
+#  define FERRET_LLIST_UNLOCK(a)                                          \
+      do                                                                  \
+      {                                                                   \
+          l4_utcb_delay_preemption_unset();                               \
+          if (L4_UNLIKELY(l4_utcb_delay_preemption_triggered()))         \
+              l4_yield();                                                 \
+      } while (0)
+#else
+#  define FERRET_LLIST_LOCK(a)
+#  define FERRET_LLIST_UNLOCK(a)
+#  warning No Delayed Preemption support found, dplist will not work.
+#endif
+#define FERRET_LLIST_INIT(l, d)
+#define FERRET_LLIST_DEINIT(l, d)
+
+#define FERRET_LLIST_LOCAL_LOCK(a)   FERRET_LLIST_LOCK(a)
+#define FERRET_LLIST_LOCAL_UNLOCK(a) FERRET_LLIST_UNLOCK(a)
+
+#undef  FERRET_LLIST_HAVE_LOCK
+#undef  ferret_dplist_lock_t
+#undef  FERRET_LLIST_HAVE_LOCAL_LOCK
+#undef  ferret_dplist_local_lock_t
+
+#undef  PREFIX
+#define PREFIX(a) ferret_dplist_ ## a
diff --git a/l4/pkg/ferret/include/sensors/__llist.h b/l4/pkg/ferret/include/sensors/__llist.h
new file mode 100644 (file)
index 0000000..4b0987b
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ * \file   ferret/include/sensors/__llist.h
+ * \brief  Functions to operate on event locked lists.
+ *
+ * \date   2007-05-16
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#if FERRET_LLIST_MAGIC != ahK6eeNa
+#error Do not directly include this file, use a propper wrapper!
+#endif
+#undef FERRET_LLIST_MAGIC
+
+#include <l4/sys/compiler.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/common.h>
+
+#include <l4/ferret/sensors/list.h>  // we reuse some types
+#include <l4/ferret/sensors/llist.h>
+
+// reorder members such that commonly used ones are in one cacheline
+typedef struct
+{
+    ferret_common_t      header;
+    ferret_llist_index_t head;            // seq. # of el. to be written next
+    uint32_t             count;           // max. # of el. (power of 2)
+    //uint32_t             count_ld;        // ld of count
+    uint32_t             count_mask;      // bitmask for count
+    uint32_t             element_size;    // size of one element
+    uint32_t             element_size_ld; // ld of size of one element
+#ifdef FERRET_LLIST_HAVE_LOCK
+    PREFIX(lock_t)       lock;            // global part of the lock
+#endif
+    uint32_t             flags;
+    // data container, align to probable cache line size
+    uint8_t data[0] __attribute__ ((aligned (FERRET_ASSUMED_CACHE_LINE_SIZE)));
+} PREFIX(t);
diff --git a/l4/pkg/ferret/include/sensors/__llist_consumer.h b/l4/pkg/ferret/include/sensors/__llist_consumer.h
new file mode 100644 (file)
index 0000000..2b8485a
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * \file   ferret/include/sensors/__llist_consumer.h
+ * \brief  locked list consumer functions.
+ *
+ * \date   2007-05-16
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#if FERRET_LLIST_MAGIC != ahK6eeNa
+#error Do not directly include this file, use a propper wrapper!
+#endif
+#undef FERRET_LLIST_MAGIC
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+/* Consumer local part of the data structure.  Allocated and
+ * initialized locally.
+ */
+typedef struct
+{
+    ferret_common_t        header;    // copy of the header, all
+                                      // sensors should start with
+                                      // same header
+    ferret_llist_index_t   next_read; // event to read next
+    uint64_t               lost;      // number of events lost so far
+    PREFIX(t)            * glob;      // pointer to globally shared area
+    char                 * out_buf;   // pointer to output element buffer
+#ifdef FERRET_LLIST_HAVE_LOCAL_LOCK
+    PREFIX(local_lock_t)   llock;     // address space specific part of the lock
+#endif
+} PREFIX(moni_t);
+
+/**
+ * @brief 
+ *
+ * @param  list locked list sensor to get elements from
+ * @param  el   pointer to memory area to copy retrieved element to
+ *
+ * @return - = 0 ok
+ *         - < 0 errorcode
+ */
+int PREFIX(get)(PREFIX(moni_t) * list, ferret_list_entry_t * el);
+
+/**
+ * @brief Setup local struct for sensor
+ *
+ * @param  addr pointer pointer to global memory area
+ * @retval addr pointer to new local area
+ */
+void PREFIX(init_consumer)(void ** addr);
+
+/**
+ * @brief De-allocate locale memory area
+ *
+ * @param addr  pointer pointer to local memory area
+ * @retval addr pointer to global memory
+ */
+void PREFIX(free_consumer)(void ** addr);
+
+EXTERN_C_END
diff --git a/l4/pkg/ferret/include/sensors/__llist_init.h b/l4/pkg/ferret/include/sensors/__llist_init.h
new file mode 100644 (file)
index 0000000..eccfe7b
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * \file   ferret/include/sensors/__llist_init.h
+ * \brief  locked list init functions.
+ *
+ * \date   2007-05-16
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#if FERRET_LLIST_MAGIC != ahK6eeNa
+#error Do not directly include this file, use a propper wrapper!
+#endif
+#undef FERRET_LLIST_MAGIC
+
+#include <l4/ferret/types.h>
+//#include <l4/ferret/sensors/llist.h>
+#include <l4/ferret/sensors/common.h>
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+int     PREFIX(init)       (PREFIX(t) * list, const char * config,
+                            char ** data);
+ssize_t PREFIX(size_config)(const char * config);
+ssize_t PREFIX(size)       (const PREFIX(t) * list);
+
+EXTERN_C_END
diff --git a/l4/pkg/ferret/include/sensors/__llist_producer.h b/l4/pkg/ferret/include/sensors/__llist_producer.h
new file mode 100644 (file)
index 0000000..b7e964b
--- /dev/null
@@ -0,0 +1,268 @@
+/**
+ * \file   ferret/include/sensors/__llist_producer.h
+ * \brief  locked list producer functions.
+ *
+ * \date   2007-05-16
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#if FERRET_LLIST_MAGIC != ahK6eeNa
+#error Do not directly include this file, use a propper wrapper!
+#endif
+#undef FERRET_LLIST_MAGIC
+
+#include <l4/sys/compiler.h>
+#include <l4/sys/ipc.h>
+
+EXTERN_C_BEGIN
+
+/**********************************************************************
+ * Declarations
+ **********************************************************************/
+
+/**********************************************************************
+ * Basic event poster functions
+ **********************************************************************/
+
+#define FERRET_POST_sig(a, b...)                                          \
+L4_INLINE void                                                            \
+PREFIX(post##a)(PREFIX(t) * l, uint16_t maj, uint16_t min,                \
+                uint16_t instance, b)
+
+L4_INLINE void
+PREFIX(post)(PREFIX(t) * l, uint16_t maj, uint16_t min, uint16_t instance);
+
+FERRET_POST_sig(_1w, uint32_t d0);
+FERRET_POST_sig(_2w, uint32_t d0, uint32_t d1);
+FERRET_POST_sig(_3w, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sig(_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3);
+
+FERRET_POST_sig(_1t,   l4_threadid_t t);
+FERRET_POST_sig(_1t1w, l4_threadid_t t, uint32_t d0);
+FERRET_POST_sig(_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1);
+FERRET_POST_sig(_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sig(_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                uint32_t d3);
+
+/**********************************************************************
+ * Experimental stuff
+ **********************************************************************/
+
+#define FERRET_POSTX_sig(a, b...)                                         \
+L4_INLINE void                                                            \
+PREFIX(postX##a)(PREFIX(t) * l, uint32_t maj_min,                         \
+                 uint16_t instance, b)
+
+FERRET_POSTX_sig(_2w, uint32_t d0, uint32_t d1);
+
+
+/**********************************************************************
+ * Conditional macros: here you can dynamically activate / deactivate
+ * logging
+ **********************************************************************/
+
+#define FERRET_POST_sigc(n, b...)                                         \
+    L4_INLINE void PREFIX(post##n##c)(int a, PREFIX(t) * l, uint16_t maj, \
+                                      uint16_t min, uint16_t instance,    \
+                                      b)
+
+L4_INLINE void PREFIX(post_c)(int a, PREFIX(t) * l, uint16_t maj, 
+                              uint16_t min, uint16_t instance);
+FERRET_POST_sigc(_1w, uint32_t d0);
+FERRET_POST_sigc(_2w, uint32_t d0, uint32_t d1);
+FERRET_POST_sigc(_3w, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sigc(_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3);
+
+FERRET_POST_sigc(_1t1w, l4_threadid_t t, uint32_t d0);
+FERRET_POST_sigc(_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1);
+FERRET_POST_sigc(_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sigc(_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                 uint32_t d3);
+
+/**********************************************************************
+ * Implementations
+ **********************************************************************/
+
+#include <l4/util/atomic.h>
+#include <l4/util/rdtsc.h>
+
+#define FERRET_POST_begin                                                 \
+{                                                                         \
+    uint32_t index;                                                       \
+    ferret_list_entry_common_t * elc;                                     \
+                                                                          \
+    FERRET_LLIST_LOCK(l);                                                 \
+    index = l->head.value & l->count_mask;                                \
+    elc = (ferret_list_entry_common_t*)                                   \
+        (l->data + (index << l->element_size_ld));                        \
+    elc->timestamp = l4_rdtsc();                                          \
+    elc->major     = maj;                                                 \
+    elc->minor     = min;                                                 \
+    elc->instance  = instance;                                            \
+    elc->cpu       = 0;  // fixme
+
+#define FERRET_POSTX_begin                                                 \
+{                                                                         \
+    uint32_t index;                                                       \
+    ferret_list_entry_common_t * elc;                                     \
+                                                                          \
+    FERRET_LLIST_LOCK(l);                                                 \
+    index = l->head.value & l->count_mask;                                \
+    elc = (ferret_list_entry_common_t*)                                   \
+        (l->data + (index << l->element_size_ld));                        \
+    elc->timestamp = l4_rdtsc();                                          \
+    elc->maj_min   = maj_min;                                             \
+    elc->instance  = instance;                                            \
+    elc->cpu       = 0;  // fixme
+
+#define FERRET_POST_end                                                   \
+    l->head.value++;                                                      \
+    FERRET_LLIST_UNLOCK(l);                                               \
+}
+
+#define FERRET_POST_assign_1w(o)                                          \
+    elc->data32[0 + (o)] = d0;
+
+#define FERRET_POST_assign_2w(o)                                          \
+    elc->data32[0 + (o)] = d0;                                            \
+    elc->data32[1 + (o)] = d1;
+
+#define FERRET_POST_assign_3w(o)                                          \
+    elc->data32[0 + (o)] = d0;                                            \
+    elc->data32[1 + (o)] = d1;                                            \
+    elc->data32[2 + (o)] = d2;
+
+#define FERRET_POST_assign_4w(o)                                          \
+    elc->data32[0 + (o)] = d0;                                            \
+    elc->data32[1 + (o)] = d1;                                            \
+    elc->data32[2 + (o)] = d2;                                            \
+    elc->data32[3 + (o)] = d3;
+
+#define FERRET_POST_assign_1t                                             \
+    elc->data64[0] = t.raw;
+
+
+L4_INLINE void
+PREFIX(post)(PREFIX(t) * l, uint16_t maj, uint16_t min, uint16_t instance)
+FERRET_POST_begin
+FERRET_POST_end
+
+FERRET_POST_sig(_1w, uint32_t d0)
+FERRET_POST_begin
+FERRET_POST_assign_1w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_2w, uint32_t d0, uint32_t d1)
+FERRET_POST_begin
+FERRET_POST_assign_2w(0)
+FERRET_POST_end
+
+FERRET_POSTX_sig(_2w, uint32_t d0, uint32_t d1)
+FERRET_POSTX_begin
+FERRET_POST_assign_2w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_3w, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_begin
+FERRET_POST_assign_3w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3)
+FERRET_POST_begin
+FERRET_POST_assign_4w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t, l4_threadid_t t)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_end
+
+FERRET_POST_sig(_1t1w, l4_threadid_t t, uint32_t d0)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_1w(1)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_2w(1)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_3w(1)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                uint32_t d3)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_4w(1)
+FERRET_POST_end
+
+#define FERRET_POST_bodyc(n, b...)                                        \
+    {                                                                     \
+        if (a)                                                            \
+        {                                                                 \
+            PREFIX(post##n)(l, maj, min, instance, b);                    \
+        }                                                                 \
+    }
+
+L4_INLINE void PREFIX(post_c)(int a, PREFIX(t) * l, uint16_t maj, 
+                              uint16_t min, uint16_t instance)
+{
+    if (a)
+    {
+        PREFIX(post)(l, maj, min, instance);
+    }
+}
+
+FERRET_POST_sigc (_1w, uint32_t d0)
+FERRET_POST_bodyc(_1w, d0)
+
+FERRET_POST_sigc (_2w, uint32_t d0, uint32_t d1)
+FERRET_POST_bodyc(_2w, d0, d1)
+
+FERRET_POST_sigc (_3w, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_bodyc(_3w, d0, d1, d2)
+
+FERRET_POST_sigc (_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3)
+FERRET_POST_bodyc(_4w, d0, d1, d2, d3)
+
+FERRET_POST_sigc (_1t1w, l4_threadid_t t, uint32_t d0)
+FERRET_POST_bodyc(_1t1w, t, d0)
+
+FERRET_POST_sigc (_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1)
+FERRET_POST_bodyc(_1t2w, t, d0, d1)
+
+FERRET_POST_sigc (_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_bodyc(_1t3w, t, d0, d1, d2)
+
+FERRET_POST_sigc (_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                  uint32_t d3)
+FERRET_POST_bodyc(_1t4w, t, d0, d1, d2, d3)
+
+
+// cleanup namespace
+#undef FERRET_POST_sig
+#undef FERRET_POSTX_sig
+#undef FERRET_POST_sigc
+#undef FERRET_POST_begin
+#undef FERRET_POSTX_begin
+#undef FERRET_POST_end
+#undef FERRET_POST_assign_1w
+#undef FERRET_POST_assign_2w
+#undef FERRET_POSTX_assign_2w
+#undef FERRET_POST_assign_3w
+#undef FERRET_POST_assign_4w
+#undef FERRET_POST_assign_1t
+#undef FERRET_POST_bodyc
+
+EXTERN_C_END
diff --git a/l4/pkg/ferret/include/sensors/__llist_producer_local.h b/l4/pkg/ferret/include/sensors/__llist_producer_local.h
new file mode 100644 (file)
index 0000000..977f074
--- /dev/null
@@ -0,0 +1,301 @@
+/**
+ * \file   ferret/include/sensors/__llist_producer_local.h
+ * \brief  locked list producer functions with producer-local part.
+ *
+ * \date   2007-06-19
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#if FERRET_LLIST_MAGIC != ahK6eeNa
+#error Do not directly include this file, use a propper wrapper!
+#endif
+#undef FERRET_LLIST_MAGIC
+
+#include <l4/sys/compiler.h>
+#include <l4/sys/ipc.h>
+
+EXTERN_C_BEGIN
+
+/**********************************************************************
+ * Declarations
+ **********************************************************************/
+
+/* Producer local part of the data structure.  Allocated and
+ * initialized locally.
+ */
+typedef struct
+{
+    ferret_common_t       header;    // copy of the header, all
+                                     // sensors should start with
+                                     // same header
+    PREFIX(t)           * glob;      // pointer to globally shared area
+#ifdef FERRET_LLIST_HAVE_LOCAL_LOCK
+    PREFIX(local_lock_t)  llock;     // address space specific part of the lock
+#endif
+} PREFIX(local_t);
+
+/**********************************************************************
+ * Basic event poster functions
+ **********************************************************************/
+
+#define FERRET_POST_sig(a, b...)                                          \
+L4_INLINE void                                                            \
+PREFIX(post##a)(PREFIX(local_t) * l, uint16_t maj, uint16_t min,          \
+                uint16_t instance, b)
+
+L4_INLINE void
+PREFIX(post)(PREFIX(local_t) * l, uint16_t maj, uint16_t min,
+             uint16_t instance);
+
+FERRET_POST_sig(_1w, uint32_t d0);
+FERRET_POST_sig(_2w, uint32_t d0, uint32_t d1);
+FERRET_POST_sig(_3w, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sig(_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3);
+
+FERRET_POST_sig(_1t,   l4_threadid_t t);
+FERRET_POST_sig(_1t1w, l4_threadid_t t, uint32_t d0);
+FERRET_POST_sig(_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1);
+FERRET_POST_sig(_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sig(_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                uint32_t d3);
+
+/**********************************************************************
+ * Experimental stuff
+ **********************************************************************/
+
+#define FERRET_POSTX_sig(a, b...)                                         \
+L4_INLINE void                                                            \
+PREFIX(postX##a)(PREFIX(local_t) * l, uint32_t maj_min,                   \
+                uint16_t instance, b)
+
+FERRET_POSTX_sig(_2w, uint32_t d0, uint32_t d1);
+
+/**********************************************************************
+ * Conditional macros: here you can dynamically activate / deactivate
+ * logging
+ **********************************************************************/
+
+#define FERRET_POST_sigc(n, b...)                                         \
+    L4_INLINE void PREFIX(post##n##c)(int a, PREFIX(local_t) * l,         \
+                                      uint16_t maj, uint16_t min,         \
+                                      uint16_t instance, b)
+
+L4_INLINE void PREFIX(post_c)(int a, PREFIX(local_t) * l, uint16_t maj,
+                              uint16_t min, uint16_t instance);
+FERRET_POST_sigc(_1w, uint32_t d0);
+FERRET_POST_sigc(_2w, uint32_t d0, uint32_t d1);
+FERRET_POST_sigc(_3w, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sigc(_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3);
+
+FERRET_POST_sigc(_1t1w, l4_threadid_t t, uint32_t d0);
+FERRET_POST_sigc(_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1);
+FERRET_POST_sigc(_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sigc(_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                 uint32_t d3);
+
+/**
+ * @brief Setup local struct for sensor
+ *
+ * @param  addr  pointer pointer to global memory area
+ * @param  alloc function pointer to memory allocating function
+ * @retval addr  pointer to new local area
+ */
+void PREFIX(init_producer)(void ** addr, void *(*alloc)(size_t size));
+
+/**
+ * @brief De-allocate local memory area
+ *
+ * @param  addr pointer pointer to local memory area
+ * @param  free function pointer to memory freeing function
+ * @retval addr pointer to referenced global memory
+ */
+void PREFIX(free_producer)(void ** addr, void (*free)(void *));
+
+/**********************************************************************
+ * Implementations
+ **********************************************************************/
+
+#include <l4/util/atomic.h>
+#include <l4/util/rdtsc.h>
+
+#define FERRET_POST_begin                                                 \
+{                                                                         \
+    uint32_t index;                                                       \
+    ferret_list_entry_common_t * elc;                                     \
+                                                                          \
+    FERRET_LLIST_LOCAL_LOCK(l);                                           \
+    index = l->glob->head.value & l->glob->count_mask;                    \
+    elc = (ferret_list_entry_common_t*)                                   \
+        (l->glob->data + (index << l->glob->element_size_ld));            \
+    elc->timestamp = l4_rdtsc();                                          \
+    elc->major     = maj;                                                 \
+    elc->minor     = min;                                                 \
+    elc->instance  = instance;                                            \
+    elc->cpu       = 0;  // fixme
+
+#define FERRET_POSTX_begin                                                \
+{                                                                         \
+    uint32_t index;                                                       \
+    ferret_list_entry_common_t * elc;                                     \
+                                                                          \
+    FERRET_LLIST_LOCAL_LOCK(l);                                           \
+    index = l->glob->head.value & l->glob->count_mask;                    \
+    elc = (ferret_list_entry_common_t*)                                   \
+        (l->glob->data + (index << l->glob->element_size_ld));            \
+    elc->timestamp = l4_rdtsc();                                          \
+    elc->maj_min   = maj_min;                                             \
+    elc->instance  = instance;                                            \
+    elc->cpu       = 0;  // fixme
+
+#define FERRET_POST_end                                                   \
+    l->glob->head.value++;                                                \
+    FERRET_LLIST_LOCAL_UNLOCK(l);                                         \
+}
+
+#define FERRET_POST_assign_1w(o)                                          \
+    elc->data32[0 + (o)] = d0;
+
+#define FERRET_POST_assign_2w(o)                                          \
+    elc->data32[0 + (o)] = d0;                                            \
+    elc->data32[1 + (o)] = d1;
+
+#define FERRET_POST_assign_3w(o)                                          \
+    elc->data32[0 + (o)] = d0;                                            \
+    elc->data32[1 + (o)] = d1;                                            \
+    elc->data32[2 + (o)] = d2;
+
+#define FERRET_POST_assign_4w(o)                                          \
+    elc->data32[0 + (o)] = d0;                                            \
+    elc->data32[1 + (o)] = d1;                                            \
+    elc->data32[2 + (o)] = d2;                                            \
+    elc->data32[3 + (o)] = d3;
+
+#define FERRET_POST_assign_1t                                             \
+    elc->data64[0] = t.raw;
+
+
+L4_INLINE void
+PREFIX(post)(PREFIX(local_t) * l, uint16_t maj, uint16_t min,
+             uint16_t instance)
+FERRET_POST_begin
+FERRET_POST_end
+
+FERRET_POST_sig(_1w, uint32_t d0)
+FERRET_POST_begin
+FERRET_POST_assign_1w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_2w, uint32_t d0, uint32_t d1)
+FERRET_POST_begin
+FERRET_POST_assign_2w(0)
+FERRET_POST_end
+
+FERRET_POSTX_sig(_2w, uint32_t d0, uint32_t d1)
+FERRET_POSTX_begin
+FERRET_POST_assign_2w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_3w, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_begin
+FERRET_POST_assign_3w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3)
+FERRET_POST_begin
+FERRET_POST_assign_4w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t, l4_threadid_t t)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_end
+
+FERRET_POST_sig(_1t1w, l4_threadid_t t, uint32_t d0)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_1w(1)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_2w(1)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_3w(1)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                uint32_t d3)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_4w(1)
+FERRET_POST_end
+
+#define FERRET_POST_bodyc(n, b...)                                        \
+    {                                                                     \
+        if (a)                                                            \
+        {                                                                 \
+            PREFIX(post##n)(l, maj, min, instance, b);                    \
+        }                                                                 \
+    }
+
+L4_INLINE void PREFIX(post_c)(int a, PREFIX(local_t) * l, uint16_t maj, 
+                              uint16_t min, uint16_t instance)
+{
+    if (a)
+    {
+        PREFIX(post)(l, maj, min, instance);
+    }
+}
+
+FERRET_POST_sigc (_1w, uint32_t d0)
+FERRET_POST_bodyc(_1w, d0)
+
+FERRET_POST_sigc (_2w, uint32_t d0, uint32_t d1)
+FERRET_POST_bodyc(_2w, d0, d1)
+
+FERRET_POST_sigc (_3w, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_bodyc(_3w, d0, d1, d2)
+
+FERRET_POST_sigc (_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3)
+FERRET_POST_bodyc(_4w, d0, d1, d2, d3)
+
+FERRET_POST_sigc (_1t1w, l4_threadid_t t, uint32_t d0)
+FERRET_POST_bodyc(_1t1w, t, d0)
+
+FERRET_POST_sigc (_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1)
+FERRET_POST_bodyc(_1t2w, t, d0, d1)
+
+FERRET_POST_sigc (_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_bodyc(_1t3w, t, d0, d1, d2)
+
+FERRET_POST_sigc (_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                  uint32_t d3)
+FERRET_POST_bodyc(_1t4w, t, d0, d1, d2, d3)
+
+
+// cleanup namespace
+#undef FERRET_POST_sig
+#undef FERRET_POST_sigc
+#undef FERRET_POSTX_sig
+#undef FERRET_POST_begin
+#undef FERRET_POSTX_begin
+#undef FERRET_POST_end
+#undef FERRET_POST_assign_1w
+#undef FERRET_POST_assign_2w
+#undef FERRET_POSTX_assign_2w
+#undef FERRET_POST_assign_3w
+#undef FERRET_POST_assign_4w
+#undef FERRET_POST_assign_1t
+#undef FERRET_POST_bodyc
+
+EXTERN_C_END
diff --git a/l4/pkg/ferret/include/sensors/__slist_magic.h b/l4/pkg/ferret/include/sensors/__slist_magic.h
new file mode 100644 (file)
index 0000000..b53f99b
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * \file   ferret/include/sensors/__slist_magic.h
+ * \brief  Template magic for L4Env Semaphore lists
+ *
+ * \date   2007-06-13
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#undef  FERRET_LLIST_LOCK
+#undef  FERRET_LLIST_UNLOCK
+#undef  FERRET_LLIST_LOCAL_LOCK
+#undef  FERRET_LLIST_LOCAL_UNLOCK
+#undef  FERRET_LLIST_INIT
+#undef  FERRET_LLIST_DEINIT
+
+#define FERRET_LLIST_LOCK(l)         l4semaphore_down(&((l)->lock))
+#define FERRET_LLIST_UNLOCK(l)       l4semaphore_up(&((l)->lock))
+#define FERRET_LLIST_LOCAL_LOCK(l)   l4semaphore_down(&((l)->glob->lock))
+#define FERRET_LLIST_LOCAL_UNLOCK(l) l4semaphore_up(&((l)->glob->lock))
+#define FERRET_LLIST_INIT(l, d)      (l)->lock = L4SEMAPHORE_INIT(1)
+#define FERRET_LLIST_DEINIT(l, d)
+
+#undef  FERRET_LLIST_HAVE_LOCK
+#undef  ferret_slist_lock_t
+#undef  FERRET_LLIST_HAVE_LOCAL_LOCK
+#undef  ferret_slist_local_lock_t
+
+#define FERRET_LLIST_HAVE_LOCK
+#define ferret_slist_lock_t       l4semaphore_t
+
+#undef  PREFIX
+#define PREFIX(a) ferret_slist_ ## a
diff --git a/l4/pkg/ferret/include/sensors/__ulist_magic.h b/l4/pkg/ferret/include/sensors/__ulist_magic.h
new file mode 100644 (file)
index 0000000..16e8665
--- /dev/null
@@ -0,0 +1,72 @@
+/**
+ * \file   ferret/include/sensors/__ulist_magic.h
+ * \brief  Template magic for Fiasco's user semaphore lists
+ *
+ * \date   2007-06-15
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/sys/user_locks.h>
+
+#undef  FERRET_LLIST_LOCK
+#undef  FERRET_LLIST_UNLOCK
+#undef  FERRET_LLIST_LOCAL_LOCK
+#undef  FERRET_LLIST_LOCAL_UNLOCK
+#undef  FERRET_LLIST_INIT
+#undef  FERRET_LLIST_DEINIT
+
+#define FERRET_LLIST_LOCAL_LOCK(l)                                            \
+    l4_usem_down((l)->llock, &((l)->glob->lock));
+#define FERRET_LLIST_LOCAL_UNLOCK(l)                                          \
+    l4_usem_up((l)->llock, &((l)->glob->lock));
+// fixme: this should be the global init part
+#define FERRET_LLIST_INIT(l, d)                                               \
+    do                                                                        \
+    {                                                                         \
+        int _sem = ferret_local_names_reserve();                              \
+        if (_sem == 0)                                                        \
+        {                                                                     \
+            enter_kdebug("PANIC, out of local names for kernel semaphores");  \
+        }                                                                     \
+        l4_usem_new(_sem, 1, &((l)->lock));                                   \
+        *d = (char *)_sem;                                                    \
+    } while (0)
+#define FERRET_LLIST_DEINIT(l, d)
+
+#define FERRET_LLIST_LOCAL_INIT(l)                                            \
+    do                                                                        \
+    {                                                                         \
+        int ksem, ret;                                                        \
+        ksem = ferret_local_names_reserve();                                  \
+        if (ksem == 0)                                                        \
+        {                                                                     \
+            Panic("Could not get local ksem entry!");                         \
+        }                                                                     \
+        ret = ferret_fpages_request(ksem, (l)->header.major,                  \
+                                    (l)->header.minor,                        \
+                                    (l)->header.instance);                    \
+        if (ret != 0)                                                         \
+        {                                                                     \
+            Panic("fpages call failed!");                                     \
+        }                                                                     \
+        (l)->llock = ksem;                                                    \
+    } while (0)
+
+#undef  FERRET_LLIST_HAVE_LOCK
+#undef  ferret_ulist_lock_t
+#undef  FERRET_LLIST_HAVE_LOCAL_LOCK
+#undef  ferret_ulist_local_lock_t
+
+#define FERRET_LLIST_HAVE_LOCK
+#define ferret_ulist_lock_t          l4_u_semaphore_t
+
+#define FERRET_LLIST_HAVE_LOCAL_LOCK
+#define ferret_ulist_local_lock_t    unsigned long
+
+#undef  PREFIX
+#define PREFIX(prefix) ferret_ulist_ ## prefix
diff --git a/l4/pkg/ferret/include/sensors/alist.h b/l4/pkg/ferret/include/sensors/alist.h
new file mode 100644 (file)
index 0000000..587c81e
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * \file   ferret/include/sensors/alist.h
+ * \brief  Functions to operate on atomic event lists.
+ *
+ * \date   2007-07-23
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_ALIST_H_
+#define __FERRET_INCLUDE_SENSORS_ALIST_H_
+
+#include <l4/sys/compiler.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/common.h>
+
+
+#define FERRET_ALIST_ELEMENT_SIZE    64
+#define FERRET_ALIST_ELEMENT_SIZE_LD 6
+
+#define FERRET_ASSUMED_CACHE_LINE_SIZE 64
+
+#define FERRET_ALIST_MAX_COUNT   16*1024*1024  // arbitrary, but large limit
+
+#include <l4/ferret/sensors/list.h>  // reuse some types
+
+typedef struct
+{
+    ferret_common_t header;
+
+    uint32_t head;
+    uint32_t count;          // max. number of elements
+    uint32_t count_ld;       // log_2(number of elements)
+    uint32_t count_mask;     // (2 << count_ld) - 1
+    uint32_t flags;
+    // data container, align to probable cache line size
+    ferret_list_entry_common_t data[0]
+      __attribute__ ((aligned (FERRET_ASSUMED_CACHE_LINE_SIZE)));
+} ferret_alist_t;
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/alist_consumer.h b/l4/pkg/ferret/include/sensors/alist_consumer.h
new file mode 100644 (file)
index 0000000..bea4613
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * \file   ferret/include/sensors/alist_consumer.h
+ * \brief  Atomic list consumer functions.
+ *
+ * \date   2007-09-27
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_ALIST_CONSUMER_H_
+#define __FERRET_INCLUDE_SENSORS_ALIST_CONSUMER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/alist.h>
+
+EXTERN_C_BEGIN
+
+/* Consumer local part of the data structure.  Allocated and
+ * initialized locally.
+ */
+typedef struct
+{
+    ferret_common_t              header;    // copy of the header, all
+                                            // sensors should start with
+                                            // same header
+    uint32_t                     next_read; // event to read next
+    uint64_t                     lost;      // number of events lost so far
+    ferret_alist_t             * glob;      // pointer to globally shared area
+    ferret_list_entry_common_t * data;      // pointer to element buffer
+} ferret_alist_moni_t;
+
+/**
+ * @brief 
+ *
+ * @param  list list sensor to get elements from
+ * @param  el   pointer to memory area to copy retrieved element to
+ *
+ * @return - = 0 ok
+ *         - < 0 errorcode
+ */
+int ferret_alist_get(ferret_alist_moni_t * list, ferret_list_entry_t * el);
+
+/**
+ * @brief Setup local struct for sensor
+ *
+ * @param  addr pointer pointer to global memory area
+ * @retval addr pointer to new local area
+ */
+void ferret_alist_init_consumer(void ** addr);
+
+/**
+ * @brief De-allocate locale memory area
+ *
+ * @param addr  pointer pointer to local memory area
+ * @retval addr pointer to global memory
+ */
+void ferret_alist_free_consumer(void ** addr);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/alist_init.h b/l4/pkg/ferret/include/sensors/alist_init.h
new file mode 100644 (file)
index 0000000..5156422
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * \file   ferret/include/sensors/alist_init.h
+ * \brief  Atomic list init functions.
+ *
+ * \date   2007-07-23
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_ALIST_INIT_H_
+#define __FERRET_INCLUDE_SENSORS_ALIST_INIT_H_
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/alist.h>
+#include <l4/ferret/sensors/common.h>
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+int ferret_alist_init(ferret_alist_t * list, const char * config);
+
+ssize_t ferret_alist_size_config(const char * config);
+
+ssize_t ferret_alist_size(const ferret_alist_t * list);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/alist_producer.h b/l4/pkg/ferret/include/sensors/alist_producer.h
new file mode 100644 (file)
index 0000000..96cbd74
--- /dev/null
@@ -0,0 +1,165 @@
+/**
+ * \file   ferret/include/sensors/alist_producer.h
+ * \brief  Atomic list producer functions.
+ *
+ * \date   2007-07-23
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_ALIST_PRODUCER_H_
+#define __FERRET_INCLUDE_SENSORS_ALIST_PRODUCER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/alist.h>
+
+EXTERN_C_BEGIN
+
+/**********************************************************************
+ * Declarations
+ **********************************************************************/
+
+L4_INLINE void
+ferret_alist_post(ferret_alist_t * l, uint16_t maj, uint16_t min,
+                  uint16_t instance);
+
+L4_INLINE void
+ferret_alist_post_2w(ferret_alist_t * l, uint16_t maj, uint16_t min,
+                     uint16_t instance, uint32_t d0, uint32_t d1);
+
+L4_INLINE void
+ferret_alist_postX_2w(ferret_alist_t * l, uint32_t maj_min,
+                      uint16_t instance, uint32_t d0, uint32_t d1);
+
+
+/**********************************************************************
+ * Implementations
+ **********************************************************************/
+
+#include <l4/util/atomic.h>
+#include <l4/util/rdtsc.h>
+
+//#define KERN_LIB_PAGE_APOST 0xef7ff000
+//#define KERN_LIB_PAGE_APOST __ferret_alist_post.bak
+
+L4_INLINE void
+ferret_alist_post(ferret_alist_t * l, uint16_t maj, uint16_t min,
+                  uint16_t instance)
+{
+    ferret_list_entry_common_t e;
+
+    e.major     = maj;
+    e.minor     = min;
+    e.instance  = instance;
+
+    asm volatile (
+        "cld                              \n\t"
+        "push %%ecx                       \n\t"
+        "push %%esi                       \n\t"
+        "push %%eax                       \n\t"
+//        "call " L4_stringify(KERN_LIB_PAGE_APOST) "-1f+4   \n\t"
+//        "1:                               \n\t"
+        "call __ferret_alist_post         \n\t"
+        "add  $0xc, %%esp                 \n\t"
+        :
+        : "S"((&(e.timestamp)) + 1), "a"(l), "c"(2)
+        : "memory", "edi", "ebx", "edx", "cc"
+        );
+}
+
+L4_INLINE void
+ferret_alist_post_2w(ferret_alist_t * l, uint16_t maj, uint16_t min,
+                     uint16_t instance, uint32_t d0, uint32_t d1)
+{
+    ferret_list_entry_common_t e;
+
+    e.major     = maj;
+    e.minor     = min;
+    e.instance  = instance;
+    e.data32[0] = d0;
+    e.data32[1] = d1;
+
+    asm volatile (
+        "cld                              \n\t"
+        "push %%ecx                       \n\t"
+        "push %%esi                       \n\t"
+        "push %%eax                       \n\t"
+        "call __ferret_alist_post         \n\t"
+        "add  $0xc, %%esp                 \n\t"
+        :
+        : "S"((&(e.timestamp)) + 1), "a"(l), "c"(4)
+        : "memory", "edi", "ebx", "edx", "cc"
+        );
+}
+
+L4_INLINE void
+ferret_alist_postX_2w(ferret_alist_t * l, uint32_t maj_min,
+                      uint16_t instance, uint32_t d0, uint32_t d1)
+{
+    ferret_list_entry_common_t e;
+
+    e.maj_min   = maj_min;
+    e.instance  = instance;
+    e.data32[0] = d0;
+    e.data32[1] = d1;
+
+    asm volatile (
+        "cld                              \n\t"
+        "push %%ecx                       \n\t"
+        "push %%esi                       \n\t"
+        "push %%eax                       \n\t"
+        "call __ferret_alist_post         \n\t"
+        "add  $0xc, %%esp                 \n\t"
+        :
+        : "S"((&(e.timestamp)) + 1), "a"(l), "c"(4)
+        : "memory", "edi", "ebx", "edx", "cc"
+        );
+}
+
+
+/* Parameter: list pointer .................... %eax (tainted by rdtsc)
+ *            pointer to parameters to copy ... %esi (tainted by rep movsl)
+ *            word count to copy .............. %ecx (tainted by rep movsl)
+ */
+asm (
+    ".p2align(12)                            \n"
+    "__ferret_alist_post.bak:                \n"
+
+    "mov    0x4(%esp),%eax                   \n"
+    "mov    0x8(%esp),%esi                   \n"
+    "mov    0xc(%esp),%ecx                   \n"
+
+    "mov    0x1c(%eax),%ebx                  \n"  // l->count_mask
+    "mov    0x10(%eax),%edx                  \n"  // l->head
+    "and    %edx,%ebx                        \n"  // &
+    "shl    $0x6,%ebx                        \n"  // *64
+    "add    %eax,%ebx                        \n"  // l+offset
+
+    "lea    0x48(%ebx),%edi                  \n"  // dest: &l.data[offset].data
+    "rep movsl %ds:(%esi),%es:(%edi)         \n"  // memcpy
+
+    "incl   %edx                             \n"  // ++edx
+    "mov    %edx,%ecx                        \n"  // save new head
+    "lea    0x10(%eax),%esi                  \n"  // &l->head
+
+    "rdtsc                                   \n"  // get timestamp
+    "mov    %eax,0x40(%ebx)                  \n"  // l.data[offset]
+    "mov    %edx,0x44(%ebx)                  \n"
+
+    "jmp 1f                                  \n"
+
+    "1:                                      \n"
+    "mov    %ecx,(%esi)                      \n"  // save new l->head
+    // forward point
+    ".p2align(6)                             \n"
+
+    "ret                                     \n"
+    );
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/common.h b/l4/pkg/ferret/include/sensors/common.h
new file mode 100644 (file)
index 0000000..a37077f
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * \file   ferret/include/sensors/common.h
+ * \brief  Common sensor function and types
+ *
+ * \date   08/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_COMMON_H_
+#define __FERRET_INCLUDE_SENSORS_COMMON_H_
+
+#include <l4/ferret/types.h>
+
+#include <l4/sys/compiler.h>
+
+typedef struct
+{
+    uint16_t         major;
+    uint16_t         minor;
+    uint16_t         instance;
+    uint16_t         type;
+       l4_cap_idx_t     ds_cap;
+       uint32_t         ds_size;
+}  ferret_common_t;
+
+
+EXTERN_C_BEGIN
+
+void ferret_common_init(ferret_common_t * c,
+                        uint16_t major, uint16_t minor,
+                        uint16_t instance, uint16_t type,
+                        l4re_ds_t *dataspace);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/dplist.h b/l4/pkg/ferret/include/sensors/dplist.h
new file mode 100644 (file)
index 0000000..deef0a3
--- /dev/null
@@ -0,0 +1,21 @@
+/**
+ * \file   ferret/include/sensors/dplist.h
+ * \brief  Functions to operate on event dplists.
+ *
+ * \date   2007-06-11
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_DPLIST_H_
+#define __FERRET_INCLUDE_SENSORS_DPLIST_H_
+
+#include <l4/ferret/sensors/__dplist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/dplist_consumer.h b/l4/pkg/ferret/include/sensors/dplist_consumer.h
new file mode 100644 (file)
index 0000000..3bd6f33
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/dplist_consumer.h
+ * \brief  delayed preemption list consumer functions.
+ *
+ * \date   2007-06-11
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_DPLIST_CONSUMER_H_
+#define __FERRET_INCLUDE_SENSORS_DPLIST_CONSUMER_H_
+
+#include <l4/ferret/sensors/dplist.h>
+
+#include <l4/ferret/sensors/__dplist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist_consumer.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/dplist_init.h b/l4/pkg/ferret/include/sensors/dplist_init.h
new file mode 100644 (file)
index 0000000..8f6dbf7
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/dplist_init.h
+ * \brief  delayed preemption list init functions.
+ *
+ * \date   2007-06-11
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_DPLIST_INIT_H_
+#define __FERRET_INCLUDE_SENSORS_DPLIST_INIT_H_
+
+#include <l4/ferret/sensors/dplist.h>
+
+#include <l4/ferret/sensors/__dplist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist_init.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/dplist_producer.h b/l4/pkg/ferret/include/sensors/dplist_producer.h
new file mode 100644 (file)
index 0000000..387304c
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/dplist_producer.h
+ * \brief  delayed preemption list producer functions.
+ *
+ * \date   2007-06-11
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_DPLIST_PRODUCER_H_
+#define __FERRET_INCLUDE_SENSORS_DPLIST_PRODUCER_H_
+
+#include <l4/ferret/sensors/dplist.h>
+
+#include <l4/ferret/sensors/__dplist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist_producer.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/histogram.h b/l4/pkg/ferret/include/sensors/histogram.h
new file mode 100644 (file)
index 0000000..0fe1de1
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * \file   ferret/include/sensors/histogram.h
+ * \brief  Functions to operate on histograms.
+ *
+ * \date   15/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_HISTOGRAM_H_
+#define __FERRET_INCLUDE_SENSORS_HISTOGRAM_H_
+
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/types.h>
+
+typedef struct
+{
+    ferret_common_t header;
+
+    ferret_time_t   low;        // lower bound for histogram data (inclusive)
+    ferret_time_t   high;       // upper bound for histogram data (exclusive)
+
+    ferret_time_t   size;       // precomputed multiplier (high - low)
+    unsigned int    bins;       // number of bins in histogram
+    unsigned int    underflow;  // number of underflows (below low) occurred
+    unsigned int    overflow;   // number of overflows (above high) occurred
+
+    ferret_time_t   val_min;    // minimum value put in so far
+    ferret_time_t   val_max;    // maximum value put in so far
+    ferret_time_t   val_sum;    // sum of the weighted values in the histogram
+    unsigned int    val_count;  // number of values in the histogram
+} ferret_histo_header_t;
+
+typedef struct
+{
+    ferret_histo_header_t head;       // header
+    unsigned int          data[0];    // data points
+}  ferret_histo_t;
+
+typedef struct
+{
+    ferret_histo_header_t head;       // header
+    ferret_utime_t        data[0];    // data points
+} ferret_histo64_t;
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/histogram_consumer.h b/l4/pkg/ferret/include/sensors/histogram_consumer.h
new file mode 100644 (file)
index 0000000..c52dd62
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * \file   ferret/include/sensors/histogram_consumer.h
+ * \brief  Histogram consumer functions.
+ *
+ * \date   15/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_HISTOGRAM_CONSUMER_H_
+#define __FERRET_INCLUDE_SENSORS_HISTOGRAM_CONSUMER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/histogram.h>
+
+EXTERN_C_BEGIN
+
+// fixme: make really inline
+
+L4_INLINE unsigned int
+ferret_histo_get(ferret_histo_t * histo, ferret_time_t x);
+
+L4_INLINE ferret_utime_t
+ferret_histo_get64(ferret_histo64_t * histo, ferret_time_t x);
+
+void ferret_histo_dump(ferret_histo_t * histo);
+void ferret_histo_dump_smart(ferret_histo_t * histo);
+void ferret_histo64_dump(ferret_histo64_t * histo);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/histogram_init.h b/l4/pkg/ferret/include/sensors/histogram_init.h
new file mode 100644 (file)
index 0000000..9a85113
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * \file   ferret/include/sensors/histogram_init.h
+ * \brief  Histogram init functions.
+ *
+ * \date   15/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_HISTOGRAM_INIT_H_
+#define __FERRET_INCLUDE_SENSORS_HISTOGRAM_INIT_H_
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/histogram.h>
+#include <l4/ferret/sensors/common.h>
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+// giving the type here makes sense, as one generic function might be
+// able to init several types
+int ferret_histo_init(ferret_histo_t * histo, const char * config);
+int ferret_histo64_init(ferret_histo64_t * histo, const char * config);
+
+ssize_t ferret_histo_size_config(const char * config);
+ssize_t ferret_histo64_size_config(const char * config);
+
+ssize_t ferret_histo_size(const ferret_histo_t * histo);
+ssize_t ferret_histo64_size(const ferret_histo64_t * histo);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/histogram_producer.h b/l4/pkg/ferret/include/sensors/histogram_producer.h
new file mode 100644 (file)
index 0000000..e4d2112
--- /dev/null
@@ -0,0 +1,225 @@
+/**
+ * \file   ferret/include/sensors/histogram_producer.h
+ * \brief  Histogram producer functions.
+ *
+ * \date   15/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_HISTOGRAM_PRODUCER_H_
+#define __FERRET_INCLUDE_SENSORS_HISTOGRAM_PRODUCER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/histogram.h>
+
+EXTERN_C_BEGIN
+
+/**********************************************************************
+ * Declarations
+ **********************************************************************/
+
+// basic histogram functions
+L4_INLINE void ferret_histo_inc(ferret_histo_t * histo, ferret_time_t x);
+L4_INLINE void ferret_histo64_inc(ferret_histo64_t * histo, ferret_time_t x);
+L4_INLINE void ferret_histo_add(ferret_histo_t * histo, ferret_time_t x,
+                                unsigned int val);
+L4_INLINE void ferret_histo64_add(ferret_histo64_t * histo, ferret_time_t x,
+                                  ferret_utime_t val);
+
+// direct bin manipulation, i.e., use the histogram as a array
+L4_INLINE void ferret_histo_bin_inc(ferret_histo_t * histo, int bin);
+L4_INLINE void ferret_histo64_bin_inc(ferret_histo64_t * histo, int bin);
+L4_INLINE void ferret_histo_bin_add(ferret_histo_t * histo, int bin,
+                                    unsigned int val);
+L4_INLINE void ferret_histo64_bin_add(ferret_histo64_t * histo, int bin,
+                                      ferret_utime_t val);
+L4_INLINE void ferret_histo_bin_set(ferret_histo_t * histo, int bin,
+                                    unsigned int val);
+L4_INLINE void ferret_histo64_bin_set(ferret_histo64_t * histo, int bin,
+                                      ferret_utime_t val);
+
+/**********************************************************************
+ * Implementations
+ **********************************************************************/
+
+#include <l4/log/l4log.h>
+#include <l4/util/atomic.h>
+
+
+L4_INLINE void ferret_histo_inc(ferret_histo_t * histo, ferret_time_t x)
+{
+    int bin;
+
+    bin = (x - histo->head.low) * histo->head.bins / histo->head.size;
+
+    // use atomic data access, such that it can be used from several places
+    if (L4_UNLIKELY(bin < 0))
+        l4util_inc32(&histo->head.underflow);
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        l4util_inc32(&histo->head.overflow);
+    else
+        l4util_inc32(&(histo->data[bin]));
+
+    if (L4_UNLIKELY(x < histo->head.val_min))
+        histo->head.val_min = x;     // fixme: make atomic
+    if (L4_UNLIKELY(x > histo->head.val_max))
+        histo->head.val_max = x;     // fixme: make atomic
+    histo->head.val_sum += x;        // fixme: make atomic
+    l4util_inc32(&histo->head.val_count);
+}
+
+L4_INLINE void ferret_histo64_inc(ferret_histo64_t * histo, ferret_time_t x)
+{
+    int bin;
+
+    bin = (x - histo->head.low) * histo->head.bins / histo->head.size;
+
+    // FIXME: use atomic data access, such that it can be used from several places
+    //      --> will work only for 64bit machines
+    if (L4_UNLIKELY(bin < 0))
+        histo->head.underflow++;
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        histo->head.overflow++;
+    else
+        histo->data[bin]++;
+
+    if (L4_UNLIKELY(x < histo->head.val_min))
+        histo->head.val_min = x;     // fixme: make atomic
+    if (L4_UNLIKELY(x > histo->head.val_max))
+        histo->head.val_max = x;     // fixme: make atomic
+    histo->head.val_sum += x;        // fixme: make atomic
+    histo->head.val_count++;
+}
+
+L4_INLINE void ferret_histo_add(ferret_histo_t * histo,
+                                ferret_time_t x, unsigned int val)
+{
+    int bin;
+
+    bin = (x - histo->head.low) * histo->head.bins / histo->head.size;
+
+    // use atomic data access, such that it can be used from several places
+    if (L4_UNLIKELY(bin < 0))
+        l4util_add32(&histo->head.underflow, val);
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        l4util_add32(&histo->head.overflow, val);
+    else
+        l4util_add32(&(histo->data[bin]), val);
+
+    if (L4_UNLIKELY(x < histo->head.val_min))
+        histo->head.val_min = x;     // fixme: make atomic
+    if (L4_UNLIKELY(x > histo->head.val_max))
+        histo->head.val_max = x;     // fixme: make atomic
+    histo->head.val_sum += val * x;  // fixme: make atomic
+    l4util_inc32(&histo->head.val_count);
+}
+
+L4_INLINE void ferret_histo64_add(ferret_histo64_t * histo,
+                                  ferret_time_t x, ferret_utime_t val)
+{
+    int bin;
+
+    bin = (x - histo->head.low) * histo->head.bins / histo->head.size;
+
+    // FIXME: use atomic data access, such that it can be used from
+    //        several places
+    if (L4_UNLIKELY(bin < 0))
+        histo->head.underflow += val;
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        histo->head.overflow += val;
+    else
+        histo->data[bin] += val;
+
+    if (L4_UNLIKELY(x < histo->head.val_min))
+        histo->head.val_min = x;     // fixme: make atomic
+    if (L4_UNLIKELY(x > histo->head.val_max))
+        histo->head.val_max = x;     // fixme: make atomic
+    histo->head.val_sum += val * x;  // fixme: make atomic
+    histo->head.val_count++;
+}
+
+L4_INLINE void ferret_histo_bin_inc(ferret_histo_t * histo, int bin)
+{
+    // FIXME: use atomic data access, such that it can be used from
+    //        several places
+    if (L4_UNLIKELY(bin < 0))
+        l4util_inc32(&histo->head.underflow);
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        l4util_inc32(&histo->head.overflow);
+    else
+        l4util_inc32(&(histo->data[bin]));
+}
+
+L4_INLINE void ferret_histo64_bin_inc(ferret_histo64_t * histo, int bin)
+{
+    // FIXME: use atomic data access, such that it can be used from
+    //        several places
+    if (L4_UNLIKELY(bin < 0))
+        histo->head.underflow++;
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        histo->head.overflow++;
+    else
+        histo->data[bin]++;
+}
+
+L4_INLINE void ferret_histo_bin_add(ferret_histo_t * histo, int bin,
+                                    unsigned int val)
+{
+    // FIXME: use atomic data access, such that it can be used from
+    //        several places
+    if (L4_UNLIKELY(bin < 0))
+        l4util_add32(&histo->head.underflow, val);
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        l4util_add32(&histo->head.overflow, val);
+    else
+        l4util_add32(&(histo->data[bin]), val);
+}
+
+L4_INLINE void ferret_histo64_bin_add(ferret_histo64_t * histo, int bin,
+                                      ferret_utime_t val)
+{
+    // FIXME: use atomic data access, such that it can be used from
+    //        several places
+    if (L4_UNLIKELY(bin < 0))
+        histo->head.underflow += val;
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        histo->head.overflow += val;
+    else
+        histo->data[bin] += val;
+}
+
+L4_INLINE void ferret_histo_bin_set(ferret_histo_t * histo, int bin,
+                                    unsigned int val)
+{
+    // FIXME: use atomic data access, such that it can be used from
+    //        several places
+    if (L4_UNLIKELY(bin < 0))
+        histo->head.underflow = val;
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        histo->head.overflow = val;
+    else
+        histo->data[bin] = val;
+}
+
+L4_INLINE void ferret_histo64_bin_set(ferret_histo64_t * histo, int bin,
+                                      ferret_utime_t val)
+{
+    // FIXME: use atomic data access, such that it can be used from
+    //        several places
+    if (L4_UNLIKELY(bin < 0))
+        histo->head.underflow = val;
+    else if (L4_UNLIKELY(bin >= histo->head.bins))
+        histo->head.overflow = val;
+    else
+        histo->data[bin] = val;
+}
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/list.h b/l4/pkg/ferret/include/sensors/list.h
new file mode 100644 (file)
index 0000000..ace4ec2
--- /dev/null
@@ -0,0 +1,192 @@
+/**
+ * \file   ferret/include/sensors/list.h
+ * \brief  Functions to operate on event lists.
+ *
+ * \date   21/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_LIST_H_
+#define __FERRET_INCLUDE_SENSORS_LIST_H_
+
+#include <l4/sys/compiler.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/common.h>
+
+
+#define FERRET_INDEX_BITS   16
+#define FERRET_ELEMENT_BITS 48
+
+#define FERRET_ASSUMED_CACHE_LINE_SIZE 64
+
+typedef union ferret_list_index_s
+{
+    // fixme: is this really packed? (uint32 and uint64)
+    struct __attribute__ ((__packed__))
+    {
+        uint32_t index:FERRET_INDEX_BITS;
+        uint64_t element:FERRET_ELEMENT_BITS;
+    } parts;
+    low_high_t   lh;
+    uint64_t     value;
+} ferret_list_index_t;
+
+/* Merge two uint16 values (major and minor) into one single uint32 */
+#define MAJ_MIN(a, b) ((uint32_t)(((uint16_t)(b)) << 16 | ((uint16_t)(a))))
+
+// fixme: maybe I should extract the list element to external header
+//        file for easy reuse in other list implementations etc.?
+/* The common header of all list elements
+ */
+typedef struct ferret_list_entry_s
+{
+    ferret_utime_t timestamp;
+    unsigned char  data[0];
+} ferret_list_entry_t;
+
+/* A basic event type header, used for cross-component interaction.
+ * This is the common header for all events to be used with magpie
+ * tools.
+ */
+typedef struct __attribute__ ((__packed__)) ferret_list_entry_common_header_s
+{
+    ferret_utime_t timestamp;
+    union __attribute__ ((__packed__))
+    {
+        struct __attribute__ ((__packed__))
+        {
+            uint16_t major;
+            uint16_t minor;
+        };
+        uint32_t     maj_min;
+    };
+    uint16_t         instance;
+    uint8_t           cpu;
+} ferret_list_entry_common_header_t;
+
+/* A basic event type, used for cross-component interaction.
+ */
+typedef struct __attribute__ ((__packed__)) ferret_list_entry_common_s
+{
+    ferret_utime_t timestamp;
+    union __attribute__ ((__packed__))
+    {
+        struct __attribute__ ((__packed__))
+        {
+            uint16_t major;
+            uint16_t minor;
+        };
+        uint32_t     maj_min;
+    };
+    uint16_t       instance;
+    uint8_t        cpu;
+    uint8_t        _pad;
+    union
+    {
+        uint64_t   data64[6];
+        uint32_t   data32[12];
+        uint16_t   data16[24];
+        uint8_t    data8[48];
+    };
+} ferret_list_entry_common_t;
+
+/* Like ferret_list_entry_common_t, but specifies common part for all
+ * kernel events
+ */
+typedef struct __attribute__ ((__packed__)) ferret_list_entry_kernel_s
+{
+    ferret_utime_t timestamp;
+    union __attribute__ ((__packed__))
+    {
+        struct __attribute__ ((__packed__))
+        {
+            uint16_t major;
+            uint16_t minor;
+        };
+        uint32_t     maj_min;
+    };
+    uint16_t       instance;
+    uint8_t        cpu;
+    uint8_t        _pad;
+    void *         context;
+    uint32_t       eip;
+    uint32_t       pmc1;
+    uint32_t       pmc2;
+    union
+    {
+        uint64_t   data64[4];
+        uint32_t   data32[8];
+        uint16_t   data16[16];
+        uint8_t    data8[32];
+    };
+} ferret_list_entry_kernel_t;
+
+
+/* list data structures are split in to parts, a shared and a local
+ * part.  The shared part contains the list elements and common data
+ * structures, such as the head and the tail pointer.  The local parts
+ * contains address space specific information, such as pointers to
+ * the output buffer and index array.
+ */
+
+/* Shared part of the data structure.  Allocated and initialized by the
+ * sensor directory.
+ */
+typedef struct
+{
+    ferret_common_t      header;
+
+    volatile ferret_list_index_t head;
+    volatile ferret_list_index_t tail;
+    uint32_t             count;          // max. number of elements
+    uint32_t             element_size;   // size of one element
+    uint32_t             flags;
+    uint32_t             element_offset; // offset for real elements
+                                         // relative to data
+    // data container, align to probable cache line size
+    uint8_t data[0] __attribute__ ((aligned (FERRET_ASSUMED_CACHE_LINE_SIZE)));
+} ferret_list_t;
+
+#if 0
+/**
+ * @brief "entry data for index" returns pointer to data in an element
+ *        for the index given
+ *
+ * @param list  list sensor to work on
+ * @param index index of element to get
+ *
+ * @return pointer to element data
+ */
+L4_INLINE char * ferret_list_ed4i(ferret_list_t * list, int index);
+L4_INLINE char * ferret_list_ed4i(ferret_list_t * list, int index)
+{
+    return ((ferret_list_entry_t *)(list->data + list->element_offset +
+                                    index * list->element_size))->data;
+}
+#endif
+
+/**
+ * @brief "entry for index" returns the element pointer for the index
+ *        given
+ *
+ * @param list  list sensor to work on
+ * @param index index of element to get
+ *
+ * @return pointer to element
+ */
+L4_INLINE ferret_list_entry_t *
+ferret_list_e4i(ferret_list_t * list, int index);
+L4_INLINE ferret_list_entry_t *
+ferret_list_e4i(ferret_list_t * list, int index)
+{
+    return (ferret_list_entry_t *)(list->data + list->element_offset +
+                                   index * list->element_size);
+}
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/list_consumer.h b/l4/pkg/ferret/include/sensors/list_consumer.h
new file mode 100644 (file)
index 0000000..d019fc1
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * \file   ferret/include/sensors/list_consumer.h
+ * \brief  list consumer functions.
+ *
+ * \date   23/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_LIST_CONSUMER_H_
+#define __FERRET_INCLUDE_SENSORS_LIST_CONSUMER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/list.h>
+
+EXTERN_C_BEGIN
+
+/* Consumer local part of the data structure.  Allocated and
+ * initialized locally.
+ */
+typedef struct
+{
+    ferret_common_t       header;      // copy of the header, all
+                                       // sensors should start with
+                                       // same header
+    uint64_t              next_read;   // event to read next
+    uint64_t              lost;        // number of events lost so far
+    ferret_list_t       * glob;        // pointer to globally shared area
+    ferret_list_index_t * ind_buf;     // pointer to index entry buffer
+    void                * out_buf;     // pointer to output element buffer
+} ferret_list_moni_t;
+
+/**
+ * @brief 
+ *
+ * @param  list list sensor to get elements from
+ * @param  el   pointer to memory area to copy retrieved element to
+ *
+ * @return - = 0 ok
+ *         - < 0 errorcode
+ */
+int ferret_list_get(ferret_list_moni_t * list, ferret_list_entry_t * el);
+
+/**
+ * @brief Setup local struct for sensor
+ *
+ * @param  addr pointer pointer to global memory area
+ * @retval addr pointer to new local area
+ */
+void ferret_list_init_consumer(void ** addr);
+
+/**
+ * @brief De-allocate locale memory area
+ *
+ * @param addr  pointer pointer to local memory area
+ * @retval addr pointer to global memory
+ */
+void ferret_list_free_consumer(void ** addr);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/list_init.h b/l4/pkg/ferret/include/sensors/list_init.h
new file mode 100644 (file)
index 0000000..fcf903e
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * \file   ferret/include/sensors/list_init.h
+ * \brief  List init functions.
+ *
+ * \date   23/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_LIST_INIT_H_
+#define __FERRET_INCLUDE_SENSORS_LIST_INIT_H_
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/list.h>
+#include <l4/ferret/sensors/common.h>
+
+#include <l4/sys/compiler.h>
+#include <unistd.h>
+
+EXTERN_C_BEGIN
+
+// giving the type here makes sense, as one generic function might be
+// able to init several types
+int ferret_list_init(ferret_list_t * list, const char * config);
+
+ssize_t ferret_list_size_config(const char * config);
+
+ssize_t ferret_list_size(const ferret_list_t * list);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/list_producer.h b/l4/pkg/ferret/include/sensors/list_producer.h
new file mode 100644 (file)
index 0000000..1942604
--- /dev/null
@@ -0,0 +1,209 @@
+/**
+ * \file   ferret/include/sensors/list_producer.h
+ * \brief  List producer functions.
+ *
+ * \date   22/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_LIST_PRODUCER_H_
+#define __FERRET_INCLUDE_SENSORS_LIST_PRODUCER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/list.h>
+
+EXTERN_C_BEGIN
+
+/**********************************************************************
+ * Declarations
+ **********************************************************************/
+
+/* Producer local part of the data structure.  Allocated and
+ * initialized locally.
+ */
+typedef struct
+{
+    ferret_common_t       header;      // copy of the header, all
+                                       // sensors should start with
+                                       // same header
+    ferret_list_t       * glob;        // pointer to globally shared area
+    ferret_list_index_t * ind_buf;     // pointer to index entry buffer
+    void                * out_buf;     // pointer to output element buffer
+} ferret_list_local_t;
+
+/* Two interface levels:
+ *  - Low level
+ *     - dequeue element
+ *     - get element for index
+ *     - enqueue element
+ *  - High level (see list_producer_wrapper.h)
+ *     - Write an element of size n
+ */
+
+/**
+ * @brief Dequeues one element from the list sensor
+ *
+ * @param list list sensor to work on
+ *
+ * @return index to dequeued output element
+ */
+L4_INLINE int ferret_list_dequeue(ferret_list_local_t * list);
+
+/**
+ * @brief Commit an previously dequeue element back to the shared
+ *        buffer
+ *
+ * @param list list sensor to work on
+ * @param index index of the element to commit
+ */
+L4_INLINE void ferret_list_commit(ferret_list_local_t * list, int index);
+
+/**
+ * @brief Setup local struct for sensor
+ *
+ * @param  addr  pointer pointer to global memory area
+ * @param  alloc function pointer to memory allocating function
+ * @retval addr  pointer to new local area
+ */
+void ferret_list_init_producer(void ** addr, void *(*alloc)(size_t size));
+
+/**
+ * @brief De-allocate local memory area
+ *
+ * @param  addr pointer pointer to local memory area
+ * @param  free function pointer to memory freeing function
+ * @retval addr pointer to referenced global memory
+ */
+void ferret_list_free_producer(void ** addr, void (*free)(void *));
+
+
+/**********************************************************************
+ * Implementations
+ **********************************************************************/
+
+#include <l4/util/atomic.h>
+#include <l4/util/rdtsc.h>
+
+L4_INLINE int ferret_list_dequeue(ferret_list_local_t * list)
+{
+    ferret_list_index_t tail, new_tail;
+    int index;
+
+    while (1)
+    {
+        // read element counter atomically (high, low, high; with retry)
+        tail.lh.high = list->glob->tail.lh.high;
+        tail.lh.low  = list->glob->tail.lh.low;
+        if (L4_UNLIKELY(tail.lh.high != list->glob->tail.lh.high))
+            continue;
+
+        index = list->ind_buf[tail.parts.index].parts.index;
+
+///*        new_tail.value = tail.value;
+//        new_tail.parts.elements++;*/
+//        new_tail.value = tail.value + (1 << FERRET_INDEX_BITS);
+//        new_tail.lh.low++;
+
+        // fixme: what is faster?
+        // increase element counter and index
+        new_tail.value = tail.value;
+        ++(new_tail.parts.element);
+        ++(new_tail.parts.index);
+
+        // care for index wrap-around
+        if (L4_UNLIKELY(new_tail.parts.index >= list->glob->count))
+            new_tail.parts.index = 0;
+
+        // finally try to dequeue element, or start from scratch
+        if (L4_LIKELY(l4util_cmpxchg64(&list->glob->tail.value,
+                                       tail.value, new_tail.value)))
+            return index;
+    }
+}
+
+L4_INLINE void ferret_list_commit(ferret_list_local_t * list, int index)
+{
+    ferret_list_index_t head, new_head, head_index, new_head_index;
+    volatile ferret_list_index_t * head_pos;  // points to shared region
+
+    // compute the output element where index points to
+    ferret_list_entry_t * oe = (ferret_list_entry_t *)
+        (((char *)(list->out_buf)) + index * list->glob->element_size);
+
+    int ret = 0;
+
+    while (1)
+    {
+        // read element counter atomically (high, low, high; with retry)
+        head.lh.high = list->glob->head.lh.high;
+        head.lh.low  = list->glob->head.lh.low;
+        if (L4_UNLIKELY(head.lh.high != list->glob->head.lh.high))
+            continue;
+
+        // read the index element head points to
+        head_pos = &(list->ind_buf[head.parts.index]);
+        head_index.lh.high = head_pos->lh.high;
+        head_index.lh.low  = head_pos->lh.low;
+        // retry if head_index changed during read or element has been
+        // written to (its elements tag is too high, the EC read is really
+        // out-dated)
+        if (L4_UNLIKELY(head_index.lh.high != head_pos->lh.high ||
+                         head_index.parts.element > head.parts.element))
+            continue;
+
+        // If element counters are equal, then the current thread is similar
+        // to the one that failed at the first cmpxchg.  Restarting the loop
+        // would result in a dead-lock (if no other thread increases the EC).
+        // Instead, the current thread must try to increase the EC as well.
+        // If the index' EC is smaller, we can try to enqueue our OE.
+        if (L4_LIKELY(head_index.parts.element < head.parts.element))
+        {
+            // Set the timestamp to now.  This is done in the loop since we
+            // want to keep timestamps ordered.  The extra costs of rdtsc
+            // are small compared to the costs of two cmpxchg8b.
+            oe->timestamp = l4_rdtsc();
+
+            // try to exchange head_index
+
+// do we need this line ???  The value is overwritten in the next line ...
+//            new_head_index.value          = head_index.value;
+
+            new_head_index.parts.index   = index;
+            new_head_index.parts.element = head.parts.element;
+            ret = l4util_cmpxchg64(&head_pos->value, head_index.value,
+                                   new_head_index.value);
+        }
+
+        // Try to advance head.  This is always done, even if the
+        // previous cmpxchg failed, since we might need to help other writers
+        // that succeeded in exchanging head_index but got preempted
+        // before they were able to increase head.
+
+      /*new_head.value = head.value + (1 << GRTMON_OE_INDEX_INDEX_BITS);
+        new_head.lh.low++;
+      */
+        // fixme: what is faster?
+        // care for wrap-around
+        new_head.value = head.value;
+        ++(new_head.parts.element);
+        ++(new_head.parts.index);
+        if (L4_UNLIKELY(new_head.parts.index >= list->glob->count))
+            new_head.parts.index = 0;
+
+        l4util_cmpxchg64(&list->glob->head.value, head.value, new_head.value);
+        // if head_index has been exchanged we're done because someone
+        // will have increased head
+        if (ret)
+            break;
+    }
+}
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/list_producer_wrap.h b/l4/pkg/ferret/include/sensors/list_producer_wrap.h
new file mode 100644 (file)
index 0000000..1fdcd4b
--- /dev/null
@@ -0,0 +1,227 @@
+/**
+ * \file   ferret/include/sensors/list_producer_wrap.h
+ * \brief  Convenience wrapper functions for creating events
+ *
+ * \date   2006-06-13
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_LIST_PRODUCER_WRAP_H_
+#define __FERRET_INCLUDE_SENSORS_LIST_PRODUCER_WRAP_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/list.h>
+#include <l4/ferret/sensors/list_producer.h>
+
+EXTERN_C_BEGIN
+
+/**********************************************************************
+ * Declarations
+ **********************************************************************/
+
+/**********************************************************************
+ * Basic event poster functions
+ **********************************************************************/
+
+#define FERRET_POST_sig(a, b...)                                          \
+L4_INLINE void                                                            \
+ferret_list_post##a(ferret_list_local_t * l, uint16_t maj, uint16_t min,  \
+                    uint16_t instance, b)
+
+L4_INLINE void
+ferret_list_post(ferret_list_local_t * l, uint16_t maj, uint16_t min,
+                 uint16_t instance);
+
+FERRET_POST_sig(_1w, uint32_t d0);
+FERRET_POST_sig(_2w, uint32_t d0, uint32_t d1);
+FERRET_POST_sig(_3w, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sig(_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3);
+
+/* No special handling for thread IDs anymore -- there _are_ non in Re. */
+#if 0
+FERRET_POST_sig(_1t,   l4_threadid_t t);
+FERRET_POST_sig(_1t1w, l4_threadid_t t, uint32_t d0);
+FERRET_POST_sig(_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1);
+FERRET_POST_sig(_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2);
+FERRET_POST_sig(_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                uint32_t d3);
+#endif
+
+/**********************************************************************
+ * Experimental stuff
+ **********************************************************************/
+
+#define FERRET_POSTX_sig(a, b...)                                         \
+L4_INLINE void                                                            \
+ferret_list_postX##a(ferret_list_local_t * l, uint32_t maj_min,           \
+                     uint16_t instance, b)
+
+FERRET_POSTX_sig(_2w, uint32_t d0, uint32_t d1);
+
+/**********************************************************************
+ * Conditional macros: here you can dynamically activate / deactivate
+ * logging
+ **********************************************************************/
+
+#define FERRET_POST_sigc_body(n, a, b...)                                 \
+    do                                                                    \
+    {                                                                     \
+        if (a)                                                            \
+        {                                                                 \
+            ferret_list_post##n(b);                                       \
+        }                                                                 \
+    } while (0)
+
+#define ferret_list_post_c(a, b...)   FERRET_POST_sigc_body(   , a, b)
+#define ferret_list_post_1wc(a, b...) FERRET_POST_sigc_body(_1w, a, b)
+#define ferret_list_post_2wc(a, b...) FERRET_POST_sigc_body(_2w, a, b)
+#define ferret_list_post_3wc(a, b...) FERRET_POST_sigc_body(_3w, a, b)
+#define ferret_list_post_4wc(a, b...) FERRET_POST_sigc_body(_4w, a, b)
+
+#if 0
+#define ferret_list_post_1tc(a, b...)   FERRET_POST_sigc_body(_1t  , a, b)
+#define ferret_list_post_1t1wc(a, b...) FERRET_POST_sigc_body(_1t1w, a, b)
+#define ferret_list_post_1t2wc(a, b...) FERRET_POST_sigc_body(_1t2w, a, b)
+#define ferret_list_post_1t3wc(a, b...) FERRET_POST_sigc_body(_1t3w, a, b)
+#define ferret_list_post_1t4wc(a, b...) FERRET_POST_sigc_body(_1t4w, a, b)
+#endif
+
+/**********************************************************************
+ * Implementations
+ **********************************************************************/
+
+#define FERRET_POST_begin                                                 \
+{                                                                         \
+    int index;                                                            \
+    ferret_list_entry_common_t * elc;                                     \
+                                                                          \
+    index = ferret_list_dequeue(l);                                       \
+    elc = (ferret_list_entry_common_t *)ferret_list_e4i(l->glob, index);  \
+    elc->major     = maj;                                                 \
+    elc->minor     = min;                                                 \
+    elc->instance  = instance;                                            \
+    elc->cpu       = 0;  // fixme
+
+#define FERRET_POSTX_begin                                                \
+{                                                                         \
+    int index;                                                            \
+    ferret_list_entry_common_t * elc;                                     \
+                                                                          \
+    index = ferret_list_dequeue(l);                                       \
+    elc = (ferret_list_entry_common_t *)ferret_list_e4i(l->glob, index);  \
+    elc->maj_min   = maj_min;                                             \
+    elc->instance  = instance;                                            \
+    elc->cpu       = 0;  // fixme
+
+#define FERRET_POST_end                                                   \
+    ferret_list_commit(l, index);                                         \
+}
+
+#define FERRET_POST_assign_1w(o)                                          \
+    elc->data32[0 + (o)] = d0;
+
+#define FERRET_POST_assign_2w(o)                                          \
+    elc->data32[0 + (o)] = d0;                                            \
+    elc->data32[1 + (o)] = d1;
+
+#define FERRET_POST_assign_3w(o)                                          \
+    elc->data32[0 + (o)] = d0;                                            \
+    elc->data32[1 + (o)] = d1;                                            \
+    elc->data32[2 + (o)] = d2;
+
+#define FERRET_POST_assign_4w(o)                                          \
+    elc->data32[0 + (o)] = d0;                                            \
+    elc->data32[1 + (o)] = d1;                                            \
+    elc->data32[2 + (o)] = d2;                                            \
+    elc->data32[3 + (o)] = d3;
+
+#if 0
+#define FERRET_POST_assign_1t                                             \
+    elc->data64[0] = t.raw;
+#endif
+
+
+L4_INLINE void
+ferret_list_post(ferret_list_local_t * l, uint16_t maj, uint16_t min,
+                 uint16_t instance)
+FERRET_POST_begin
+FERRET_POST_end
+
+FERRET_POST_sig(_1w, uint32_t d0)
+FERRET_POST_begin
+FERRET_POST_assign_1w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_2w, uint32_t d0, uint32_t d1)
+FERRET_POST_begin
+FERRET_POST_assign_2w(0)
+FERRET_POST_end
+
+FERRET_POSTX_sig(_2w, uint32_t d0, uint32_t d1)
+FERRET_POSTX_begin
+FERRET_POST_assign_2w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_3w, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_begin
+FERRET_POST_assign_3w(0)
+FERRET_POST_end
+
+FERRET_POST_sig(_4w, uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3)
+FERRET_POST_begin
+FERRET_POST_assign_4w(0)
+FERRET_POST_end
+
+#if 0
+FERRET_POST_sig(_1t, l4_threadid_t t)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_end
+
+FERRET_POST_sig(_1t1w, l4_threadid_t t, uint32_t d0)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_1w(1)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t2w, l4_threadid_t t, uint32_t d0, uint32_t d1)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_2w(1)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t3w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_3w(1)
+FERRET_POST_end
+
+FERRET_POST_sig(_1t4w, l4_threadid_t t, uint32_t d0, uint32_t d1, uint32_t d2,
+                uint32_t d3)
+FERRET_POST_begin
+FERRET_POST_assign_1t
+FERRET_POST_assign_4w(1)
+FERRET_POST_end
+#endif
+
+// cleanup namespace
+#undef FERRET_POST_sig
+#undef FERRET_POSTX_sig
+#undef FERRET_POST_begin
+#undef FERRET_POSTX_begin
+#undef FERRET_POST_end
+#undef FERRET_POST_assign_1w
+#undef FERRET_POST_assign_2w
+#undef FERRET_POSTX_assign_2w
+#undef FERRET_POST_assign_3w
+#undef FERRET_POST_assign_4w
+#undef FERRET_POST_assign_1t
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/llist.h b/l4/pkg/ferret/include/sensors/llist.h
new file mode 100644 (file)
index 0000000..d106230
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+ * \file   ferret/include/sensors/llist.h
+ * \brief  locked list generic types.
+ *
+ * \date   2007-06-12
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_LLIST_H_
+#define __FERRET_INCLUDE_SENSORS_LLIST_H_
+
+#define FERRET_LLIST_MAX_COUNT   16*1024*1024  // arbitrary, but large limit
+#define FERRET_LLIST_MAX_ELEMENT 4096          // arbitrary, but large limit
+
+/* reuse:
+    - ferret_list_entry_t
+    - ferret_list_entry_common_header_t
+    - ferret_list_entry_common_t
+    - ferret_list_entry_kernel_t
+ */
+
+/* Fixme: This should merely be a wrapper that sets up
+ *        SET_DELAY_PREEMPTION and UNSET_DELAY_PREEMPTION (resp. LOCK and
+ *        UNLOCK) to a specific implementation.  We can than include a
+ *        template which only uses the macros defined here.
+ *
+ *        We also need more macros for the lock objects:
+ *         - INIT, DESTROY, TYPE, ...
+ */
+
+/* 64 bit type with direct access to low 32 bit part
+ */
+typedef union ferret_llist_index_s
+{
+    low_high_t lh;
+    uint64_t   value;
+} ferret_llist_index_t;
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/scalar.h b/l4/pkg/ferret/include/sensors/scalar.h
new file mode 100644 (file)
index 0000000..92edbe6
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * \file   ferret/include/sensors/scalar.h
+ * \brief  Functions to operate on the most basic sensors type: scalars.
+ *
+ * \date   08/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ * \author Bjoern Doebel   <doebel@tudos.org>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_SCALAR_H_
+#define __FERRET_INCLUDE_SENSORS_SCALAR_H_
+
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/types.h>
+
+/* fixme: - convert data to array
+ *        - optionally support word sized data entries for faster access
+ */
+
+typedef struct
+{
+    ferret_common_t header;
+
+    ferret_time_t   low;       // lower bound for valid range
+    ferret_time_t   high;      // upper bound for valid range
+    ferret_time_t   val_min;   // minimum value put in so far
+    ferret_time_t   val_max;   // maximum value put in so far
+    long long       val_count; // number of values inserted
+    ferret_time_t   val_sum;   // sum of all values inserted
+    ferret_time_t   data;      // finally the data itself
+}  ferret_scalar_t;
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/scalar_consumer.h b/l4/pkg/ferret/include/sensors/scalar_consumer.h
new file mode 100644 (file)
index 0000000..6aa1c32
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * \file   ferret/include/sensors/scalar_consumer.h
+ * \brief  Scalar consumer functions.
+ *
+ * \date   08/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_SCALAR_CONSUMER_H_
+#define __FERRET_INCLUDE_SENSORS_SCALAR_CONSUMER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/scalar.h>
+
+EXTERN_C_BEGIN
+
+ferret_time_t ferret_scalar_get(ferret_scalar_t * scalar);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/scalar_init.h b/l4/pkg/ferret/include/sensors/scalar_init.h
new file mode 100644 (file)
index 0000000..34d9134
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * \file   ferret/include/sensors/scalar_init.h
+ * \brief  Scalar init functions.
+ *
+ * \date   08/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_SCALAR_INIT_H_
+#define __FERRET_INCLUDE_SENSORS_SCALAR_INIT_H_
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/scalar.h>
+#include <l4/ferret/sensors/common.h>
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+// giving the type here makes sense, as one generic function might be
+// able to init several types
+int ferret_scalar_init(ferret_scalar_t * scalar, const char * config);
+
+l4_ssize_t ferret_scalar_size_config(const char * config);
+
+l4_ssize_t ferret_scalar_size(const ferret_scalar_t * scalar);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/scalar_producer.h b/l4/pkg/ferret/include/sensors/scalar_producer.h
new file mode 100644 (file)
index 0000000..af2a4af
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+ * \file   ferret/include/sensors/scalar_producer.h
+ * \brief  Scalar producer functions.
+ *
+ * \date   08/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_SCALAR_PRODUCER_H_
+#define __FERRET_INCLUDE_SENSORS_SCALAR_PRODUCER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/scalar.h>
+
+EXTERN_C_BEGIN
+
+/**********************************************************************
+ * Declarations
+ **********************************************************************/
+
+L4_INLINE void
+ferret_scalar_put(ferret_scalar_t * scalar, ferret_time_t data);
+L4_INLINE void
+ferret_scalar_add(ferret_scalar_t * scalar, ferret_time_t data);
+L4_INLINE void
+ferret_scalar_sub(ferret_scalar_t * scalar, ferret_time_t data);
+L4_INLINE void ferret_scalar_inc(ferret_scalar_t * scalar);
+L4_INLINE void ferret_scalar_dec(ferret_scalar_t * scalar);
+
+/**********************************************************************
+ * Implementations
+ **********************************************************************/
+
+#include <l4/util/atomic.h>
+
+// fixme: care for max, min, ...
+
+L4_INLINE void
+ferret_scalar_put(ferret_scalar_t * scalar, ferret_time_t data)
+{
+    scalar->data = data;
+}
+
+L4_INLINE void
+ferret_scalar_add(ferret_scalar_t * scalar, ferret_time_t data)
+{
+    ferret_time_t _old, _new;
+
+    do
+    {
+        _old = scalar->data;
+        _new = _old + data;
+    } while (! l4util_cmpxchg64((l4_uint64_t*)&(scalar->data), _old, _new));
+}
+
+L4_INLINE void
+ferret_scalar_sub(ferret_scalar_t * scalar, ferret_time_t data)
+{
+    ferret_time_t _old, _new;
+
+    do
+    {
+        _old = scalar->data;
+        _new = _old - data;
+    } while (! l4util_cmpxchg64((l4_uint64_t*)&(scalar->data), _old, _new));
+}
+
+L4_INLINE void ferret_scalar_inc(ferret_scalar_t * scalar)
+{
+    ferret_time_t _old, _new;
+
+    do
+    {
+        _old = scalar->data;
+        _new = _old + 1;
+    } while (! l4util_cmpxchg64((l4_uint64_t*)&(scalar->data), _old, _new));
+}
+
+L4_INLINE void ferret_scalar_dec(ferret_scalar_t * scalar)
+{
+    ferret_time_t _old, _new;
+
+    do
+    {
+        _old = scalar->data;
+        _new = _old - 1;
+    } while (! l4util_cmpxchg64((l4_uint64_t*)&(scalar->data), _old, _new));
+}
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/slist.h b/l4/pkg/ferret/include/sensors/slist.h
new file mode 100644 (file)
index 0000000..29523f5
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/slist.h
+ * \brief  Functions to operate on event slists.
+ *
+ * \date   2007-06-13
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_SLIST_H_
+#define __FERRET_INCLUDE_SENSORS_SLIST_H_
+
+#include <l4/semaphore/semaphore.h>
+
+#include <l4/ferret/sensors/__slist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/slist_consumer.h b/l4/pkg/ferret/include/sensors/slist_consumer.h
new file mode 100644 (file)
index 0000000..c9c4c9e
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/slist_consumer.h
+ * \brief  l4env semaphore list consumer functions.
+ *
+ * \date   2007-06-13
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_SLIST_CONSUMER_H_
+#define __FERRET_INCLUDE_SENSORS_SLIST_CONSUMER_H_
+
+#include <l4/ferret/sensors/slist.h>
+
+#include <l4/ferret/sensors/__slist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist_consumer.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/slist_init.h b/l4/pkg/ferret/include/sensors/slist_init.h
new file mode 100644 (file)
index 0000000..98def95
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/slist_init.h
+ * \brief  delayed preemption list init functions.
+ *
+ * \date   2007-06-13
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_SLIST_INIT_H_
+#define __FERRET_INCLUDE_SENSORS_SLIST_INIT_H_
+
+#include <l4/ferret/sensors/slist.h>
+
+#include <l4/ferret/sensors/__slist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist_init.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/slist_producer.h b/l4/pkg/ferret/include/sensors/slist_producer.h
new file mode 100644 (file)
index 0000000..e07c941
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/slist_producer.h
+ * \brief  l4env semaphore list producer functions.
+ *
+ * \date   2007-06-13
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_SLIST_PRODUCER_H_
+#define __FERRET_INCLUDE_SENSORS_SLIST_PRODUCER_H_
+
+#include <l4/ferret/sensors/slist.h>
+
+#include <l4/ferret/sensors/__slist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist_producer.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/tbuf.h b/l4/pkg/ferret/include/sensors/tbuf.h
new file mode 100644 (file)
index 0000000..aac00f9
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * \file   ferret/include/sensors/tbuf.h
+ * \brief  Functions to operate on the trace buffer.
+ *
+ * \date   06/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_TBUF_H_
+#define __FERRET_INCLUDE_SENSORS_TBUF_H_
+
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/maj_min.h>
+
+#include <l4/sys/ktrace.h>
+#include <l4/sys/ktrace_events.h>
+
+// just collect some includes for now ...
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/tbuf_consumer.h b/l4/pkg/ferret/include/sensors/tbuf_consumer.h
new file mode 100644 (file)
index 0000000..33ea451
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+ * \file   ferret/include/sensors/tbuf_consumer.h
+ * \brief  Tracebuffer consumer functions.
+ *
+ * \date   06/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_TBUF_CONSUMER_H_
+#define __FERRET_INCLUDE_SENSORS_TBUF_CONSUMER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/list.h>
+
+#include <l4/sys/ktrace.h>
+#include <l4/sys/ktrace_events.h>
+
+EXTERN_C_BEGIN
+
+/* Also the tracebuffer sensor has two parts, the kernel-provided
+ * global part and the process-local status memory.  The tracebuffer
+ * cannot be transported with dataspaces but must be allocated
+ * directly at the kernel (I assume).
+ *
+ * The shared part is described in <l4/sys/ktrace.h> and
+ * <l4/sys/ktrace_events.h>, the local part in "tbuf_consumer.h"
+ */
+
+/* Consumer local part of the data structure.  Allocated and
+ * initialized locally.
+ */
+typedef struct
+{
+    ferret_common_t           header;    // copy of the header, all
+                                         // sensors should start with
+                                         // same header
+    uint64_t                  next_read; // event to read next
+    uint64_t                  lost;      // number of events lost so far
+    l4_tracebuffer_status_t * status;    // pointer to globally shared area
+    int                       size;      // size of tracebuffer in bytes
+    int                       count;     // number of tracebuffer entries
+    int                       count2;    // number of tracebuffer entries / 2
+    uint32_t                  mask;      // bitmask to create index
+                                         // from counter
+    uint32_t                  offset;    // how many bits offset for
+                                         // version[01] to combine
+                                         // with event number ->
+                                         // element counter
+} ferret_tbuf_moni_t;
+
+/**
+ * @brief Get one event out of the tracebuffer
+ *
+ * @param  list list sensor to get elements from
+ * @param  el   pointer to memory area to copy retrieved element to
+ *
+ * @return - = 0 ok
+ *         - < 0 errorcode
+ */
+int ferret_tbuf_get(ferret_tbuf_moni_t * tbuf, l4_tracebuffer_entry_t * el);
+
+/**
+ * @brief Setup local struct for sensor
+ *
+ * @param  addr pointer pointer to global memory area
+ * @retval addr pointer to new local area
+ */
+void ferret_tbuf_init_consumer(void ** addr);
+
+/**
+ * @brief De-allocate locale memory area
+ *
+ * @param addr  pointer pointer to local memory area
+ * @retval addr pointer to global memory
+ */
+void ferret_tbuf_free_consumer(void ** addr);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/ulist.h b/l4/pkg/ferret/include/sensors/ulist.h
new file mode 100644 (file)
index 0000000..6338f7f
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/ulist.h
+ * \brief  Functions to operate on event ulists.
+ *
+ * \date   2007-06-19
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_ULIST_H_
+#define __FERRET_INCLUDE_SENSORS_ULIST_H_
+
+#include <l4/semaphore/semaphore.h>
+
+#include <l4/ferret/sensors/__ulist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/ulist_consumer.h b/l4/pkg/ferret/include/sensors/ulist_consumer.h
new file mode 100644 (file)
index 0000000..acf3e2a
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/ulist_consumer.h
+ * \brief  Fiasco's user semaphore lists consumer functions.
+ *
+ * \date   2007-06-19
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_ULIST_CONSUMER_H_
+#define __FERRET_INCLUDE_SENSORS_ULIST_CONSUMER_H_
+
+#include <l4/ferret/sensors/ulist.h>
+
+#include <l4/ferret/sensors/__ulist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist_consumer.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/ulist_init.h b/l4/pkg/ferret/include/sensors/ulist_init.h
new file mode 100644 (file)
index 0000000..7ee7631
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/ulist_init.h
+ * \brief  Fiasco's user semaphore lists producer functions.
+ *
+ * \date   2007-06-19
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_ULIST_INIT_H_
+#define __FERRET_INCLUDE_SENSORS_ULIST_INIT_H_
+
+#include <l4/ferret/sensors/ulist.h>
+
+#include <l4/ferret/sensors/__ulist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist_init.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/ulist_producer.h b/l4/pkg/ferret/include/sensors/ulist_producer.h
new file mode 100644 (file)
index 0000000..16fd2c6
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/include/sensors/ulist_producer.h
+ * \brief  Fiasco's user semaphore lists producer functions.
+ *
+ * \date   2007-06-19
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_ULIST_PRODUCER_H_
+#define __FERRET_INCLUDE_SENSORS_ULIST_PRODUCER_H_
+
+#include <l4/ferret/sensors/ulist.h>
+
+#include <l4/ferret/sensors/__ulist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include <l4/ferret/sensors/__llist_producer_local.h>
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/vlist.h b/l4/pkg/ferret/include/sensors/vlist.h
new file mode 100644 (file)
index 0000000..b7fd552
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * \file   ferret/include/sensors/vlist.h
+ * \brief  Functions to operate on variable event lists.
+ *
+ * \date   2007-09-26
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_VLIST_H_
+#define __FERRET_INCLUDE_SENSORS_VLIST_H_
+
+#include <l4/sys/compiler.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/common.h>
+
+
+#define FERRET_ASSUMED_CACHE_LINE_SIZE 64
+
+#define FERRET_VLIST_MAX_SIZE   64*1024*1024  // arbitrary, but large limit
+
+#include <l4/ferret/sensors/list.h>  // reuse some types
+
+typedef union ferret_vlist_index_s
+{
+    struct
+    {
+        uint32_t low;
+        uint32_t high;
+    };
+    uint64_t     value;
+} ferret_vlist_index_t;
+
+typedef struct
+{
+    ferret_common_t      header;
+
+    uint32_t             head;       // maybe make 64-bit too?
+    ferret_vlist_index_t tail;
+    uint32_t             size;       // size of sensor data in bytes (must
+                                     // be power of two)
+    uint32_t             size_ld;    // ld_2(size)
+    uint32_t             size_mask;  // (2 << size_ld) - 1
+    uint32_t             flags;
+
+    uint8_t              data[0]     // data, align to cache line size
+      __attribute__ ((aligned (FERRET_ASSUMED_CACHE_LINE_SIZE)));
+} ferret_alist_t;
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/vlist_consumer.h b/l4/pkg/ferret/include/sensors/vlist_consumer.h
new file mode 100644 (file)
index 0000000..7424757
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * \file   ferret/include/sensors/vlist_consumer.h
+ * \brief  Atomic list consumer functions.
+ *
+ * \date   2007-09-27
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_VLIST_CONSUMER_H_
+#define __FERRET_INCLUDE_SENSORS_VLIST_CONSUMER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/vlist.h>
+
+EXTERN_C_BEGIN
+
+/* Consumer local part of the data structure.  Allocated and
+ * initialized locally.
+ */
+typedef struct
+{
+    ferret_common_t              header;    // copy of the header, all
+                                            // sensors should start with
+                                            // same header
+    ferret_vlist_index_t         next_read; // event to read next
+    uint64_t                     lost;      // number of events lost so far
+    ferret_alist_t             * glob;      // pointer to globally shared area
+    ferret_list_entry_common_t * data;      // pointer to element buffer
+} ferret_alist_moni_t;
+
+/**
+ * @brief 
+ *
+ * @param  list list sensor to get elements from
+ * @param  size size of el
+ * @param  el   pointer to memory area to copy retrieved element to
+ *
+ * @param  size number of bytes actually written to el
+ * @return - = 0 ok
+ *         - < 0 errorcode
+ */
+int ferret_vlist_get(ferret_vlist_moni_t * list, size_t * size,
+                     ferret_list_entry_t * el);
+
+/*
+
+++ wrap all 64 bit reads into hlh reads
+
+
+retry:
+    uint64_t current_tail = (volatile uint64_t)(list->glob->tail);
+    if (current_tail > old_index->value)   // did we loose stuff?
+    {
+        list->lost += current_tail - old_index->value;
+        old_index->value = list->tail.value;   // adapt
+    }
+
+retry2:
+    esize = *((size_t *)(list->data[old_index->l & list->size_mask]));
+    if (old_index->l & list->size_mask + esize > list->size)  // illegal size
+    {
+        uint64_t current_tail = (volatile uint64_t)(list->glob->tail);
+        if (current_tail > old_index->value)  // temp. of perm. problem?
+            goto retry;   // retry
+        else
+            return -1;     // sensor corrupt
+    }
+    memcpy(dest,
+           &(list->data) + (old_index->l & list->size_mask) + sizeof(size_t),
+           MIN(*size, esize));
+
+    uint64_t current_tail = (volatile uint64_t)(list->glob->tail);
+    if (list->tail.value > old_index->value)  // did we loose stuff?
+    {
+        old_index->value = list->tail.value;   // adapt
+        goto retry2;
+    }
+
+    *size = MIN(size, esize);
+ */
+
+
+/**
+ * @brief Setup local struct for sensor
+ *
+ * @param  addr pointer pointer to global memory area
+ * @retval addr pointer to new local area
+ */
+void ferret_vlist_init_consumer(void ** addr);
+
+/**
+ * @brief De-allocate locale memory area
+ *
+ * @param addr  pointer pointer to local memory area
+ * @retval addr pointer to global memory
+ */
+void ferret_vlist_free_consumer(void ** addr);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/vlist_init.h b/l4/pkg/ferret/include/sensors/vlist_init.h
new file mode 100644 (file)
index 0000000..92cbfe9
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * \file   ferret/include/sensors/vlist_init.h
+ * \brief  Variable list init functions.
+ *
+ * \date   2007-09-26
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_VLIST_INIT_H_
+#define __FERRET_INCLUDE_SENSORS_VLIST_INIT_H_
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/vlist.h>
+#include <l4/ferret/sensors/common.h>
+
+#include <l4/sys/compiler.h>
+
+EXTERN_C_BEGIN
+
+int ferret_vlist_init(ferret_vlist_t * list, const char * config);
+
+ssize_t ferret_vlist_size_config(const char * config);
+
+ssize_t ferret_vlist_size(const ferret_vlist_t * list);
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/sensors/vlist_producer.h b/l4/pkg/ferret/include/sensors/vlist_producer.h
new file mode 100644 (file)
index 0000000..0d8cd08
--- /dev/null
@@ -0,0 +1,152 @@
+/**
+ * \file   ferret/include/sensors/vlist_producer.h
+ * \brief  Variable list producer functions.
+ *
+ * \date   2007-09-26
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_SENSORS_VLIST_PRODUCER_H_
+#define __FERRET_INCLUDE_SENSORS_VLIST_PRODUCER_H_
+
+#include <l4/sys/compiler.h>
+#include <l4/ferret/sensors/vlist.h>
+
+EXTERN_C_BEGIN
+
+/**********************************************************************
+ * Declarations
+ **********************************************************************/
+
+L4_INLINE void
+ferret_vlist_post(ferret_vlist_t * l, uint16_t maj, uint16_t min,
+                  uint16_t instance);
+
+L4_INLINE void
+ferret_vlist_post_2w(ferret_vlist_t * l, uint16_t maj, uint16_t min,
+                     uint16_t instance, uint32_t d0, uint32_t d1);
+
+/* Post an event of variable size, size and pointer to payload must be
+ * given.
+ */
+L4_INLINE void
+ferret_vlist_post_v(ferret_vlist_t * l, uint16_t maj, uint16_t min,
+                    uint16_t instance, size_t size, void * p);
+
+/* Post an event of variable size in raw format, only timestamp is
+ * prepended on post, size and pointer to payload must be given.
+ */
+L4_INLINE void
+ferret_vlist_post_v(ferret_vlist_t * l, size_t size, void * p);
+
+/**********************************************************************
+ * Implementations
+ **********************************************************************/
+
+#include <l4/util/atomic.h>
+#include <l4/util/rdtsc.h>
+
+L4_INLINE void
+ferret_vlist_post(ferret_vlist_t * l, uint16_t maj, uint16_t min,
+                  uint16_t instance)
+{
+    ferret_list_entry_common_t e;
+
+    e.major     = maj;
+    e.minor     = min;
+    e.instance  = instance;
+
+    // fixme: call into real post event code in kern_lib_page
+
+    /*
+    asm volatile (
+        "cld                              \n\t"
+        "push %%ecx                       \n\t"
+        "push %%esi                       \n\t"
+        "push %%eax                       \n\t"
+        "call __ferret_alist_post         \n\t"
+        "add  $0xc, %%esp                 \n\t"
+        :
+        : "S"((&(e.timestamp)) + 1), "a"(l), "c"(2)
+        : "memory", "edi", "ebx", "edx", "cc"
+        );
+    */
+}
+
+/*
+// write:
+// parameters: size. *p
+// fixme: care for wrap-around in memcpy
+    retry:
+    while (((l->head + l->size) - (l->tail.low & l->size_mask)) &
+           l->size_mask <
+           size + sizeof(size_t))
+    {
+        new_tail = l->tail.value + sizeof(size_t) + size;
+        cmpxchg8b(l->tail.value, new_tail, &l->tail.value);  // We are
+            //  executed atomically, so we don't have to store
+            //  l->tail.value somewhere else.  This is basically just
+            //  an atomic 64-bit move.
+    }
+
+    // we fill the remainder of the buffer with a pseudo event, in
+    // case of wrap-around.
+    //  - small events (< 12 bytes) are such events
+    //  - larger events with a timestamp of 0 too
+
+    // we could also split the memcpy ???
+
+    free = l->size - l->head;
+    assert(free >= sizeof(size_t));
+    if (free < size + sizeof(size_t))
+    {
+        dest = l->head + &(l->data);
+        *dest = free - sizeof(size_t);
+        if (free >= sizeof(size_t) + sizeof(ferret_utime_t))
+            (ferret_utime_t *)(dest + 2) = 0;  // 0 means 
+        goto retry:
+    }
+
+    *p = rdtsc();
+    *(l->head.low & l->size_mask) + &(l->data) = size;
+    memcpy((l->head.low & l->size_mask) + &(l->data) + sizeof(size_t),
+           p, size);
+
+    new_head = (l->head + sizeof(size_t) + size) & l->size_mask;
+    // rollforward point
+    l->head = new_head;
+ */
+
+/*
+// read:
+// parameters: *old_index (64 bit), *dest
+// fixme: we can not know how many events we lost, but just about how
+//        many bytes ...
+
+retry:
+    if (l->tail.value > old_index->value)   // did we loose stuff?
+        old_index->value = l->tail.value;   // adapt
+
+retry2:
+    size = *(&(l->data) + (old_index->l & l->size_mask));
+    if (old_index->l + size > l->size)  // got illegal size
+        if (l->tail.value > old_index->value)  // temp. of permament problem?
+            goto retry;   // retry
+        else
+            return 1;     // sensor corrupt
+    memcpy(dest,
+           &(l->data) + (old_index->l & l->size_mask) + sizeof(size_t),
+           size);
+    if (l->tail.value > old_index->value)  // did we loose stuff?
+        old_index->value = l->tail.value;   // adapt
+        goto retry2;
+ */
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/include/types.h b/l4/pkg/ferret/include/types.h
new file mode 100644 (file)
index 0000000..ca1e1a6
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * \file   ferret/include/types.h
+ * \brief  Global types for ferret.
+ *
+ * \date   04/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_TYPES_H_
+#define __FERRET_INCLUDE_TYPES_H_
+
+#include <l4/ferret/maj_min.h>
+#include <l4/re/c/dataspace.h>
+
+#ifdef __cplusplus
+#define __STDC_LIMIT_MACROS
+#endif
+
+#if defined (__KERNEL__)
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#include <sys/types.h>
+#endif
+
+EXTERN_C_BEGIN
+/*********************************************************************
+ * Simple types
+ *********************************************************************/
+
+typedef struct
+{
+    uint32_t low;  ///< Low 32 Bits
+    uint32_t high; ///< High 32 Bits
+} low_high_t;
+
+typedef int64_t  ferret_time_t;
+typedef uint64_t ferret_utime_t;
+
+#ifndef __KERNEL__
+// XXX: This is only used by histogram code _and_ the MAX/MIN macros are
+//      missing in Linux kernel code - why not move this somewhere else?
+static const ferret_time_t FERRET_TIME_MIN = INT64_MIN;
+static const ferret_time_t FERRET_TIME_MAX = INT64_MAX;
+#endif
+
+#define FERRET_DIR_NAME "FerretDir"
+
+#define FERRET_ROOT_INSTANCE 0
+
+/*********************************************************************
+ * Structure types
+ *********************************************************************/
+
+enum SensorType
+{
+       FERRET_UNDEFINED = 0,
+       FERRET_SCALAR    = 1,
+       FERRET_HISTO     = 2,
+       FERRET_HISTO_2D  = 3,
+       FERRET_LIST      = 4,
+       FERRET_TBUF      = 5,
+       FERRET_HISTO64   = 6,
+       /* XXX BjoernD, 2009-03-02: We turn off these special kinds of sensors for now
+        *                          until we know which of these we really want.
+        *                          (Suppose, this was only for Martin's measurements.)
+        */
+#if 0
+       FERRET_DPLIST    = 7,  // list protected with Delayed Preemption
+       FERRET_SLIST     = 8,  // list protected with L4Env Semaphores
+       FERRET_ULIST     = 9,  // list protected with Fiasco's User Semaphores
+       FERRET_ALIST     = 10, // list protected with Fiasco-supported
+                                 // atomic roll-back sections
+       FERRET_VLIST     = 11, // list protected with Fiasco-supported
+                              // atomic roll-back sections, supports
+                              // variable element sizes
+#endif
+};
+
+/*********************************************************************
+ * Flags
+ *********************************************************************/
+
+enum
+{
+       FERRET_PERMANENT  = 0x00000001, // keep this sensor in the
+                                       // directory, even if its usage
+                                       // count drops to zero
+       FERRET_SUPERPAGES = 0x00010000, // use superpages for sensor
+                                       // dataspace if it would be
+                                       // larger than one page
+};
+
+EXTERN_C_END
+#endif
diff --git a/l4/pkg/ferret/include/util.h b/l4/pkg/ferret/include/util.h
new file mode 100644 (file)
index 0000000..f2ee622
--- /dev/null
@@ -0,0 +1,103 @@
+/**
+ * \file   ferret/include/util.h
+ * \brief  Some helper functions
+ *
+ * \date   29/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_INCLUDE_UTIL_H_
+#define __FERRET_INCLUDE_UTIL_H_
+
+#if 0
+#include <l4/sys/ktrace_events.h>
+#endif
+#include <l4/ferret/sensors/list.h>
+
+EXTERN_C_BEGIN
+
+/**
+ * @brief Pack a number of parameters according to format string into
+ *        memory buffer
+ *
+ * Currently the following tags are valid in format strings: "xbBhHlLqQsp"
+ *
+ * x       padding byte, no parameter required
+ *
+ * b,B     Byte and Boolean, one byte is packed in to the memory area
+ *
+ * h,H     Short word, one 16 bit integer is packed
+ *
+ * l,L     Long word, one 32 bit integer is packed
+ *
+ * q,Q     Quad word, one 64 bit integer is packed
+ *
+ * s       c-String, one c string is packed, terminated by a zero byte
+ *
+ * p       Pascal-String, one c string is packed as Pascal string,
+ *         preceded with one byte of length information (-> max length 255)
+ *
+ * <count> number before regular tokens are interpreted as
+ *         multipliers, before strings they denote the length to use for
+ *         storing the string
+ *
+ * Example: "hhxb10s2xq" will pack to two shorts, one padding byte,
+ * one regular byte, a string of length 10 (+ 1 terminating zero
+ * byte), two more padding bytes, and a 64 bit integer.  This
+ * corresponds to the following struct defintion in c:
+ *
+ * struct  __attribute__((__packed__)) foo_s
+ * {
+ *     int16_t a;
+ *     int16_t b;
+ *     int8_t  _pad1;
+ *     char    c[11];
+ *     int8_t  _pad2[2];
+ *     int64_t d;
+ * };
+ *
+ * @param format format string desribing the memory layout (see
+ *               Pythons struct.pack)
+ * @param buffer pointer to target memory area
+ *
+ * @return - >= 0 number of bytes written
+ *           < 0 error in format string
+ */
+L4_CV int ferret_util_pack(const char * format, void * buffer, ...);
+
+
+/**
+ * @brief Unpack a number of parameters according to format string from
+ *        memory buffer
+ *
+ * @param format format string desribing the memory layout (see
+ *               Pythons struct.pack)
+ * @param buffer pointer to source memory area
+ *
+ * @return - >= 0 number of bytes parsed
+ *           < 0 error in format string
+ */
+
+L4_CV int ferret_util_unpack(const char * format, const void * buffer, ...);
+
+
+#if 0
+/**
+ * @brief Layout-converts kernel tracebuffer entries to common list
+ *        entry subtypes.
+ *
+ * @param tb_e pointer to tracebuffer entry to get data from
+ * @param lec  pointer to common list entry to put data to
+ */
+L4_CV void ferret_util_convert_k2c(const l4_tracebuffer_entry_t * tb_e,
+                                   ferret_list_entry_kernel_t * lec);
+#endif
+
+EXTERN_C_END
+
+#endif
diff --git a/l4/pkg/ferret/lib/Makefile b/l4/pkg/ferret/lib/Makefile
new file mode 100644 (file)
index 0000000..4455d2a
--- /dev/null
@@ -0,0 +1,6 @@
+PKGDIR ?= ..
+L4DIR  ?= $(PKGDIR)/../..
+
+TARGET = common consumer producer
+
+include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/ferret/lib/common/Makefile b/l4/pkg/ferret/lib/common/Makefile
new file mode 100644 (file)
index 0000000..c9c45fd
--- /dev/null
@@ -0,0 +1,15 @@
+PKGDIR   ?= ../..
+L4DIR    ?= $(PKGDIR)/../..
+
+# all the producer stuff is inline, so no lib is needed
+SRC_CC_libferret_util.a     = pack.cc unpack.cc util.cc
+SRC_CC_libferret_comm.a     = comm.cc
+
+# convert.cc switched off until we know about the tbuf interface
+
+TARGET    = libferret_util.a libferret_comm.a
+REQUIRES_LIBS = libpthread
+
+PC_FILENAME = ferret-common
+
+include $(L4DIR)/mk/lib.mk
diff --git a/l4/pkg/ferret/lib/common/comm.cc b/l4/pkg/ferret/lib/common/comm.cc
new file mode 100644 (file)
index 0000000..97bd95a
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * \file   ferret/lib/comm/comm.cc
+ * \brief  Helper stuff for finding the sensor directory.
+ *
+ * \date   10/03/2009
+ * \author Bjoern Doebel <doebel@tudos.org>
+ */
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/comm.h>
+#include <l4/re/c/util/cap_alloc.h>
+#include <l4/re/c/namespace.h>
+#include <iostream>          // std::cout
+
+l4_cap_idx_t lookup_sensordir(void)
+{
+       l4_cap_idx_t srv = l4re_env_get_cap("ferret");
+       if (l4_is_invalid_cap(srv))
+               std::cout << "Ups...\n";
+       else
+               std::cout << "Found 'ferret' in ns.\n";
+
+       return srv;
+}
diff --git a/l4/pkg/ferret/lib/common/convert.cc b/l4/pkg/ferret/lib/common/convert.cc
new file mode 100644 (file)
index 0000000..0d30578
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * \file   ferret/lib/util/convert.c
+ * \brief  Convert kernel tracebuffer entries to common header format.
+ *
+ * \date   09/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <l4/ferret/sensors/tbuf.h>
+#include <l4/ferret/util.h>
+#include <l4/ferret/types.h>
+
+void ferret_util_convert_k2c(const l4_tracebuffer_entry_t * tb_e,
+                             ferret_list_entry_kernel_t * lec)
+{
+    // common part for list entry
+    lec->timestamp = tb_e->tsc;
+    lec->major     = FERRET_TBUF_MAJOR;
+    lec->minor     = tb_e->type;
+    lec->instance  = FERRET_TBUF_INSTANCE;
+    lec->cpu       = 0;  // fixme: later
+
+    // common part for all kernel events
+    lec->context   = (void *)tb_e->context;  // thread
+    lec->eip       = tb_e->eip;
+    lec->pmc1      = tb_e->pmc1;
+    lec->pmc2      = tb_e->pmc2;
+
+    lec->data8[0]  = 0;  // padding byte
+
+    // kernel event specific parts, directly after padding byte
+    memcpy(&lec->data8[1], &tb_e->m, sizeof(tb_e->m.fit._pad));
+}
diff --git a/l4/pkg/ferret/lib/common/pack.cc b/l4/pkg/ferret/lib/common/pack.cc
new file mode 100644 (file)
index 0000000..ddd9d78
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * \file   ferret/lib/util/pack.c
+ * \brief  Utility functions.
+ *
+ * \date   29/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <l4/ferret/util.h>
+
+// format modifiers "xbBhHlLqQsp"
+
+int ferret_util_pack(const char *fmt, void * _buf, ...)
+{
+    unsigned char * buf = static_cast<unsigned char *>(_buf);
+    va_list argp;
+    int written;
+
+    uint64_t q;
+    uint32_t l;
+    uint16_t s;
+    uint8_t  c;
+
+    size_t len = 0;
+    int has_count = 0;
+       size_t count = 1, i;
+    char * ptr;
+
+    va_start(argp, _buf);
+    written = 0;
+    for (; *fmt; ++fmt)
+    {
+        // numbers
+        if (*fmt >= '0' && *fmt <= '9')
+        {
+            if (! has_count)
+                count = 0;    // first digit ...
+            else
+                count *= 10;  // ... next digit
+            count += *fmt - '0';
+            has_count = 1;
+            continue;
+        }
+        // strings
+        switch (*fmt)
+        {
+            case 's':  // c string, 0-terminated
+                ptr = static_cast<char*>(va_arg(argp, char *));
+                len = strlen(ptr);
+                //LOG("%p, %d, %d, %d", ptr, count, len, has_count);
+                if (len < count || ! has_count)
+                {
+                    strncpy(reinterpret_cast<char*>(buf), ptr, len);
+                    if (has_count)  // zero out remainder
+                    {
+                        memset(buf + len, 0, count - len + 1);
+                        //LOG("%p, %d, %d, %d", o + len, count, len, has_count);
+                        buf     += count + 1;
+                        written += count + 1;
+                    }
+                    else
+                    {
+                        buf     += len + 1;
+                        written += len + 1;
+                    }
+                }
+                else
+                {
+                    strncpy(reinterpret_cast<char *>(buf), ptr, count);
+                    *(buf + count) = '\0';
+                    buf     += count + 1;
+                    written += count + 1;
+                }
+                count     = 0;
+                has_count = 0;
+                continue;
+            case 'p':  // pascal string, leading length byte
+                ptr = static_cast<char *>(va_arg(argp, char *));
+                len = strlen(ptr);
+                if (len > 255)
+                    len = 255;  // truncate string at 255 bytes
+                if (count > 255)
+                    count = 255;  // truncate string at 255 bytes
+
+                if (len < count || ! has_count)
+                {
+                    if (has_count)  // prefix output with length
+                        *buf = static_cast<uint8_t>(count);
+                    else
+                        *buf = static_cast<uint8_t>(len);
+                    buf += 1;
+                    written += 1;
+                    strncpy(reinterpret_cast<char *>(buf), ptr, len);
+                    if (has_count)  // zero out remainder
+                    {
+                        memset(buf + len, 0, count - len);
+                        buf     += count;
+                        written += count;
+                    }
+                    else
+                    {
+                        buf     += len;
+                        written += len;
+                    }
+                }
+                else
+                {
+                    *buf = static_cast<uint8_t>(count);  // prefix output with length
+                    buf += 1;
+                    written += 1;
+                    strncpy(reinterpret_cast<char *>(buf), ptr, count);
+                    buf     += count;
+                    written += count;
+                }
+                count     = 0;
+                has_count = 0;
+                continue;
+        }
+        // other stuff
+        for (i = 0; i < count; ++i)
+        {
+            switch (*fmt)
+            {
+            case 'x':  // padding byte
+                // fixme: we should not do this for performance reasons
+                *(buf) = '\0';  // zero out padding stuff
+                buf += 1;
+                break;
+            case 'b':
+            case 'B':  // byte
+                c = static_cast<uint8_t>(va_arg(argp, int));
+                *buf = c;
+                buf += 1;
+                written += 1;
+                break;
+            case 'h':
+            case 'H':  // short (16 bit)
+                s = static_cast<uint16_t>(va_arg(argp, int));
+                *((uint16_t *)buf) = s;
+                buf += 2;
+                written += 2;
+                break;
+            case 'l':
+            case 'L':  // long (32 bit)
+                l = static_cast<uint32_t>(va_arg(argp, uint32_t));
+                *((uint32_t *)buf) = l;
+                buf += 4;
+                written += 4;
+                break;
+            case 'q':
+            case 'Q':  // long long (64 bit)
+                q = static_cast<uint64_t>(va_arg(argp, uint64_t));
+                //LOG("Q:%lld", q);
+                *((uint64_t *)buf) = q;
+                buf += 8;
+                written += 8;
+                break;
+            default:
+                return -1;
+            }
+        }
+        count = 1;
+        has_count = 0;
+    }
+    va_end(argp);
+    return written;
+}
diff --git a/l4/pkg/ferret/lib/common/unpack.cc b/l4/pkg/ferret/lib/common/unpack.cc
new file mode 100644 (file)
index 0000000..2ea27c1
--- /dev/null
@@ -0,0 +1,157 @@
+/**
+ * \file   ferret/lib/util/unpack.c
+ * \brief  Utility functions.
+ *
+ * \date   29/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdarg.h>
+#include <string.h>
+
+#include <l4/ferret/util.h>
+
+int ferret_util_unpack(const char *fmt, const void * _buf, ...)
+{
+    va_list argp;
+    int got;
+
+    size_t len = 0;
+    int has_count = 0;
+    size_t count = 1, i;
+    char * ptr;
+    unsigned char * buf = const_cast<unsigned char*>(static_cast<const unsigned char *>(_buf));
+
+    va_start(argp, _buf);
+    got = 0;
+    for (; *fmt; ++fmt)
+    {
+        // numbers
+        if (*fmt >= '0' && *fmt <= '9')
+        {
+            if (! has_count)
+                count = 0;    // first digit ...
+            else
+                count *= 10;  // ... next digit
+            count += *fmt - '0';
+            has_count = 1;
+            continue;
+        }
+        // strings
+        switch (*fmt)
+        {
+            case 's':  // c string, 0-terminated
+                ptr = static_cast<char *>(va_arg(argp, char *));
+                len = strlen(reinterpret_cast<char *>(buf));
+                //LOG("%p, %d, %d, %d", ptr, count, len, has_count);
+                if (len < count || ! has_count)
+                {
+                    strncpy(ptr, reinterpret_cast<char *>(buf), len);
+                    if (has_count)  // zero out remainder
+                    {
+                        memset(ptr + len, 0, count - len + 1);
+                        //LOG("%p, %d, %d, %d", o + len, count, len, has_count);
+                        buf += count + 1;
+                        got += count + 1;
+                    }
+                    else
+                    {
+                        buf += len + 1;
+                        got += len + 1;
+                    }
+                }
+                else
+                {
+                    strncpy(ptr, reinterpret_cast<char *>(buf), count);
+                    *(ptr + count) = '\0';
+                    buf += count + 1;
+                    got += count + 1;
+                }
+                count     = 0;
+                has_count = 0;
+                continue;
+            case 'p':  // pascal string, leading length byte
+                ptr = static_cast<char *>(va_arg(argp, char *));
+                len = static_cast<unsigned char>(*buf);  // read length prefix
+                buf += 1;
+                got += 1;
+                if (count > 255)
+                    count = 255;  // truncate string at 255 bytes
+
+                if (len < count || ! has_count)
+                {
+                    strncpy(ptr, reinterpret_cast<char *>(buf), len);
+                    *(ptr + len + 1) = '\0';
+                    if (has_count)  // zero out remainder
+                    {
+                        buf += count;
+                        got += count;
+                    }
+                    else
+                    {
+                        buf += len;
+                        got += len;
+                    }
+                }
+                else
+                {
+                    strncpy(ptr, reinterpret_cast<char *>(buf), count);
+                    *(ptr + count + 1) = '\0';
+                    buf += count;
+                    got += count;
+                }
+                count     = 0;
+                has_count = 0;
+                continue;
+        }
+        // other stuff
+        for (i = 0; i < count; ++i)
+        {
+            switch (*fmt)
+            {
+            case 'x':  // padding byte
+                buf += 1;
+                break;
+            case 'b':
+            case 'B':  // byte
+                *(static_cast<char *>(va_arg(argp, void *)))
+                                                     = *(reinterpret_cast<char *>(buf));
+                buf += 1;
+                got += 1;
+                break;
+            case 'h':
+            case 'H':  // short (16 bit)
+                *(static_cast<uint16_t *>(va_arg(argp, void *))) 
+                                                         = *(reinterpret_cast<uint16_t *>(buf));
+                buf += 2;
+                got += 2;
+                break;
+            case 'l':
+            case 'L':  // long (32 bit)
+                *(static_cast<uint32_t *>(va_arg(argp, void *))) 
+                                                         = *(reinterpret_cast<uint32_t *>(buf));
+                buf += 4;
+                got += 4;
+                break;
+            case 'q':
+            case 'Q':  // long long (64 bit)
+                *(static_cast<uint64_t *>(va_arg(argp, void *))) 
+                                                         = *(reinterpret_cast<uint64_t *>(buf));
+                buf += 8;
+                got += 8;
+                break;
+            default:
+                return -1;
+            }
+        }
+        count = 1;
+        has_count = 0;
+    }
+    va_end(argp);
+    return got;
+}
diff --git a/l4/pkg/ferret/lib/common/util.cc b/l4/pkg/ferret/lib/common/util.cc
new file mode 100644 (file)
index 0000000..ca03722
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/clock.h>
+#include <l4/ferret/types.h>
+#include <pthread-l4.h>
+
+ferret_time_t ferret_rel_utime()
+{
+       l4_cap_idx_t c = pthread_getl4cap(pthread_self());
+       l4_thread_stats_time(c);
+       return (ferret_time_t)l4_utcb_mr()->mr[0];
+}
diff --git a/l4/pkg/ferret/lib/consumer/Makefile b/l4/pkg/ferret/lib/consumer/Makefile
new file mode 100644 (file)
index 0000000..0409d2f
--- /dev/null
@@ -0,0 +1,12 @@
+PKGDIR   ?= ../..
+L4DIR    ?= $(PKGDIR)/../..
+
+SRC_CC_libferret_monitor.a    = monitor.cc
+SRC_C_libferret_consumer.a    = scalar_consumer.c list_consumer.c
+
+TARGET    = libferret_monitor.a \
+                       libferret_consumer.a
+
+PC_FILENAME = ferret-consumer
+
+include $(L4DIR)/mk/lib.mk
diff --git a/l4/pkg/ferret/lib/consumer/__llist_consumer.c b/l4/pkg/ferret/lib/consumer/__llist_consumer.c
new file mode 100644 (file)
index 0000000..04e6e3d
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * \file   ferret/lib/sensor/__llist_consumer.c
+ * \brief  locked list consumer functions.
+ *
+ * \date   2007-05-16
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#if FERRET_LLIST_MAGIC != ahK6eeNa
+#error Do not directly include this file, use a propper wrapper!
+#endif
+#undef FERRET_LLIST_MAGIC
+
+#include <stdlib.h>
+
+// fixme: debug
+//#include <l4/log/l4log.h>
+
+#include <l4/ferret/types.h>
+
+#include <l4/sys/ipc.h>
+
+// fixme: maybe later we need functions to get more than 1 element out
+//        of the buffer, thereby saving some locking overhead
+int PREFIX(get)(PREFIX(moni_t) * list, ferret_list_entry_t * el)
+{
+    uint32_t index;
+
+    /* 1. lock list
+     * 2. check if new data is available (no -> return -1)
+     * 3. check if we lost something and update lost counter
+     * 4. compute offset in locked list's data array
+     * 5. copy data
+     * 6. lock list
+     */
+
+    FERRET_LLIST_LOCAL_LOCK(list);
+
+    // check if we have new events for the consumer
+    if (L4_UNLIKELY(list->glob->head.value <= list->next_read.value))
+        return -1;  // we have no new events
+    // check if we have lost events
+    if (L4_UNLIKELY(list->glob->head.value - list->next_read.value >
+                    list->glob->count))
+    {
+        list->lost += list->glob->head.value - list->next_read.value -
+                      list->glob->count;
+        list->next_read.value = list->glob->head.value - list->glob->count;
+    }
+    index = list->next_read.lh.low & list->glob->count_mask;
+    memcpy(el, list->out_buf + (index << list->glob->element_size_ld),
+           list->glob->element_size);
+
+    list->next_read.value++;
+    FERRET_LLIST_LOCAL_UNLOCK(list);
+    return 0;
+
+    //return -2;  // corrupt sensor
+}
+
+void PREFIX(init_consumer)(void ** addr)
+{
+    PREFIX(moni_t) * temp;
+
+    temp = malloc(sizeof(PREFIX(moni_t)));
+
+    // setup some pointers
+    temp->glob    = *addr;  // store pointer to global structure
+    temp->out_buf = temp->glob->data;
+
+    // copy header
+    temp->header.major    = temp->glob->header.major;
+    temp->header.minor    = temp->glob->header.minor;
+    temp->header.instance = temp->glob->header.instance;
+    temp->header.type     = temp->glob->header.type;
+
+    // init. local information
+    temp->lost            = 0;
+    temp->next_read.value = 0;
+
+#ifdef FERRET_LLIST_HAVE_LOCAL_LOCK
+    FERRET_LLIST_LOCAL_INIT(temp);
+#endif
+
+    *addr = temp;
+}
+
+void PREFIX(free_consumer)(void ** addr)
+{
+    void * temp = ((PREFIX(moni_t) *)(*addr))->glob;
+
+    free(*addr);
+
+    *addr = temp;
+}
diff --git a/l4/pkg/ferret/lib/consumer/alist_consumer.c b/l4/pkg/ferret/lib/consumer/alist_consumer.c
new file mode 100644 (file)
index 0000000..bfa94af
--- /dev/null
@@ -0,0 +1,95 @@
+/**
+ * \file   ferret/lib/sensor/alist_consumer.c
+ * \brief  Atomic list consumer functions.
+ *
+ * \date   2007-09-27
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/alist.h>
+#include <l4/ferret/sensors/alist_consumer.h>
+
+int ferret_alist_get(ferret_alist_moni_t * list, ferret_list_entry_t * el)
+{
+    /*
+      check if our own pointer is still valid
+          if not, update it to tail
+          update lost counter too
+
+      retry:
+          memcpy entry from buffer
+
+          check if our own pointer is still valid
+              if not, update it to tail
+              update lost counter too
+              goto retry
+    */
+
+    uint32_t current_tail = (volatile uint32_t)(list->glob->head) -
+        (list->glob->count - 1);
+
+    if (list->next_read < current_tail)  // have we lost stuff?
+    {
+        list->lost += current_tail - list->next_read;  // update counter
+        list->next_read = current_tail;  // try oldest avail. instead
+    }
+
+retry:
+
+    memcpy(el, &list->data[list->next_read & list->glob->count_mask],
+           FERRET_ALIST_ELEMENT_SIZE);
+
+    current_tail = (volatile uint32_t)(list->glob->head) -
+        (list->glob->count - 1);
+
+    if (list->next_read < current_tail)  // have we possibly read
+                                         // inconsistant stuff?
+    {
+        uint32_t lost = current_tail - list->next_read;
+        list->lost += lost;              // update counter
+        list->next_read = current_tail;  // try oldest avail. instead
+        goto retry;
+    }
+
+    return 0;
+}
+
+void ferret_alist_init_consumer(void ** addr)
+{
+    ferret_alist_moni_t * temp;
+
+    temp = malloc(sizeof(ferret_alist_moni_t));
+
+    // setup some pointers
+    temp->glob = *addr;  // store pointer to global structure
+    temp->data = temp->glob->data;
+
+    // copy header
+    temp->header.major    = temp->glob->header.major;
+    temp->header.minor    = temp->glob->header.minor;
+    temp->header.instance = temp->glob->header.instance;
+    temp->header.type     = temp->glob->header.type;
+
+    // init. local information
+    temp->lost      = 0;
+    temp->next_read = 0;
+
+    *addr = temp;
+}
+
+void ferret_alist_free_consumer(void ** addr)
+{
+    void * temp = ((ferret_alist_moni_t *)(*addr))->glob;
+
+    free(*addr);
+
+    *addr = temp;
+}
diff --git a/l4/pkg/ferret/lib/consumer/dplist_consumer.c b/l4/pkg/ferret/lib/consumer/dplist_consumer.c
new file mode 100644 (file)
index 0000000..591a4fe
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * \file   ferret/lib/sensor/dplist_consumer.c
+ * \brief  dplist consumer functions.
+ *
+ * \date   2007-06-12
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/sensors/dplist.h>
+#include <l4/ferret/sensors/dplist_consumer.h>
+
+#include <l4/ferret/sensors/__dplist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include "__llist_consumer.c"
diff --git a/l4/pkg/ferret/lib/consumer/histogram_consumer.c b/l4/pkg/ferret/lib/consumer/histogram_consumer.c
new file mode 100644 (file)
index 0000000..da8bbbe
--- /dev/null
@@ -0,0 +1,102 @@
+/**
+ * \file   ferret/lib/sensor/histogram_consumer.c
+ * \brief  Histogram consumer functions.
+ *
+ * \date   17/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/histogram.h>
+#include <l4/ferret/sensors/histogram_consumer.h>
+
+#include <stdio.h>
+
+L4_INLINE unsigned int
+ferret_histo_get(ferret_histo_t * histo, ferret_time_t x)
+{
+    int bin;
+
+    bin = (x - histo->head.low) * histo->head.bins / histo->head.size;
+    if (bin < 0 || bin >= histo->head.bins)
+        return 0;  // fail fast an silent, caller should know our range
+    else
+        return histo->data[bin];
+}
+
+L4_INLINE ferret_utime_t
+ferret_histo_get64(ferret_histo64_t * histo, ferret_time_t x)
+{
+    int bin;
+
+    bin = (x - histo->head.low) * histo->head.bins / histo->head.size;
+    if (bin < 0 || bin >= histo->head.bins)
+        return 0;  // fail fast an silent, caller should know our range
+    else
+        return histo->data[bin];
+}
+
+static void ferret_histo_dump_head(ferret_histo_header_t * h)
+{
+    printf("Histogram(%hu:%hu:%hu:%hu) [%lld, %lld>, bins: %u,"
+           " underflow: %u, overflow: %u\n",
+           h->header.major, h->header.minor,
+           h->header.instance, h->header.type,
+           h->low, h->high, h->bins, h->underflow, h->overflow);
+}
+
+void ferret_histo_dump(ferret_histo_t * h)
+{
+    unsigned int i;
+
+    ferret_histo_dump_head(&h->head);
+    for (i = 0; i < h->head.bins; i++)
+    {
+        printf("%u\t%u\n", i, h->data[i]);
+    }
+
+}
+
+void ferret_histo_dump_smart(ferret_histo_t * h)  // what a name :-/
+{
+    unsigned int i;
+
+    ferret_histo_dump_head(&h->head);
+    // do not print consecutive lines of 0s, only the border ones
+    if (h->head.bins < 3)  // print everything very small histograms
+    {
+        for (i = 0; i < h->head.bins; i++)
+        {
+            printf("%u\t%u\n", i, h->data[i]);
+        }
+    }
+    else
+    {
+        for (i = 0; i < h->head.bins; i++)
+        {
+            if ((h->data[i] == 0)                                  &&
+                ((i == 0)                || (h->data[i - 1] == 0)) &&
+                ((i == h->head.bins - 1) || (h->data[i + 1] == 0)))
+            {
+                continue;  // skip if we have at least three 0s in a row
+            }
+            printf("%u\t%u\n", i, h->data[i]);
+        }
+    }
+}
+
+void ferret_histo64_dump(ferret_histo64_t * h)
+{
+    unsigned int i;
+
+    ferret_histo_dump_head(&h->head);
+    for (i = 0; i < h->head.bins; i++)
+    {
+        printf("%u: %llu\n", i, h->data[i]);
+    }
+}
diff --git a/l4/pkg/ferret/lib/consumer/list_consumer.c b/l4/pkg/ferret/lib/consumer/list_consumer.c
new file mode 100644 (file)
index 0000000..1eb14fe
--- /dev/null
@@ -0,0 +1,127 @@
+/**
+ * \file   ferret/lib/sensor/list_consumer.c
+ * \brief  List consumer functions.
+ *
+ * \date   23/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/list.h>
+#include <l4/ferret/sensors/list_consumer.h>
+
+int ferret_list_get(ferret_list_moni_t * list, ferret_list_entry_t * el)
+{
+    /* 1. read tail pointer atomically
+     *  - do we still have the element requested?
+     *    No -> increase seq sensibly, Yes -> Go on!
+     * 2. read head pointer atomically
+     *  - do we already have the element requested? No -> Return, Yes -> Go on!
+     * 3. Get element (copy)
+     * 4. Check if we got an valid element (if we were not overtaken by tail)
+     *  - Yes -> Return valid data!
+     *  - No  -> Return, that we missed it!
+     */
+
+    ferret_list_index_t head, tail;
+    uint32_t index, el_ind;
+    int tries;
+
+    do    // get tail pointer
+    {
+        tail.lh.high = list->glob->tail.lh.high;
+        tail.lh.low  = list->glob->tail.lh.low;
+    } while (tail.lh.high != list->glob->tail.lh.high);
+
+    for (tries = 0; tries < 3; ++tries)
+    {
+        if (tail.parts.element > list->next_read)
+        {
+            // fixme: maybe we should skip more ?
+            list->lost += tail.parts.element - list->next_read;
+            list->next_read = tail.parts.element;
+        }
+
+        do    // get head pointer
+        {
+            head.lh.high = list->glob->head.lh.high;
+            head.lh.low  = list->glob->head.lh.low;
+        } while (head.lh.high != list->glob->head.lh.high);
+
+        if (head.parts.element > list->next_read)
+        {
+            // fixme: we should cache this information
+            index  = list->next_read % list->glob->count;
+            el_ind = list->ind_buf[index].parts.index;
+            if (el_ind >= list->glob->count)
+                continue;  // probably concurrent update -> inconsistent data
+
+            memcpy(el, ferret_list_e4i(list->glob, el_ind),
+                   list->glob->element_size);
+
+            // get tail pointer again to check whether we were
+            // overtaken in the last couple steps
+            do
+            {
+                tail.lh.high = list->glob->tail.lh.high;
+                tail.lh.low  = list->glob->tail.lh.low;
+            } while (tail.lh.high != list->glob->tail.lh.high);
+            if (tail.parts.element > list->next_read)
+            {
+                continue;  // probably inconsistent data, try once more
+            }
+            else           // consistent data, return it
+            {
+                ++(list->next_read);
+                return 0;
+            }
+        }
+        else
+        {
+            return -1;  // no new data available
+        }
+    }
+    return -2;  // corrupt sensor
+}
+
+void ferret_list_init_consumer(void ** addr)
+{
+    ferret_list_moni_t * temp;
+
+    temp = malloc(sizeof(ferret_list_moni_t));
+
+    // setup some pointers
+    temp->glob    = *addr;  // store pointer to global structure
+    temp->ind_buf = (ferret_list_index_t *)(temp->glob->data);
+    temp->out_buf = temp->glob->data +
+        sizeof(ferret_list_index_t) * temp->glob->count;
+
+    // copy header
+    temp->header.major    = temp->glob->header.major;
+    temp->header.minor    = temp->glob->header.minor;
+    temp->header.instance = temp->glob->header.instance;
+    temp->header.type     = temp->glob->header.type;
+
+    // init. local information
+    temp->lost      = 0;
+    temp->next_read = temp->glob->count;
+
+    *addr = temp;
+}
+
+void ferret_list_free_consumer(void ** addr)
+{
+    void * temp = ((ferret_list_moni_t *)(*addr))->glob;
+
+    free(*addr);
+
+    *addr = temp;
+}
diff --git a/l4/pkg/ferret/lib/consumer/monitor.cc b/l4/pkg/ferret/lib/consumer/monitor.cc
new file mode 100644 (file)
index 0000000..aa640ff
--- /dev/null
@@ -0,0 +1,202 @@
+/**
+ * \file   ferret/lib/monitor/monitor.cc
+ * \brief  Functions to access sensors from monitors.
+ *
+ * \date   10/03/2009
+ * \author Martin Pohlack <mp26@os.inf.tu-dresden.de>
+ * \author Bjoern Doebel <doebel@tudos.org>
+ */
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+
+#include <stdlib.h>
+#include <iostream>    // std::cout
+#include <l4/cxx/ipc_stream>    // L4::Ipc::Iostream
+#include <l4/re/util/cap_alloc> // L4::Cap
+#include <l4/re/dataspace>      // L4Re::Dataspace
+#include <l4/re/mem_alloc>      // mem_alloc()
+#include <l4/re/rm>             // L4::Rm
+#include <l4/re/env>            // L4::Env
+
+
+//#include <l4/ferret/clock.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/monitor.h>
+#include <l4/ferret/monitor_list.h>
+#include <l4/ferret/sensordir.h>
+
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/sensors/list_consumer.h>
+//#include <l4/ferret/sensors/dplist_consumer.h>
+//#include <l4/ferret/sensors/slist_consumer.h>
+//#include <l4/ferret/sensors/ulist_consumer.h>
+//#include <l4/ferret/sensors/tbuf.h>
+//#include <l4/ferret/sensors/tbuf_consumer.h>
+
+int ferret_attach(l4_cap_idx_t srv,
+                  uint16_t major, uint16_t minor,
+                  uint16_t instance, void ** addr)
+{
+       /*
+        * Locally alloc a cap for the new DS
+        */
+    L4::Cap<L4Re::Dataspace> ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
+
+       L4::Ipc::Iostream s(l4_utcb());
+       s << l4_umword_t(Attach);
+       s << major << minor << instance;
+       s << L4::Ipc::Small_buf(ds.cap(), 0);
+
+       l4_msgtag_t res = s.call(srv, /* Protocol = */ Monitor);
+       if (l4_ipc_error(res, l4_utcb()))
+       {
+               std::cout << "IPC error in " << __func__ << "()\n";
+               return -1;
+       }
+
+       /*
+        * unpack return val
+        */
+       int ret, err;
+       s >> ret;
+
+       /*
+        * Post-processing
+        */
+       if (ret == 0)
+       {
+#if DEBUG
+               std::cout << "Successfully attached. Got DS.\n";
+#endif
+               if (!ds.is_valid())
+               {
+                       std::cout << "No DS mapped during attach.\n";
+                       return -1;
+               }
+
+               err =  L4Re::Env::env()->rm()->attach(addr, ds->size(),
+                                                     L4Re::Rm::Search_addr,
+                                                     ds);
+               if (err < 0)
+               {
+                       std::cout << "Could not attach DS in " << __func__ << "\n";
+                       std::cout << "Error: " <<  l4sys_errtostr(err) << "\n";
+                       return -1;
+               }
+
+               /*
+                * Sensor-specific processing
+                */
+               switch(((ferret_common_t*)*addr)->type)
+               {
+                       case FERRET_LIST:
+                               ferret_list_init_consumer(addr);
+                               break;
+                       case FERRET_SCALAR:
+                               // fall through
+                       default:
+                               break;
+               }
+       }
+       else
+       {
+               std::cout << "Failure attaching to sensor " << ret << "\n";
+       }
+
+       return ret;
+}
+
+int ferret_detach(l4_cap_idx_t srv,
+                  uint16_t major, uint16_t minor,
+                  uint16_t instance, void ** addr)
+{
+       L4::Ipc::Iostream s(l4_utcb());
+       s << l4_umword_t(Detach);
+       s << major << minor << instance;
+
+       l4_msgtag_t res = s.call(srv, /* Protocol = */ Monitor);
+       if (l4_ipc_error(res, l4_utcb()))
+       {
+               std::cout << "IPC error in " << __func__ << "()\n";
+               return -1;
+       }
+
+       /*
+        * unpack return val
+        */
+       int ret;
+       s >> ret;
+
+       if (ret == 0)
+       {
+               /*
+                * Sensor-specific processing
+                */
+               switch(((ferret_common_t*)*addr)->type)
+               {
+                       case FERRET_SCALAR:
+                               // fall through
+                       default:
+                               break;
+               }
+
+               // detach dataspace
+               L4::Cap<L4Re::Dataspace> ds(((ferret_common_t*)*addr)->ds_cap);
+
+               int err =  L4Re::Env::env()->rm()->detach(*addr, 0);
+#if DEBUG
+               std::cout << "detach: " << err << "\n";
+#endif
+               if (err == L4Re::Rm::Detached_ds)
+               {
+                       l4_msgtag_t res = l4_task_unmap(L4RE_THIS_TASK_CAP,
+                                                       ds.fpage(), L4_FP_ALL_SPACES);
+                       if (l4_error(res))
+                       {
+                               std::cout << "unmap error: " << l4_error(res) << "\n";
+                               ret = -1;
+                       }
+               }
+               else
+               {
+                       std::cout << "Error detaching sensor ds.\n";
+                       ret = -1;
+               }
+       }
+       else
+       {
+               std::cout << "Failure detaching sensor: " << ret << "\n";
+       }
+
+       return ret;
+}
+
+int ferret_list(l4_cap_idx_t srv __attribute__((unused)),
+                ferret_monitor_list_entry_t ** entries __attribute__((unused)),
+                int count __attribute__((unused)),
+                int offset __attribute__((unused)))
+{
+#if 0
+    int ret;
+    CORBA_Environment _dice_corba_env = dice_default_environment;
+    _dice_corba_env.malloc = (dice_malloc_func)malloc;
+    _dice_corba_env.free = (dice_free_func)free;
+
+    // get sensor_dir task id lazily
+    if (l4_is_invalid_id(ferret_sensor_dir))
+        ferret_sensor_dir = ferret_comm_get_threadid();
+
+    ret = ferret_monitor_list_call(&ferret_sensor_dir, entries, &count, offset,
+                                    &_dice_corba_env);
+    if (ret < 0)
+        return ret;
+    else
+        return count;
+#endif
+       return -1;
+}
diff --git a/l4/pkg/ferret/lib/consumer/scalar_consumer.c b/l4/pkg/ferret/lib/consumer/scalar_consumer.c
new file mode 100644 (file)
index 0000000..e0a5366
--- /dev/null
@@ -0,0 +1,21 @@
+/**
+ * \file   ferret/lib/sensor/scalar_consumer.c
+ * \brief  Scalar consumer functions.
+ *
+ * \date   08/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/scalar.h>
+#include <l4/ferret/sensors/scalar_consumer.h>
+
+ferret_time_t ferret_scalar_get(ferret_scalar_t * scalar)
+{
+    return scalar->data;
+}
diff --git a/l4/pkg/ferret/lib/consumer/slist_consumer.c b/l4/pkg/ferret/lib/consumer/slist_consumer.c
new file mode 100644 (file)
index 0000000..a554482
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * \file   ferret/lib/sensor/slist_consumer.c
+ * \brief  slist consumer functions.
+ *
+ * \date   2007-06-13
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/sensors/slist.h>
+#include <l4/ferret/sensors/slist_consumer.h>
+
+#include <l4/ferret/sensors/__slist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include "__llist_consumer.c"
diff --git a/l4/pkg/ferret/lib/consumer/tbuf_consumer.c b/l4/pkg/ferret/lib/consumer/tbuf_consumer.c
new file mode 100644 (file)
index 0000000..3b3a8e6
--- /dev/null
@@ -0,0 +1,141 @@
+/**
+ * \file   ferret/lib/sensor/tbuf_consumer.c
+ * \brief  Tracebuffer consumer functions.
+ *
+ * \date   06/12/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+// fixme: debug
+//#include <l4/log/l4log.h>
+
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/tbuf.h>
+#include <l4/ferret/sensors/tbuf_consumer.h>
+
+int ferret_tbuf_get(ferret_tbuf_moni_t * tbuf, l4_tracebuffer_entry_t * el)
+{
+    /* 1. compute index from next_read
+     * 2. compare count in element + version with next_read
+     * 3. copy element
+     * 4. check count again
+     */
+
+    unsigned int index, ec;
+    uint64_t ecl;
+    uint64_t version, version2, version3;
+
+    while (1)
+    {
+        index = ((uint32_t)(tbuf->next_read - 1)) & tbuf->mask;
+
+        if (index < tbuf->count2)
+            version = tbuf->status->version0;
+        else
+            version = tbuf->status->version1;
+
+        // fixme: memory barrier
+
+        ec = tbuf->status->tracebuffer0[index].number;
+
+        if (tbuf->status->tracebuffer0[index].type == l4_ktrace_tbuf_unused)
+        {
+            //LOG("XXXu %p, %d", tbuf->status->tracebuffer0, index);
+            return -1;  // unused event, no more data available
+        }
+
+        //LOG("version %llu, number %u", version, ec);
+        ecl = ((ec - 1) | ((version >> tbuf->offset) << (sizeof(ec) * 8)));
+        if (ecl >= (version + 1) * tbuf->count)
+            ecl -= 1LL << (sizeof(ec) * 8);  // 2 ^ 32
+        ++ecl;
+        //LOG("next %llu, ecl %llu", tbuf->next_read, ecl);
+
+        if (index < tbuf->count2)
+            version2 = tbuf->status->version0;
+        else
+            version2 = tbuf->status->version1;
+
+        if (version != version2)
+            continue;  // found inconsistent values, retry
+
+        if (ecl < tbuf->next_read)
+        {
+            //LOG("XXXl %p, %d", tbuf->status->tracebuffer0, index);
+            return -1;  // we have reached the limit -> no new data available
+        }
+        else if (ecl > tbuf->next_read)
+        {
+            //LOG("XXXlost");
+            // fixme: find better way to compute new element
+            tbuf->lost += ecl - tbuf->next_read;
+            tbuf->next_read = ecl;
+            continue;
+        }
+        memcpy(el, &tbuf->status->tracebuffer0[index],
+               sizeof(l4_tracebuffer_entry_t));
+
+        // fixme: enforce new memory access
+        if (index < tbuf->count2)
+            version3 = tbuf->status->version0;
+        else
+            version3 = tbuf->status->version1;
+        if (ec != tbuf->status->tracebuffer0[index].number ||
+            version2 != version3)
+        {
+            continue;  // we might have lost this event -> retry
+        }
+        ++(tbuf->next_read);
+        return 0;  // everything ok, got data
+    }
+}
+
+void ferret_tbuf_init_consumer(void ** addr)
+{
+    ferret_tbuf_moni_t * temp;
+    int ld, count;
+
+    temp = malloc(sizeof(ferret_tbuf_moni_t));
+
+    // setup some pointers
+    temp->status = *addr;  // store pointer to global structure
+
+    // copy header
+    temp->header.major    = FERRET_TBUF_MAJOR;
+    temp->header.minor    = FERRET_TBUF_MINOR;
+    temp->header.instance = FERRET_TBUF_INSTANCE;
+    temp->header.type     = FERRET_TBUF;
+
+    // init. local information
+    temp->lost      = 0;
+    temp->next_read = 1;  // fixme: set this to current element
+    temp->size      = temp->status->size0 + temp->status->size1;
+    temp->count     = temp->size / sizeof(l4_tracebuffer_entry_t);
+    temp->count2    = temp->count / 2;
+    temp->mask      = temp->count - 1;
+
+    // compute log2(count)
+    for (ld = 0, count = temp->count; count > 1; ++ld)
+        count = count / 2;
+
+    temp->offset    = sizeof(unsigned int) * 8 - ld;
+
+    *addr = temp;
+}
+
+void ferret_tbuf_free_consumer(void ** addr)
+{
+    void * temp = ((ferret_tbuf_moni_t *)(*addr))->status;
+
+    free(*addr);
+
+    *addr = temp;
+}
diff --git a/l4/pkg/ferret/lib/consumer/ulist_consumer.c b/l4/pkg/ferret/lib/consumer/ulist_consumer.c
new file mode 100644 (file)
index 0000000..c2186aa
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/lib/sensor/slist_consumer.c
+ * \brief  ulist consumer functions.
+ *
+ * \date   2007-06-19
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/sensors/ulist.h>
+#include <l4/ferret/sensors/ulist_consumer.h>
+
+#include <l4/ferret/fpages.h>
+#include <l4/ferret/local_names.h>
+#include <l4/util/macros.h>
+
+#include <l4/ferret/sensors/__ulist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include "__llist_consumer.c"
diff --git a/l4/pkg/ferret/lib/fpages/Makefile b/l4/pkg/ferret/lib/fpages/Makefile
new file mode 100644 (file)
index 0000000..be9e2d8
--- /dev/null
@@ -0,0 +1,13 @@
+PKGDIR   ?= ../..
+L4DIR    ?= $(PKGDIR)/../..
+
+CLIENTIDL = ferret_fpages.idl
+SRC_C     = fpages.c
+
+MODE      = l4env_minimal
+
+SYSTEMS   = x86-l4f
+
+TARGET    = libferret_fpages.a
+
+include $(L4DIR)/mk/lib.mk
diff --git a/l4/pkg/ferret/lib/fpages/broken b/l4/pkg/ferret/lib/fpages/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/lib/fpages/fpages.c b/l4/pkg/ferret/lib/fpages/fpages.c
new file mode 100644 (file)
index 0000000..e788dd1
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * \file   ferret/lib/fpages/fpages.c
+ * \brief  IDL wrapper for fpages interface
+ *
+ * \date   2007-06-21
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006, 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/l4rm/l4rm.h>
+#include <l4/log/l4log.h>
+
+#include <l4/ferret/ferret_fpages-client.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/client.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/fpages.h>
+
+int ferret_fpages_request(int ksem, uint16_t major, uint16_t minor,
+                          uint16_t instance)
+{
+    int ret;
+    l4_snd_fpage_t page;
+
+    CORBA_Environment _dice_corba_env = dice_default_environment;
+    _dice_corba_env.malloc = (dice_malloc_func)malloc;
+    _dice_corba_env.free = (dice_free_func)free;
+
+    // get ferret_sensor_dir task id lazily
+    if (l4_is_invalid_id(ferret_sensor_dir))
+        ferret_sensor_dir = ferret_comm_get_threadid();
+
+    _dice_corba_env.rcv_fpage = l4_iofpage(ksem, 0, 0);
+    _dice_corba_env.rcv_fpage.iofp.zero2 = 2;
+    _dice_corba_env.rcv_fpage.raw       |= 2;  // what is this?
+
+    ret = ferret_fpages_request_call(&ferret_sensor_dir, major, minor,
+                                     instance, &page, &_dice_corba_env);
+    return ret;
+}
diff --git a/l4/pkg/ferret/lib/gcc_instrument/Makefile b/l4/pkg/ferret/lib/gcc_instrument/Makefile
new file mode 100644 (file)
index 0000000..4fd9fb0
--- /dev/null
@@ -0,0 +1,13 @@
+PKGDIR   ?= ../..
+L4DIR    ?= $(PKGDIR)/../..
+
+SRC_C_libferret_gcc_instrument.a     = instrument.c
+SRC_C_libferret_gcc_instrument_std.a = std_instrument.c
+
+MODE      = l4env_minimal
+
+SYSTEMS   = x86-l4f
+
+TARGET    = libferret_gcc_instrument.a libferret_gcc_instrument_std.a
+
+include $(L4DIR)/mk/lib.mk
diff --git a/l4/pkg/ferret/lib/gcc_instrument/broken b/l4/pkg/ferret/lib/gcc_instrument/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/lib/gcc_instrument/instrument.c b/l4/pkg/ferret/lib/gcc_instrument/instrument.c
new file mode 100644 (file)
index 0000000..691b634
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * \file   ferret/lib/gcc-instrument/instrument.c
+ * \brief  Support functions for gcc-function-level instrumentation
+ *
+ * \date   2007-10-09
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+// fixme: provide explicit init call with function pointers for
+//        myself() and malloc()
+
+#include <stdlib.h>
+
+#include <l4/log/l4log.h>
+
+#include <l4/ferret/gcc_instrument.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/list_producer_wrap.h>
+
+/*
+ * declarations
+ */
+void __cyg_profile_func_enter(void *func_address, void *call_site)
+    __attribute__ ((no_instrument_function));
+
+void __cyg_profile_func_exit (void *func_address, void *call_site)
+    __attribute__ ((no_instrument_function));
+
+void main_constructor(void)
+    __attribute__ ((no_instrument_function, constructor));
+
+void main_destructor(void)
+    __attribute__ ((no_instrument_function, destructor));
+
+/*
+ * implementations
+ */
+ferret_list_local_t * __func_trace_list = NULL;
+l4_threadid_t (*ferret_gcc_instrument_myself_func)(void) = NULL;
+
+void __cyg_profile_func_enter(void *func_address, void *callsite)
+{
+    if (__func_trace_list)
+        ferret_list_post_1t2w(__func_trace_list,
+                              FERRET_FUNC_TRACE_MAJOR,
+                              FERRET_FUNC_TRACE_MINOR_ENTER, 0,
+                              l4_myself(), (int)func_address, (int)callsite);
+}
+
+void __cyg_profile_func_exit(void *func_address, void *callsite)
+{
+    if (__func_trace_list)
+        ferret_list_post_1t2w(__func_trace_list,
+                              FERRET_FUNC_TRACE_MAJOR,
+                              FERRET_FUNC_TRACE_MINOR_EXIT, 0,
+                              l4_myself(), (int)func_address, (int)callsite);
+}
+
+
+/*
+void main_constructor(void)
+{
+    int ret;
+
+    ret = ferret_create(FERRET_FUNC_TRACE_MAJOR, FERRET_FUNC_TRACE_MINOR_EXIT,
+                        0, FERRET_LIST, FERRET_SUPERPAGES, "64:65000",
+                        __func_trace_list, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+}
+
+void main_destructor(void)
+{
+    // fixme: close specific sensor here
+}
+*/
+
+/* Set two function pointers and create sensor.
+ */
+void ferret_gcc_instrument_init(void *(*alloc)(size_t s),
+                                l4_threadid_t (*myself)(void))
+{
+    int ret;
+    ferret_gcc_instrument_myself_func = myself;
+
+    // smaller event size, we know what will be inside
+    ret = ferret_create(FERRET_FUNC_TRACE_MAJOR, FERRET_FUNC_TRACE_MINOR_EXIT,
+                        0, FERRET_LIST, FERRET_SUPERPAGES, "32:65000",
+                        __func_trace_list, alloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+}
diff --git a/l4/pkg/ferret/lib/gcc_instrument/std_instrument.c b/l4/pkg/ferret/lib/gcc_instrument/std_instrument.c
new file mode 100644 (file)
index 0000000..efa473e
--- /dev/null
@@ -0,0 +1,78 @@
+/**
+ * \file   ferret/lib/gcc-instrument/std_instrument.c
+ * \brief  Support functions for gcc-function-level instrumentation,
+ *         std version for L4
+ *
+ * \date   2007-10-10
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <stdlib.h>
+
+#include <l4/crtx/ctor.h>
+#include <l4/log/l4log.h>
+
+#include <l4/ferret/gcc_instrument.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/list_producer_wrap.h>
+
+/*
+ * declarations
+ */
+void __cyg_profile_func_enter(void *func_address, void *call_site)
+    __attribute__ ((no_instrument_function));
+
+void __cyg_profile_func_exit (void *func_address, void *call_site)
+    __attribute__ ((no_instrument_function));
+
+/*
+ * implementations
+ */
+ferret_list_local_t * __func_trace_list = NULL;
+
+void __cyg_profile_func_enter(void *func_address, void *callsite)
+{
+    ferret_list_post_1t2wc(__func_trace_list, __func_trace_list,
+                           FERRET_FUNC_TRACE_MAJOR,
+                           FERRET_FUNC_TRACE_MINOR_ENTER, 0,
+                           l4_myself(), (int)func_address, (int)callsite);
+}
+
+void __cyg_profile_func_exit(void *func_address, void *callsite)
+{
+    ferret_list_post_1t2wc(__func_trace_list, __func_trace_list,
+                           FERRET_FUNC_TRACE_MAJOR,
+                           FERRET_FUNC_TRACE_MINOR_EXIT, 0,
+                           l4_myself(), (int)func_address, (int)callsite);
+}
+
+void main_constructor(void)
+{
+    int ret;
+
+    // smaller event size, we know what will be inside
+    ret = ferret_create(FERRET_FUNC_TRACE_MAJOR, FERRET_FUNC_TRACE_MINOR_EXIT,
+                        0, FERRET_LIST, FERRET_SUPERPAGES, "32:65000",
+                        __func_trace_list, &malloc);
+    if (ret)
+    {
+        LOG("Error creating sensor: ret = %d", ret);
+        exit(1);
+    }
+}
+L4C_CTOR(main_constructor, 4000);
+
+void main_destructor(void)
+{
+    // fixme: close specific sensor here
+}
+L4C_DTOR(main_destructor, 4000);
diff --git a/l4/pkg/ferret/lib/local_names/Makefile b/l4/pkg/ferret/lib/local_names/Makefile
new file mode 100644 (file)
index 0000000..c4449aa
--- /dev/null
@@ -0,0 +1,12 @@
+PKGDIR   ?= ../..
+L4DIR    ?= $(PKGDIR)/../..
+
+SRC_C     = local_names.c
+
+MODE      = l4env_minimal
+
+SYSTEMS   = x86-l4f
+
+TARGET    = libferret_local_names.a
+
+include $(L4DIR)/mk/lib.mk
diff --git a/l4/pkg/ferret/lib/local_names/broken b/l4/pkg/ferret/lib/local_names/broken
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/l4/pkg/ferret/lib/local_names/local_names.c b/l4/pkg/ferret/lib/local_names/local_names.c
new file mode 100644 (file)
index 0000000..a205c9a
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * \file   ferret/lib/local_names/local_names.c
+ * \brief  Manage local names for kernel objects (e.g., Fiasco's User
+ *         Semaphores)
+ *
+ * \date   2007-06-20
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/l4rm/l4rm.h>
+#include <l4/log/l4log.h>
+#include <l4/sys/l4int.h>
+#include <l4/util/bitops.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/local_names.h>
+
+#define MAX_LOCAL_NAMES 256  // fixme: the kernel should export this constant
+
+static l4_mword_t
+bitarray[(MAX_LOCAL_NAMES + L4_MWORD_BITS - 1) / L4_MWORD_BITS];
+
+int ferret_local_names_reserve(void)
+{
+    int i;
+    for (i = 1; i < MAX_LOCAL_NAMES; i++)
+    {
+        if (! l4util_bts(i % L4_MWORD_BITS, &(bitarray[i / L4_MWORD_BITS])))
+        {
+            break;
+        }
+    }
+    if (i >= MAX_LOCAL_NAMES)
+        return 0;
+    else
+        return i;
+}
+
+void ferret_local_names_dispose(int index)
+{
+    if (index < MAX_LOCAL_NAMES)
+    {
+        l4util_clear_bit(index % L4_MWORD_BITS,
+                         &(bitarray[index / L4_MWORD_BITS]));
+    }
+}
diff --git a/l4/pkg/ferret/lib/producer/Makefile b/l4/pkg/ferret/lib/producer/Makefile
new file mode 100644 (file)
index 0000000..329ee3f
--- /dev/null
@@ -0,0 +1,19 @@
+PKGDIR   ?= ../..
+L4DIR    ?= $(PKGDIR)/../..
+
+SRC_CC_libferret_client.a     = create.cc
+SRC_C_libferret_init.a        = scalar_init.c list_init.c
+SRC_C_libferret_producer.a    = list_producer.c
+
+PC_FILENAME = ferret-producer
+
+#free.c instance.c create.c create_dir.c
+
+SYSTEMS   = x86-l4f
+REQUIRES_LIBS = libboost-lite
+
+TARGET    = libferret_client.a \
+                       libferret_init.a   \
+                       libferret_producer.a
+
+include $(L4DIR)/mk/lib.mk
diff --git a/l4/pkg/ferret/lib/producer/__llist_init.c b/l4/pkg/ferret/lib/producer/__llist_init.c
new file mode 100644 (file)
index 0000000..ee00537
--- /dev/null
@@ -0,0 +1,129 @@
+/**
+ * \file   ferret/lib/sensor/__llist_init.c
+ * \brief  locked list init functions.
+ *
+ * \date   2007-05-16
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#if FERRET_LLIST_MAGIC != ahK6eeNa
+#error Do not directly include this file, use a propper wrapper!
+#endif
+#undef FERRET_LLIST_MAGIC
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/common.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <l4/util/bitops.h>
+
+//#include <l4/log/l4log.h>
+
+int PREFIX(init)(PREFIX(t) * list, const char * config, char ** data)
+{
+    uint32_t size, size_ld, count, count_ld;
+    int ret;
+
+    // "<element size>:<element count>"
+    ret = sscanf(config, "%u:%u", &size, &count);
+    //LOG("Config found: %u:%u", size, count);
+
+    if (ret != 2 ||
+        size > FERRET_LLIST_MAX_ELEMENT || size < sizeof(ferret_utime_t) ||
+        count > FERRET_LLIST_MAX_COUNT || count < 2)
+    {
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+        return -1;
+    }
+
+    // compute next power of two for element
+    size_ld = l4util_log2(size);
+    if (size > (1 << size_ld))
+        size_ld++;
+    size = (1 << size_ld);
+
+    // compute next power of two for count
+    count_ld = l4util_log2(count);
+    if (count > (1 << count_ld))
+        count_ld++;
+    count = (1 << count_ld);
+
+    if (((long long)size) * count > SSIZE_MAX)
+    {
+        //LOG("Warning: buffer would be too large!");
+        return -2;
+    }
+
+    list->head.value         = 0;
+    list->count              = count;
+    //list->count_ld           = count_ld;
+    list->count_mask         = (1 << count_ld) - 1;
+    list->element_size       = size;
+    list->element_size_ld    = size_ld;
+    list->flags              = 0;
+
+    FERRET_LLIST_INIT(list, data);
+
+    memset(list->data, 0, list->count * list->element_size);
+
+    return 0;
+}
+
+// fixme: all of the sensor type functions should be stored in a
+//        function table
+ssize_t PREFIX(size_config)(const char * config)
+{
+    uint32_t size, size_ld, count, count_ld;
+    int ret;
+
+    // "<element size>:<element count>"
+    ret = sscanf(config, "%u:%u", &size, &count);
+    //LOG("Config found: %u:%u", size, count);
+
+    if (ret != 2 ||
+        size > FERRET_LLIST_MAX_ELEMENT || size < sizeof(ferret_utime_t) ||
+        count > FERRET_LLIST_MAX_COUNT || count < 2)
+    {
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+        return -1;
+    }
+
+    // compute next power of two for element
+    size_ld = l4util_log2(size);
+    if (size > (1 << size_ld))
+        size_ld++;
+    size = (1 << size_ld);
+
+    // compute next power of two for count
+    count_ld = l4util_log2(count);
+    if (count > (1 << count_ld))
+        count_ld++;
+    count = (1 << count_ld);
+
+    if (((long long)size) * count > SSIZE_MAX)
+    {
+        //LOG("Warning: buffer would be too large!");
+        return -2;
+    }
+
+    // header + element buffer
+    return sizeof(PREFIX(t)) + size * count;
+}
+
+ssize_t PREFIX(size)(const PREFIX(t) * list)
+{
+    uint32_t size, count;
+
+    size  = list->element_size;
+    count = list->count;
+
+    return sizeof(PREFIX(t)) + size * count;
+}
diff --git a/l4/pkg/ferret/lib/producer/__llist_producer.c b/l4/pkg/ferret/lib/producer/__llist_producer.c
new file mode 100644 (file)
index 0000000..fbcb053
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * \file   ferret/lib/sensor/__llist_producer.c
+ * \brief  locked list producer functions.
+ *
+ * \date   2007-06-19
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#if FERRET_LLIST_MAGIC != ahK6eeNa
+#error Do not directly include this file, use a propper wrapper!
+#endif
+#undef FERRET_LLIST_MAGIC
+
+#include <stdlib.h>
+
+// fixme: debug
+//#include <l4/log/l4log.h>
+#include <l4/ferret/types.h>
+
+#include <l4/sys/ipc.h>
+
+void PREFIX(init_producer)(void ** addr, void *(*alloc)(size_t size))
+{
+    PREFIX(local_t) * temp;
+
+    temp = (*alloc)(sizeof(PREFIX(local_t)));
+
+    // setup some pointers
+    temp->glob    = *addr;  // store pointer to global structure
+
+    // copy header
+    temp->header.major    = temp->glob->header.major;
+    temp->header.minor    = temp->glob->header.minor;
+    temp->header.instance = temp->glob->header.instance;
+    temp->header.type     = temp->glob->header.type;
+
+#ifdef FERRET_LLIST_HAVE_LOCAL_LOCK
+    FERRET_LLIST_LOCAL_INIT(temp);
+#endif
+
+    *addr = temp;
+}
+
+void PREFIX(free_producer)(void ** addr, void (*free)(void *))
+{
+    void * temp = ((PREFIX(local_t) *)(*addr))->glob;
+
+    // fixme: remove local mappings
+    (*free)(*addr);
+
+    *addr = temp;
+}
diff --git a/l4/pkg/ferret/lib/producer/alist_init.c b/l4/pkg/ferret/lib/producer/alist_init.c
new file mode 100644 (file)
index 0000000..ebf1fe6
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+ * \file   ferret/lib/sensor/alist_init.c
+ * \brief  Atomic list init functions.
+ *
+ * \date   2007-07-23
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <l4/ferret/sensors/alist.h>
+#include <l4/ferret/sensors/alist_init.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <l4/util/bitops.h>
+
+int ferret_alist_init(ferret_alist_t * list, const char * config)
+{
+    uint32_t count, count_ld;
+    int ret;
+
+    // "<element count>"
+    ret = sscanf(config, "%u", &count);
+
+    if (ret != 1 ||
+        count > FERRET_ALIST_MAX_COUNT || count < 2)
+    {
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+        return -1;
+    }
+
+    // compute next power of two for count
+    count_ld = l4util_log2(count);
+    if (count > (1 << count_ld))
+        count_ld++;
+    count = (1 << count_ld);
+
+    if (((long long)FERRET_ALIST_ELEMENT_SIZE) * count > SSIZE_MAX)
+    {
+        //LOG("Warning: buffer would be too large!");
+        return -2;
+    }
+
+    list->head               = 0;
+    list->count              = count;
+    list->count_ld           = count_ld;
+    list->count_mask         = (1 << count_ld) - 1;
+    list->flags              = 0;
+
+    memset(list->data, 0, list->count * FERRET_ALIST_ELEMENT_SIZE);
+
+    return 0;
+}
+
+ssize_t ferret_alist_size_config(const char * config)
+{
+    uint32_t count, count_ld;
+    int ret;
+
+    // "<element count>"
+    ret = sscanf(config, "%u", &count);
+
+    if (ret != 1 ||
+        count > FERRET_ALIST_MAX_COUNT || count < 2)
+    {
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+        return -1;
+    }
+
+    // compute next power of two for count
+    count_ld = l4util_log2(count);
+    if (count > (1 << count_ld))
+        count_ld++;
+    count = (1 << count_ld);
+
+    if (((long long)FERRET_ALIST_ELEMENT_SIZE) * count > SSIZE_MAX)
+    {
+        //LOG("Warning: buffer would be too large!");
+        return -2;
+    }
+
+    // header + element buffer
+    return sizeof(ferret_alist_t) + count * FERRET_ALIST_ELEMENT_SIZE;
+}
+
+ssize_t ferret_alist_size(const ferret_alist_t * list)
+{
+    return sizeof(ferret_alist_t) + FERRET_ALIST_ELEMENT_SIZE * list->count;
+}
diff --git a/l4/pkg/ferret/lib/producer/alist_producer.S b/l4/pkg/ferret/lib/producer/alist_producer.S
new file mode 100644 (file)
index 0000000..41d6f85
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+__ferret_kern_lib_page = 0xef7ff000
+.hidden __ferret_kern_lib_page
+
+       .macro  kern_lib_page_entry entry,offset
+\entry = __ferret_kern_lib_page + \offset
+.global \entry
+.hidden \entry
+       .endm
+
+       kern_lib_page_entry     __ferret_alist_post, 0x0
diff --git a/l4/pkg/ferret/lib/producer/common.c b/l4/pkg/ferret/lib/producer/common.c
new file mode 100644 (file)
index 0000000..b100b17
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * \file   ferret/lib/sensors/common.c
+ * \brief  Common sensor header functions
+ *
+ * \date   08/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <l4/ferret/sensors/common.h>
+
+void ferret_common_init(ferret_common_t * c,
+                        uint16_t major, uint16_t minor,
+                        uint16_t instance, uint16_t type,
+                        l4dm_dataspace_t ds)
+{
+    c->major    = major;
+    c->minor    = minor;
+    c->instance = instance;
+    c->type     = type;
+    c->ds       = ds;
+}
diff --git a/l4/pkg/ferret/lib/producer/create.cc b/l4/pkg/ferret/lib/producer/create.cc
new file mode 100644 (file)
index 0000000..35a1256
--- /dev/null
@@ -0,0 +1,187 @@
+/**
+ * \file   ferret/lib/client/create.cc
+ * \brief  Function to create a new sensor at the directory.
+ *
+ * \date   2009-03-07
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ * \author Bjoern Doebel   <doebel@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+
+#include <iostream>    // std::cout
+#include <l4/cxx/ipc_stream>    // L4::Ipc::Iostream
+#include <l4/re/util/cap_alloc> // L4::Cap
+#include <l4/re/dataspace>      // L4Re::Dataspace
+#include <l4/re/mem_alloc>      // mem_alloc()
+#include <l4/re/rm>             // L4::Rm
+#include <l4/re/env>            // L4::Env
+#include <l4/sys/kdebug.h>      // enter_kdebug()
+
+#include <string>
+#include <vector>
+#include <boost/tokenizer.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/format.hpp>
+
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/sensors/scalar.h>
+#include <l4/ferret/sensors/scalar_init.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/list_init.h>
+#include <l4/ferret/sensordir.h>
+
+#define DEBUG 0
+
+static int _ferret_create_sensor(l4_cap_idx_t dir_cap,
+                                 uint16_t major, uint16_t minor,
+                                 uint16_t instance, uint16_t type,
+                                 uint32_t flags, const char * config,
+                                 void ** addr, void *(*alloc)(size_t s))
+{
+#if DEBUG
+       std::cout << __func__ << "\n";
+       std::cout << Client << " .. " << Create << "\n";
+       std::cout << "(" << major << "," << minor << "," << instance << ")\n";
+       std::cout << type << ", " << flags << "\n";
+#endif
+       int err;
+       unsigned e_size = 0, e_num = 0;
+
+       switch (type)
+       {
+               case FERRET_SCALAR:
+                       break;
+               case FERRET_LIST:
+                       {
+                               std::vector<std::string> v(2);
+                               boost::split(v, config, boost::is_any_of(":"));
+                               e_size = atoi(v[0].c_str());
+                               e_num  = atoi(v[1].c_str());
+#if DEBUG
+                               std::cout << "size = " << e_size << " * " << e_num
+                                         << " = " << e_size * e_num << "\n";
+#endif
+
+                       }
+       }
+
+       /*
+        * Locally alloc a cap for the new DS
+        */
+    L4::Cap<L4Re::Dataspace> ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
+
+#if DEBUG
+       std::cout << "allocated cap: " << ds.cap() << "\n";
+#endif
+
+       L4::Ipc::Iostream s(l4_utcb());
+       s << l4_umword_t(Create);                         // Opcode
+       s << major << minor << instance << type << flags; // Parameters
+
+       /*
+        * Sensor-specific parameters
+        */
+       switch(type)
+       {
+               case FERRET_SCALAR:
+                       // fall through
+               case FERRET_LIST:
+                       s << e_size << e_num;
+               default:
+                       break;
+       }
+
+       // recv fpage is final parameter
+       s << L4::Ipc::Small_buf(ds.cap(), 0);                  // Recv. fpage for ds cap
+
+       l4_msgtag_t res = s.call(dir_cap, /* Protocol = */ Client);
+       if (l4_ipc_error(res, l4_utcb()))
+       {
+               std::cout << "IPC error in " << __func__ << "()\n";
+               return -1;
+       }
+
+       /*
+        * unpack return val
+        */
+       int ret;
+       s >> ret;
+
+       /*
+        * Post-processing
+        */
+       if (ret == 0)
+       {
+               if (!ds.is_valid())
+               {
+                       std::cout << "Did not get a cap mapped in create_sensor()\n";
+                       return -1;
+               }
+
+               /*
+                * Fill sensor header
+                */
+               err =  L4Re::Env::env()->rm()->attach(addr, ds->size(),
+                                                     L4Re::Rm::Search_addr | L4Re::Rm::Eager_map,
+                                                     ds);
+               if (err < 0)
+               {
+                       std::cout << "Attach DS failed in " << __func__ << "\n";
+                       return -1;
+               }
+
+               ferret_common_t *_head = (ferret_common_t*)(*addr);
+               _head->major    = major;
+               _head->minor    = minor;
+               _head->instance = instance;
+               _head->type     = type;
+               _head->ds_cap   = ds.cap();
+               _head->ds_size  = ds->size();
+
+               /*
+                * Sensor-specific processing
+                */
+               switch(type)
+               {
+                       case FERRET_SCALAR:
+                               err = ferret_scalar_init((ferret_scalar_t*)*addr, config);
+                               if (err)
+                                       std::cout << "Error configuring scalar sensor\n";
+                               break;
+                       case FERRET_LIST:
+                               ferret_list_init((ferret_list_t*)*addr, config);
+                               ferret_list_init_producer(addr, alloc);
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+       return ret;
+}
+
+int ferret_create_sensor(l4_cap_idx_t dir_cap,
+                         uint16_t major, uint16_t minor,
+                         uint16_t instance, uint16_t type,
+                         uint32_t flags, const char * config,
+                         void ** addr, void *(*alloc)(size_t s))
+{
+#if 0
+    // get ferret_sensor_dir thread_id lazily
+    if (l4_is_invalid_id(ferret_sensor_dir))
+        ferret_sensor_dir = ferret_comm_get_threadid();
+#endif
+
+    return _ferret_create_sensor(dir_cap, major, minor, instance, type,
+                                 flags, config, addr, alloc);
+}
diff --git a/l4/pkg/ferret/lib/producer/create_dir.c b/l4/pkg/ferret/lib/producer/create_dir.c
new file mode 100644 (file)
index 0000000..795e6cd
--- /dev/null
@@ -0,0 +1,108 @@
+/**
+ * \file   ferret/lib/client/create_dir.c
+ * \brief  Function to create a new sensor at the directory for non
+ *         L4Env clients.
+ *
+ * \date   2006-04-06
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/dm_phys/dm_phys.h>
+#include <l4/log/l4log.h>
+#include <l4/sys/types.h>
+#include <l4/util/macros.h>
+
+#include <l4/ferret/ferret_client-client.h>
+
+#include <l4/ferret/clock.h>
+#include <l4/ferret/types.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/ulist_producer.h>
+
+int ferret_create_sensor_dir(uint16_t major, uint16_t minor,
+                             uint16_t instance, uint16_t type,
+                             uint32_t flags, const char * config,
+                             void ** addr, void *(*alloc)(size_t s),
+                             l4_threadid_t dir)
+{
+    // explicitly set ferret_sensor_dir
+    ferret_sensor_dir = dir;
+
+    int ret;
+    size_t size;
+    l4dm_dataspace_t ds;
+    CORBA_Environment _dice_corba_env = dice_default_environment;
+
+    // create the sensor at the directory
+    ret = ferret_client_create_call(&ferret_sensor_dir, major, minor,
+                                    instance, type, flags, config, &ds,
+                                    &_dice_corba_env);
+    if (ret < 0)
+    {
+        LOG_Error("Creating sensor: %d", ret);
+        return ret;
+    }
+
+    // now use the received dataspace ID to acquire the size
+    ret = l4dm_mem_size(&ds, &size);
+    if (ret)
+    {
+        LOG("Could not get size for dataspace: %u at "l4util_idfmt" !",
+            ds.id, l4util_idstr(ds.manager));
+        return ret;
+    }
+
+    // Check the *addr for == NULL, otherwise use l4rm_attach_to_region()
+    if (*addr == NULL)
+    {
+        LOG("Could not attach dataspace, you must define destination address!");
+        return -1;
+    }
+    else
+    {
+        ret = l4dm_map_ds(&ds, 0, (l4_addr_t)*addr, size, L4DM_RW);
+        if (ret)
+        {
+            LOG("Could not attach dataspace to region %p!", *addr);
+            return ret;
+        }
+    }
+
+    switch(type)
+    {
+    case FERRET_SCALAR:
+    case FERRET_HISTO:
+    case FERRET_HISTO64:
+    case FERRET_DPLIST:
+    case FERRET_SLIST:
+    case FERRET_ALIST:
+        // no special setup required
+        break;
+    case FERRET_ULIST:
+        ferret_ulist_init_producer(addr, alloc);
+        break;
+    case FERRET_LIST:
+        ferret_list_init_producer(addr, alloc);
+        break;
+    default:
+        LOG("Unknown sensor type mapped: %d, ignored", type);
+        return -1;
+    }
+
+    // fixme: check if we really need this all the time
+    l4sigma0_kip_map(L4_INVALID_ID);
+    ferret_calibrate_clock(FERRET_TIME_REL_US_FAST);
+
+    return 0;
+}
diff --git a/l4/pkg/ferret/lib/producer/dplist_init.c b/l4/pkg/ferret/lib/producer/dplist_init.c
new file mode 100644 (file)
index 0000000..cc95cf9
--- /dev/null
@@ -0,0 +1,20 @@
+/**
+ * \file   ferret/lib/sensor/dplist_init.c
+ * \brief  dplist init functions.
+ *
+ * \date   2007-06-12
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <l4/ferret/sensors/dplist.h>
+#include <l4/ferret/sensors/dplist_init.h>
+
+#include <l4/ferret/sensors/__dplist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include "__llist_init.c"
diff --git a/l4/pkg/ferret/lib/producer/free.c b/l4/pkg/ferret/lib/producer/free.c
new file mode 100644 (file)
index 0000000..4908aaa
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * \file   ferret/lib/client/free.c
+ * \brief  Function to release sensors at directory.
+ *
+ * \date   2006-04-06
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/l4rm/l4rm.h>
+#include <l4/log/l4log.h>
+
+#include <l4/ferret/ferret_client-client.h>
+#include <l4/ferret/types.h>
+#include <l4/ferret/client.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/sensors/list_producer.h>
+#include <l4/ferret/sensors/ulist_producer.h>
+
+// fixme: we don't really need the first three attributes, as these
+//        are available in the sensor's head
+int ferret_free_sensor(uint16_t major, uint16_t minor,
+                       uint16_t instance, void * addr,
+                       void (*free)(void *))
+{
+    int ret;
+    CORBA_Environment _dice_corba_env = dice_default_environment;
+    _dice_corba_env.malloc = (dice_malloc_func)malloc;
+    _dice_corba_env.free = (dice_free_func)free;
+
+    // get ferret_sensor_dir task id lazily
+    if (l4_is_invalid_id(ferret_sensor_dir))
+        ferret_sensor_dir = ferret_comm_get_threadid();
+
+    switch(((ferret_common_t *)addr)->type)
+    {
+    case FERRET_SCALAR:
+    case FERRET_HISTO:
+    case FERRET_HISTO64:
+    case FERRET_DPLIST:
+    case FERRET_SLIST:
+    case FERRET_ALIST:
+        // no special setup required
+        break;
+    case FERRET_ULIST:
+        ferret_ulist_free_producer(&addr, free);
+        break;
+    case FERRET_LIST:
+        ferret_list_free_producer(&addr, free);
+        break;
+    default:
+        LOG("Unknown sensor type mapped: %d, ignored",
+            ((ferret_common_t *)addr)->type);
+        return -1;
+    }
+
+    // unmap shared memory
+    ret = l4rm_detach(addr);
+    if (ret)
+    {
+        LOG("Could not dettach dataspace, ignored!");
+    }
+
+    return ferret_client_free_call(&ferret_sensor_dir, major, minor,
+                                    instance, &_dice_corba_env);
+}
diff --git a/l4/pkg/ferret/lib/producer/histogram_init.c b/l4/pkg/ferret/lib/producer/histogram_init.c
new file mode 100644 (file)
index 0000000..2742c96
--- /dev/null
@@ -0,0 +1,138 @@
+/**
+ * \file   ferret/lib/sensor/histogram_init.c
+ * \brief  Histogram init functions.
+ *
+ * \date   17/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/sensors/histogram.h>
+#include <l4/ferret/sensors/histogram_init.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <l4/log/l4log.h>
+
+static void ferret_histo_init_head(ferret_histo_header_t *head, ferret_time_t low,
+                                   ferret_time_t high, unsigned int bins);
+static void ferret_histo_init_head(ferret_histo_header_t *head, ferret_time_t low,
+                                   ferret_time_t high, unsigned int bins)
+{
+    head->low  = low;
+    head->high = high;
+    head->bins = bins;
+    head->size = high - low;
+
+    head->underflow = 0;
+    head->overflow  = 0;
+    head->val_min   = FERRET_TIME_MAX;
+    head->val_max   = FERRET_TIME_MIN;
+    head->val_sum   = 0;
+    head->val_count = 0;
+}
+
+int ferret_histo_init(ferret_histo_t * histo, const char * config)
+{
+    ferret_time_t low, high;
+    unsigned int bins;
+    int ret, i;
+
+    // "<low value>:<high value>:<bins>"
+    ret = sscanf(config, "%lld:%lld:%u", &low, &high, &bins);
+    //LOG("Config found: %lld, %lld, %u", low, high, bins);
+
+    if (ret != 3 || bins < 1 || low >= high)
+    {
+        return -1;
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+    }
+    else
+    {
+        ferret_histo_init_head(&histo->head, low, high, bins);
+        for (i = 0; i < bins; ++i)
+            histo->data[i] = 0;
+    }
+    return 0;
+}
+
+int ferret_histo64_init(ferret_histo64_t * histo, const char * config)
+{
+    ferret_time_t low, high;
+    unsigned int bins;
+    int ret, i;
+
+    // "<low value>:<high value>:<bins>"
+    ret = sscanf(config, "%lld:%lld:%u", &low, &high, &bins);
+    //LOG("Config found: %lld, %lld, %u", low, high, bins);
+
+    if (ret != 3 || bins < 1 || low >= high)
+    {
+        return -1;
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+    }
+    else
+    {
+        ferret_histo_init_head(&histo->head, low, high, bins);
+        for (i = 0; i < bins; ++i)
+            histo->data[i] = 0;
+    }
+    return 0;
+}
+
+// fixme: all of the sensor type functions should be stored in a
+//        function table
+ssize_t ferret_histo_size_config(const char * config)
+{
+    ferret_time_t low, high;
+    unsigned int bins;
+    int ret;
+    ferret_histo_t temp;
+
+    ret = sscanf(config, "%lld:%lld:%u", &low, &high, &bins);
+    //LOG("Config found: %lld, %lld, %u", low, high, bins);
+
+    if (ret != 3 || bins < 1 || low >= high)
+    {
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+        return -1;
+    }
+
+    return sizeof(ferret_histo_t) + sizeof(temp.data[0]) * bins;
+}
+
+ssize_t ferret_histo64_size_config(const char * config)
+{
+    ferret_time_t low, high;
+    unsigned int bins;
+    int ret;
+    ferret_histo64_t temp;
+
+    ret = sscanf(config, "%lld:%lld:%u", &low, &high, &bins);
+    //LOG("Config found: %lld, %lld, %u", low, high, bins);
+
+    if (ret != 3 || bins < 1 || low >= high)
+    {
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+        return -1;
+    }
+
+    return sizeof(ferret_histo64_t) + sizeof(temp.data[0]) * bins;
+}
+
+ssize_t ferret_histo_size(const ferret_histo_t * histo)
+{
+    return sizeof(ferret_histo_t) + sizeof(histo->data[0]) * histo->head.bins;
+}
+
+ssize_t ferret_histo64_size(const ferret_histo64_t * histo)
+{
+    return sizeof(ferret_histo64_t) + sizeof(histo->data[0]) * histo->head.bins;
+}
diff --git a/l4/pkg/ferret/lib/producer/instance.c b/l4/pkg/ferret/lib/producer/instance.c
new file mode 100644 (file)
index 0000000..6c628de
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * \file   ferret/lib/client/instance.c
+ * \brief  Function to get a new instance at sensors directory.
+ *
+ * \date   2006-04-06
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <stdlib.h>
+
+#include <l4/ferret/ferret_client-client.h>
+
+#include <l4/ferret/client.h>
+#include <l4/ferret/comm.h>
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/sensors/list_producer.h>
+
+int ferret_create_instance()
+{
+    CORBA_Environment _dice_corba_env = dice_default_environment;
+    _dice_corba_env.malloc = (dice_malloc_func)malloc;
+    _dice_corba_env.free = (dice_free_func)free;
+
+    // get ferret_sensor_dir task id lazily
+    if (l4_is_invalid_id(ferret_sensor_dir))
+        ferret_sensor_dir = ferret_comm_get_threadid();
+
+    return ferret_client_new_instance_call(&ferret_sensor_dir,
+                                           &_dice_corba_env);
+}
diff --git a/l4/pkg/ferret/lib/producer/l4lx_client.c b/l4/pkg/ferret/lib/producer/l4lx_client.c
new file mode 100644 (file)
index 0000000..6671f05
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * \file   ferret/lib/sensor/l4lx_client.c
+ * \brief  Helper function for L4Linux user mode clients.
+ *
+ * \date   2006-04-03
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/l4lx_client.h>
+
+static ferret_list_local_t _list;
+ferret_list_local_t * ferret_l4lx_user = NULL;
+
+static void * _alloc(size_t s)
+{
+    return &_list;
+}
+
+void ferret_list_l4lx_user_init(void)
+{
+    ferret_l4lx_user = (ferret_list_local_t *)(0x8000 + 0xBFC00000UL + 0x1000);
+    ferret_list_init_producer((void **)&ferret_l4lx_user, &_alloc);
+}
diff --git a/l4/pkg/ferret/lib/producer/list_init.c b/l4/pkg/ferret/lib/producer/list_init.c
new file mode 100644 (file)
index 0000000..3e2bf74
--- /dev/null
@@ -0,0 +1,116 @@
+/**
+ * \file   ferret/lib/sensor/list_init.c
+ * \brief  List init functions.
+ *
+ * \date   23/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/sensors/list.h>
+#include <l4/ferret/sensors/list_init.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+
+int ferret_list_init(ferret_list_t * list, const char * config)
+{
+    uint32_t size, count, i;
+    int ret;
+    ferret_list_index_t * index;
+
+    // "<element size>:<element count>"
+    ret = sscanf(config, "%u:%u", &size, &count);
+    //printf("Config found: %u:%u\n", size, count);
+
+    if (ret != 2 ||
+        size > 4096 || size < sizeof(ferret_utime_t) ||
+        count > (2 << FERRET_INDEX_BITS) - 2 || count < 2)
+    {
+        printf("Warning: config string not recognized or flawed: %s!\n", config);
+        return -1;
+    }
+
+    // align element size to 8 bytes
+    size += 7;
+    size -= size % 8;
+
+    list->head.parts.element = count;
+    list->head.parts.index   = 0;
+    list->tail.value         = 0;
+    list->count              = count;
+    list->element_size       = size;
+    list->flags              = 0;
+    list->element_offset     = list->count * sizeof(ferret_list_index_t);
+       list->element_offset    += sizeof(ferret_list_t);
+    // care for cache line size alignment
+    list->element_offset += FERRET_ASSUMED_CACHE_LINE_SIZE - 1;
+    list->element_offset -= list->element_offset %
+                            FERRET_ASSUMED_CACHE_LINE_SIZE;
+
+    index = (ferret_list_index_t *)(list->data);
+       //printf("list @ %p, data %p\n", list, list->data);
+
+    for (i = 0; i < count; ++i)
+    {
+        index[i].parts.element = 0;
+        index[i].parts.index   = i;
+    }
+
+    return 0;
+}
+
+// fixme: all of the sensor type functions should be stored in a
+//        function table
+ssize_t ferret_list_size_config(const char * config)
+{
+    uint32_t size, count;
+    int ret;
+    uint32_t ret_size;
+
+    // "<element size>:<element count>"
+    ret = sscanf(config, "%u:%u", &size, &count);
+    //LOG("Config found: %u:%u", size, count);
+
+    if (ret != 2 ||
+        size > 4096 || size < sizeof(ferret_utime_t) ||
+        count > (2 << FERRET_INDEX_BITS) - 2 || count < 2)
+    {
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+        return -1;
+    }
+
+    // align element size to 8 bytes
+    size += 7;
+    size -= size % 8;
+
+    // header + index buffer + ...
+    ret_size = sizeof(ferret_list_t) +
+               sizeof(ferret_list_index_t) * count;
+    // ... now care for alignment of elements
+    ret_size += FERRET_ASSUMED_CACHE_LINE_SIZE - 1;
+    ret_size -= ret_size % FERRET_ASSUMED_CACHE_LINE_SIZE;
+
+    // ... element buffer
+    ret_size += size * count;
+
+    return ret_size;
+}
+
+ssize_t ferret_list_size(const ferret_list_t * list)
+{
+    uint32_t size, count;
+
+    size  = list->element_size;
+    count = list->count;
+
+    return sizeof(ferret_list_t) +
+           size * count +
+           sizeof(ferret_list_index_t) * count;
+}
diff --git a/l4/pkg/ferret/lib/producer/list_producer.c b/l4/pkg/ferret/lib/producer/list_producer.c
new file mode 100644 (file)
index 0000000..1063d63
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * \file   ferret/lib/sensor/list_producer.c
+ * \brief  List producer functions.
+ *
+ * \date   25/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+//#include <stdlib.h>
+
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/list.h>
+#include <l4/ferret/sensors/list_producer.h>
+
+void ferret_list_init_producer(void ** addr, void *(*alloc)(size_t size))
+{
+    ferret_list_local_t * temp;
+
+    temp = (*alloc)(sizeof(ferret_list_local_t));
+
+    // setup some pointers
+    temp->glob    = *addr;  // store pointer to global structure
+    temp->ind_buf = (ferret_list_index_t *)(temp->glob->data);
+       temp->out_buf = temp->glob->data + temp->glob->element_offset;
+
+    // copy header
+    temp->header.major    = temp->glob->header.major;
+    temp->header.minor    = temp->glob->header.minor;
+    temp->header.instance = temp->glob->header.instance;
+    temp->header.type     = temp->glob->header.type;
+
+    *addr = temp;
+}
+
+void ferret_list_free_producer(void ** addr, void (*free)(void *))
+{
+    void * temp = ((ferret_list_local_t *)(*addr))->glob;
+
+    (*free)(*addr);
+
+    *addr = temp;
+}
diff --git a/l4/pkg/ferret/lib/producer/scalar_init.c b/l4/pkg/ferret/lib/producer/scalar_init.c
new file mode 100644 (file)
index 0000000..f8c13ac
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * \file   ferret/lib/sensor/scalar_init.c
+ * \brief  Scalar init functions.
+ *
+ * \date   08/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/common.h>
+#include <l4/ferret/sensors/scalar.h>
+#include <l4/ferret/sensors/scalar_init.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+
+//#include <l4/log/l4log.h>
+
+int ferret_scalar_init(ferret_scalar_t * scalar, const char * config)
+{
+    ferret_time_t low, high;
+    int ret;
+
+    // "<low value>:<high value>"
+    ret = sscanf(config, "%lld:%lld", &low, &high);
+    //LOG("Config found: %lld, %lld", low, high);
+
+    if (ret != 2)
+    {
+        // LOG("Warning: config string not recognized: %s!", config);
+        return -1;
+    }
+    else
+    {
+        scalar->low  = low;
+        scalar->high = high;
+        scalar->data = 0;
+    }
+    return 0;
+}
+
+// fixme: all of the sensor type functions should be stored in a
+//        function table
+l4_ssize_t ferret_scalar_size_config(const char * config __attribute__((unused)))
+{
+    return sizeof(ferret_scalar_t);
+}
+
+l4_ssize_t ferret_scalar_size(const ferret_scalar_t * scalar __attribute__((unused)))
+{
+    return sizeof(ferret_scalar_t);
+}
diff --git a/l4/pkg/ferret/lib/producer/slist_init.c b/l4/pkg/ferret/lib/producer/slist_init.c
new file mode 100644 (file)
index 0000000..8e6f5f1
--- /dev/null
@@ -0,0 +1,20 @@
+/**
+ * \file   ferret/lib/sensor/slist_init.c
+ * \brief  slist init functions.
+ *
+ * \date   2007-06-13
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <l4/ferret/sensors/slist.h>
+#include <l4/ferret/sensors/slist_init.h>
+
+#include <l4/ferret/sensors/__slist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include "__llist_init.c"
diff --git a/l4/pkg/ferret/lib/producer/ulist_init.c b/l4/pkg/ferret/lib/producer/ulist_init.c
new file mode 100644 (file)
index 0000000..f3ccc62
--- /dev/null
@@ -0,0 +1,21 @@
+/**
+ * \file   ferret/lib/sensor/ulist_init.c
+ * \brief  ulist init functions.
+ *
+ * \date   2007-06-19
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <l4/ferret/local_names.h>
+#include <l4/ferret/sensors/ulist.h>
+#include <l4/ferret/sensors/ulist_init.h>
+
+#include <l4/ferret/sensors/__ulist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include "__llist_init.c"
diff --git a/l4/pkg/ferret/lib/producer/ulist_producer.c b/l4/pkg/ferret/lib/producer/ulist_producer.c
new file mode 100644 (file)
index 0000000..fb40e96
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+ * \file   ferret/lib/sensor/ulist_producer.c
+ * \brief  ulist producer functions.
+ *
+ * \date   2007-06-19
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/ulist.h>
+#include <l4/ferret/sensors/ulist_producer.h>
+
+#include <l4/ferret/fpages.h>
+#include <l4/ferret/local_names.h>
+#include <l4/util/macros.h>
+
+#include <l4/ferret/sensors/__ulist_magic.h>
+#define FERRET_LLIST_MAGIC ahK6eeNa
+#include "__llist_producer.c"
diff --git a/l4/pkg/ferret/lib/producer/vlist_init.c b/l4/pkg/ferret/lib/producer/vlist_init.c
new file mode 100644 (file)
index 0000000..664b575
--- /dev/null
@@ -0,0 +1,83 @@
+/**
+ * \file   ferret/lib/sensor/vlist_init.c
+ * \brief  Variable list init functions.
+ *
+ * \date   2007-09-27
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2007-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <l4/ferret/sensors/vlist.h>
+#include <l4/ferret/sensors/vlist_init.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <l4/util/bitops.h>
+
+int ferret_vlist_init(ferret_alist_t * list, const char * config)
+{
+    uint32_t size, size_ld;
+    int ret;
+
+    // "<sensor size>"
+    ret = sscanf(config, "%u", &count);
+
+    if (ret != 1 || size > FERRET_VLIST_MAX_SIZE || size < 4096)
+    {
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+        return -1;
+    }
+
+    // compute next power of two for size
+    size_ld = l4util_log2(size);
+    if (size > (1 << size_ld))
+        size_ld++;
+    size = (1 << size_ld);
+
+    list->head       = 0;
+    list->tail.value = 0;
+    list->size       = size;
+    list->size_ld    = size_ld;
+    list->size_mask  = (1 << size_ld) - 1;
+    list->flags      = 0;
+
+    memset(list->data, 0, list->size);
+
+    return 0;
+}
+
+ssize_t ferret_alist_size_config(const char * config)
+{
+    uint32_t size, size_ld;
+    int ret;
+
+    // "<sensor size>"
+    ret = sscanf(config, "%u", &count);
+
+    if (ret != 1 || size > FERRET_VLIST_MAX_SIZE || size < 4096)
+    {
+        //LOG("Warning: config string not recognized or flawed: %s!", config);
+        return -1;
+    }
+
+    // compute next power of two for size
+    size_ld = l4util_log2(size);
+    if (size > (1 << size_ld))
+        size_ld++;
+    size = (1 << size_ld);
+
+    // header + element buffer
+    return sizeof(ferret_vlist_t) + size;
+}
+
+ssize_t ferret_alist_size(const ferret_alist_t * list)
+{
+    return sizeof(ferret_vlist_t) + size;
+}
diff --git a/l4/pkg/ferret/server/Makefile b/l4/pkg/ferret/server/Makefile
new file mode 100644 (file)
index 0000000..f11249c
--- /dev/null
@@ -0,0 +1,6 @@
+PKGDIR ?= ..
+L4DIR  ?= $(PKGDIR)/../..
+
+TARGET = re 
+
+include $(L4DIR)/mk/subdir.mk
diff --git a/l4/pkg/ferret/server/re/Makefile b/l4/pkg/ferret/server/re/Makefile
new file mode 100644 (file)
index 0000000..2065f5c
--- /dev/null
@@ -0,0 +1,11 @@
+PKGDIR          ?= ../..
+L4DIR           ?= $(PKGDIR)/../..
+
+TARGET                   = ferret_sensor_dir
+
+REQUIRES_LIBS= libstdc++
+
+SRC_CC = main.cc sensor.cc sensordir.cc
+
+include $(L4DIR)/mk/prog.mk
+
diff --git a/l4/pkg/ferret/server/re/main.cc b/l4/pkg/ferret/server/re/main.cc
new file mode 100644 (file)
index 0000000..a82b27a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+#include <iostream>          // std::cout
+#include <l4/util/backtrace.h>        // l4util_backtrace()
+
+#include "sensor.h"
+
+int main(/*int argc, char **argv*/)
+{
+       Ferret::SensorDir dir;
+
+       dir.start();
+
+       std::cout << "Server loop exited!\n";
+
+       std::cout << "===== Backtrace =====\n";
+       int len = 16;
+       void *array[len];
+       int r = l4util_backtrace(&array[0], len);
+       for (int i=0; i < r; ++i)
+               std::cout << "\t" << array[i] << "\n";
+       std::cout << "=====================\n";
+
+       return 0;
+}
diff --git a/l4/pkg/ferret/server/re/sensor.cc b/l4/pkg/ferret/server/re/sensor.cc
new file mode 100644 (file)
index 0000000..6badd49
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <l4/ferret/types.h>
+#include <l4/ferret/sensors/list.h>
+#include <l4/cxx/ipc_server>          // L4::Server*
+#include <iostream>
+
+#include "sensor.h"
+
+void * operator new(size_t size) throw(std::bad_alloc)
+{
+       return malloc(size);
+}
+
+
+void * operator new[](size_t size) throw(std::bad_alloc)
+{
+       return malloc(size);
+}
+
+
+void operator delete(void *p) throw()
+{
+       free(p);
+}
+
+
+void operator delete[](void *p) throw()
+{
+       free(p);
+}
+
+
+/******************************************************************************
+ *                                                                            *
+ * Sensor                                                                     *
+ *                                                                            *
+ ******************************************************************************/
+Ferret::Sensor::Sensor(uint16_t const major, uint16_t const minor,
+                       uint16_t const instance, uint16_t const type,
+                                          uint32_t e_size = 0, uint32_t e_num = 0)
+       : _refcount(0), _major(major), _minor(minor), _instance(instance),
+      _type(type), _elemsize(e_size), _num_elem(e_num)
+{
+       unsigned space_req = 0;
+
+       switch(type)
+       {
+               case FERRET_SCALAR:
+                       space_req = sizeof(ferret_scalar_t);
+                       break;
+               case FERRET_LIST:
+                       space_req = _num_elem * sizeof(ferret_list_index_t);
+                       space_req += sizeof(ferret_list_t);
+                       space_req += FERRET_ASSUMED_CACHE_LINE_SIZE - 1;
+                       space_req -= space_req % FERRET_ASSUMED_CACHE_LINE_SIZE;
+                       space_req += _num_elem * _elemsize;
+                       break;
+       }
+
+       _dataspace = get_dataspace(space_req);
+}
+
+
+L4::Cap<L4Re::Dataspace> Ferret::Sensor::get_dataspace(size_t const bytes)
+{
+    L4::Cap<L4Re::Dataspace> ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
+       if (!ds.is_valid())
+               std::cout << "Dataspace allocation failed.\n";
+
+       int err =  L4Re::Env::env()->mem_alloc()->alloc(bytes, ds, 0);
+       if (err < 0) {
+               std::cout << "mem_alloc->alloc() failed.\n";
+               L4Re::Util::cap_alloc.free(ds);
+       }
+
+       return ds;
+}
+
+
+std::ostream& operator<<(std::ostream& os, Ferret::Sensor const & obj)
+{
+       os << "(" << obj.major() << "," << obj.minor()
+          << "," << obj.instance() << ")";
+       switch(obj.type())
+       {
+               case FERRET_SCALAR:
+                       os << " scalar";
+                       break;
+               case FERRET_HISTO:
+                       os << " histo";
+                       break;
+               case FERRET_HISTO_2D:
+                       os << " histo2D";
+                       break;
+               case FERRET_TBUF:
+                       os << " tbuf";
+                       break;
+               case FERRET_LIST:
+                       os << " list";
+                       break;
+               default:
+                       break;
+       }
+       return os;
+}
+
+
+/******************************************************************************
+ *                                                                            *
+ * SensorRegistry                                                             *
+ *                                                                            *
+ ******************************************************************************/
+Ferret::SensorRegistry::SensorRegistry()
+       : _sensors()
+{
+}
+
+
+void Ferret::SensorRegistry::register_sensor(Ferret::Sensor *s)
+{
+#if DEBUG
+       std::cout << "adding " << *s << "\n";
+#endif
+       _sensors.push_back(s);
+}
+
+
+void Ferret::SensorRegistry::unregister_sensor(Ferret::Sensor *s)
+{
+       for (std::list<Sensor*>::iterator i = _sensors.begin();
+                i != _sensors.end(); ++i)
+       {
+               if ((s->major() == (*i)->major()) &&
+                       (s->minor() == (*i)->minor()) &&
+                       (s->instance() == (*i)->instance())) {
+                       _sensors.erase(i);
+                       break;
+               }
+       }
+}
+
+
+Ferret::Sensor *Ferret::SensorRegistry::lookup(uint16_t const major,
+                                               uint16_t const minor,
+                                               uint16_t const instance) const
+{
+       for (std::list<Sensor*>::const_iterator i = _sensors.begin();
+                i != _sensors.end(); ++i)
+       {
+               if ((major == (*i)->major()) &&
+                       (minor == (*i)->minor()) &&
+                       (instance == (*i)->instance()))
+                       return *i;
+       }
+
+       return 0;
+}
+
+
diff --git a/l4/pkg/ferret/server/re/sensor.h b/l4/pkg/ferret/server/re/sensor.h
new file mode 100644 (file)
index 0000000..a8e2fdd
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#pragma once
+#include <l4/ferret/types.h>          // types
+
+#include <l4/cxx/ipc_server>    // L4::Server*
+#include <iostream>    // std::cout
+#include <l4/cxx/ipc_stream>    // L4::Ipc::Iostream
+#include <l4/re/util/cap_alloc> // L4::Cap
+#include <l4/re/dataspace>      // L4Re::Dataspace
+#include <l4/re/mem_alloc>      // mem_alloc()
+#include <l4/re/rm>             // L4::Rm
+#include <l4/re/env>            // L4::Env
+#include <l4/re/util/object_registry>
+
+#include <l4/ferret/sensordir.h>      // Protocol & Opcodes
+#include <l4/ferret/sensors/common.h> // sensor types
+#include <l4/ferret/sensors/scalar.h>
+
+#include <cstdlib>
+#include <list>
+
+#define DEBUG 0
+
+namespace Ferret
+{
+       /**
+        * Sensors are the basic server objects managed by the sensor directory.
+        *
+        * A sensor resides in a dataspace. The dataspace contains a common head,
+        * followed by a type-specific head. This head is used to describe the
+        * sensor. The rest of the DS is used to contain the sensor's event
+        * payload, which again, depends on the sensor type.
+        *
+        * The sensor directory does _not_ distinguish sensors of different
+        * types. This is up to clients and monitors. The directory only cares
+        * about their common subset - major, minor and instance numbers.
+        */
+       class Sensor
+       {
+               public:
+                       uint16_t major() const     { return _major; }
+                       uint16_t minor() const     { return _minor; }
+                       uint16_t instance() const  { return _instance; }
+                       uint16_t type() const      { return _type; }
+                       unsigned int refcount()    { return _refcount; }
+                       void inc() { ++_refcount; }
+                       void dec() { --_refcount; }
+
+                       uint32_t elem_size() const { return _elemsize; }
+                       void elem_size(uint32_t v) { _elemsize = v; }
+                       uint32_t num_elem() const  { return _num_elem; }
+                       void num_elem(uint32_t v)  { _num_elem = v; }
+
+                       L4::Cap<L4Re::Dataspace> const ds_cap() { return _dataspace; }
+
+                       Sensor(uint16_t const major, uint16_t const minor,
+                              uint16_t const instance, uint16_t const type,
+                              uint32_t e_size, uint32_t e_num);
+
+                       ~Sensor()
+                       {
+                               // No need to rm->detach() -- we did not ever attach this ds
+                               l4_msgtag_t r = l4_task_unmap(L4RE_THIS_TASK_CAP,
+                                                             _dataspace.fpage(), L4_FP_ALL_SPACES);
+                               if (l4_error(r))
+                                       std::cout << "Error unmapping dataspace? (" << l4_error(r) << ")\n";
+
+                               L4Re::Util::cap_alloc.free(_dataspace);
+                       }
+
+               private:
+                       unsigned int             _refcount; /**< reference count */
+                       uint16_t                 _major;    /**< major number */
+                       uint16_t                 _minor;    /**< minor number */
+                       uint16_t                 _instance; /**< instance number */
+                       uint16_t                 _type;     /**< sensor type */
+                       uint32_t                 _elemsize; /**< size of a list element XXX -> subclass! */
+                       uint32_t                 _num_elem; /**< number of list elements XXX -> subclass! */
+                       L4::Cap<L4Re::Dataspace> _dataspace; /**< cap to sensor data space */
+
+                       L4::Cap<L4Re::Dataspace> get_dataspace(size_t bytes);
+       };
+
+
+       /* 
+        * The sensor registry is used to manage and lookup sensors. It is not a
+        * L4Re IPC server registry, because we do not expose sensor objects to
+        * clients directly (XXX maybe later?).
+        */
+       class SensorRegistry
+       {
+               public:
+                       SensorRegistry();
+                       void register_sensor(Sensor *r);
+                       void unregister_sensor(Sensor *r);
+                       Sensor *lookup(uint16_t const major, uint16_t const minor, uint16_t const instance) const;
+
+               private:
+                       std::list<Sensor*> _sensors;
+//                     std::map<int, Sensor*> _map;
+       };
+
+       /**
+        * Server implementation. The sensor directory manages clients (event producers)
+        * and monitors (event consumers).
+        */
+       class SensorDir : public L4::Server_object
+       {
+               public:
+                       SensorDir(void);
+
+                       /**
+                        * Dispatch message
+                        */
+                       int dispatch(l4_umword_t, L4::Ipc::Iostream &ios);
+
+                       /**
+                        * Dispatch monitor messages.
+                        */
+                       int dispatch_monitor(L4::Ipc::Iostream &ios);
+
+                       /**
+                        * Dispatch client messages.
+                        */
+                       int dispatch_client(L4::Ipc::Iostream &ios);
+
+                       /**
+                        * Start the sensor dir server 
+                        */
+                       void start();
+
+                       char const * name() const { return "sensordir"; }
+
+               private:
+                       L4Re::Util::Registry_server<> _server;
+                       SensorRegistry _reg;
+       };
+
+}
+
+std::ostream& operator<<(std::ostream& os, Ferret::Sensor const & obj);
diff --git a/l4/pkg/ferret/server/re/sensordir.cc b/l4/pkg/ferret/server/re/sensordir.cc
new file mode 100644 (file)
index 0000000..25f6b09
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include "sensor.h"
+#include <iostream>
+#include <l4/re/error_helper>
+
+/******************************************************************************
+ *                                                                            *
+ * SensorDir                                                                  *
+ *                                                                            *
+ ******************************************************************************/
+Ferret::SensorDir::SensorDir(void)
+       : _server(), _reg()
+{
+        L4Re::chkcap(_server.registry()->register_obj(this, name()), "registering seonsordir", 0);
+}
+
+
+void Ferret::SensorDir::start()
+{
+       std::cout << "Server loop\n";
+       _server.loop();
+}
+
+
+int Ferret::SensorDir::dispatch(l4_umword_t, L4::Ipc::Iostream &ios)
+{
+       l4_msgtag_t tag;
+       ios >> tag;
+
+       /* 
+        * Label sanity check
+        */
+       if ((tag.label() != Client) && (tag.label() != Monitor))
+               return L4_EBADPROTO;
+
+       /*
+        * Redirect to corresponding dispatch fn.
+        */
+       switch (tag.label())
+       {
+               case Client:
+                       return dispatch_client(ios);
+                       break;
+               case Monitor:
+                       return dispatch_monitor(ios);
+                       break;
+               default:
+                       return -L4_EINVAL;
+       }
+}
+
+
+int Ferret::SensorDir::dispatch_monitor(L4::Ipc::Iostream &ios)
+{
+       int opcode;
+       int ret = -L4_ENOSYS;
+       uint16_t maj, min, inst;
+       Sensor *s;
+
+       ios >> opcode;
+       ios >> maj >> min >> inst;
+
+#if DEBUG
+       std::cout << "(" << maj << ", " << min << ", " << inst << ")\n";
+#endif
+       switch(opcode)
+       {
+               case Attach:
+                       s = _reg.lookup(maj, min, inst);
+                       if (s) {
+                               std::cout << "Found " << *s << "\n";
+                               s->inc();
+                               unsigned flags = L4_FPAGE_RO;
+                               ios << 0 << L4::Ipc::Snd_fpage(s->ds_cap().fpage(flags));
+                               ret = 0;
+                       }
+                       else {
+                               std::cout << "Could not find sensor for (" << maj
+                                        << "," << min << "," << inst << ")\n";
+                               ios << -L4_ENOENT;
+                               ret = -L4_ENOENT;
+                       }
+                       break;
+               case Detach:
+                       s = _reg.lookup(maj, min, inst);
+                       if (s) {
+                               s->dec();
+                               if (s->refcount() == 0) {
+                                       _reg.unregister_sensor(s);
+                                       delete s;
+                               }
+                               ios << 0;
+                               ret = 0;
+                       }
+                       else {
+                               std::cout << "Could not find sensor for (" << maj
+                                        << "," << min << "," << inst << ")\n";
+                               ios << -L4_ENOENT;
+                               ret = -L4_ENOENT;
+                       }
+                       break;
+               case List:
+                       std::cout << "list\n";
+                       ios << ret;
+                       break;
+       }
+
+       return ret;
+}
+
+
+int Ferret::SensorDir::dispatch_client(L4::Ipc::Iostream &ios)
+{
+       int opcode;
+       uint16_t maj, min, inst, typ;
+       uint32_t flags;
+       Sensor *sensor = 0;
+
+       ios >> opcode;
+       ios >> maj >> min >> inst >> typ >> flags;
+
+#if DEBUG
+       std::cout << "(" << maj << "," << min << "," << inst << ")\n";
+       std::cout << typ << ", " << flags << "\n";
+#endif
+
+       int ret = -L4_ENOSYS;
+       switch(opcode)
+       {
+               case Create:
+                       {
+                               unsigned e_size = 0, e_num = 0;
+                               switch(typ)
+                               {
+                                       case FERRET_LIST:
+                                               ios >> e_size >> e_num;
+#if DEBUG
+                                               std::cout << e_num << " elements of size " << e_size << "\n";
+#endif
+                                       default:
+                                               break;
+                               }
+                               sensor = _reg.lookup(maj, min, inst);
+                               // is this a re-open?
+                               if (sensor)     {
+                                       if (sensor->type() != typ) {
+                                               std::cout << "type mismatch!\n";
+                                               ios << -L4_EEXIST;
+                                               sensor = 0;
+                                       }
+                                       else if (typ == FERRET_LIST && (sensor->elem_size() != e_size ||
+                                                        sensor->num_elem()  != e_num)) {
+                                               std::cout << "DS size mismatch.\n";
+                                               ios << -L4_EEXIST;
+                                               sensor = 0;
+                                       }
+                                       else {
+                                               // reopen ok, inc use count
+                                               sensor->inc();
+                                       }
+                               }
+                               else {
+                                       switch(typ)
+                                       {
+                                               case FERRET_SCALAR:
+                                                       // fall through
+                                               case FERRET_LIST:
+                                                       sensor = new Sensor(maj, min, inst, typ, e_size, e_num);
+                                                       break;
+                                               default:
+                                                       break;
+                                       }
+
+                                       if (sensor)     {
+                                               _reg.register_sensor(sensor);
+                                               sensor->inc();
+                                       }
+                               }
+
+#if DEBUG
+                               if (sensor) {
+                                       std::cout << *sensor << "\n";
+                                       std::cout << "sensor ds size: " << sensor->ds_cap()->size() << "\n";
+                                       std::cout << "sensor cap: " << sensor->ds_cap().fpage().raw << "\n";
+                               }
+                               else
+                                       std::cout << "Invalid sensor request.\n";
+#endif
+
+                               if (sensor) {
+                                       /*
+                                        * ATTENTION! For mapping a data space writable, the
+                                        *   'X' bit in the fpage flags needs to be set. Reason:
+                                        *   those bits are overloaded for capabilities and have
+                                        *   a meaning different from the original one:
+                                        *
+                                        *   R - needs to be set anyway, otherwise nothing is mapped
+                                        *   W - 'isolate' bit. If set, the cap can potentially be used
+                                        *       to map other writable objects through it.
+                                        *   X - 'user-defined' bit that depends on the kind of object
+                                        *       this cap refers to. For data spaces, it means writable.
+                                        */
+                                       unsigned flags = L4_FPAGE_RWX;
+                                       ios << 0 << L4::Ipc::Snd_fpage(sensor->ds_cap().fpage(flags));
+                               }
+                       }
+
+                       ret = 0;
+                       break;
+
+               case Free:
+                       sensor = _reg.lookup(maj, min, inst);
+                       sensor->dec();
+                       if (sensor->refcount() == 0) {
+                               _reg.unregister_sensor(sensor);
+                               delete sensor;
+                       }
+
+                       ios << 0;
+
+                       break;
+
+               case NewInstance:
+                       // XXX create a new instance of a sensor
+                       break;
+               default:
+                       break;
+       }
+
+       return ret;
+}
diff --git a/l4/pkg/ferret/server/sensor_directory/Makefile b/l4/pkg/ferret/server/sensor_directory/Makefile
new file mode 100644 (file)
index 0000000..a30492c
--- /dev/null
@@ -0,0 +1,21 @@
+# directories we need to know
+PKGDIR       ?= ../..
+L4DIR        ?=  $(PKGDIR)/../..
+
+SYSTEMS       = x86-l4f
+
+# source files
+SERVERIDL     = ferret_dir.idl ferret_client.idl ferret_fpages.idl ferret_monitor.idl
+
+SRC_C         = dir.c sensors.c server.c clients.c
+
+MODE          = l4env_minimal
+DEFAULT_RELOC = 0x002fd000
+
+TARGET        = fer_sensor_dir
+LIBS          = -lparsecmdline -lferret_init                     \
+                -ll4vfs_name_server -ll4vfs_name_space_provider  \
+                -ll4vfs_object_server-server                     \
+                -ll4vfs_tree_helper -lferret_local_names
+
+include $(L4DIR)/mk/prog.mk
diff --git a/l4/pkg/ferret/server/sensor_directory/README b/l4/pkg/ferret/server/sensor_directory/README
new file mode 100644 (file)
index 0000000..986a273
--- /dev/null
@@ -0,0 +1,7 @@
+The coordinator has the following purposes:
+ - It acts as well known instance for monitored software (to be more
+   precise: for the used client library), it receives dataspace ids
+   and read right on the dataspaces.
+ - It acts as well known instance for the monitoring software, it
+   should list available dataspaces, and allows the request access to
+   certain dataspaces
diff --git a/l4/pkg/ferret/server/sensor_directory/clients.c b/l4/pkg/ferret/server/sensor_directory/clients.c
new file mode 100644 (file)
index 0000000..abe1eae
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * \file   ferret/server/sensor_directory/clients.c
+ * \brief  Client handling.
+ *
+ * \date   02/22/2006
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2006-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include "clients.h"
+
+client_t clients[MAX_CLIENTS];
+
+int  clients_get_free(void)
+{
+    int i;
+
+    for (i = 0; i < MAX_CLIENTS; i++)
+    {
+        if (clients[i].open == 0)
+            return i;
+    }
+    return -1;
+}
+
+int  clients_is_open(int handle)
+{
+    return clients[handle].open;
+}
diff --git a/l4/pkg/ferret/server/sensor_directory/clients.h b/l4/pkg/ferret/server/sensor_directory/clients.h
new file mode 100644 (file)
index 0000000..429ae83
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * (c) 2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_SERVER_SENSOR_DIRECTORY_CLIENTS_H_
+#define __FERRET_SERVER_SENSOR_DIRECTORY_CLIENTS_H_
+
+#include <l4/dm_generic/types.h>
+#include <l4/l4vfs/tree_helper.h>
+#include <l4/l4vfs/types.h>
+
+#define MAX_CLIENTS 1024
+
+typedef struct client_s
+{
+    int               open;
+    int               mode;
+    l4vfs_size_t      seek;
+    l4_threadid_t     client;
+    l4vfs_th_node_t * node;
+} client_t;
+
+extern client_t clients[MAX_CLIENTS];
+
+int  clients_get_free(void);
+int  clients_is_open(int handle);
+
+#endif
diff --git a/l4/pkg/ferret/server/sensor_directory/dir.c b/l4/pkg/ferret/server/sensor_directory/dir.c
new file mode 100644 (file)
index 0000000..e8e7754
--- /dev/null
@@ -0,0 +1,116 @@
+/**
+ * \file   ferret/server/sensor_directory/dir.c
+ * \brief  Directory server, serves as well known instance and
+ *         naming service for sensors
+ *
+ * \date   04/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+//#include <l4/dm_generic/dm_generic.h>
+//#include <l4/dm_phys/dm_phys.h>
+#include <l4/l4vfs/tree_helper.h>
+#include <l4/l4vfs/name_server.h>
+#include <l4/l4vfs/name_space_provider.h>
+#include <l4/log/l4log.h>
+#include <l4/names/libnames.h>
+#include <l4/util/l4_macros.h>
+#include <l4/util/parse_cmd.h>
+#include <l4/util/util.h>
+
+#include <l4/ferret/ferret_dir-server.h>
+#include <l4/ferret/sensors/tbuf.h>
+
+#include <stdlib.h>
+
+#include "sensors.h"
+
+char LOG_tag[9] = FERRET_DIR_NAME;
+int verbose;
+int reg_l4vfs;
+l4vfs_th_node_t * root;
+
+#define MIN ((a)<(b)?(a):(b))
+
+int main(int argc, const char *argv[])
+{
+    object_id_t root_id;
+    l4dm_dataspace_t ds = L4DM_INVALID_DATASPACE;
+    int i, ret;
+    sensor_entry_t * se;
+    CORBA_Server_Environment env = dice_default_server_environment;
+
+    if (parse_cmdline(&argc, &argv,
+
+                      'v', "verbose",
+                      "be verbose by dumping progress information to via log",
+                      PARSE_CMD_SWITCH, 1, &verbose,
+
+                      'l', "l4vfs", "register volume_id at L4VFS' name_server",
+                      PARSE_CMD_SWITCH, 1, &reg_l4vfs,
+
+                      0, 0) != 0)
+    {
+        return 1;
+    }
+
+    // create root node for tree_helper
+    root = l4vfs_th_new_node("[ferret root]", L4VFS_TH_TYPE_DIRECTORY,
+                             NULL, NULL);
+
+    // register at L4VFS' name_server
+
+    if (reg_l4vfs)
+    {
+        l4_threadid_t ns;
+        root_id.volume_id = FERRET_L4VFS_VOLUME_ID;
+        root_id.object_id = 0;
+
+        ns = l4vfs_get_name_server_threadid();
+        if (l4_is_invalid_id(ns))
+        {
+            exit(1);
+        }
+        LOGd(verbose, "Got name_server thread_id ...");
+        for (i = 0; i < 3; i++)
+        {
+            ret = l4vfs_register_volume(ns, l4_myself(), root_id);
+            // register ok --> done
+            if (ret == 0)
+                break;
+            else
+                LOG("Error registering at name_server: %d, retrying ...", ret);
+            l4_sleep(500);
+        }
+        if (ret)
+        {
+            LOG("Could not register at name_server, gave up!");
+            exit(1);
+        }
+        LOGd(verbose, "Registered my volume_id at name_server.");
+    }
+
+    // register special sensors ...
+
+    // trace buffer
+    se = sensors_new_entry(&ds, FERRET_TBUF_MAJOR, FERRET_TBUF_MINOR,
+                           0, FERRET_TBUF, FERRET_PERMANENT, "", NULL);
+    if (! se)
+    {
+        LOG("Could not register trace buffer as sensor, ignored!");
+    }
+
+    env.malloc = (dice_malloc_func)malloc;
+    env.free = (dice_free_func)free;
+
+    LOGd(verbose, "Registering at names ...");
+    names_register(FERRET_DIR_NAME);
+
+    LOGd(verbose, "Starting server loop ...");
+    ferret_dir_server_loop(&env);
+}
diff --git a/l4/pkg/ferret/server/sensor_directory/dir.h b/l4/pkg/ferret/server/sensor_directory/dir.h
new file mode 100644 (file)
index 0000000..c0155f3
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * \file   ferret/server/sensor_directory/dir.h
+ * \brief  Directory server, serves as well known instance and
+ *         naming service for sensors
+ *
+ * \date   07/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_SERVER_SENSOR_DIRECTORY_DIR_H_
+#define __FERRET_SERVER_SENSOR_DIRECTORY_DIR_H_
+
+#include <l4/l4vfs/tree_helper.h>
+
+extern int verbose;
+extern l4vfs_th_node_t * root;
+
+#endif
diff --git a/l4/pkg/ferret/server/sensor_directory/sensors.c b/l4/pkg/ferret/server/sensor_directory/sensors.c
new file mode 100644 (file)
index 0000000..4f48949
--- /dev/null
@@ -0,0 +1,321 @@
+/**
+ * \file   ferret/server/coord/clients.c
+ * \brief  Sensors management
+ *
+ * \date   04/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <l4/dm_generic/dm_generic.h>
+#include <l4/log/l4log.h>
+
+#include "sensors.h"
+#include "dir.h"
+
+#define MAX_PATH 100
+
+
+sensor_entry_t * sensors_new_entry(const l4dm_dataspace_t *ds,
+                                   int major, int minor, int instance,
+                                   int type, int flags, const char * config,
+                                   void * data)
+{
+    char path[MAX_PATH];
+    l4vfs_th_node_t * parent_node;
+    local_object_id_t parent_id;
+    sensor_entry_t * se;
+    l4vfs_th_node_t * node;
+
+    // major
+    snprintf(path, MAX_PATH, "/%d", major);
+    parent_id = l4vfs_th_resolve(0, path);
+    if (parent_id == L4VFS_ILLEGAL_OBJECT_ID)
+    {
+        snprintf(path, MAX_PATH, "%d", major);
+        parent_node = l4vfs_th_new_node(path, L4VFS_TH_TYPE_DIRECTORY,
+                                        root, NULL);
+        if (parent_node == NULL)
+        {
+            LOGd(verbose, "Failed to allocate new tree node, probably "
+                 "out of memory?");
+            return NULL;
+        }
+    }
+    else
+        parent_node = l4vfs_th_node_for_id(parent_id);
+
+    // minor
+    snprintf(path, MAX_PATH, "/%d/%d", major, minor);
+    parent_id = l4vfs_th_resolve(0, path);
+    if (parent_id == L4VFS_ILLEGAL_OBJECT_ID)
+    {
+        snprintf(path, MAX_PATH, "%d", minor);
+        parent_node = l4vfs_th_new_node(path, L4VFS_TH_TYPE_DIRECTORY,
+                                        parent_node, NULL);
+        if (parent_node == NULL)
+        {
+            LOGd(verbose, "Failed to allocate new tree node, probably "
+                 "out of memory?");
+            return NULL;
+        }
+    }
+    else
+        parent_node = l4vfs_th_node_for_id(parent_id);
+
+    // instance
+    snprintf(path, MAX_PATH, "%d", instance);
+    se = malloc(sizeof(sensor_entry_t));
+    if (se == NULL)
+    {
+        LOG("Failed to allocate new sensor_entry, probably out of memory?");
+        return NULL;
+    }
+    node = l4vfs_th_new_node(path, L4VFS_TH_TYPE_OBJECT, parent_node, se);
+    if (node == NULL)
+    {
+        LOG("Failed to allocate new tree node, probably out of memory?");
+        free(se);
+        return NULL;
+    }
+
+    se->ds          = *ds;
+    se->node        = node;
+    se->node->usage_count = 1;
+    se->major       = major;
+    se->minor       = minor;
+    se->instance    = instance;
+    se->type        = type;
+    se->flags       = flags;
+    se->config      = strdup(config);
+    se->data        = data;
+
+    return se;
+}
+
+#if 0
+int sensors_get_index_for_id(int id)
+{
+    int i;
+    for (i = 0; i < FERRET_MAX_SENSORS; i++)
+    {
+        if (sensor_table[i].usage_count > 0)
+        {
+            if (sensor_table[i].id == id)
+                return i;
+        }
+    }
+    return -1;
+}
+
+int sensors_get_index_for_prop(int major, int minor, int instance)
+{
+    int i;
+    for (i = 0; i < FERRET_MAX_SENSORS; i++)
+    {
+        if (sensor_table[i].usage_count > 0)
+        {
+            if (sensor_table[i].major == major &&
+                sensor_table[i].minor == minor &&
+                sensor_table[i].instance == instance)
+                return i;
+        }
+    }
+    return -1;
+}
+#endif
+
+void sensors_check_and_free(l4vfs_th_node_t * node)
+{
+    /* 1. check usage count
+     * 2. == 0 && ! permanent flag -> close ds & cleanup node
+     */
+
+    int ret;
+    sensor_entry_t * se = (sensor_entry_t *)(node->data);
+
+    if (node->usage_count <= 0 && ! (se->flags & FERRET_PERMANENT))
+    {
+        ret = l4dm_close(&(se->ds));
+        if (ret)
+        {
+            LOG("Problem closing dataspace: ret = %d!", ret);
+        }
+
+        free(se->config);
+        free(se);
+        ret = l4vfs_th_destroy_child(node->parent, node);
+        if (ret)
+        {
+            LOG("Problem freeing node: ret = %d, ignored!", ret);
+        }
+    }
+}
+
+int sensors_fill_list(ferret_monitor_list_entry_t * list, int offset,
+                      int count)
+{
+    /* 1. Find offset'th entry
+     * 2. start filling from there the next count entries
+     */
+
+    int i;
+    l4vfs_th_node_t * current;
+    sensor_entry_t * se;
+
+    for (i = 0, current = sensors_next_nth_leaf(offset, root);
+         i < count && current != NULL;
+         i++, current = sensors_next_nth_leaf(1, current))
+    {
+        se = (sensor_entry_t *)current->data;
+        list[i].major    = se->major;
+        list[i].minor    = se->minor;
+        list[i].instance = se->instance;
+        list[i].type     = se->type;
+        list[i].id       = current->id;
+    }
+    return i;
+}
+
+#if 0
+l4vfs_th_node_t * sensors_first_leaf(l4vfs_th_node_t * root)
+{
+    return sensors_next_nth_leaf(0, root)
+}
+
+l4vfs_th_node_t * sensors_first_leaf(l4vfs_th_node_t * root)
+{
+    l4vfs_th_node_t * ret;
+    l4vfs_th_node_t * current = root;
+
+    for (; current != NULL; current = current->next)
+    {
+        if (current->type == L4VFS_TH_TYPE_OBJECT)
+        {
+            return current;
+        }
+        else
+        {
+            ret = sensors_first_leaf(current);
+            if (ret != NULL)
+                return ret;
+        }
+    }
+
+    return NULL;
+}
+#endif
+
+/**
+ * @brief Traverse the tree, starting at start to find the n'th leaf
+ *        node.
+ *
+ * If start is a leaf node itself, give n == 1 to find the next leaf
+ * according to depth-first-search.  If start is a non-leaf node
+ * specify n == 0 to find the first leaf.
+ *
+ * @param n find the n'th leaf node after start
+ * @param start node to start lookup at in the tree
+ *
+ * @return pointer to found node or NULL if nothing was found
+ */
+l4vfs_th_node_t * sensors_next_nth_leaf(int n, l4vfs_th_node_t * start)
+{
+    typedef enum direction_e {DOWN, NEXT, UP} direction_t;
+    direction_t dir = DOWN;
+    l4vfs_th_node_t * current = start;
+
+    /* 1. check for object type and n < 0 -> yes? return current
+     * 2. switch direction
+     *     - DOWN: go down if possible (current = current->first_child)
+     *       -> yes? continue
+     *          no? switch to NEXT
+     *     - NEXT: go next if possible (current = current->next)
+     *       -> yes? dir = DOWN; continue
+     *          no? switch to UP
+     *     - UP: go up if possible (current = current->parent)
+     *       -> yes? dir = NEXT; continue
+     *          no? return NULL
+     */
+
+    while (1)
+    {
+        if (current->type == L4VFS_TH_TYPE_OBJECT)
+        {
+            n--;
+            if (n < 0)
+                return current;
+        }
+
+        switch (dir)
+        {
+        case DOWN:
+            if (current->first_child)
+            {
+                current = current->first_child;
+                continue;
+            }
+            else
+            {
+                dir = NEXT;
+            }
+            // fall through
+        case NEXT:
+            if (current->next)
+            {
+                current = current->next;
+                dir = DOWN;
+                continue;
+            }
+            else
+            {
+                dir = UP;
+            }
+            // fall through
+        case UP:
+            if (current->parent)
+            {
+                current = current->parent;
+                dir = NEXT;
+                continue;
+            }
+            else
+            {
+                return NULL;
+            }
+        }
+    }
+}
+
+
+void sensors_dump_tree(l4vfs_th_node_t * start, int indent)
+{
+    l4vfs_th_node_t * current;
+    sensor_entry_t * se;
+    int i;
+
+    for (current = start; current; current = current->next)
+    {
+        se = (sensor_entry_t *)(current->data);
+        for (i = 0; i < indent; i++)
+            printf("    ");
+        if (se)
+        {
+            printf("%d:%d:%d (%d)\n",
+                   se->major, se->minor, se->instance, current->id);
+        }
+        else
+        {
+            printf("%s (%d)\n", current->name, current->id);
+        }
+        sensors_dump_tree(current->first_child, indent + 1);
+    }
+}
diff --git a/l4/pkg/ferret/server/sensor_directory/sensors.h b/l4/pkg/ferret/server/sensor_directory/sensors.h
new file mode 100644 (file)
index 0000000..31387c0
--- /dev/null
@@ -0,0 +1,56 @@
+/**
+ * \file   ferret/server/coord/sensors.h
+ * \brief  Sensor management
+ *
+ * \date   04/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+#ifndef __FERRET_SERVER_SENSOR_DIRECTORY_SENSORS_H_
+#define __FERRET_SERVER_SENSOR_DIRECTORY_SENSORS_H_
+
+#include <l4/dm_generic/types.h>
+#include <l4/ferret/types.h>
+#include <l4/l4vfs/tree_helper.h>
+#include "ferret_monitor-server.h"
+
+#define FERRET_MAX_SENSORS 100
+
+typedef struct
+{
+    l4dm_dataspace_t  ds;
+    int               major;
+    int               minor;
+    int               instance;
+    int               type;
+    int               flags;
+    char            * config;
+    l4vfs_th_node_t * node;  // pointer to corresponding tree_helper node
+    char            * data;  // pointer to further, sensor-specific data
+} sensor_entry_t;
+
+/* Obviously a linear table is not the fastest data structure for
+ * searching in it, feel free to optimize here if you have performance
+ * problems!
+ */
+sensor_entry_t * sensors_new_entry(const l4dm_dataspace_t *ds,
+                                   int major, int minor, int instance,
+                                   int type, int flags, const char * config,
+                                   void * data);
+int sensors_get_index_for_id(int id);
+int sensors_get_index_for_prop(int major, int minor, int instance);
+void sensors_check_and_free(l4vfs_th_node_t * node);
+int sensors_fill_list(ferret_monitor_list_entry_t * list, int offset,
+                      int count);
+//l4vfs_th_node_t * sensors_first_leaf(l4vfs_th_node_t * root);
+l4vfs_th_node_t * sensors_next_nth_leaf(int n, l4vfs_th_node_t * start);
+
+// debug stuff
+void sensors_dump_tree(l4vfs_th_node_t * start, int indent);
+
+#endif
diff --git a/l4/pkg/ferret/server/sensor_directory/server.c b/l4/pkg/ferret/server/sensor_directory/server.c
new file mode 100644 (file)
index 0000000..2779b38
--- /dev/null
@@ -0,0 +1,705 @@
+/**
+ * \file   ferret/server/sensor_directory/server.c
+ * \brief  Implements IDL function templates
+ *
+ * \date   07/11/2005
+ * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
+ */
+/*
+ * (c) 2005-2009 Technische Universität Dresden
+ * This file is part of TUD:OS and distributed under the terms of the
+ * GNU General Public License 2.
+ * Please see the COPYING-GPL-2 file for details.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <l4/dm_generic/dm_generic.h>
+#include <l4/dm_phys/dm_phys.h>
+#include <l4/log/l4log.h>
+
+#include "ferret_dir-server.h"
+
+#include "dir.h"
+#include "sensors.h"
+#include "clients.h"
+
+#include <l4/ferret/sensors/scalar_init.h>
+#include <l4/ferret/sensors/histogram_init.h>
+#include <l4/ferret/sensors/list_init.h>
+#include <l4/ferret/sensors/alist_init.h>
+#include <l4/ferret/sensors/dplist_init.h>
+#include <l4/ferret/sensors/slist_init.h>
+#include <l4/ferret/sensors/ulist_init.h>
+#include <l4/ferret/sensors/tbuf.h>
+
+#include <l4/l4vfs/types.h>
+#include <l4/l4vfs/name_space_provider.h>
+
+
+#define MAX_PATH 100
+
+static int instance_counter = 1;  // 0 reserved for ROOT instance
+
+
+int32_t
+ferret_client_create_component(CORBA_Object _dice_corba_obj,
+                               uint16_t major,
+                               uint16_t minor,
+                               uint16_t instance,
+                               uint16_t type,
+                               uint32_t flags,
+                               const char* config,
+                               l4dm_dataspace_t *ds,
+                               CORBA_Server_Environment *_dice_corba_env)
+{
+    int ret;
+    void * temp;
+    char * data;
+    ssize_t size = 0;
+    char path[MAX_PATH];
+    l4vfs_th_node_t * node;
+    local_object_id_t id;
+    sensor_entry_t * se;
+
+    LOGd(verbose, "create: %hd:%hd:%hd:%hd", major, minor, instance, type);
+    // fixme: - check flags
+    //        - care for shared opens
+    //        - care for usage count on reopens
+
+    /* 1. check of we have this node -> reopen
+     *    yes ? -> as usual + increment usage count
+     *    no ?  -> create directories on demand and finally create the
+     *             corresponding node itself
+     */
+
+    snprintf(path, MAX_PATH, "/%d/%d/%d", major, minor, instance);
+    id = l4vfs_th_resolve(0, path);
+    if (id != L4VFS_ILLEGAL_OBJECT_ID)
+    {
+        node = l4vfs_th_node_for_id(id);
+        se = (sensor_entry_t *)(node->data);
+        // check some properties, reopen works only with similar properties
+        if (type != se->type)
+        {
+            LOG("Given type '%d' does not match old one '%d' on reopen!",
+                type, se->type);
+            return -1;
+        }
+        if (flags != se->flags)
+        {
+            LOG("Given flags '%d' do not match old ones '%d' on reopen!",
+                type, se->flags);
+            return -1;
+        }
+        if (strcmp(config, se->config) != 0)
+        {
+            LOG("Given config '%s' does not match old one '%s' on reopen!",
+                config, se->config);
+            return -1;
+        }
+
+        *ds = se->ds;
+        ret = l4dm_share(ds, *_dice_corba_obj, L4DM_RW);
+        if (ret)
+        {
+            LOG("Cannot share access rights for ds: ret = %d", ret);
+            return -1;
+        }
+        node->usage_count++;
+    }
+    else
+    {
+        unsigned dm_flags = L4DM_PINNED + L4RM_MAP + L4DM_CONTIGUOUS;
+
+        // create ds
+        switch (type)
+        {
+        case FERRET_SCALAR:
+            size = ferret_scalar_size_config(config);
+            break;
+        case FERRET_HISTO:
+            size = ferret_histo_size_config(config);
+            break;
+        case FERRET_HISTO64:
+            size = ferret_histo64_size_config(config);
+            break;
+        case FERRET_LIST:
+            size = ferret_list_size_config(config);
+            break;
+        case FERRET_DPLIST:
+            size = ferret_dplist_size_config(config);
+            break;
+        case FERRET_SLIST:
+            size = ferret_slist_size_config(config);
+            break;
+        case FERRET_ULIST:
+            size = ferret_ulist_size_config(config);
+            break;
+        case FERRET_ALIST:
+            size = ferret_alist_size_config(config);
+            break;
+        case FERRET_TBUF:
+            LOG("The tracebuffer sensor can not be instantiated, it exists"
+                " in the kernel!");
+            return -1;
+        default:
+            LOG("Unknown sensor type requested: %d", type);
+            return -1;
+        }
+        LOGd(verbose, "Size: %d", (int)size);  // %z in not printf compatible
+        if (flags & FERRET_SUPERPAGES && size > L4_PAGESIZE)
+            dm_flags += L4DM_MEMPHYS_SUPERPAGES;
+        temp = l4dm_mem_ds_allocate(size, dm_flags, ds);
+        if (! temp)
+            return -1;
+
+        ferret_common_init((ferret_common_t *)temp, major, minor, instance,
+                           type, *ds);
+        switch (type)
+        {
+        case FERRET_SCALAR:
+            ret = ferret_scalar_init((ferret_scalar_t *) temp, config);
+            if (ret != 0)
+            {
+                LOG("Something wrong in scalar_init: %d, %s", ret, config);
+                // fixme: free allocated memory
+                return -2;
+            }
+            break;
+        case FERRET_HISTO:
+            ret = ferret_histo_init((ferret_histo_t *) temp, config);
+            if (ret != 0)
+            {
+                LOG("Something wrong in histo_init: %d, %s", ret, config);
+                // fixme: free allocated memory
+                return -2;
+            }
+            break;
+        case FERRET_HISTO64:
+            ret = ferret_histo64_init((ferret_histo64_t *) temp, config);
+            if (ret != 0)
+            {
+                LOG("Something wrong in histo64_init: %d, %s", ret, config);
+                // fixme: free allocated memory
+                return -2;
+            }
+            break;
+        case FERRET_LIST:
+            ret = ferret_list_init((ferret_list_t *) temp, config);
+            if (ret != 0)
+            {
+                LOG("Something wrong in list_init: %d, %s", ret, config);
+                // fixme: free allocated memory
+                return -2;
+            }
+            break;
+        case FERRET_ALIST:
+            ret = ferret_alist_init((ferret_alist_t *) temp, config);
+            if (ret != 0)
+            {
+                LOG("Something wrong in alist_init: %d, %s", ret, config);
+                // fixme: free allocated memory
+                return -2;
+            }
+            break;
+        case FERRET_DPLIST:
+            ret = ferret_dplist_init((ferret_dplist_t *) temp, config, &data);
+            if (ret != 0)
+            {
+                LOG("Something wrong in dplist_init: %d, %s", ret, config);
+                // fixme: free allocated memory
+                return -2;
+            }
+            break;
+        case FERRET_SLIST:
+            ret = ferret_slist_init((ferret_slist_t *) temp, config, &data);
+            if (ret != 0)
+            {
+                LOG("Something wrong in slist_init: %d, %s", ret, config);
+                // fixme: free allocated memory
+                return -2;
+            }
+            break;
+        case FERRET_ULIST:
+            ret = ferret_ulist_init((ferret_ulist_t *) temp, config, &data);
+            if (ret != 0)
+            {
+                LOG("Something wrong in ulist_init: %d, %s", ret, config);
+                // fixme: free allocated memory
+                return -2;
+            }
+            break;
+        default:
+            LOG("Unknown sensor type requested: %d", type);
+            return -1;
+        }
+        LOGd(verbose, "Size: %d", (int)size);  // %z in not printf compatible
+
+        se = sensors_new_entry(ds, major, minor, instance, type, flags,
+                               config, data);
+        if (! se)
+        {
+            return -1;
+        }
+        id = se->node->id;
+        LOGd(verbose, "Registered with id = %d.", id);
+
+        ret = l4dm_share(ds, *_dice_corba_obj, L4DM_RW);
+        if (ret)
+        {
+            // free ds
+            l4dm_mem_release(temp);
+
+            LOG("Cannot share access rights for ds: ret = %d", ret);
+            return -1;
+        }
+
+    }
+
+    return 0;
+}
+
+
+int32_t
+ferret_client_free_component(CORBA_Object _dice_corba_obj,
+                             uint16_t major,
+                             uint16_t minor,
+                             uint16_t instance,
+                             CORBA_Server_Environment *_dice_corba_env)
+{
+    #warning "ferret_client_free_sensor_component is not implemented!"
+    return -1;
+}
+
+
+int32_t
+ferret_client_new_instance_component(CORBA_Object _dice_corba_obj,
+                                     CORBA_Server_Environment *_dice_corba_env)
+{
+    // fixme: care for overflow
+    return instance_counter++;
+}
+
+
+int32_t
+ferret_monitor_attach_component(CORBA_Object _dice_corba_obj,
+                                uint16_t major,
+                                uint16_t minor,
+                                uint16_t instance,
+                                l4dm_dataspace_t *ds,
+                                CORBA_Server_Environment *_dice_corba_env)
+{
+    local_object_id_t id;
+    l4vfs_th_node_t * node;
+    char path[MAX_PATH];
+    int ret;
+
+    if (major == FERRET_TBUF_MAJOR && minor == FERRET_TBUF_MINOR)
+    {
+        LOGd(verbose, "Request for trace buffer");
+        return -2;  // not found
+    }
+
+    snprintf(path, MAX_PATH, "/%d/%d/%d", major, minor, instance);
+    id = l4vfs_th_resolve(0, path);
+    if (id == L4VFS_ILLEGAL_OBJECT_ID)
+    {
+        LOGd(verbose, "Request for unknown sensor");
+        return -1;  // not found
+    }
+    node = l4vfs_th_node_for_id(id);
+    *ds = ((sensor_entry_t *)(node->data))->ds;
+
+    LOGd(verbose, "Found id = %d.", id);
+    ret = l4dm_share(ds, *_dice_corba_obj, L4DM_RO);
+    if (ret)
+    {
+        LOG("Cannot share access rights for ds: ret = %d", ret);
+        return -1;
+    }
+
+    node->usage_count++;
+
+    return 0;
+}
+
+
+int32_t
+ferret_monitor_detach_component(CORBA_Object _dice_corba_obj,
+                                uint16_t major,
+                                uint16_t minor,
+                                uint16_t instance,
+                                CORBA_Server_Environment *_dice_corba_env)
+{
+    local_object_id_t id;
+    l4vfs_th_node_t * node;
+    int ret;
+    char path[MAX_PATH];
+    l4dm_dataspace_t ds;
+
+    snprintf(path, MAX_PATH, "/%d/%d/%d", major, minor, instance);
+    id = l4vfs_th_resolve(0, path);
+    if (id == L4VFS_ILLEGAL_OBJECT_ID)
+    {
+        LOGd(verbose, "Request for unknown sensor");
+        return -1;  // not found
+    }
+    node = l4vfs_th_node_for_id(id);
+    ds = ((sensor_entry_t *)(node->data))->ds;
+
+    ret = l4dm_revoke(&ds, *_dice_corba_obj, L4DM_ALL_RIGHTS);
+    if (ret)
+    {
+        LOG("Cannot revoke access rights for ds: ret = %d", ret);
+        return -1;
+    }
+    node->usage_count--;
+    sensors_check_and_free(node);
+
+    return 0;
+}
+
+
+int32_t
+ferret_monitor_list_component(CORBA_Object _dice_corba_obj,
+                              ferret_monitor_list_entry_t **entries,
+                              int32_t *count,
+                              int32_t offset,
+                              CORBA_Server_Environment *_dice_corba_env)
+{
+    LOGd(verbose, "list request with offset = '%d', count = '%d'.",
+         offset, *count);
+    //sensors_dump_tree(root, 0);
+
+    *count = sensors_fill_list(*entries, offset, *count);
+
+    if (*count < 0)
+        return -1;
+    else
+        return 0;
+}
+
+
+/****************************** L4VFS stuff ******************************/
+
+
+l4_threadid_t
+l4vfs_basic_name_server_thread_for_volume_component(
+    CORBA_Object _dice_corba_obj,
+    volume_id_t volume_id,
+    CORBA_Server_Environment *_dice_corba_env)
+{
+    if (volume_id == FERRET_L4VFS_VOLUME_ID)
+    {
+        return l4_myself();
+    }
+    return L4_INVALID_ID;
+}
+
+
+object_handle_t
+l4vfs_basic_io_open_component(CORBA_Object _dice_corba_obj,
+                              const object_id_t *object_id,
+                              int32_t flags,
+                              CORBA_Server_Environment *_dice_corba_env)
+{
+    /* 1. check if valid id
+     * 2. check of mode == RO
+     * 3. check if dir
+     * 4. create a new client state
+     * 5. return handle
+     */
+    l4vfs_th_node_t * node;
+    int handle;
+
+    // 1.
+    if (object_id->volume_id != FERRET_L4VFS_VOLUME_ID)
+        return -ENOENT;
+    node = l4vfs_th_node_for_id(object_id->object_id);
+    if (node == NULL)
+        return -ENOENT;
+
+    // 2.
+    if ((flags & O_ACCMODE) != O_RDONLY)
+        return -EROFS;
+
+    // 3.
+    if (node->type != L4VFS_TH_TYPE_DIRECTORY)
+        return -EINVAL;
+
+    // 4.
+    handle = clients_get_free();
+    if (handle < 0)
+        return ENOMEM;
+    clients[handle].open   = 1;
+    clients[handle].mode   = flags;
+    clients[handle].seek   = 0;
+    clients[handle].client = *_dice_corba_obj;
+    clients[handle].node   = node;
+    node->usage_count++;
+
+    return handle;
+}
+
+
+int32_t
+l4vfs_common_io_close_component(CORBA_Object _dice_corba_obj,
+                                object_handle_t handle,
+                                CORBA_Server_Environment *_dice_corba_env)
+{
+    if (handle < 0 || handle >= MAX_CLIENTS)
+        return -EBADF;
+    if (! clients_is_open(handle))
+        return -EBADF;
+    if (! l4_task_equal(clients[handle].client, *_dice_corba_obj))
+        return -EBADF;
+    if (clients[handle].node->type != L4VFS_TH_TYPE_DIRECTORY)
+        return -EBADF;
+
+    clients[handle].node->usage_count--;
+    clients[handle].open = 0;
+
+    // fixme: check for cleaning up dirs here later
+    if (clients[handle].node->usage_count <= 0)
+    {
+        //_check_and_clean_node(clients[handle].node);
+    }
+
+    return 0;
+}
+
+
+object_id_t
+l4vfs_basic_name_server_resolve_component(
+    CORBA_Object _dice_corba_obj,
+    const object_id_t *base,
+    const char* pathname,
+    CORBA_Server_Environment *_dice_corba_env)
+{
+    local_object_id_t l_id;
+    object_id_t id;
+
+    LOG("resolve called with: %d:%d, '%s'",
+        base->volume_id, base->object_id, pathname);
+
+    if (base->volume_id != FERRET_L4VFS_VOLUME_ID)
+    {
+        id.volume_id = L4VFS_ILLEGAL_VOLUME_ID;
+        id.object_id = L4VFS_ILLEGAL_OBJECT_ID;
+        return id;
+    }
+
+    l_id = l4vfs_th_resolve(base->object_id, pathname);
+
+    if (l_id == L4VFS_ILLEGAL_OBJECT_ID)
+    {
+        id.volume_id = L4VFS_ILLEGAL_VOLUME_ID;
+        id.object_id = L4VFS_ILLEGAL_OBJECT_ID;
+    }
+    else
+    {
+        id.volume_id = FERRET_L4VFS_VOLUME_ID;
+        id.object_id = l_id;
+    }
+    return id;
+}
+
+
+char*
+l4vfs_basic_name_server_rev_resolve_component(
+    CORBA_Object _dice_corba_obj,
+    const object_id_t *dest,
+    object_id_t *parent,
+    CORBA_Server_Environment *_dice_corba_env)
+{
+    char * ret;
+
+    if (dest->volume_id != FERRET_L4VFS_VOLUME_ID ||
+        parent->volume_id != FERRET_L4VFS_VOLUME_ID)
+    {
+        return NULL;
+    }
+
+    ret = l4vfs_th_rev_resolve(dest->object_id, &(parent->object_id));
+
+    // tell dice to free the pointer after the reply
+    dice_set_ptr(_dice_corba_env, ret);
+
+    return ret;
+}
+
+
+int32_t
+l4vfs_basic_io_getdents_component(CORBA_Object _dice_corba_obj,
+                                  object_handle_t handle,
+                                  l4vfs_dirent_t **dirp,
+                                  uint32_t *count,
+                                  CORBA_Server_Environment *_dice_corba_env)
+{
+    int ret, seek;
+    l4vfs_th_node_t * node;
+    int __count;
+
+    if (*count > INT_MAX)
+        __count = INT_MAX;
+    else
+        __count = (int)*count;
+
+    if (handle < 0 || handle >= MAX_CLIENTS)
+        return -EBADF;
+    if (! clients_is_open(handle))
+        return -EBADF;
+    if (! l4_task_equal(clients[handle].client, *_dice_corba_obj))
+        return -EBADF;
+
+    node = clients[handle].node;
+    seek = clients[handle].seek;
+    ret = l4vfs_th_dir_fill_dirents(node, seek, *dirp, &__count);
+    clients[handle].seek = ret;  // set new seekpointer
+
+    if (__count < 0)
+        return -EINVAL;
+    else
+        return *count;
+}
+
+
+int32_t
+l4vfs_basic_io_stat_component(CORBA_Object _dice_corba_obj,
+                              const object_id_t *object_id,
+                              l4vfs_stat_t *buf,
+                              CORBA_Server_Environment *_dice_corba_env)
+{
+    /* 1. check if object exists
+     * 2. fill data structure
+     * 3. return it
+     */
+    l4vfs_th_node_t * node;
+
+    // 1.
+    if (object_id->volume_id != FERRET_L4VFS_VOLUME_ID)
+        return -ENOENT;
+    node = l4vfs_th_node_for_id(object_id->object_id);
+    if (node == NULL)
+        return -ENOENT;
+
+    // 2.
+    buf->st_dev   = FERRET_L4VFS_VOLUME_ID;
+    buf->st_ino   = object_id->object_id;
+    if (node->type == L4VFS_TH_TYPE_OBJECT)
+        buf->st_mode = S_IFREG;
+    else
+        buf->st_mode  = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
+    buf->st_nlink = 1;
+    // fixme: other fields are undefined for now ...
+
+    return 0;
+}
+
+
+l4vfs_off_t
+l4vfs_basic_io_lseek_component(CORBA_Object _dice_corba_obj,
+                               object_handle_t handle,
+                               l4vfs_off_t offset,
+                               int32_t whence,
+                               CORBA_Server_Environment *_dice_corba_env)
+{
+    if (handle < 0 || handle >= MAX_CLIENTS)
+        return -EBADF;
+    if (! clients_is_open(handle))
+        return -EBADF;
+    if (! l4_task_equal(clients[handle].client, *_dice_corba_obj))
+        return -EBADF;
+
+    switch (whence)  // fixme: care for all the other cases ...
+    {
+    case SEEK_SET:
+        if (offset != 0)
+            return -EINVAL;
+        clients[handle].seek = offset;
+        break;
+    default:
+        return -EINVAL;
+    }
+    return 0;
+}
+
+
+l4vfs_ssize_t
+l4vfs_common_io_read_component(CORBA_Object _dice_corba_obj,
+                               object_handle_t fd,
+                               char **buf,
+                               l4vfs_size_t *count,
+                               short *_dice_reply,
+                               CORBA_Server_Environment *_dice_corba_env)
+{
+    // fixme: we could distinguish between EINVAL and EBADF
+    //        etc. depending on whether we have this file open or not
+    return -EINVAL;
+}
+
+
+l4vfs_ssize_t
+l4vfs_common_io_write_component(CORBA_Object _dice_corba_obj,
+                                object_handle_t fd,
+                                const char *buf,
+                                l4vfs_size_t *count,
+                                short *_dice_reply,
+                                CORBA_Server_Environment *_dice_corba_env)
+{
+    // fixme: we could distinguish between EINVAL and EBADF
+    //        etc. depending on whether we have this file open or not
+    return -EINVAL;
+}
+
+int32_t
+ferret_fpages_request_component (CORBA_Object _dice_corba_obj,
+                                 uint16_t major,
+                                 uint16_t minor,
+                                 uint16_t instance,
+                                 l4_snd_fpage_t *page,
+                                 CORBA_Server_Environment *_dice_corba_env)
+{
+    local_object_id_t id;
+    l4vfs_th_node_t * node;
+    char path[MAX_PATH];
+    sensor_entry_t * se;
+    int ksem;
+
+    LOG("entry");
+
+    snprintf(path, MAX_PATH, "/%d/%d/%d", major, minor, instance);
+    id = l4vfs_th_resolve(0, path);
+    if (id == L4VFS_ILLEGAL_OBJECT_ID)
+    {
+        LOGd(verbose, "Request for unknown sensor");
+        return -1;  // not found
+    }
+    node = l4vfs_th_node_for_id(id);
+    se = (sensor_entry_t *)(node->data);
+    if (se->type != FERRET_ULIST)
+    {
+        LOGd(verbose, "Request on wrong sensor type for this operation");
+        return -2;
+    }
+    ksem = (int)se->data;
+
+    page->snd_base = 0;  // fixme: is this right?
+    page->fpage.iofp.grant  = 0;
+    page->fpage.iofp.zero1  = 0;
+    page->fpage.iofp.iosize = 0;
+    page->fpage.iofp.zero2  = 2;
+    page->fpage.iofp.iopage = ksem;
+    page->fpage.iofp.f      = 0xf;
+
+    LOG("exit");
+
+    return 0;
+}
diff --git a/repomgr b/repomgr
index ff521fe1564c777563b35b30141d3e176ec06279..892e08a97642c059bfb7054a7f5b7a112952b4ba 100755 (executable)
--- a/repomgr
+++ b/repomgr
@@ -112,6 +112,7 @@ my %modules =
                    expat2
                    fb-drv
                    fbterminal
+                   ferret
                    fuxfprov
                    gnu-efi
                    hello