--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+PKGDIR ?= .
+L4DIR ?= $(PKGDIR)/../..
+
+include $(L4DIR)/mk/subdir.mk
+
+examples: lib
+server: lib
--- /dev/null
+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 ...
--- /dev/null
+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
--- /dev/null
+PKGDIR ?= ..
+L4DIR ?= $(PKGDIR)/../..
+
+TARGET = benchmarks demo monitors
+
+include $(L4DIR)/mk/subdir.mk
--- /dev/null
+PKGDIR ?= ../..
+L4DIR ?= $(PKGDIR)/../..
+
+TARGET = dp_test pthread_test #performance
+
+include $(L4DIR)/mk/subdir.mk
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+PKGDIR ?= ../..
+L4DIR ?= $(PKGDIR)/../..
+
+TARGET = histo_demo list_demo_re ulist_demo scalar_demo test l4linux_user \
+ gcc_instrument
+
+include $(L4DIR)/mk/subdir.mk
--- /dev/null
+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
--- /dev/null
+/*
+ * (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;
+}
--- /dev/null
+/*
+ * (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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/*
+ * (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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+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
--- /dev/null
+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.
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+# 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()
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+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.
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/*
+ * (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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
+
--- /dev/null
+ - open sensors also later if they become available
+ - allow time triggered mode for start, stop, and dump
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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);
+ }
+ }
+}
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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
--- /dev/null
+# 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()
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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);
+}
--- /dev/null
+/**
+ * \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
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+PKGDIR ?= ..
+L4DIR ?= $(PKGDIR)/../..
+
+include $(L4DIR)/mk/include.mk
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/*
+ * (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,
+};
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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);
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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
--- /dev/null
+PKGDIR ?= ..
+L4DIR ?= $(PKGDIR)/../..
+
+TARGET = common consumer producer
+
+include $(L4DIR)/mk/subdir.mk
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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));
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/*
+ * (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];
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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"
--- /dev/null
+/**
+ * \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]);
+ }
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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"
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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"
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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);
+ }
+}
--- /dev/null
+/**
+ * \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);
--- /dev/null
+PKGDIR ?= ../..
+L4DIR ?= $(PKGDIR)/../..
+
+SRC_C = local_names.c
+
+MODE = l4env_minimal
+
+SYSTEMS = x86-l4f
+
+TARGET = libferret_local_names.a
+
+include $(L4DIR)/mk/lib.mk
--- /dev/null
+/**
+ * \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]));
+ }
+}
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/*
+ * (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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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);
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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"
--- /dev/null
+/**
+ * \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);
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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);
+}
--- /dev/null
+/**
+ * \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);
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/**
+ * \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);
+}
--- /dev/null
+/**
+ * \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"
--- /dev/null
+/**
+ * \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"
--- /dev/null
+/**
+ * \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"
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+PKGDIR ?= ..
+L4DIR ?= $(PKGDIR)/../..
+
+TARGET = re
+
+include $(L4DIR)/mk/subdir.mk
--- /dev/null
+PKGDIR ?= ../..
+L4DIR ?= $(PKGDIR)/../..
+
+TARGET = ferret_sensor_dir
+
+REQUIRES_LIBS= libstdc++
+
+SRC_CC = main.cc sensor.cc sensordir.cc
+
+include $(L4DIR)/mk/prog.mk
+
--- /dev/null
+/*
+ * (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;
+}
--- /dev/null
+/*
+ * (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;
+}
+
+
--- /dev/null
+/*
+ * (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);
--- /dev/null
+/*
+ * (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;
+}
--- /dev/null
+# 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
--- /dev/null
+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
--- /dev/null
+/**
+ * \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;
+}
--- /dev/null
+/*
+ * (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
--- /dev/null
+/**
+ * \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, ®_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);
+}
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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);
+ }
+}
--- /dev/null
+/**
+ * \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
--- /dev/null
+/**
+ * \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;
+}
expat2
fb-drv
fbterminal
+ ferret
fuxfprov
gnu-efi
hello