Merge branch 'master' of ssh://code.systems.ethz.ch:8006/diffusion/BFI/barrelfish
authorAdam Turowski <adam.turowski@inf.ethz.ch>
Tue, 26 Jul 2016 11:58:57 +0000 (13:58 +0200)
committerAdam Turowski <adam.turowski@inf.ethz.ch>
Tue, 26 Jul 2016 11:58:57 +0000 (13:58 +0200)
Signed-off-by: Adam Turowski <adam.turowski@inf.ethz.ch>

140 files changed:
errors/errno.fugu
if/acpi.if
if/ahci_mgmt.if
if/arrakis.if
if/ata_rw28.if
if/bcache.if
if/bench.if
if/bfs.if
if/bulk_ctrl.if
if/bulkbench.if
if/dist_event.if
if/intermon.if
if/interphi.if
if/monitor.if
if/monitor_blocking.if
if/octopus.if
if/pci.if
if/ping_pong.if
if/rcce.if
if/serial.if
if/skb.if
if/spawn.if
if/terminal.if
if/terminal_config.if
if/test.if
if/trivfs.if
if/unixsock.if
if/usb_driver.if
if/usb_manager.if
if/xeon_phi.if
if/xmplcr.if
if/xmplmsg.if
if/xmplrpc.if
if/xmplthc.if
if/xomp.if
include/barrelfish/barrelfish.h
include/barrelfish/dispatcher.h
include/barrelfish/lmp_chan.h
include/barrelfish/threads.h
include/barrelfish/ump_chan.h
include/barrelfish/ump_endpoint.h
include/barrelfish/ump_impl.h
include/barrelfish/waitset.h
include/barrelfish_kpi/dispatcher_shared.h
include/flounder/flounder.h
include/flounder/flounder_support.h
include/flounder/flounder_support_lmp.h
include/flounder/flounder_support_ump.h
include/k_r_malloc.h
include/skb/skb.h
lib/angler/angler.c
lib/barrelfish/debug.c
lib/barrelfish/deferred.c
lib/barrelfish/dispatch.c
lib/barrelfish/domain.c
lib/barrelfish/event_mutex.c
lib/barrelfish/flounder_support.c
lib/barrelfish/include/threads_priv.h
lib/barrelfish/include/waitset_chan_priv.h
lib/barrelfish/lmp_chan.c
lib/barrelfish/lmp_endpoints.c
lib/barrelfish/morecore.c
lib/barrelfish/multihop_chan.c
lib/barrelfish/nameservice_client.c
lib/barrelfish/spawn_client.c
lib/barrelfish/threads.c
lib/barrelfish/ump_chan.c
lib/barrelfish/ump_endpoint.c
lib/barrelfish/waitset.c
lib/newlib/newlib/libc/sys/barrelfish/oldmalloc.c
lib/octopus/client/barriers.c
lib/octopus/client/getset.c
lib/octopus/client/locking.c
lib/octopus/client/pubsub.c
lib/octopus/client/semaphores.c
lib/octopus/client/trigger.c
lib/octopus/server/capstorage.c
lib/octopus/server/service.c
lib/pci/pci_client.c
lib/posixcompat/dirent.c
lib/posixcompat/pty.c
lib/skb/skb.c
lib/skb/skb_functions.c
lib/spawndomain/spawn_omp.c
lib/term/client/client_blocking.c
lib/usb/usb_manager_client.c
lib/usb/usb_request.c
lib/vfs/vfs_blockdevfs_ahci.c
lib/vfs/vfs_blockdevfs_ata.c
lib/vfs/vfs_fat.c
lib/vfs/vfs_ramfs.c
lib/xeon_phi/xeon_phi_domain.c
tools/flounder/AHCI.hs
tools/flounder/Backend.lhs
tools/flounder/BackendCommon.hs
tools/flounder/CAbsSyntax.hs
tools/flounder/GCBackend.hs
tools/flounder/GHBackend.hs
tools/flounder/LMP.hs
tools/flounder/Loopback.hs
tools/flounder/Main.lhs
tools/flounder/MsgBuf.hs
tools/flounder/MsgFragments.hs
tools/flounder/Multihop.hs
tools/flounder/Parser.hs
tools/flounder/RPCClient.hs
tools/flounder/Syntax.lhs
tools/flounder/THCBackend.hs
tools/flounder/THCStubsBackend.hs
tools/flounder/UMPCommon.hs
usr/acpi/acpi_service.c
usr/drivers/cpuboot/main.c
usr/drivers/cpuboot/x86boot.c
usr/drivers/serial/basic_service.c
usr/drivers/serial/terminal_service.c
usr/drivers/xeon_phi/domain.c
usr/examples/xmpl-msg/msg.c
usr/examples/xmpl-rpc/rpc_msg.c
usr/examples/xmpl-thc-binding/thc-binding.c
usr/fish/fish_common.c
usr/kaluga/start_cpu.c
usr/kaluga/start_pci.c
usr/monitor/arch/aarch64/monitor_server.c
usr/monitor/arch/armv7/monitor_server.c
usr/monitor/arch/x86/monitor_server.c
usr/monitor/capops/internal.c
usr/monitor/inter.c
usr/monitor/monitor_server.c
usr/monitor/multihop_support.c
usr/monitor/ram_alloc.c
usr/monitor/resource_ctrl.c
usr/monitor/ump_support.c
usr/pci/pci.c
usr/pci/pci_service.c
usr/ramfsd/service.c
usr/skb/include/skb_server.h
usr/skb/skb_main.c
usr/skb/skb_service.c
usr/spawnd/service.c
usr/tests/ata_rw28_test/ata_rw28_test.c

index bedd73c..ae3d347 100755 (executable)
@@ -405,6 +405,7 @@ errors libbarrelfish LIB_ERR_ {
 errors flounder FLOUNDER_ERR_ {
     failure INVALID_STATE       "Invalid/corrupt state in binding structure",
     failure TX_BUSY             "Cannot queue message for transmit: queue is full",
+    failure TX_MSG_SIZE         "Trying to send a message which is larger than declared",
     failure RX_EMPTY_MSG        "Incoming message invalid: empty payload",
     failure RX_INVALID_MSGNUM   "Incoming message invalid: unknown message code",
     failure RX_INVALID_LENGTH   "Incoming message has invalid length",
index 28c1ac0..fdda0ba 100644 (file)
@@ -21,13 +21,13 @@ interface acpi "acpi RPC Interface" {
                            out uint8 startbus,
                            out uint8 endbus);
 
-    rpc read_irq_table(in string handle,
+    rpc read_irq_table(in String handle[256],
                        in pci_address addr,
                        in uint8 bus,
                        out errval error,
-                       out string child);
+                       out String child[256]);
 
-    rpc set_device_irq(in string handle,
+    rpc set_device_irq(in String handle[2048],
                        in uint32 irq,
                        out errval error);
 
@@ -39,8 +39,8 @@ interface acpi "acpi RPC Interface" {
     rpc reset(out errval err);
     rpc sleep(in uint32 state, out errval err);
 
-    rpc get_handle(in string devid, out uint64 handle, out errval err);
-    rpc eval_integer(in uint64 handle, in string path, out uint64 val, out errval err); 
+    rpc get_handle(in String devid[2048], out uint64 handle, out errval err);
+    rpc eval_integer(in uint64 handle, in String path[2048], out uint64 val, out errval err);
 
     // Kludge: retrieve frame cap to VBE BIOS;
     rpc get_vbe_bios_cap(out errval err, out cap cap, out uint32 size);
@@ -54,7 +54,7 @@ interface acpi "acpi RPC Interface" {
     rpc vtd_remove_device(in uint32 seg, in uint32 bus, in uint32 dev, in uint32 funct, in cap pml4, out errval err);
 
     rpc vtd_id_dom_add_devices(out errval err);
-    
+
     // More Kludge; cap retrieval for pci
     // We need a designated service to maintain the physical address
     // space caps (to avoid sibling errors).
index 45fe658..75fcf6d 100644 (file)
@@ -9,8 +9,8 @@
 
 interface ahci_mgmt "AHCI Management Daemon" {
 
-    rpc list(out uint8 port_ids[len]);
-    rpc identify(in uint8 port_id, out uint8 identify_data[data_len]);
+    rpc list(out uint8 port_ids[len, 128]);
+    rpc identify(in uint8 port_id, out uint8 identify_data[data_len, 512]);
 
     rpc open(in uint8 port_id, out errval status, out cap controller_mem, out uint64 offset, out uint32 capabilities);
     rpc close(in uint8 port_id, out errval status);
index 0c39156..1425d47 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 interface arrakis "Interface to arrakismon" {
-    rpc spawn_arrakis_domain(in string path, in char argvbuf[argvbytes],
-       in char envbuf[envbytes], out errval err, out domainid domain_id);
+    rpc spawn_arrakis_domain(in String path[2048], in char argvbuf[argvbytes, 2048],
+       in char envbuf[envbytes, 2048], out errval err, out domainid domain_id);
 };
+
index c890e8b..ef02fce 100644 (file)
 interface ata_rw28 "ATA read & write with 28-bit LBA" {
 
     @ata(command=0xC8, dma_arg=buffer, dma_size=read_size, lba=start_lba)
-    rpc read_dma(in uint32 read_size, in uint32 start_lba, out uint8 buffer[buffer_size]);
+    rpc read_dma(in uint32 read_size, in uint32 start_lba, out uint8 buffer[buffer_size, 2048]);
 
     @ata(command=0xC8, dma_arg=buffer, dma_size=512, lba=lba)
-    rpc read_dma_block(in uint32 lba, out uint8 buffer[buffer_size]);
+    rpc read_dma_block(in uint32 lba, out uint8 buffer[buffer_size, 2048]);
 
     @ata(command=0xCA, dma_arg=buffer, is_write=1, lba=lba)
-    rpc write_dma(in uint8 buffer[buffer_size], in uint32 lba, out errval status);
+    rpc write_dma(in uint8 buffer[buffer_size, 2048], in uint32 lba, out errval status);
 
     @ata(command=0xEC, dma_arg=buffer, dma_size=512)
-    rpc identify_device(out uint8 buffer[buffer_size]);
+    rpc identify_device(out uint8 buffer[buffer_size, 2048]);
 
     @ata(command=0xE7)
     rpc flush_cache(out errval status);
 };
+
index ae9c0c7..e56e64c 100644 (file)
@@ -12,8 +12,9 @@ interface bcache "Buffer cache" {
 
     rpc new_client(out cap bulk);
 
-    rpc get_start(in char key[key_len], out uint64 idx, out bool haveit, out uint64 transid, out uint64 size);
+    rpc get_start(in char key[key_len, 2048], out uint64 idx, out bool haveit, out uint64 transid, out uint64 size);
     rpc get_stop(in uint64 transid, in uint64 idx, in uint64 length);
 
     rpc print_stats();
 };
+
index 77dd899..79a4232 100644 (file)
@@ -27,8 +27,8 @@ interface bench "The bench Interface" {
         message fsb_init_msg(uint8 coreid);
        message fsb_empty_request();
        message fsb_empty_reply();
-       message fsb_buffer_request(uint8 buf[size]);
-       message fsb_buffer_reply(uint8 buf[size]);
+       message fsb_buffer_request(uint8 buf[size, 2048]);
+       message fsb_buffer_reply(uint8 buf[size, 2048]);
 
        message fsb_payload_request(int word0, int word1, int word2, int word3);
        message fsb_payload_reply(int word0, int word1, int word2, int word3);
@@ -106,3 +106,4 @@ interface bench "The bench Interface" {
        message shmc_start();
        message shmc_done();
 };
+
index 491caf4..afdb859 100644 (file)
--- a/if/bfs.if
+++ b/if/bfs.if
@@ -52,8 +52,8 @@ typedef enum {
  * --------
  * The storage server implements a log-structured data store,
  * from which data can be read or written in terms of chunks.
- * A chunk is a block of data of a specific size with a 
- * unique ID.  A client or directory server can read or 
+ * A chunk is a block of data of a specific size with a
+ * unique ID.  A client or directory server can read or
  * write chunks from the storage by passing the ID of the chunk.
  */
 
@@ -133,14 +133,14 @@ rpc ns_unlock(in object_key object, out errval err);
 rpc ds_create(
     in  OBJECT_TYPE         ob_type,
     in  OBJECT_ACCESS_PERM  ob_perm,
-    in  string              ob_name,
+    in  String              ob_name[2048],
     in  uint64              client_id,
     out object_key          object);
 
-rpc ds_open(        
+rpc ds_open(
     in  OBJECT_TYPE         ob_type,
     in  OBJECT_ACCESS_PERM  ob_perm,
-    in  string              ob_name,
+    in  String              ob_name[2048],
     in  uint64             client_id,
     out object_key          object);
 
@@ -154,14 +154,13 @@ message ds_invalidate_cache(object_key object);
  * -----------------------------------------------
  * XXX TO DO: make the maintenance of replicated state
  * be implicit via a consensus protocol.
- * 
+ *
  * Name server can broadcast current list of servers
  * to all SS and DS servers in the system.  This is a
  * one-way notification.
  */
-message ss_notify_registered_servers(
-       uint64   server);
-message ds_notify_registered_servers(
-       uint64   server);
+message ss_notify_registered_servers(uint64 server);
+message ds_notify_registered_servers(uint64 server);
 
 };
+
index ed7f2d9..61f6d7f 100644 (file)
@@ -83,13 +83,13 @@ interface bulk_ctrl "bulk control channel interface" {
  *  tid is a transaction id, used to mark which request a given reply belongs to
  *
  */
+
     /*
     rpc move(in poolid poolid,
              in  uint32     bufferid,
              in  uint32     tid,
              in  cap        cap,
-             in  uint8      meta[metasize],
+             in  uint8      meta[metasize, 2048],
              out error      error,
              out uint32     tid);
     */
@@ -98,12 +98,12 @@ interface bulk_ctrl "bulk control channel interface" {
                                 uint32     bufferid,
                                 uint32     tid,
                                 cap        cap,
-                                uint8      meta[metasize]);
+                                uint8      meta[metasize, 2048]);
 
     message move_trusted_call(poolid poolid,
                               uint32     bufferid,
                               uint32     tid,
-                              uint8      meta[metasize]);
+                              uint8      meta[metasize, 2048]);
 
 
     message move_response(error      error,
@@ -114,7 +114,7 @@ interface bulk_ctrl "bulk control channel interface" {
              in  uint32     bufferid,
              in  uint32     tid,
              in  cap        cap,
-             in  uint8      meta[metasize],
+             in  uint8      meta[metasize, 2048],
              out error      error,
              out uint32     tid);
     */
@@ -123,12 +123,12 @@ interface bulk_ctrl "bulk control channel interface" {
                                 uint32     bufferid,
                                 uint32     tid,
                                 cap        cap,
-                                uint8      meta[metasize]);
+                                uint8      meta[metasize, 2048]);
 
     message copy_trusted_call(poolid     poolid,
                               uint32     bufferid,
                               uint32     tid,
-                              uint8      meta[metasize]);
+                              uint8      meta[metasize, 2048]);
 
 
     message copy_response(error      error,
@@ -139,7 +139,7 @@ interface bulk_ctrl "bulk control channel interface" {
              in  uint32     bufferid,
              in  uint32     tid,
              in  cap        cap,
-             in  uint8      meta[metasize],
+             in  uint8      meta[metasize, 2048],
              out error      error,
              out uint32     tid);
     */
@@ -148,12 +148,12 @@ interface bulk_ctrl "bulk control channel interface" {
                                 uint32     bufferid,
                                 uint32     tid,
                                 cap        cap,
-                                uint8      meta[metasize]);
+                                uint8      meta[metasize, 2048]);
 
     message pass_trusted_call(poolid     poolid,
                               uint32     bufferid,
                               uint32     tid,
-                              uint8      meta[metasize]);
+                              uint8      meta[metasize, 2048]);
 
     message pass_response(error      error,
                           uint32     tid);
@@ -173,3 +173,4 @@ interface bulk_ctrl "bulk control channel interface" {
     message release_response(error       error,
                              uint32      tid);
 };
+
index 0eb8867..1ac1144 100644 (file)
@@ -8,12 +8,13 @@
  */
 
 interface bulkbench "Bulk benchmark Interface" {
-       message bulk_init(cap shared_mem);
-       message bulk_init_reply();
+    message bulk_init(cap shared_mem);
+    message bulk_init_reply();
 
-       message message_request(uint8 msg[size]);
-       message message_reply();
+    message message_request(uint8 msg[size, 2048]);
+    message message_reply();
 
-       message bulk_message_request(uint64 id, uint64 size, uint8 last_fragment);
-        message bulk_message_reply(uint64 id, uint8 last_fragment);
+    message bulk_message_request(uint64 id, uint64 size, uint8 last_fragment);
+    message bulk_message_reply(uint64 id, uint8 last_fragment);
 };
+
index f326d52..0b8ba69 100644 (file)
@@ -9,9 +9,10 @@
 
 interface dist_event "dist2 Publish/Subscribe Events" {
     message identify(uint64 id);
-    
-    message subscribed_message(uint64 id, string record);
-    message watch_event(uint64 id, string record);
-    
-    message trigger(uint64 id, string record);
+
+    message subscribed_message(uint64 id, String record[2048]);
+    message watch_event(uint64 id, String record[2048]);
+
+    message trigger(uint64 id, String record[2048]);
 };
+
index 26f7a5f..dbdb1b3 100644 (file)
@@ -102,7 +102,7 @@ interface intermon "The Interface between monitors" {
     // Resource control
     message rsrc_join(rsrcid id, coreid coreid);
     message rsrc_join_complete(rsrcid id);
-    message rsrc_phase_data(rsrcid id, uint32 phase, uint8 data[len]);
+    message rsrc_phase_data(rsrcid id, uint32 phase, uint8 data[len, 2048]);
     message rsrc_timer_sync(uint64 timestamp);
     message rsrc_timer_sync_reply(errval err);
 
@@ -119,10 +119,10 @@ interface intermon "The Interface between monitors" {
     message multihop_routing_table_response(errval err,
             coreid source_coreid,
             coreid max_coreid,
-            coreid to[len]);
+            coreid to[len, 2048]);
 
     // grow the routing table to a set of desination cores, via a given forwarder
-    message multihop_routing_table_grow(coreid forwarder, coreid destinations[len]);
+    message multihop_routing_table_grow(coreid forwarder, coreid destinations[len, 2048]);
 
     // set up a new multihop virtual circuit
     message bind_multihop_intermon_request(iref iref, vci sender_vci,
@@ -131,7 +131,7 @@ interface intermon "The Interface between monitors" {
                                          errval err);
 
     message multihop_message(vci vci, uint8 direction, uint8 flags, uint32 ack,
-                             uint8 payload[size]);
+                             uint8 payload[size, 2048]);
     message multihop_cap_send(vci vci, uint8 direction, capid capid, errval err,
                               caprep cap, bool null_cap, coreid owner);
 
@@ -200,3 +200,4 @@ interface intermon "The Interface between monitors" {
     message forward_kcb_rm_request(uint64 kcb_base);
     message forward_kcb_rm_response(errval err);
 };
+
index 9bd04fc..33fb889 100644 (file)
  */
 
 interface interphi "Interface between host and card side driver" {
-    
-    rpc domain_lookup(in char name[length],
+
+    rpc domain_lookup(in char name[length, 2048],
                       out uint64 domid,
                       out errval msgerr);
-    
-    rpc domain_wait(in char name[length],
+
+    rpc domain_wait(in char name[length, 2048],
                     in uint64 state,
                     out uint64 domid,
                     out uint64 rstate,
                     out errval msgerr);
-    
-    rpc domain_register(in char name[length],
+
+    rpc domain_register(in char name[length, 2048],
                         in uint64 domid,
                         out errval msgerr);
-    
+
     /**
      * \
      */
-    rpc spawn(in uint8 core, 
-              in char cmdline[length],
+    rpc spawn(in uint8 core,
+              in char cmdline[length, 2048],
               in uint8 flags,
               out uint64 domainid,
               out errval msgerr);
-    
+
     /**
-     * 
+     *
      */
-    rpc spawn_with_cap(in uint8 core, 
-                       in char cmdline[length],
+    rpc spawn_with_cap(in uint8 core,
+                       in char cmdline[length, 2048],
                        in uint8 flags,
                        in uint64 cap_base,
                        in uint8 cap_size_bits,
                        out uint64 domainid,
                        out errval msgerr);
-    
+
     /**
-     * 
+     *
      */
-    rpc kill(in uint64 domainid, 
+    rpc kill(in uint64 domainid,
              out errval msgerr);
-    
-    
+
+
     /**
-     * 
+     *
      */
     rpc bootstrap(in uint64 base,
                   in uint64 offset,
@@ -63,7 +63,7 @@ interface interphi "Interface between host and card side driver" {
                   in uint8 xid,
                   in uint8 is_client,
                   out errval msgerr);
-    
+
     rpc chan_open(in uint64 source_did,
                   in uint64 target_did,
                   in uint64 usrdata,
@@ -74,16 +74,16 @@ interface interphi "Interface between host and card side driver" {
     /*
      * host driver only
      */
-    
-    
-    rpc register(in uint8 id, 
+
+
+    rpc register(in uint8 id,
                  in uint64 local_apt_base,
-                 in uint64 local_apt_size, 
-                 out errval msgerr, 
+                 in uint64 local_apt_size,
+                 out errval msgerr,
                  out uint64 other_apt_base,
                  out uint64 other_apt_size);
-    
-    rpc bootstrap_remote(in uint64 base, 
-                         in uint8 bits, 
-                         out errval msgerr); 
-};
\ No newline at end of file
+
+    rpc bootstrap_remote(in uint64 base,
+                         in uint8 bits,
+                         out errval msgerr);
+};
index 9701902..4df4ad5 100644 (file)
@@ -161,7 +161,7 @@ interface monitor "The monitor to client Interface" {
     message multihop_routing_table_new(coreid max_coreid, coreid nentries);
     // Subsequent messages (repeated) which each contain
     // a portion of the routing table from a single core
-    message multihop_routing_table_set(coreid from, coreid to[len]);
+    message multihop_routing_table_set(coreid from, coreid to[len, 128]);
 
     // Connection set-up between monitor and client
     message multihop_bind_client_request(iref iref, vci sender_vci);
@@ -175,7 +175,7 @@ interface monitor "The monitor to client Interface" {
 
     // user message
     message multihop_message(vci vci, uint8 direction, uint8 flags, uint32 ack,
-                             uint8 payload[size]);
+                             uint8 payload[size, 256]);
 
     // cap transfer
     message multihop_cap_send(vci vci, uint8 direction, errval err, cap cap,
index fdbadeb..4e3c802 100644 (file)
@@ -39,7 +39,7 @@ interface monitor_blocking "The monitor to client RPC interface" {
     rpc get_irq_dest_cap(out cap io, out errval err);
 
     // Resource control
-    rpc rsrc_manifest(in cap dispatcher, in string manifest,
+    rpc rsrc_manifest(in cap dispatcher, in String manifest[2048],
             out rsrcid id, out errval err);
     rpc rsrc_join(in rsrcid id, in cap dispatcher, out errval err);
     rpc rsrc_phase(in rsrcid id, in uint32 phase);
index 8b3907d..99d189e 100644 (file)
@@ -28,8 +28,8 @@ interface octopus "octopus RPC Interface" {
     //
     rpc get_identifier(out uint64 id);
     rpc identify(in uint64 id, in binding_type type);
-    
-    
+
+
     //
     // Get/Set API
     //
@@ -37,13 +37,13 @@ interface octopus "octopus RPC Interface" {
     /**
      * \param query Records to find.
      * \param t Additional trigger to watch for future events.
-     * \param output Comma separated string of record names or NULL on error.
+     * \param output Comma separated String of record names or NULL on error.
      * \param tid Id of registered trigger (0 in case no trigger registered).
      * \param error_code Error value of request.
      */
-    rpc get_names(in string query, in trigger t, out string output,
+    rpc get_names(in String query[2048], in trigger t, out String output[2048],
                   out trigger_id tid, out errval error_code);
-    
+
     /**
      * \param query Record to find.
      * \param t Additional trigger to watch for future events.
@@ -51,21 +51,21 @@ interface octopus "octopus RPC Interface" {
      * \param tid Id of registered trigger (0 in case no trigger registered).
      * \param error_code Error value of request.
      */
-    rpc get(in string query, in trigger t, out string output,
+    rpc get(in String query[2048], in trigger t, out String output[2048],
             out trigger_id tid, out errval error_code);
-        
+
     /**
      * \param query Record to set.
      * \param mode Set mode (see getset.h).
      * \param t Additional trigger to watch for future events.
      * \param get Return record if it has been set.
-     * \param record In case get is true and no error_code is ok 
+     * \param record In case get is true and no error_code is ok
      * contains record, otherwise NULL
      * \param tid Id of registered trigger (0 in case no trigger registered).
      * \param error_code Error value of request
      */
-    rpc set(in string query, in uint64 mode, in trigger t, in bool get,
-            out string record, out trigger_id tid, out errval error_code);
+    rpc set(in String query[2048], in uint64 mode, in trigger t, in bool get,
+            out String record[2048], out trigger_id tid, out errval error_code);
 
     /**
      * Find a record using an ID capability as the key/name of the record.
@@ -76,7 +76,7 @@ interface octopus "octopus RPC Interface" {
      * \param tid Id of registered trigger (0 in case no trigger registered).
      * \param error_code Error value of request.
      */
-    rpc get_with_idcap(in cap idcap, in trigger t, out string output,
+    rpc get_with_idcap(in cap idcap, in trigger t, out String output[2048],
                        out trigger_id tid, out errval error_code);
 
     /**
@@ -92,28 +92,28 @@ interface octopus "octopus RPC Interface" {
      * \param tid Id of registered trigger (0 in case no trigger registered).
      * \param error_code Error value of request
      */
-    rpc set_with_idcap(in cap idcap, in string attributes, in uint64 mode,
-                       in trigger t, in bool get, out string record,
+    rpc set_with_idcap(in cap idcap, in String attributes[2048], in uint64 mode,
+                       in trigger t, in bool get, out String record[2048],
                        out trigger_id tid, out errval error_code);
-    
+
     /**
      * \param query Record(s) to delete.
      * \param t Additional trigger to watch for future events.
      * \param tid Id of registered trigger (0 in case no trigger registered).
      * \param error_code Error value of request
      */
-    rpc del(in string query, in trigger t, out trigger_id tid,
+    rpc del(in String query[2048], in trigger t, out trigger_id tid,
             out errval error_code);
-    
+
     /**
      * \param query
      * \param t Additional trigger to watch for future events.
      * \param tid Id of registered trigger (0 in case no trigger registered).
      * \param error_code Error value of request.
      */
-    rpc exists(in string query, in trigger t, out trigger_id tid,
+    rpc exists(in String query[2048], in trigger t, out trigger_id tid,
                out errval error_code);
-    
+
     /**
      * \brief Blocks until a record matching the provided query is registered.
      *
@@ -127,12 +127,12 @@ interface octopus "octopus RPC Interface" {
      * \param record
      * \param error_code
      */
-    rpc wait_for(in string query, out string record, out errval error_code);
-    
+    rpc wait_for(in String query[2048], out String record[2048], out errval error_code);
+
     /**
      * \brief Used to remove Triggers in case they are not needed anymore.
      *
-     * Note that non persistent trigger are removed automatically after 
+     * Note that non persistent trigger are removed automatically after
      * they have fired. For persistent triggers be aware that you might
      * still get a notification after the trigger has been removed because
      * trigger events are sent over another binding.
@@ -141,50 +141,50 @@ interface octopus "octopus RPC Interface" {
      * \param error_code Error of operation
      */
     rpc remove_trigger(in uint64 id, out errval error_code);
-    
+
 
     //
     // Publish/Subscribe API
     //
-    
+
     /**
      * \param query
      * \param client_state Additional state supplied by client.
      * \param id Identifier for this subscription supplied by server.
      * \param error_code Status of request.
      */
-    rpc subscribe(in string query, in uint64 trigger_fn, in uint64 state,
+    rpc subscribe(in String query[2048], in uint64 trigger_fn, in uint64 state,
                   out uint64 id, out errval error_code);
-    
+
     /**
      * \param id Id for the subscription
      * \param error_code Status of request
      */
     rpc unsubscribe(in uint64 id, out errval error_code);
-    
+
     /**
      * \param record Message to publish.
      * \param error_code Status of request.
      */
-    rpc publish(in string record, out errval error_code);
+    rpc publish(in String record[2048], out errval error_code);
 
 
     //
     // Async events (sent by server to client)
     //
-    message trigger(trigger_id id, uint64 trigger_fn, mode m, string record,
+    message trigger(trigger_id id, uint64 trigger_fn, mode m, String record[2048],
                     uint64 state);
 
     message subscription(trigger_id id, uint64 trigger_fn, mode m,
-                         string record, uint64 state);
-    
+                         String record[2048], uint64 state);
+
 
     //
     // Backward compability with chips
     //
-    
+
     // Simple capability storage
-    rpc get_cap(in string key, out cap retcap, out errval reterr);
-    rpc put_cap(in string key, in cap storecap, out errval reterr);
-    rpc remove_cap(in string key, out errval reterr);
+    rpc get_cap(in String key[2048], out cap retcap, out errval reterr);
+    rpc put_cap(in String key[2048], in cap storecap, out errval reterr);
+    rpc remove_cap(in String key[2048], out errval reterr);
 };
index 3deca93..5dc1271 100644 (file)
--- a/if/pci.if
+++ b/if/pci.if
@@ -21,7 +21,12 @@ interface pci "The PCI Interface" {
                         in uint32 fun,
                         out errval err,
                         out uint8 nr_allocated_bars, // Number of bars supported
-                        out caps_per_bar caps_per_bar);
+                        out uint32 caps_per_bar0,
+                        out uint32 caps_per_bar1,
+                        out uint32 caps_per_bar2,
+                        out uint32 caps_per_bar3,
+                        out uint32 caps_per_bar4,
+                        out uint32 caps_per_bar5);
 
     /* Init legacy IO device */
     rpc init_legacy_device(in uint16 iomin,
index 4db04fd..338e224 100644 (file)
 interface ping_pong "Ping-Pong async example Interface" {
         // The following messages are used in the test program
 
-       message rsrc_join_request(uint32 id);
-       message rsrc_join_reply();
-       message init();
-       message ping(uint64 val);
-       message pong(uint64 val);
+    message rsrc_join_request(uint32 id);
+    message rsrc_join_reply();
+    message init();
+    message ping(uint64 val);
+    message pong(uint64 val);
 
        message slow_op(uint64 val);
        message slow_reply(uint64 val);
 
-        message stop();
-
-        rpc testrpc(in uint64 testin, out uint64 testout);
-        rpc testrpc2(in uint64 testin, out uint64 testout);
-
-        rpc outoforder(in uint64 seq_in,
-                       out uint64 seq_out,
-                       in uint64 testin,
-                       out uint64 testout);
-
-        // The following messages are not used in practice, but
-        // exercise the THC Flounder back-end
-
-        message str0(uint32 arg1, string s);
-        message str1(uint32 arg1, string s);
-        message str2(uint32 arg1, string s);
-        rpc str3(in uint32 arg1, in string s);
-        rpc str4(out uint32 arg1, out string s);
-        rpc str5(in uint64 seq_in,
-                 out uint64 seq_out,
-                 in uint32 arg1, in string s);
-        rpc str6(in uint64 seq_in,
-                 out uint64 seq_out,
-                 out uint32 arg1, out string s);
-
-        message arr0(uint32 arg1, char a[l]);
-        message arr1(uint32 arg1, char a[l]);
-        message arr2(uint32 arg1, char a[l]);
+    message stop();
+
+    rpc testrpc(in uint64 testin, out uint64 testout);
+    rpc testrpc2(in uint64 testin, out uint64 testout);
+
+    rpc outoforder(in uint64 seq_in,
+                   out uint64 seq_out,
+                   in uint64 testin,
+                   out uint64 testout);
+
+    // The following messages are not used in practice, but
+    // exercise the THC Flounder back-end
+
+    message str0(uint32 arg1, String s[2048]);
+    message str1(uint32 arg1, String s[2048]);
+    message str2(uint32 arg1, String s[2048]);
+    rpc str3(in uint32 arg1, in String s[2048]);
+    rpc str4(out uint32 arg1, out String s[2048]);
+    rpc str5(in uint64 seq_in,
+             out uint64 seq_out,
+             in uint32 arg1, in String s[2048]);
+    rpc str6(in uint64 seq_in,
+             out uint64 seq_out,
+             out uint32 arg1, out String s[2048]);
+
+    message arr0(uint32 arg1, char a[l, 2048]);
+    message arr1(uint32 arg1, char a[l, 2048]);
+    message arr2(uint32 arg1, char a[l, 2048]);
 };
index 609a271..479a67a 100644 (file)
@@ -24,7 +24,7 @@ interface rcce "The RCCE Interface" {
 
        message error_reply(errval err, uint64 state);
 
-       message message_request(uint16 coreid, uint8 msg[size]);
+       message message_request(uint16 coreid, uint8 msg[size, 2048]);
        message message_reply(uint16 coreid);
 
        message bulk_message_request(uint16 coreid, uint64 id, uint64 size,
index b7aeda6..056129c 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 interface serial "Serial characters" {
-    message output(char data[len]);
-    message input(char data[len]);
+    message output(char data[len, 128]);
+    message input(char data[len, 128]);
     message associate_stdin();
 };
index 78c157a..e312384 100644 (file)
--- a/if/skb.if
+++ b/if/skb.if
@@ -8,24 +8,23 @@
  */
 
 interface skb "SKB RPC Interface" {
-    rpc run( in  string input,
-            out string output,
-                out string str_error,
-                out int    int_error);
+    rpc run( in  String input[2048],
+             out String output[4096],
+             out String str_error[512],
+             out int    int_error);
 
-  
     /*  Used by dist2 library (move in extra interface?) */
     rpc get_identifier(out uint64 id);
     rpc identify(in uint64 id);
     
-       rpc get(in string query, out string output, out string error, out errval error_code);
-       rpc set(in string input, out string error, out errval error_code);
-       rpc del(in string query, out errval error_code);
-       
-    rpc subscribe(in string query, in uint64 id, out errval err);
+    rpc get(in String query[2048], out String output[2048], out String error[2048], out errval error_code);
+    rpc set(in String input[2048], out String error[2048], out errval error_code);
+    rpc del(in String query[2048], out errval error_code);
+
+    rpc subscribe(in String query[2048], in uint64 id, out errval err);
     rpc unsubscribe(in uint64 id, out errval err);
-    rpc publish(in string object, out errval err);
+    rpc publish(in String object[2048], out errval err);
 
-    rpc lock(in string object, out errval err);
-    rpc unlock(in string object, out errval err);
+    rpc lock(in String object[2048], out errval err);
+    rpc unlock(in String object[2048], out errval err);
 };
index 2c2e4aa..1a2f38b 100644 (file)
@@ -12,11 +12,11 @@ interface spawn "Interface to spawn domains" {
     uint8 status;
     } ps_entry;
 
-    rpc spawn_domain(in string path, in char argvbuf[argvbytes], in char envbuf[envbytes],
+    rpc spawn_domain(in String path[2048], in char argvbuf[argvbytes, 2048], in char envbuf[envbytes, 2048],
                      in uint8 flags, out errval err, out domainid domain_id);
 
-    rpc spawn_domain_with_caps(in string path, in char argvbuf[argvbytes],
-                               in char envbuf[envbytes], in cap inheritcn_cap,
+    rpc spawn_domain_with_caps(in String path[2048], in char argvbuf[argvbytes, 2048],
+                               in char envbuf[envbytes, 2048], in cap inheritcn_cap,
                                in cap argcn_cap, in uint8 flags, out errval err,
                                out domainid domain_id);
 
@@ -32,9 +32,9 @@ interface spawn "Interface to spawn domains" {
     rpc wait(in domainid domain_id, in bool nohang, out uint8 exitcode, out errval err);
 
     // XXX: Should be domainid instead of uint8, but it's not yet supported
-    rpc get_domainlist(out uint8 domains[len]);
+    rpc get_domainlist(out uint8 domains[len, 2048]);
 
-    rpc status(in domainid domain_id, out ps_entry ps_entry, out char argv[len],
+    rpc status(in domainid domain_id, out ps_entry ps_entry, out char argv[len, 2048],
               out errval err);
 
     // Capability debugging
index daf6efb..87631d8 100644 (file)
@@ -16,5 +16,5 @@ interface terminal "Unidirectional character stream." {
      * \param buffer Buffer holding characters.
      * \param length Amount of characters in the buffer.
      */
-    message characters(char buffer[length]);
+    message characters(char buffer[length, 2048]);
 };
index df52095..2622eab 100644 (file)
@@ -17,7 +17,7 @@ interface terminal_config "Terminal Configuration Interface" {
      * \param opt Configuration option.
      * \param argument Optional argument. Interpretation depends on opt.
      */
-    message configuration(option opt, string argument);
+    message configuration(option opt, String argument[2048]);
 
     /**
      * \brief Signals that a client wants to teardown a connection.
index 1e867c0..676e02b 100644 (file)
@@ -9,7 +9,7 @@
 
 interface test "Test interface" {
         message basic(uint32 arg);
-        message str(uint32 arg, string s);
+        message str(uint32 arg, String s[2048]);
         message caps(uint32 arg, cap cap1, cap cap2);
-        message buf(uint8 buf[buflen]);
+        message buf(uint8 buf[buflen, 2048]);
 };
index f63123b..63ef6bd 100644 (file)
@@ -22,10 +22,10 @@ interface trivfs "Trivial file system interface" {
     // read the name/type/size of the i'th entry in the given directory
     // (yes, there's no protection against concurrent addition/deletion)
     rpc readdir(in fh dir, in uint32 idx,
-                out errval err, out string name, out bool isdir, out fsize size);
+                out errval err, out String name[2048], out bool isdir, out fsize size);
 
     // look for a named entry in the given directory, return the fh if found
-    rpc lookup(in fh dir, in string name,
+    rpc lookup(in fh dir, in String name[2048],
                out errval err, out fh fh, out bool isdir);
 
     // return the type/size of the given fh
@@ -34,8 +34,8 @@ interface trivfs "Trivial file system interface" {
 
     // read/write: fairly straightforward
     rpc read(in fh file, in offset offset, in fsize maxlen,
-             out errval err, out uint8 data[retlen]);
-    rpc write(in fh file, in offset offset, in uint8 data[len],
+             out errval err, out uint8 data[retlen, 2048]);
+    rpc write(in fh file, in offset offset, in uint8 data[len, 2048],
               out errval err);
 
     // read/write using bulk data
@@ -49,11 +49,11 @@ interface trivfs "Trivial file system interface" {
                  out errval err);
 
     // create a new file in the given directory, fail if it already exists
-    rpc create(in fh dir, in string name,
+    rpc create(in fh dir, in String name[2048],
                out errval err, out fh fh);
 
     // create a new subdirectory in the given directory
-    rpc mkdir(in fh dir, in string name,
+    rpc mkdir(in fh dir, in String name[2048],
               out errval err, out fh fh);
 
     // delete a file or directory
index eaccdda..04cc2c0 100644 (file)
@@ -8,5 +8,5 @@
  */
 
 interface unixsock "UNIX socket" {
-         message send(uint8 msg[size]);
+         message send(uint8 msg[size, 2048]);
 };
index 2c62953..0c58297 100644 (file)
@@ -9,7 +9,7 @@
 
 
 interface usb_driver "USB Drive Interface" {
-    
+
     message device_detach_notify();
-    message transfer_done_notify(uint32 tid, uint32 error, uint8 data[length]);
-};
\ No newline at end of file
+    message transfer_done_notify(uint32 tid, uint32 error, uint8 data[length, 2048]);
+};
index 94ca1e9..f2dac96 100644 (file)
@@ -9,7 +9,7 @@
 
 
 interface usb_manager "USB Manager Interface" {
-    
+
     /* transfer setup parameters, keep in sync with struct usb_transfer_setup */
     typedef struct {
  uint32 max_bytes;             ///< maximum bytes to to transfer
@@ -22,75 +22,75 @@ interface usb_manager "USB Manager Interface" {
     uint8 endpoint;               ///< the associated endpoint of the transfer
     uint8 iface;              ///< the itnerface to use
     } setup_param;
-    
-    /* 
+
+    /*
      * ----------------------------------------------------------------------
      * connecting to the USB manager
-     * ---------------------------------------------------------------------- 
+     * ----------------------------------------------------------------------
      */
-    
-    rpc connect(in iref driver_iref, in uint16 init_config, out uint32 ret_error, out uint8 ret_desc[length]);
+
+    rpc connect(in iref driver_iref, in uint16 init_config, out uint32 ret_error, out uint8 ret_desc[length, 2048]);
 
     rpc device_disconnect_notify();
-    
 
-    /* 
+
+    /*
      * ----------------------------------------------------------------------
      * Request handling
-     * ---------------------------------------------------------------------- 
+     * ----------------------------------------------------------------------
      */
-     
-    rpc request_read(in uint8 request[req_length], 
-                            out uint8 data[data_length], 
+
+    rpc request_read(in uint8 request[req_length, 2048],
+                            out uint8 data[data_length, 2048],
                             out uint32 ret_status);
-                            
-    rpc request_write(in uint8 request[req_length], 
-                            in uint8 data[data_length],
+
+    rpc request_write(in uint8 request[req_length, 2048],
+                            in uint8 data[data_length, 2048],
                             out uint32 ret_status);
-                            
-    rpc request(in uint8 request[req_length], out uint32 ret_status);
-    
-    
-    /* 
+
+    rpc request(in uint8 request[req_length, 2048], out uint32 ret_status);
+
+
+    /*
      * ----------------------------------------------------------------------
      * transfer management
-     * ---------------------------------------------------------------------- 
+     * ----------------------------------------------------------------------
      */
-        
-    rpc transfer_setup(in uint8 type, in setup_param params, 
-                       out uint32 ret_error, out uint32 ret_tid);  
-    
+
+    rpc transfer_setup(in uint8 type, in setup_param params,
+                       out uint32 ret_error, out uint32 ret_tid);
+
     rpc transfer_unsetup(in uint32 tid, out uint32 ret_error);
-    
+
     rpc transfer_start(in uint32 tid, out uint32 ret_error);
-    
+
     rpc transfer_stop(in uint32 tid, out uint32 ret_error);
-      
-    rpc transfer_status(in uint32 tid, out uint32 ret_error, 
-                        out uint32 ret_actlen, out uint32 ret_length, 
+
+    rpc transfer_status(in uint32 tid, out uint32 ret_error,
+                        out uint32 ret_actlen, out uint32 ret_length,
                         out uint32 ret_actframes, out uint32 ret_numframes);
-    
+
     rpc transfer_state(in uint32 tid, out uint32 ret_error, out uint32 ret_state);
-    
+
     rpc transfer_clear_stall(in uint32 tid, out uint32 ret_error);
-    
-    rpc transfer_done_notify(out uint32 tid, out uint32 error, out uint8 data[length]);
-    
-    /* 
+
+    rpc transfer_done_notify(out uint32 tid, out uint32 error, out uint8 data[length, 2048]);
+
+    /*
      * ----------------------------------------------------------------------
      * device management
-     * ---------------------------------------------------------------------- 
+     * ----------------------------------------------------------------------
      */
-     
+
      rpc device_get_speed(out uint8 ret_speed);
-     
+
      rpc device_get_state(out uint8 ret_state);
-     
+
      rpc device_suspend(out uint32 ret_error);
-     
+
      rpc device_resume(out uint32 ret_error);
-     
+
      rpc device_powersave(in uint8 powerstate, out uint32 ret_error);
-     
-     
-};
\ No newline at end of file
+
+
+};
index 7627b61..3f7b6bb 100644 (file)
  */
 
 interface xeon_phi "Xeon Phi Messaging Interface" {
-    
-    rpc domain_lookup(in char name[length],
+
+    rpc domain_lookup(in char name[length, 2048],
                       out uint64 domid,
                       out errval msgerr);
-    
-    rpc domain_wait(in char name[length],
+
+    rpc domain_wait(in char name[length, 2048],
                     out uint64 domid,
                     out errval msgerr);
-    
-    rpc domain_register(in char name[length],
+
+    rpc domain_register(in char name[length, 2048],
                        in uint64 domid,
                        out errval msgerr);
-                    
-    rpc domain_init(in domainid domain, 
+
+    rpc domain_init(in domainid domain,
                                in coreid core,
-                    in char name[length],
+                    in char name[length, 2048],
                     out errval msgerr);
-    
+
     /*
      * Spawning of Domains
-     */    
-    
+     */
+
     /**
      * \
      */
-    rpc spawn(in uint8 xid, 
-              in uint8 core, 
-              in char cmdline[length],
+    rpc spawn(in uint8 xid,
+              in uint8 core,
+              in char cmdline[length, 2048],
               in uint8 flags,
               out uint64 domainid,
               out errval msgerr);
-    
-    rpc spawn_with_cap(in uint8 xid, 
-                       in uint8 core, 
-                       in char cmdline[length],
+
+    rpc spawn_with_cap(in uint8 xid,
+                       in uint8 core,
+                       in char cmdline[length, 2048],
                        in uint8 flags,
                        in cap capability,
                        out uint64 domainid,
                        out errval msgerr);
-    
+
     rpc kill(in uint8 xid,
-             in uint64 domainid, 
+             in uint64 domainid,
              out errval msgerr);
-    
-    
-    rpc chan_open_request(in uint8 xphi, 
-                          in cap msgframe, 
-                          in uint8 type, 
+
+
+    rpc chan_open_request(in uint8 xphi,
+                          in cap msgframe,
+                          in uint8 type,
                           in uint64 domain,
                           in uint64 usrdata,
                           out errval msgerr);
-    
 
-    
+
+
     rpc chan_open(in uint64 domain,
                          in uint64 usrdata,
-                  in cap msgframe, 
+                  in cap msgframe,
                   in uint8 type,
                   out errval msgerr);
 
-};
\ No newline at end of file
+};
index c016aca..7b2e942 100644 (file)
@@ -13,5 +13,5 @@
 
 interface xmplcr "Example call reply interface" {
     message mycall(int i);
-    message myresponse(string s);
-};
\ No newline at end of file
+    message myresponse(String s[2048]);
+};
index 6326584..e72c6e3 100644 (file)
@@ -13,5 +13,5 @@
 
 interface xmplmsg "Example message interface" {
          message msg_ints(int i, int j);
-         message msg_string(string s);
-};
\ No newline at end of file
+         message msg_string(String s[2048]);
+};
index 067c23f..889a24d 100644 (file)
@@ -12,5 +12,5 @@
  */
 
 interface xmplrpc "Example rpc interface" {
-         rpc myrpc(in int i, out string s);
-};
\ No newline at end of file
+    rpc myrpc(in int i, out String s[2048]);
+};
index 4f6c628..80f9375 100644 (file)
@@ -1,5 +1,5 @@
 /** \file
- *  \brief Example interface for use with thc 
+ *  \brief Example interface for use with thc
  */
 
 /*
@@ -14,6 +14,6 @@
 interface xmplthc "Example thc interface" {
     message mymsg(int i);
     message mycall(int i);
-    message myresponse(string s);
-    rpc myrpc(in int i, out string s);
+    message myresponse(String s[2048]);
+    rpc myrpc(in int i, out String s[2048]);
 };
index 3fade93..a594142 100644 (file)
@@ -45,7 +45,7 @@ interface xomp "Xeon Phi openMP interface" {
                       in uint8  direction,
                       in uint64 state,
                       out errval msg_err,
-                      out uint64 state);
+                      out uint64 out_state);
 
     /**
      * \brief notifies the worker domain to obtain memory from the local
index 5f91cad..1fad374 100644 (file)
@@ -82,6 +82,14 @@ static inline uint8_t log2ceil(uintptr_t num)
     }
 }
 
+/// Duplicate memory
+static inline void * memdup(const void *ptr, size_t size) {
+    void *res = malloc(size);
+    assert(res);
+    memcpy(res, ptr, size);
+    return res;
+}
+
 /* XXX: glue junk for old IDC system, to be removed!! */
 
 void messages_wait_and_handle_next(void);
index 42123fc..d59164b 100644 (file)
@@ -79,11 +79,14 @@ struct dispatcher_generic {
     /// size of the eh frame
     size_t   eh_frame_size;
 
-        /// virtual address of the eh_frame
+    /// virtual address of the eh_frame
     lvaddr_t eh_frame_hdr;
 
     /// size of the eh frame
     size_t   eh_frame_hdr_size;
+
+    /// list of polled channels
+    struct waitset_chanstate *polled_channels;
 };
 
 #endif // BARRELFISH_DISPATCHER_H
index 271a6f1..0a99f37 100644 (file)
@@ -134,6 +134,17 @@ static inline errval_t lmp_chan_recv(struct lmp_chan *lc,
 }
 
 /**
+ * \brief Check if a channel has data to receive
+ */
+
+static inline bool lmp_chan_can_recv(struct lmp_chan *lc)
+{
+    assert(lc);
+    assert(lc->endpoint);
+    return lmp_endpoint_can_recv(lc->endpoint);
+}
+
+/**
  * \brief Set the receive capability slot for an LMP channel
  *
  * \param lc LMP channel
@@ -179,6 +190,15 @@ static inline lmp_send_flags_t idc_control_to_lmp_flags(idc_control_t control,
     }
 }
 
+/**
+ * \brief Get a receiving chanstate of LMP channel
+ */
+static inline struct waitset_chanstate * lmp_chan_get_receiving_channel(struct lmp_chan *chan)
+{
+    assert(chan->endpoint);
+    return &chan->endpoint->waitset_state;
+}
+
 #include <barrelfish/lmp_chan_arch.h>
 
 __END_DECLS
index f4afb01..5b7adf3 100644 (file)
@@ -23,6 +23,7 @@
 #include <barrelfish_kpi/registers_arch.h>
 #include <barrelfish_kpi/dispatcher_handle.h>
 #include <errors/errno.h>
+#include <barrelfish/waitset.h>
 
 __BEGIN_DECLS
 
@@ -42,7 +43,7 @@ errval_t thread_join(struct thread *thread, int *retval);
 errval_t thread_detach(struct thread *thread);
 
 void thread_pause(struct thread *thread);
-void thread_pause_and_capture_state(struct thread *thread, 
+void thread_pause_and_capture_state(struct thread *thread,
                                     arch_registers_state_t **ret_regs,
                                     arch_registers_fpu_state_t **ret_fpuregs);
 void thread_resume(struct thread *thread);
@@ -75,6 +76,20 @@ uintptr_t thread_id(void);
 uintptr_t thread_get_id(struct thread *t);
 void thread_set_id(uintptr_t id);
 
+uint32_t thread_set_token(struct waitset_chanstate *channel);
+void thread_clear_token(struct waitset_chanstate *channel);
+uint32_t thread_current_token(void);
+
+void thread_set_outgoing_token(uint32_t token);
+void thread_get_outgoing_token(uint32_t *token);
+
+struct flounder_rpc_context;
+
+void thread_set_rpc_in_progress(bool v);
+bool thread_get_rpc_in_progress(void);
+void thread_set_async_error(errval_t e);
+errval_t thread_get_async_error(void);
+
 extern __thread thread_once_t thread_once_local_epoch;
 extern void thread_once_internal(thread_once_t *control, void (*func)(void));
 
index a5089c7..dee287c 100644 (file)
@@ -118,9 +118,16 @@ static inline errval_t ump_chan_recv(struct ump_chan *uc,
                                      volatile struct ump_message **msg)
 {
     assert(msg != NULL);
+    assert(uc != NULL);
     return ump_endpoint_recv(&uc->endpoint, msg);
 }
 
+static inline errval_t ump_chan_can_recv(struct ump_chan *uc)
+{
+    assert(uc != NULL);
+    return ump_endpoint_can_recv(&uc->endpoint);
+}
+
 static inline volatile struct ump_message *ump_chan_get_next(
                                 struct ump_chan *uc, struct ump_control *ctrl)
 {
@@ -140,6 +147,12 @@ static inline void ump_chan_migrate_recv(struct ump_chan *lc,
     ump_endpoint_migrate(&lc->endpoint, ws);
 }
 
+static inline struct waitset_chanstate * ump_chan_get_receiving_channel(struct ump_chan *chan)
+{
+    return &chan->endpoint.waitset_state;
+}
+
+
 __END_DECLS
 
 #endif // BARRELFISH_UMP_CHAN_H
index 899f024..f6800ef 100644 (file)
@@ -64,6 +64,18 @@ static inline errval_t ump_endpoint_recv(struct ump_endpoint *ep,
     }
 }
 
+static inline bool ump_endpoint_poll(struct waitset_chanstate *channel)
+{
+    struct ump_endpoint *ep = (struct ump_endpoint *)
+        ((char *)channel - offsetof(struct ump_endpoint, waitset_state));
+
+    if (ump_endpoint_can_recv(ep)) {
+        return true;
+    }
+    return false;
+}
+
+
 __END_DECLS
 
 #endif // LIBBARRELFISH_UMP_ENDPOINT_H
index f73304e..bf7cd3b 100644 (file)
@@ -44,10 +44,10 @@ __BEGIN_DECLS
 // This needs to be such that ump_payload defined in params in flounder/UMP.hs
 // and the size of the UMP headers fits into it. It also needs to be a multiple
 // of a cache-line.
-#define UMP_PAYLOAD_BYTES  64
-#define UMP_PAYLOAD_WORDS  (UMP_PAYLOAD_BYTES / sizeof(uintptr_t) - 1)
-#define UMP_MSG_WORDS      (UMP_PAYLOAD_WORDS + 1)
-#define UMP_MSG_BYTES      (UMP_MSG_WORDS * sizeof(uintptr_t))
+#define UMP_MSG_BYTES      64
+#define UMP_MSG_WORDS      (UMP_MSG_BYTES / sizeof(uintptr_t))
+#define UMP_PAYLOAD_BYTES  (UMP_MSG_BYTES - sizeof(uint64_t))
+#define UMP_PAYLOAD_WORDS  (UMP_PAYLOAD_BYTES / sizeof(uintptr_t))
 
 /// Default size of a unidirectional UMP message buffer, in bytes
 #define DEFAULT_UMP_BUFLEN  (BASE_PAGE_SIZE / 2 / UMP_MSG_BYTES * UMP_MSG_BYTES)
@@ -60,16 +60,17 @@ typedef uint32_t ump_control_t;
 struct ump_control {
     ump_control_t epoch:UMP_EPOCH_BITS;
     ump_control_t header:UMP_HEADER_BITS;
+    ump_control_t token:32;
 };
 
 struct ump_message {
     uintptr_t data[UMP_PAYLOAD_WORDS] __attribute__((aligned (CACHELINE_BYTES)));
     union {
         struct ump_control control;
-        uintptr_t raw;
+        uint64_t raw;
     } header;
 };
-STATIC_ASSERT((sizeof(struct ump_message)%CACHELINE_BYTES)==0, 
+STATIC_ASSERT((sizeof(struct ump_message)%CACHELINE_BYTES)==0,
                "Size of UMP message is not a multiple of cache-line size");
 
 /// Type used for indices of UMP message slots
@@ -152,9 +153,8 @@ static inline volatile struct ump_message *ump_impl_poll(struct ump_chan_state *
     ump_control_t ctrl_epoch =  c->buf[c->pos].header.control.epoch;
     if (ctrl_epoch == c->epoch) {
         return &c->buf[c->pos];
-    } else {
-        return NULL;
     }
+    return NULL;
 }
 
 /**
@@ -169,15 +169,14 @@ static inline volatile struct ump_message *ump_impl_recv(struct ump_chan_state *
 {
     volatile struct ump_message *msg = ump_impl_poll(c);
 
-    if(msg != NULL) {
+    if (msg != NULL) {
         if (++c->pos == c->bufmsgs) {
             c->pos = 0;
             c->epoch = !c->epoch;
         }
         return msg;
-    } else {
-        return NULL;
     }
+    return NULL;
 }
 
 /**
@@ -196,6 +195,7 @@ static inline volatile struct ump_message *ump_impl_get_next(
 
     // construct header
     ctrl->epoch = c->epoch;
+    ctrl->token = 0;
 
 #ifdef __x86_64__
     if(debug_notify_syscall) {
index aecda10..f2e208b 100644 (file)
@@ -19,6 +19,7 @@
 #include <barrelfish/types.h>
 #include <errors/errno.h>
 #include <sys/cdefs.h>
+#include <barrelfish/dispatch.h>
 
 __BEGIN_DECLS
 
@@ -64,7 +65,8 @@ enum ws_chanstate {
     CHAN_UNREGISTERED,  ///< Initialised, but not yet registered on a waitset
     CHAN_IDLE,          ///< Has a registered event handler, but the event has not fired
     CHAN_POLLED,        ///< Idle and polled. Channel implementation must be called to check for pending events
-    CHAN_PENDING        ///< Has a pending event waiting to be delivered
+    CHAN_PENDING,       ///< Has a pending event waiting to be delivered
+    CHAN_WAITING        ///< There's no registered event handler (for now)
 };
 
 /**
@@ -79,6 +81,11 @@ struct waitset_chanstate {
     struct event_closure closure;           ///< Event closure to run when channel is ready
     enum ws_chantype chantype;              ///< Channel type
     enum ws_chanstate state;                ///< Channel event state
+
+    uint32_t token;                         ///< Token of an event
+    bool persistent;                        ///< Channel should be always registered
+    struct waitset_chanstate *polled_next, *polled_prev;    ///< Dispatcher's polled queue
+    struct thread *wait_for;                ///< Thread waiting for this event
 };
 
 /**
@@ -90,21 +97,25 @@ struct waitset_chanstate {
 struct waitset {
     struct waitset_chanstate *pending, ///< Channels with pending events
                              *polled,  ///< Channels that need to be polled
-                             *idle;    ///< All other channels on this waitset
+                             *idle,    ///< All other channels on this waitset
+                             *waiting; ///< Channels waiting for an event handler registration
 
     /// Queue of threads blocked on this waitset (when no events are pending)
     struct thread *waiting_threads;
-
-    /// Is a thread currently polling this waitset?
-    volatile bool polling;
 };
 
+void poll_channels_disabled(dispatcher_handle_t handle);
+
 void waitset_init(struct waitset *ws);
 errval_t waitset_destroy(struct waitset *ws);
 
 errval_t get_next_event(struct waitset *ws, struct event_closure *retclosure);
-errval_t check_for_event(struct waitset *ws, struct event_closure *retclosure);
+errval_t get_next_event_disabled(struct waitset *ws, struct waitset_chanstate **retchan,
+        struct event_closure *retclosure, struct waitset_chanstate *waitfor, dispatcher_handle_t handle, bool debug);
+errval_t check_for_event(struct waitset *ws);
 errval_t event_dispatch(struct waitset *ws);
+errval_t wait_for_channel(struct waitset *ws, struct waitset_chanstate *channel, errval_t *error_var);
+errval_t event_dispatch_disabled(struct waitset *ws, dispatcher_handle_t handle);
 errval_t event_dispatch_debug(struct waitset *ws);
 errval_t event_dispatch_non_block(struct waitset *ws);
 
index 35c1f1a..dbabeee 100644 (file)
@@ -38,10 +38,10 @@ enum task_type {
 
 ///< Architecture generic kernel/user shared dispatcher struct
 struct dispatcher_shared_generic {
-    uint32_t   disabled;           ///< Disabled flag (Must be able to change atomically)
-    uint32_t   haswork;            ///< Has work (ie. is runnable) (Must be able to change atomically)
+    uint32_t   disabled;                        ///< Disabled flag (Must be able to change atomically)
+    uint32_t   haswork;                         ///< Has work (ie. is runnable) (Must be able to change atomically)
 
-    lvaddr_t    udisp;             ///< User-mode pointer to dispatcher
+    lvaddr_t    udisp;                          ///< User-mode pointer to dispatcher
     uint32_t    lmp_delivered, lmp_seen;        ///< # LMP words delivered and seen
     lvaddr_t    lmp_hint;                       ///< Hint for location of LMP
     lvaddr_t    dispatcher_run;                 ///< Run entry
@@ -50,14 +50,14 @@ struct dispatcher_shared_generic {
     lvaddr_t    dispatcher_pagefault_disabled;  ///< Disabled pagefault entry
     lvaddr_t    dispatcher_trap;                ///< Trap entry
 
-    systime_t   systime; ///< System time when last dispatched/resumed (W/O to kernel)
-    systime_t   wakeup;  ///< System time at which to wake dispatcher from sleep (R/O by kernel, on yield)
+    systime_t   systime;                        ///< System time when last dispatched/resumed (W/O to kernel)
+    systime_t   wakeup;                         ///< System time at which to wake dispatcher from sleep (R/O by kernel, on yield)
 
-    char        name[DISP_NAME_LEN];///< Name of domain, for debugging purposes
-    uint32_t    fpu_used;               ///< Was FPU used while disabled?
-    uint32_t    fpu_trap;               ///< State of FPU trap
-       
-    coreid_t    curr_core_id;  ///< Core id of current core, in this part so kernel can update
+    char        name[DISP_NAME_LEN];            ///< Name of domain, for debugging purposes
+    uint32_t    fpu_used;                       ///< Was FPU used while disabled?
+    uint32_t    fpu_trap;                       ///< State of FPU trap
+
+    coreid_t    curr_core_id;                   ///< Core id of current core, in this part so kernel can update
 #ifdef __k1om__
     uint8_t     xeon_phi_id;
 #endif
index a5d6aaf..cf093fd 100644 (file)
 /// No-op continuation, to be passed to message send functions
 #define NOP_CONT    NOP_CLOSURE
 
+/// Blocking continuation, block until a sending completes
+void blocking_cont(void *v);
+#define BLOCKING_CONT   MKCLOSURE(blocking_cont, NULL)
+
 /// Utility macro to construct a continuation structure (handler & arg)
 #define MKCONT(h,a) MKCLOSURE(h,a)
 
index 600412d..cbdb87c 100644 (file)
@@ -43,6 +43,7 @@ errval_t flounder_support_register(struct waitset *ws,
                                    bool trigger_now);
 void flounder_support_deregister_chan(struct waitset_chanstate *wc);
 void flounder_support_waitset_chanstate_init(struct waitset_chanstate *wc);
+void flounder_support_waitset_chanstate_init_persistent(struct waitset_chanstate *wc);
 void flounder_support_waitset_chanstate_destroy(struct waitset_chanstate *wc);
 errval_t flounder_support_change_monitor_waitset(struct monitor_binding *mb,
                                                  struct waitset *ws);
index 42f8e98..c36ae4e 100644 (file)
@@ -26,14 +26,14 @@ errval_t flounder_stub_lmp_send_string(struct lmp_chan *chan,
                                        lmp_send_flags_t flags,
                                        const char *str,
                                        size_t *pos, size_t *len);
-errval_t flounder_stub_lmp_recv_string(struct lmp_recv_msg *msg, char **str,
-                                       size_t *pos, size_t *len);
+errval_t flounder_stub_lmp_recv_string(struct lmp_recv_msg *msg, char *str,
+                                       size_t *pos, size_t *len, size_t maxsize);
 
 errval_t flounder_stub_lmp_send_buf(struct lmp_chan *chan,
                                     lmp_send_flags_t flags, const void *buf,
                                     size_t len, size_t *pos);
-errval_t flounder_stub_lmp_recv_buf(struct lmp_recv_msg *msg, void **buf,
-                                    size_t *len, size_t *pos);
+errval_t flounder_stub_lmp_recv_buf(struct lmp_recv_msg *msg, void *buf,
+                                    size_t *len, size_t *pos, size_t maxsize);
 
 __END_DECLS
 
index 31f6a4f..963b7ca 100644 (file)
@@ -43,6 +43,7 @@ struct flounder_ump_state {
     ump_index_t last_ack;  ///< Last acknowledgement we sent to remote
 
     struct flounder_cap_state capst; ///< State for indirect cap tx/rx machinery
+    uint32_t token;        ///< Outgoing message's token
 };
 
 void flounder_stub_ump_state_init(struct flounder_ump_state *s, void *binding);
@@ -52,18 +53,22 @@ errval_t flounder_stub_ump_send_string(struct flounder_ump_state *s,
                                        size_t *pos, size_t *len);
 
 errval_t flounder_stub_ump_recv_string(volatile struct ump_message *msg,
-                                       char **str, size_t *pos, size_t *len);
+                                       char *str, size_t *pos, size_t *len,
+                                       size_t maxsize);
 
 errval_t flounder_stub_ump_send_buf(struct flounder_ump_state *s,
                                        int msgnum, const void *buf,
                                        size_t len, size_t *pos);
 
 errval_t flounder_stub_ump_recv_buf(volatile struct ump_message *msg,
-                                    void **buf, size_t *len, size_t *pos);
+                                    void *buf, size_t *len, size_t *pos,
+                                    size_t maxsize);
+
 
 /// Computes (from seq/ack numbers) whether we can currently send on the channel
 static inline bool flounder_stub_ump_can_send(struct flounder_ump_state *s) {
-    return (ump_index_t)(s->next_id - s->ack_id) <= s->chan.max_send_msgs;
+    bool r = (ump_index_t)(s->next_id - s->ack_id) <= s->chan.max_send_msgs;
+    return r;
 }
 
 #define ENABLE_MESSAGE_PASSING_TRACE 1
@@ -80,6 +85,7 @@ static inline void flounder_stub_ump_control_fill(struct flounder_ump_state *s,
     assert(s->chan.sendid != 0);
     assert(msgtype < (1 << FL_UMP_MSGTYPE_BITS)); // check for overflow
     ctrl->header = ((uintptr_t)msgtype << UMP_INDEX_BITS) | (uintptr_t)s->seq_id;
+    ctrl->token = s->token;
     s->last_ack = s->seq_id;
     s->next_id++;
 }
index 9488030..ce90bf6 100644 (file)
@@ -12,6 +12,7 @@ typedef long long Align;      /* for alignment to long long boundary */
 union header {                 /* block header */
        struct {
                union header   *ptr;    /* next block if on free list */
+               unsigned                magic;  /* to mark malloced region */
                unsigned        size;   /* size of this block */
        } s;
        Align           x;      /* force alignment of blocks */
index b35b84f..a97f91d 100644 (file)
@@ -21,7 +21,6 @@ errval_t skb_add_fact(char *fmt, ...) __attribute__((format(printf, 1, 2)));
 errval_t skb_set_memory_affinity(void);
 
 #define ELEMENT_NAME_BUF_SIZE 80
-#define SKB_REPLY_BUF_SIZE (128*1024)
 
 struct list_parser_status {
     char *s;
index 32fe54f..c502000 100644 (file)
@@ -177,7 +177,6 @@ static errval_t store_session_state(struct capref *session_id,
     struct octopus_rpc_client *rpc_client = NULL;
     char *attributes = NULL;
     size_t attributes_len = 0;
-    char *record = NULL;
     octopus_trigger_id_t tid;
 
     rpc_client = get_octopus_rpc_client();
@@ -195,7 +194,7 @@ static errval_t store_session_state(struct capref *session_id,
     /* Store record at octopus. */
     err = rpc_client->vtbl.set_with_idcap(rpc_client, *session_id, attributes,
                                            SET_DEFAULT, NOP_TRIGGER, false,
-                                           &record, &tid, &error);
+                                           NULL, &tid, &error);
     if (err_is_fail(err)) {
         goto out;
     }
index 9fde3d1..fee7b45 100644 (file)
@@ -111,12 +111,16 @@ errval_t debug_dump_hw_ptables(void)
 
 void debug_printf(const char *fmt, ...)
 {
+    struct thread *me = thread_self();
     va_list argptr;
+    char id[32] = "-";
     char str[256];
     size_t len;
 
-    len = snprintf(str, sizeof(str), "\033[34m%.*s.\033[31m%u.%"PRIuPTR"\033[0m: ",
-                   DISP_NAME_LEN, disp_name(), disp_get_core_id(), thread_id());
+    if (me)
+        snprintf(id, sizeof(id), "%"PRIuPTR, thread_get_id(me));
+    len = snprintf(str, sizeof(str), "\033[34m%.*s.\033[31m%u.%s\033[0m: ",
+                   DISP_NAME_LEN, disp_name(), disp_get_core_id(), id);
     if (len < sizeof(str)) {
         va_start(argptr, fmt);
         vsnprintf(str + len, sizeof(str) - len, fmt, argptr);
index 3a536b2..65bfc30 100644 (file)
@@ -149,11 +149,11 @@ errval_t barrelfish_usleep(delayus_t delay)
 errval_t deferred_event_cancel(struct deferred_event *event)
 {
     enum ws_chanstate chanstate = event->waitset_state.state;
-    dispatcher_handle_t dh = disp_disable();
-    errval_t err = waitset_chan_deregister_disabled(&event->waitset_state);
+    dispatcher_handle_t handle = disp_disable();
+    errval_t err = waitset_chan_deregister_disabled(&event->waitset_state, handle);
     if (err_is_ok(err) && chanstate != CHAN_PENDING) {
         // remove from dispatcher queue
-        struct dispatcher_generic *disp = get_dispatcher_generic(dh);
+        struct dispatcher_generic *disp = get_dispatcher_generic(handle);
         if (event->prev == NULL) {
             disp->deferred_events = event->next;
         } else {
@@ -162,10 +162,10 @@ errval_t deferred_event_cancel(struct deferred_event *event)
         if (event->next != NULL) {
             event->next->prev = event->prev;
         }
-        update_wakeup_disabled(dh);
+        update_wakeup_disabled(handle);
     }
 
-    disp_enable(dh);
+    disp_enable(handle);
     return err;
 }
 
index 7b64646..01030a6 100644 (file)
@@ -110,6 +110,8 @@ void disp_run(dispatcher_handle_t handle)
     // Trigger any send events for LMP channels
     lmp_channels_retry_send_disabled(handle);
 #endif // CONFIG_INTERCONNECT_DRIVER_LMP
+    // Check polled channels
+    poll_channels_disabled(handle);
 
     // Run, saving state of previous thread if required
     thread_run_disabled(handle);
index 7fda57c..e88e512 100644 (file)
@@ -37,7 +37,7 @@
 ///< Struct to maintain per dispatcher domain library state
 struct domain_state {
     iref_t iref;  ///< Iref for the interdisp service
-    struct interdisp_binding *b[MAX_CPUS];
+    struct interdisp_binding *binding[MAX_CPUS];
     struct waitset interdisp_ws;
     struct thread *default_waitset_handler;
     struct thread *remote_wakeup_queue;
@@ -80,7 +80,7 @@ static void dispatcher_initialized_handler(void *arg)
 
     // XXX: Tell currently active interdisp-threads to handle default waitset
     for(int i = 0; i < MAX_CPUS; i++) {
-        struct interdisp_binding *b = domain_state->b[i];
+        struct interdisp_binding *b = domain_state->binding[i];
 
         if(disp_get_core_id() != i &&
            span_domain_state->core_id != i && b != NULL) {
@@ -289,7 +289,7 @@ static void span_eager_connect_request(struct interdisp_binding *b,
     struct domain_state *domain_state = get_domain_state();
 
     /* Store the sending core's connection */
-    domain_state->b[core_id] = b;
+    domain_state->binding[core_id] = b;
 }
 
 static struct interdisp_rx_vtbl interdisp_vtbl = {
@@ -331,7 +331,7 @@ static void client_connected(void *st, errval_t err,
 
     /* Set it on the domain library state */
     b->rx_vtbl = interdisp_vtbl;
-    domain_state->b[state->cnt] = b;
+    domain_state->binding[state->cnt] = b;
 
     // Send it our core id
     err = b->tx_vtbl.span_eager_connect(b, NOP_CONT, disp_get_core_id());
@@ -355,7 +355,7 @@ static void client_connected(void *st, errval_t err,
             USER_PANIC_ERR(err, "Binding to inter-dispatcher service");
         }
     } else {
-        struct interdisp_binding *sb = domain_state->b[state->core_id];
+        struct interdisp_binding *sb = domain_state->binding[state->core_id];
         /* Send initialized msg to the dispatcher that spanned us */
         errval_t err2 = sb->tx_vtbl.
             dispatcher_initialized(sb, NOP_CONT,
@@ -424,9 +424,9 @@ static void handle_wakeup_on(void *arg)
         /* coreid_t core_id = disp_handle_get_core_id(thread->disp); */
         coreid_t core_id = thread->coreid;
 
-        assert(domain_state->b[core_id] != NULL);
+        assert(domain_state->binding[core_id] != NULL);
 
-        struct interdisp_binding *b = domain_state->b[core_id];
+        struct interdisp_binding *b = domain_state->binding[core_id];
         err = b->tx_vtbl.wakeup_thread(b, NOP_CONT, (genvaddr_t)(uintptr_t)thread);
         if (err_is_fail(err)) {
             USER_PANIC_ERR(err, "wakeup_thread");
@@ -546,7 +546,7 @@ errval_t domain_init(void)
     waitset_chanstate_init(&domain_state->remote_wakeup_event,
                            CHANTYPE_EVENT_QUEUE);
     for (int i = 0; i < MAX_CPUS; i++) {
-        domain_state->b[i] = NULL;
+        domain_state->binding[i] = NULL;
     }
 
     waitset_init(&domain_state->interdisp_ws);
@@ -776,18 +776,16 @@ static errval_t domain_new_dispatcher_varstack(coreid_t core_id,
     /* Wait to use the monitor binding */
     struct monitor_binding *mcb = get_monitor_binding();
     event_mutex_enqueue_lock(&mcb->mutex, &span_domain_state->event_qnode,
-                             (struct event_closure) {
-                                 .handler = span_domain_request_sender_wrapper,
-                                     .arg = span_domain_state });
+                          (struct event_closure) {
+                              .handler = span_domain_request_sender_wrapper,
+                                  .arg = span_domain_state });
 
-#if 1
     while(!span_domain_state->initialized) {
         event_dispatch(get_default_waitset());
     }
 
     /* Free state */
     free(span_domain_state);
-#endif
 
     return SYS_ERR_OK;
 }
@@ -813,14 +811,14 @@ errval_t domain_send_cap(coreid_t core_id, struct capref cap)
 {
     errval_t err;
     struct domain_state *domain_state = get_domain_state();
-    if (!domain_state->b[core_id]) {
+    if (!domain_state->binding[core_id]) {
         return LIB_ERR_NO_SPANNED_DISP;
     }
 
     send_cap_err = SYS_ERR_OK;
     cap_received = false;
 
-    struct interdisp_binding *b = domain_state->b[core_id];
+    struct interdisp_binding *b = domain_state->binding[core_id];
     err = b->tx_vtbl.send_cap_request(b, NOP_CONT, cap, (uintptr_t)&cap);
     if (err_is_fail(err)) {
         return err_push(err, LIB_ERR_SEND_CAP_REQUEST);
@@ -856,7 +854,7 @@ static errval_t domain_wakeup_on_coreid_disabled(coreid_t core_id,
 
     // Catch this early
     assert_disabled(ds != NULL);
-    if (ds->b[core_id] == NULL) {
+    if (ds->binding[core_id] == NULL) {
         return LIB_ERR_NO_SPANNED_DISP;
     }
 
@@ -953,11 +951,11 @@ errval_t domain_thread_create_on_varstack(coreid_t core_id,
         struct domain_state *domain_state = get_domain_state();
         errval_t err;
 
-        if (domain_state->b[core_id] == NULL) {
+        if (domain_state->binding[core_id] == NULL) {
             return LIB_ERR_NO_SPANNED_DISP;
         }
 
-        struct interdisp_binding *b = domain_state->b[core_id];
+        struct interdisp_binding *b = domain_state->binding[core_id];
         struct create_thread_req *req = malloc(sizeof(*req));
         req->reply_received = false;
         // use special waitset to make sure loop exits properly.
@@ -1003,11 +1001,11 @@ errval_t domain_thread_join(struct thread *thread, int *retval)
         struct domain_state *domain_state = get_domain_state();
         errval_t err;
 
-        if (domain_state->b[core_id] == NULL) {
+        if (domain_state->binding[core_id] == NULL) {
             return LIB_ERR_NO_SPANNED_DISP;
         }
 
-        struct interdisp_binding *b = domain_state->b[core_id];
+        struct interdisp_binding *b = domain_state->binding[core_id];
         struct join_thread_req *req = malloc(sizeof(*req));
         req->reply_received = false;
         // use special waitset to make sure loop exits properly.
index d8c5fd6..7132143 100644 (file)
@@ -72,10 +72,9 @@ void event_mutex_threaded_lock(struct event_mutex *em)
         thread_mutex_unlock(&em->tmutex);
     } else {
         // add ourselves to the thread queue and block
-        // XXX: TODO: the mutex unlock and block on the queue must be atomic
-        assert(!"this is broken without thread_block_and_release_mutex()");
-        thread_mutex_unlock(&em->tmutex);
-        void *wakeup_reason = thread_block(&em->tqueue);
+        dispatcher_handle_t handle = disp_disable();
+        thread_mutex_unlock_disabled(handle, &em->tmutex);
+        void *wakeup_reason = thread_block_and_release_spinlock_disabled(handle, &em->tqueue, NULL);
 
         assert(wakeup_reason == em);
         assert(em->locked);
index bbf0cc4..e0132a6 100644 (file)
 #include <flounder/flounder_support_caps.h>
 #include <if/monitor_defs.h>
 
+/// Special continuation for blocking
+void blocking_cont(void *v)
+{
+    debug_printf("%s: should never be called!\n", __func__);
+    assert(0);
+}
+
 /*
  * NB: many of these functions are trivial, but exist so that we don't need to
  * expose private libbarrelfish headers or generated flounder headers to every
@@ -61,6 +68,10 @@ errval_t flounder_support_register(struct waitset *ws,
     if (trigger_now) {
         return waitset_chan_trigger_closure(ws, wc, ec);
     } else {
+        if (ec.handler == blocking_cont) {
+            assert(!wc->wait_for);          // this event should be received
+            wc->wait_for = thread_self();   // only by our thread
+        }
         return waitset_chan_register(ws, wc, ec);
     }
 }
@@ -70,6 +81,12 @@ void flounder_support_waitset_chanstate_init(struct waitset_chanstate *wc)
     waitset_chanstate_init(wc, CHANTYPE_FLOUNDER);
 }
 
+void flounder_support_waitset_chanstate_init_persistent(struct waitset_chanstate *wc)
+{
+    waitset_chanstate_init(wc, CHANTYPE_FLOUNDER);
+    wc->persistent = true;
+}
+
 void flounder_support_waitset_chanstate_destroy(struct waitset_chanstate *wc)
 {
     waitset_chanstate_destroy(wc);
@@ -169,7 +186,7 @@ static void putword(uintptr_t word, uint8_t *buf, size_t *pos, size_t len)
     }
 
     for (int i = 0; *pos < len && i < sizeof(uintptr_t); i++) {
-        buf[(*pos)++] = (word & ((uintptr_t)0xff << shift_bits)) >> shift_bits;
+        buf[(*pos)++] = word >> shift_bits;
         word <<= NBBY;
     }
 }
@@ -289,11 +306,13 @@ errval_t flounder_stub_lmp_send_buf(struct lmp_chan *chan,
     return err;
 }
 
-errval_t flounder_stub_lmp_recv_buf(struct lmp_recv_msg *msg, void **bufp,
-                                    size_t *len, size_t *pos)
+errval_t flounder_stub_lmp_recv_buf(struct lmp_recv_msg *msg, void *buf,
+                                    size_t *len, size_t *pos, size_t maxsize)
 {
     int msgpos;
 
+    assert(buf);
+
     // is this the first fragment?
     // if so, unmarshall the length and allocate a buffer
     if (*pos == 0) {
@@ -302,21 +321,12 @@ errval_t flounder_stub_lmp_recv_buf(struct lmp_recv_msg *msg, void **bufp,
         }
 
         *len = msg->words[0];
-        if (*len == 0) {
-            *bufp = NULL;
-        } else {
-            *bufp = malloc(*len);
-            if (*bufp == NULL) {
-                return LIB_ERR_MALLOC_FAIL;
-            }
-        }
+        assert(*len < maxsize);
         msgpos = 1;
     } else {
         msgpos = 0;
     }
 
-    uint8_t *buf = *bufp;
-
     // copy remainder of fragment to buffer
     for (; msgpos < msg->buf.msglen && *pos < *len; msgpos++) {
         putword(msg->words[msgpos], buf, pos, *len);
@@ -350,10 +360,16 @@ errval_t flounder_stub_lmp_send_string(struct lmp_chan *chan,
     return flounder_stub_lmp_send_buf(chan, flags, str, *len, pos);
 }
 
-errval_t flounder_stub_lmp_recv_string(struct lmp_recv_msg *msg, char **strp,
-                                       size_t *pos, size_t *len)
+errval_t flounder_stub_lmp_recv_string(struct lmp_recv_msg *msg, char *str,
+                                       size_t *pos, size_t *len, size_t maxsize)
 {
-    return flounder_stub_lmp_recv_buf(msg, (void **)strp, len, pos);
+    errval_t err;
+
+    err = flounder_stub_lmp_recv_buf(msg, (void *)str, len, pos, maxsize);
+    if (*len == 0) {
+        str[0] = '\0';
+    }
+    return err;
 }
 #endif // CONFIG_INTERCONNECT_DRIVER_LMP
 
@@ -368,6 +384,7 @@ void flounder_stub_ump_state_init(struct flounder_ump_state *s, void *binding)
     s->seq_id = 0;
     s->ack_id = 0;
     s->last_ack = 0;
+    s->token = 0;
     flounder_stub_cap_state_init(&s->capst, binding);
 }
 
@@ -415,31 +432,24 @@ errval_t flounder_stub_ump_send_buf(struct flounder_ump_state *s,
 }
 
 errval_t flounder_stub_ump_recv_buf(volatile struct ump_message *msg,
-                                    void **bufp, size_t *len, size_t *pos)
+                                    void *buf, size_t *len, size_t *pos,
+                                    size_t maxsize)
 {
     int msgpos;
 
+    assert(buf);
+
     // is this the first fragment?
     // if so, unmarshall the length and allocate a buffer
     if (*pos == 0) {
         *len = msg->data[0];
-        if (*len == 0) {
-            *bufp = NULL;
-        } else {
-            *bufp = malloc(*len);
-            if (*bufp == NULL) {
-                return LIB_ERR_MALLOC_FAIL;
-            }
-        }
-
+        assert(*len <= maxsize);
         // XXX: skip as many words as the largest word size
         msgpos = (sizeof(uint64_t) / sizeof(uintptr_t));
     } else {
         msgpos = 0;
     }
 
-    uint8_t *buf = *bufp;
-
     // copy remainder of fragment to buffer
     for (; msgpos < UMP_PAYLOAD_WORDS && *pos < *len; msgpos++) {
         putword(msg->data[msgpos], buf, pos, *len);
@@ -473,9 +483,16 @@ errval_t flounder_stub_ump_send_string(struct flounder_ump_state *s,
 }
 
 errval_t flounder_stub_ump_recv_string(volatile struct ump_message *msg,
-                                       char **strp, size_t *pos, size_t *len)
+                                       char *str, size_t *pos, size_t *len,
+                                       size_t maxsize)
 {
-    return flounder_stub_ump_recv_buf(msg, (void **)strp, len, pos);
+    errval_t err;
+
+    err = flounder_stub_ump_recv_buf(msg, (void *)str, len, pos, maxsize);
+    if (*len == 0) {
+        str[0] = '\0';
+    }
+    return err;
 }
 
 #endif // CONFIG_INTERCONNECT_DRIVER_UMP
index 760450b..692bc47 100644 (file)
@@ -65,7 +65,7 @@ struct thread {
     bool                paused;             ///< Thread is paused (not runnable)
     bool                detached;           ///< true if detached
     bool                joining;            ///< true if someone is joining
-    bool                in_exception;       ///< true iff running exception handler
+    bool                in_exception;       ///< true if running exception handler
     bool                used_fpu;           ///< Ever used FPU?
 #if defined(__x86_64__)
     uint16_t            thread_seg_selector; ///< Segment selector for TCB
@@ -73,6 +73,14 @@ struct thread {
     arch_registers_fpu_state_t fpu_state;   ///< FPU state
     void                *slab;              ///< Base of slab block containing this TCB
     uintptr_t           id;                 ///< User-defined thread identifier
+
+    uint32_t            token_number;      ///< RPC next token
+    uint32_t            token;             ///< Token to be received
+    struct waitset_chanstate *channel;      ///< on right channel
+
+    bool    rpc_in_progress;               ///< RPC in progress
+    errval_t    async_error;                ///< RPC async error
+    uint32_t    outgoing_token;             ///< Token of outgoing message
 };
 
 void thread_enqueue(struct thread *thread, struct thread **queue);
@@ -82,7 +90,7 @@ void thread_remove_from_queue(struct thread **queue, struct thread *thread);
 /* must only be called by dispatcher, while disabled */
 void thread_init_disabled(dispatcher_handle_t handle, bool init_domain);
 
-/// Returns true iff there is non-threaded work to be done on this dispatcher
+/// Returns true if there is non-threaded work to be done on this dispatcher
 /// (ie. if we still need to run)
 static inline bool havework_disabled(dispatcher_handle_t handle)
 {
@@ -91,6 +99,7 @@ static inline bool havework_disabled(dispatcher_handle_t handle)
 #ifdef CONFIG_INTERCONNECT_DRIVER_LMP
             || disp->lmp_send_events_list != NULL
 #endif
+            || disp->polled_channels != NULL
             ;
 }
 
index 37408ee..ba695a1 100644 (file)
@@ -23,7 +23,8 @@ errval_t waitset_chan_trigger_closure_disabled(struct waitset *ws,
                                                struct waitset_chanstate *chan,
                                                struct event_closure closure,
                                                dispatcher_handle_t handle);
-errval_t waitset_chan_deregister_disabled(struct waitset_chanstate *chan);
+errval_t waitset_chan_deregister_disabled(struct waitset_chanstate *chan,
+                                          dispatcher_handle_t handle);
 errval_t waitset_chan_register_disabled(struct waitset *ws,
                                         struct waitset_chanstate *chan,
                                         struct event_closure closure);
@@ -31,7 +32,5 @@ errval_t waitset_chan_register_polled_disabled(struct waitset *ws,
                                                struct waitset_chanstate *chan,
                                                struct event_closure closure,
                                                dispatcher_handle_t handle);
-errval_t waitset_chan_start_polling(struct waitset_chanstate *chan);
-errval_t waitset_chan_stop_polling(struct waitset_chanstate *chan);
 
 #endif // BARRELFISH_WAITSET_CHAN_PRIV_H
index e321bf4..c41c4dc 100644 (file)
@@ -213,7 +213,7 @@ void lmp_chan_destroy(struct lmp_chan *lc)
 struct bind_lmp_reply_state {
     struct monitor_binding *b;
     struct lmp_chan *lc;
-    struct monitor_bind_lmp_reply_monitor__args args;
+    struct monitor_bind_lmp_reply_monitor__tx_args args;
     struct event_queue_node qnode;
 };
 
index 102468b..59441ce 100644 (file)
@@ -90,7 +90,7 @@ void lmp_endpoint_free(struct lmp_endpoint *ep)
  * \param dest    Location of empty slot in which to create endpoint
  * \param retep   Double pointer to LMP endpoint, filled-in with allocated EP
  *
- * This function mints into the given slot an endpoint capability to the 
+ * This function mints into the given slot an endpoint capability to the
  * current dispatcher.
  */
 errval_t lmp_endpoint_create_in_slot(size_t buflen, struct capref dest,
@@ -318,7 +318,7 @@ errval_t lmp_endpoint_deregister(struct lmp_endpoint *ep)
     dispatcher_handle_t handle = disp_disable();
     struct dispatcher_generic *dp = get_dispatcher_generic(handle);
 
-    errval_t err = waitset_chan_deregister_disabled(&ep->waitset_state);
+    errval_t err = waitset_chan_deregister_disabled(&ep->waitset_state, handle);
     if (err_is_ok(err)) {
         /* dequeue from poll list */
         if (ep->next == ep) {
index b7eb34a..2504c51 100644 (file)
@@ -44,6 +44,15 @@ static void *morecore_alloc(size_t bytes, size_t *retbytes)
     errval_t err;
     struct morecore_state *state = get_morecore_state();
 
+    struct ram_alloc_state *ram_alloc_state = get_ram_alloc_state();
+    if(ram_alloc_state->ram_alloc_func != ram_alloc_fixed) {
+        if (bytes < LARGE_PAGE_SIZE) {
+            bytes = LARGE_PAGE_SIZE;
+        }
+
+        bytes = ROUND_UP(bytes, LARGE_PAGE_SIZE);
+    }
+
     void *buf = NULL;
     size_t mapped = 0;
     size_t step = bytes;
index 428fc6a..7b90382 100644 (file)
@@ -243,7 +243,7 @@ static void multihop_new_monitor_binding_continuation2(void *st, errval_t err,
 struct bind_multihop_reply_state {
     struct multihop_chan *mc;
     struct monitor_binding *monitor_binding;
-    struct monitor_multihop_bind_service_reply__args args;
+    struct monitor_multihop_bind_service_reply__tx_args args;
     struct event_queue_node qnode;
 };
 
index eb66ffe..0818cf0 100644 (file)
@@ -38,14 +38,14 @@ errval_t nameservice_lookup(const char *iface, iref_t *retiref)
         return LIB_ERR_NAMESERVICE_NOT_BOUND;
     }
 
-    char* record = NULL;
-    octopus_trigger_id_t tid;
-    errval_t error_code;
-    err = r->vtbl.get(r, iface, NOP_TRIGGER, &record, &tid, &error_code);
+
+    struct octopus_get_names_response__rx_args reply;
+    err = r->vtbl.get(r, iface, NOP_TRIGGER, reply.output, &reply.tid,
+                      &reply.error_code);
     if (err_is_fail(err)) {
         goto out;
     }
-    err = error_code;
+    err = reply.error_code;
     if (err_is_fail(err)) {
         if (err_no(err) == OCT_ERR_NO_RECORD) {
             err = err_push(err, LIB_ERR_NAMESERVICE_UNKNOWN_NAME);
@@ -54,7 +54,7 @@ errval_t nameservice_lookup(const char *iface, iref_t *retiref)
     }
 
     uint64_t iref_number = 0;
-    err = oct_read(record, "_ { iref: %d }", &iref_number);
+    err = oct_read(reply.output, "_ { iref: %d }", &iref_number);
     if (err_is_fail(err) || iref_number == 0) {
         err = err_push(err, LIB_ERR_NAMESERVICE_INVALID_NAME);
         goto out;
@@ -64,7 +64,6 @@ errval_t nameservice_lookup(const char *iface, iref_t *retiref)
     }
 
 out:
-    free(record);
     return err;
 }
 
@@ -83,13 +82,12 @@ errval_t nameservice_blocking_lookup(const char *iface, iref_t *retiref)
         return LIB_ERR_NAMESERVICE_NOT_BOUND;
     }
 
-    char* record = NULL;
-    errval_t error_code;
-    err = r->vtbl.wait_for(r, iface, &record, &error_code);
+    struct octopus_wait_for_response__rx_args reply;
+    err = r->vtbl.wait_for(r, iface, reply.record, &reply.error_code);
     if (err_is_fail(err)) {
         goto out;
     }
-    err = error_code;
+    err = reply.error_code;
     if (err_is_fail(err)) {
         if (err_no(err) == OCT_ERR_NO_RECORD) {
             err = err_push(err, LIB_ERR_NAMESERVICE_UNKNOWN_NAME);
@@ -98,7 +96,7 @@ errval_t nameservice_blocking_lookup(const char *iface, iref_t *retiref)
     }
 
     uint64_t iref_number = 0;
-    err = oct_read(record, "_ { iref: %d }", &iref_number);
+    err = oct_read(reply.record, "_ { iref: %d }", &iref_number);
     if (err_is_fail(err)) {
         err = err_push(err, LIB_ERR_NAMESERVICE_INVALID_NAME);
         goto out;
@@ -108,7 +106,6 @@ errval_t nameservice_blocking_lookup(const char *iface, iref_t *retiref)
     }
 
 out:
-    free(record);
     return err;
 }
 
@@ -136,10 +133,9 @@ errval_t nameservice_register(const char *iface, iref_t iref)
     }
     snprintf(record, len+1, format, iface, iref);
 
-    char* ret = NULL;
     octopus_trigger_id_t tid;
     errval_t error_code;
-    err = r->vtbl.set(r, record, 0, NOP_TRIGGER, 0, &ret, &tid, &error_code);
+    err = r->vtbl.set(r, record, 0, NOP_TRIGGER, 0, NULL, &tid, &error_code);
     if (err_is_fail(err)) {
         goto out;
     }
index 904549d..bcec47e 100644 (file)
@@ -421,22 +421,19 @@ errval_t spawn_program_on_all_cores(bool same_core, const char *path,
     }
 
     // FIXME: world's most (kinda less now) broken implementation...
-    
-    char* buffer = NULL;
-    errval_t error_code;
-    octopus_trigger_id_t tid;
-    
     char** names = NULL;
     size_t count = 0;
-    
+
     static char* spawnds = "r'spawn.[0-9]+' { iref: _ }";
-        err = r->vtbl.get_names(r, spawnds, NOP_TRIGGER, &buffer, &tid, &error_code);
-    if (err_is_fail(err) || err_is_fail(error_code)) {
+    struct octopus_get_names_response__rx_args reply;
+    err = r->vtbl.get_names(r, spawnds, NOP_TRIGGER, reply.output, &reply.tid,
+                            &reply.error_code);
+    if (err_is_fail(err) || err_is_fail(reply.error_code)) {
         err = err_push(err, SPAWN_ERR_FIND_SPAWNDS);
         goto out;
     }
 
-    err = oct_parse_names(buffer, &names, &count);
+    err = oct_parse_names(reply.output, &names, &count);
     if (err_is_fail(err)) {
         goto out;
     }
@@ -464,7 +461,6 @@ errval_t spawn_program_on_all_cores(bool same_core, const char *path,
     }
 
 out:
-    free(buffer);
     oct_free_names(names, count);
     return err;
 }
@@ -578,11 +574,13 @@ errval_t spawn_get_domain_list(uint8_t **domains, size_t *len)
     }
     assert(cl != NULL);
 
-    err = cl->vtbl.get_domainlist(cl, domains, len);
+    struct spawn_get_domainlist_response__rx_args reply;
+    err = cl->vtbl.get_domainlist(cl, reply.domains, len);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "get_domainlist");
     }
 
+    *domains = memdup(reply.domains, *len);
     return SYS_ERR_OK;
 }
 
@@ -601,12 +599,14 @@ errval_t spawn_get_status(uint8_t domain, struct spawn_ps_entry *pse,
     }
     assert(cl != NULL);
 
-    err = cl->vtbl.status(cl, domain, (spawn_ps_entry_t *)pse, argbuf, arglen,
-                          reterr);
+    struct spawn_status_response__rx_args reply;
+    err = cl->vtbl.status(cl, domain, (spawn_ps_entry_t *)pse, reply.argv,
+                          arglen, reterr);
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "status");
     }
 
+    *argbuf = memdup(reply.argv, *arglen);
     return SYS_ERR_OK;
 }
 
index 1bac6da..203e6e5 100644 (file)
@@ -251,6 +251,11 @@ static void thread_init(dispatcher_handle_t disp, struct thread *newthread)
     newthread->used_fpu = false;
     newthread->paused = false;
     newthread->slab = NULL;
+    newthread->token = 0;
+    newthread->token_number = 1;
+
+    newthread->rpc_in_progress = false;
+    newthread->async_error = SYS_ERR_OK;
 }
 
 /**
@@ -602,6 +607,70 @@ void thread_set_id(uintptr_t id)
     me->id = id;
 }
 
+uint32_t thread_set_token(struct waitset_chanstate *channel)
+{
+    struct thread *me = thread_self();
+    // generate new token
+    uint32_t outgoing_token = (uint32_t)((me->id << 16) |
+         (me->coreid << 24) | ((me->token_number & 255) << 8)) | 1;
+    assert(me->token == 0);
+    me->token_number++;
+    me->token = outgoing_token & ~1;    // wait for this token
+    me->channel = channel;              // on that channel
+    return outgoing_token;
+}
+
+void thread_clear_token(struct waitset_chanstate *channel)
+{
+    struct thread *me = thread_self();
+
+    me->token = 0;      // don't wait anymore
+    me->channel = NULL;
+}
+
+uint32_t thread_current_token(void)
+{
+    return thread_self()->token;
+}
+
+void thread_set_outgoing_token(uint32_t token)
+{
+    struct thread *me = thread_self();
+
+    assert(!me->outgoing_token);
+    me->outgoing_token = token;
+}
+
+void thread_get_outgoing_token(uint32_t *token)
+{
+    struct thread *me = thread_self();
+    // if thread's outgoing token is set, get it
+    if (me->outgoing_token) {
+        *token = me->outgoing_token;
+        me->outgoing_token = 0;
+    }
+}
+
+void thread_set_rpc_in_progress(bool v)
+{
+    thread_self()->rpc_in_progress = v;
+}
+
+bool thread_get_rpc_in_progress(void)
+{
+    return thread_self()->rpc_in_progress;
+}
+
+void thread_set_async_error(errval_t e)
+{
+    thread_self()->async_error = e;
+}
+
+errval_t thread_get_async_error(void)
+{
+    return thread_self()->async_error;
+}
+
 /**
  * \brief Yield the calling thread
  *
@@ -629,6 +698,8 @@ void thread_yield(void)
         }
     } while(next->yield_epoch == disp_gen->timeslice);
 
+    poll_channels_disabled(handle);
+
     if (next != me) {
         fpu_context_switch(disp_gen, next);
         disp_gen->current = next;
@@ -964,7 +1035,12 @@ struct thread *thread_unblock_one_disabled(dispatcher_handle_t handle,
  */
 struct thread *thread_unblock_one(struct thread **queue, void *reason)
 {
-    return thread_unblock_one_disabled(disp_disable(), queue, reason);
+    struct thread *thread;
+
+    dispatcher_handle_t handle = disp_disable();
+    thread = thread_unblock_one_disabled(handle, queue, reason);
+    disp_enable(handle);
+    return thread;
 }
 
 /**
index ef748be..6bda739 100644 (file)
@@ -93,7 +93,7 @@ static void bind_ump_reply_handler(struct monitor_binding *b, uintptr_t mon_id,
 struct bind_ump_reply_state {
     struct monitor_binding *b;
     struct ump_chan *uc;
-    struct monitor_bind_ump_reply_monitor__args args;
+    struct monitor_bind_ump_reply_monitor__tx_args args;
     struct event_queue_node qnode;
 };
 
@@ -105,7 +105,7 @@ static void send_bind_reply(void *arg)
 
     // send back a bind success/failure message to the monitor
     err =
-        st->b->tx_vtbl.bind_ump_reply_monitor(st->b, NOP_CONT, st->args.mon_id,
+        st->b->tx_vtbl.bind_ump_reply_monitor(b, NOP_CONT, st->args.mon_id,
                                               st->args.conn_id, st->args.err,
                                               st->args.notify);
     if (err_is_ok(err)) {
@@ -242,7 +242,7 @@ errval_t ump_chan_bind(struct ump_chan *uc, struct ump_bind_continuation cont,
     void *buf;
     err = vspace_map_one_frame_attr(&buf, framesize, uc->frame, UMP_MAP_ATTR,
                                     NULL, &uc->vregion);
-    if (err_is_fail(err)) { 
+    if (err_is_fail(err)) {
         cap_destroy(uc->frame);
         return err_push(err, LIB_ERR_VSPACE_MAP);
     }
index 76869c1..cdf694d 100644 (file)
@@ -63,7 +63,7 @@ errval_t ump_endpoint_register(struct ump_endpoint *ep, struct waitset *ws,
     assert(ep != NULL);
     assert(ws != NULL);
 
-    if (ump_endpoint_can_recv(ep)) { // trigger event immediately
+    if (ump_endpoint_poll(&ep->waitset_state)) { // trigger event immediately
         return waitset_chan_trigger_closure(ws, &ep->waitset_state, closure);
     } else {
         return waitset_chan_register_polled(ws, &ep->waitset_state, closure);
index 8c772a0..e13437e 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
+#include <flounder/flounder.h>
+
 #ifdef CONFIG_INTERCONNECT_DRIVER_UMP
 #  include <barrelfish/ump_endpoint.h>
 #endif
 
-#if defined(__k1om__) || defined(__aarch64__)
-#include <barrelfish_kpi/asm_inlines_arch.h>
-static inline cycles_t cyclecount(void)
+/// Dequeue a chanstate from a queue
+static void dequeue(struct waitset_chanstate **queue, struct waitset_chanstate *chan)
 {
-    return rdtsc();
+    if (chan->next == chan) {
+        assert(chan->prev == chan);
+        assert(*queue == chan);
+        *queue = NULL;
+    } else {
+        chan->prev->next = chan->next;
+        chan->next->prev = chan->prev;
+        if (*queue == chan) {
+            *queue = chan->next;
+        }
+    }
+    chan->prev = chan->next = NULL;
 }
-#elif defined(__x86_64__) || defined(__i386__)
-#include <arch/x86/barrelfish_kpi/asm_inlines_arch.h>
-static inline cycles_t cyclecount(void)
+
+/// Enqueue a chanstate on a queue
+static void enqueue(struct waitset_chanstate **queue, struct waitset_chanstate *chan)
 {
-    return rdtsc();
+    if (*queue == NULL) {
+        *queue = chan;
+        chan->next = chan->prev = chan;
+    } else {
+        chan->next = *queue;
+        chan->prev = (*queue)->prev;
+        chan->next->prev = chan;
+        chan->prev->next = chan;
+    }
 }
-#elif defined(__arm__) && defined(__gem5__)
-/**
- * XXX: Gem5 doesn't support the ARM performance monitor extension
- * therefore we just poll a fixed number of times instead of using
- * cycle counts. POLL_COUNT is deliberately set to 42, guess why! ;)
- */
-#define POLL_COUNT     42
-#elif defined(__aarch64__) && defined(__gem5__)
-#define POLL_COUNT  42
-#elif defined(__arm__)
-#include <arch/arm/barrelfish_kpi/asm_inlines_arch.h>
-static inline cycles_t cyclecount(void)
+
+/// Dequeue a chanstate from polled queue
+static void dequeue_polled(struct waitset_chanstate **queue,
+                            struct waitset_chanstate *chan)
 {
-    return get_cycle_count();
+    if (chan->polled_next == chan) {
+        assert(chan->polled_prev == chan);
+        assert(*queue == chan);
+        *queue = NULL;
+    } else {
+        chan->polled_prev->polled_next = chan->polled_next;
+        chan->polled_next->polled_prev = chan->polled_prev;
+        if (*queue == chan) {
+            *queue = chan->polled_next;
+        }
+    }
+    chan->polled_prev = chan->polled_next = NULL;
 }
-#else
-static inline cycles_t cyclecount(void)
+
+/// Enqueue a chanstate on polled queue
+static void enqueue_polled(struct waitset_chanstate **queue,
+                            struct waitset_chanstate *chan)
 {
-    USER_PANIC("called on non-x86 architecture. why are we polling?");
-    return 0;
+    if (*queue == NULL) {
+        *queue = chan;
+        chan->polled_next = chan->polled_prev = chan;
+    } else {
+        chan->polled_next = *queue;
+        chan->polled_prev = (*queue)->polled_prev;
+        chan->polled_next->polled_prev = chan;
+        chan->polled_prev->polled_next = chan;
+    }
 }
-#endif
-
-// FIXME: bogus default value. need to measure this at boot time
-#define WAITSET_POLL_CYCLES_DEFAULT 2000
-
-/// Maximum number of cycles to spend polling channels before yielding CPU
-cycles_t waitset_poll_cycles = WAITSET_POLL_CYCLES_DEFAULT;
 
 /**
  * \brief Initialise a new waitset
@@ -79,9 +104,8 @@ cycles_t waitset_poll_cycles = WAITSET_POLL_CYCLES_DEFAULT;
 void waitset_init(struct waitset *ws)
 {
     assert(ws != NULL);
-    ws->pending = ws->polled = ws->idle = NULL;
+    ws->pending = ws->polled = ws->idle = ws->waiting = NULL;
     ws->waiting_threads = NULL;
-    ws->polling = false;
 }
 
 /**
@@ -127,55 +151,61 @@ errval_t waitset_destroy(struct waitset *ws)
     return SYS_ERR_OK;
 }
 
-/// Returns a channel with a pending event on the given waitset, or NULL
-static struct waitset_chanstate *get_pending_event_disabled(struct waitset *ws)
+/// Check if a thread can receive an event
+static bool waitset_check_token(struct waitset_chanstate *chan,
+                                struct thread *thread)
 {
-    // are there any pending events on the waitset?
-    if (ws->pending == NULL) {
-        return NULL;
-    }
-
-    // dequeue next pending event
-    struct waitset_chanstate *chan = ws->pending;
-    if (chan->next == chan) {
-        assert_disabled(chan->prev == chan);
-        ws->pending = NULL;
-    } else {
-        ws->pending = chan->next;
-        chan->prev->next = chan->next;
-        chan->next->prev = chan->prev;
-    }
-#ifndef NDEBUG
-    chan->prev = chan->next = NULL;
-#endif
-
-    // mark not pending
-    assert_disabled(chan->state == CHAN_PENDING);
-    chan->state = CHAN_UNREGISTERED;
-    chan->waitset = NULL;
+    bool res = false;
 
-    return chan;
+    if (chan->wait_for) // if a thread is waiting for this specific event
+        res = chan->wait_for == thread;
+    else
+        res = (chan->token & 1 && !thread->token) // incoming token is a request
+            // and a thread is not waiting for a token
+            || (!chan->token && chan != thread->channel) // there's no token
+            // and a thread is not waiting specifically for that event
+            || (chan->token == thread->token && chan == thread->channel);
+            // there is a token and it matches thread's token and event
+    return res;
 }
 
-#ifdef CONFIG_INTERCONNECT_DRIVER_UMP
-/**
- * \brief Poll an incoming UMP endpoint.
- * This is logically part of the UMP endpoint implementation, but placed here
- * for easier inlining.
- */
-static inline void ump_endpoint_poll(struct waitset_chanstate *chan)
+/// Returns a channel with a pending event on the given waitset matching
+/// our thread
+static struct waitset_chanstate *get_pending_event_disabled(struct waitset *ws,
+                                    struct waitset_chanstate *chan)
 {
-    /* XXX: calculate location of endpoint from waitset channel state */
-    struct ump_endpoint *ep = (struct ump_endpoint *)
-        ((char *)chan - offsetof(struct ump_endpoint, waitset_state));
+    struct thread *me = thread_self();
 
-    if (ump_endpoint_can_recv(ep)) {
-        errval_t err = waitset_chan_trigger(chan);
-        assert(err_is_ok(err)); // should not be able to fail
+    if (chan) { // channel that we wait for
+        if (chan->state == CHAN_PENDING && waitset_check_token(chan, me)) {
+            return chan;
+        }
+        if (chan->state == CHAN_WAITING && waitset_check_token(chan, me)) {
+            return chan;
+        }
+    }
+    // check a waiting queue for matching event
+    for (chan = ws->waiting; chan; ) {
+        if (waitset_check_token(chan, me)) {
+            assert_disabled(chan->state == CHAN_WAITING);
+            return chan;
+        }
+        chan = chan->next;
+        if (chan == ws->waiting)
+            break;
+    }
+    // check a pending queue for matching event
+    for (chan = ws->pending; chan;) {
+        if (waitset_check_token(chan, me)) {
+            assert_disabled(chan->state == CHAN_PENDING);
+            return chan;
+        }
+        chan = chan->next;
+        if (chan == ws->pending)
+            break;
     }
+    return NULL;
 }
-#endif // CONFIG_INTERCONNECT_DRIVER_UMP
-
 
 void arranet_polling_loop_proxy(void) __attribute__((weak));
 void arranet_polling_loop_proxy(void)
@@ -190,210 +220,166 @@ void poll_ahci(struct waitset_chanstate *chan)
     assert(err_is_ok(err)); // should not be able to fail
 }
 
-/// Helper function that knows how to poll the given channel, based on its type
-static void poll_channel(struct waitset_chanstate *chan)
-{
-    switch (chan->chantype) {
+/// Check polled channels
+void poll_channels_disabled(dispatcher_handle_t handle) {
+    struct dispatcher_generic *dp = get_dispatcher_generic(handle);
+    struct waitset_chanstate *chan;
+
+    if (!dp->polled_channels)
+        return;
+    chan = dp->polled_channels;
+    do {
+        switch (chan->chantype) {
 #ifdef CONFIG_INTERCONNECT_DRIVER_UMP
-    case CHANTYPE_UMP_IN:
-        ump_endpoint_poll(chan);
-        break;
+        case CHANTYPE_UMP_IN: {
+            if (ump_endpoint_poll(chan)) {
+                errval_t err = waitset_chan_trigger_disabled(chan, handle);
+                assert(err_is_ok(err)); // should not fail
+                if (!dp->polled_channels) // restart scan
+                    return;
+                chan = dp->polled_channels;
+                continue;
+            } else
+                chan = chan->polled_next;
+        } break;
 #endif // CONFIG_INTERCONNECT_DRIVER_UMP
-
-    case CHANTYPE_LWIP_SOCKET:
-        arranet_polling_loop_proxy();
-        break;
-
-    case CHANTYPE_AHCI:
-        poll_ahci(chan);
-        break;
-
-    default:
-        assert(!"invalid channel type to poll!");
-    }
+        case CHANTYPE_LWIP_SOCKET:
+            arranet_polling_loop_proxy();
+            break;
+        case CHANTYPE_AHCI:
+            poll_ahci(chan);
+            break;
+        default:
+            assert(!"invalid channel type to poll!");
+        }
+    } while (chan != dp->polled_channels);
 }
 
-// pollcycles_*: arch-specific implementation for polling.
-//               Used by get_next_event().
-//
-//   pollcycles_reset()  -- return the number of pollcycles we want to poll for
-//   pollcycles_update() -- update the pollcycles variable. This is needed for
-//                          implementations where we don't have a cycle counter
-//                          and we just count the number of polling operations
-//                          performed
-//   pollcycles_expired() -- check if pollcycles have expired
-//
-// We might want to move them to architecture-specific files, and/or create a
-// cleaner interface. For now, I just wanted to keep them out of
-// get_next_event()
-
-#if defined(__ARM_ARCH_7A__) && defined(__GNUC__) \
-       && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 && __GNUC_PATCHLEVEL__ <= 3
-static __attribute__((noinline, unused))
-#else
-static inline
-#endif
-cycles_t pollcycles_reset(void)
+/// Re-register a channel (if persistent)
+static void reregister_channel(struct waitset *ws, struct waitset_chanstate *chan,
+                                dispatcher_handle_t handle)
 {
-    cycles_t pollcycles;
-#if defined(__arm__) && !defined(__gem5__)
-    reset_cycle_counter();
-    pollcycles = waitset_poll_cycles;
-#elif defined(__arm__) && defined(__gem5__)
-    pollcycles = 0;
-#elif defined(__aarch64__) && defined(__gem5__)
-    pollcycles = 0;
-#else
-    pollcycles = cyclecount() + waitset_poll_cycles;
-#endif
-    return pollcycles;
-}
+    assert(chan->waitset == ws);
+    if (chan->state == CHAN_PENDING) {
+        dequeue(&ws->pending, chan);
+    } else {
+        assert(chan->state == CHAN_WAITING);
+        dequeue(&ws->waiting, chan);
+    }
 
-#if defined(__ARM_ARCH_7A__) && defined(__GNUC__) \
-       && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 && __GNUC_PATCHLEVEL__ <= 3
-static __attribute__((noinline, unused))
-#else
-static inline
-#endif
-cycles_t pollcycles_update(cycles_t pollcycles)
-{
-    cycles_t ret = pollcycles;
-    #if defined(__arm__) && defined(__gem5__)
-    ret++;
-       #elif defined(__aarch64__) && defined(__gem5__)
-       ret++;
-    #endif
-    return ret;
+    chan->token = 0;
+    if (chan->chantype == CHANTYPE_UMP_IN
+        || chan->chantype == CHANTYPE_LWIP_SOCKET 
+        || chan->chantype == CHANTYPE_AHCI) {
+        enqueue(&ws->polled, chan);
+        enqueue_polled(&get_dispatcher_generic(handle)->polled_channels, chan);
+        chan->state = CHAN_POLLED;
+    } else {
+        enqueue(&ws->idle, chan);
+        chan->state = CHAN_IDLE;
+    }
 }
 
-#if defined(__ARM_ARCH_7A__) && defined(__GNUC__) \
-       && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 && __GNUC_PATCHLEVEL__ <= 3
-static __attribute__((noinline, unused))
-#else
-static inline
-#endif
-bool pollcycles_expired(cycles_t pollcycles)
+/// Find a thread that is able to receive an event
+static struct thread * find_recipient(struct waitset *ws,
+                        struct waitset_chanstate *channel, struct thread *me)
 {
-    bool ret;
-    #if defined(__arm__) && !defined(__gem5__)
-    ret = (cyclecount() > pollcycles || is_cycle_counter_overflow());
-    #elif defined(__arm__) && defined(__gem5__)
-    ret = pollcycles >= POLL_COUNT;
-    #elif defined(__aarch64__) && defined(__gem5__)
-    ret = pollcycles >= POLL_COUNT;
-    #else
-    ret = cyclecount() > pollcycles;
-    #endif
-    return ret;
+    struct thread *t = ws->waiting_threads;
+
+    if (!t)
+        return NULL;
+    do {
+        if (waitset_check_token(channel, t))
+            return t;
+        t = t->next;
+    } while (t != ws->waiting_threads);
+    return ws->waiting_threads;
 }
 
-static errval_t get_next_event_debug(struct waitset *ws,
-        struct event_closure *retclosure, bool debug)
+/// Wake up other thread if there's more pending events
+static void wake_up_other_thread(dispatcher_handle_t handle, struct waitset *ws)
 {
-    struct waitset_chanstate *chan;
-    bool was_polling = false;
-    cycles_t pollcycles;
-
-    assert(ws != NULL);
-    assert(retclosure != NULL);
-
-    // unconditionally disable ourselves and check for events
-    // if we decide we have to start polling, we'll jump back up here
-    goto check_for_events;
-
-    /* ------------ POLLING LOOP; RUNS WHILE ENABLED ------------ */
-polling_loop:
-    was_polling = true;
-    assert(ws->polling); // this thread is polling
-    // get the amount of cycles we want to poll for
-    pollcycles = pollcycles_reset();
-
-    // while there are no pending events, poll channels
-    while (ws->polled != NULL && ws->pending == NULL) {
-        struct waitset_chanstate *nextchan = NULL;
-        // NB: Polling policy is to return as soon as a pending event
-        // appears, not bother looking at the rest of the polling queue
-        for (chan = ws->polled;
-             chan != NULL && chan->waitset == ws && chan->state == CHAN_POLLED
-                 && ws->pending == NULL;
-             chan = nextchan) {
-
-            nextchan = chan->next;
-            poll_channel(chan);
-            // update pollcycles
-            pollcycles = pollcycles_update(pollcycles);
-            // yield the thread if we exceed the cycle count limit
-            if (ws->pending == NULL && pollcycles_expired(pollcycles)) {
-                if (debug) {
-                if (strcmp(disp_name(), "netd") != 0) {
-                    // Print the callback trace so that we know which call is leading
-                    // the schedule removal and
-                    printf("%s: callstack: %p %p %p %p\n", disp_name(),
-                            __builtin_return_address(0),
-                            __builtin_return_address(1),
-                            __builtin_return_address(2),
-                            __builtin_return_address(3));
-                }
-
-                }
-                thread_yield();
-                pollcycles = pollcycles_reset();
-            }
-        }
+    if (ws->pending && ws->waiting_threads) {
+        struct thread *t;
 
-        // ensure that we restart polling from the place we left off here,
-        // if the next channel is a valid one
-        if (nextchan != NULL && nextchan->waitset == ws
-            && nextchan->state == CHAN_POLLED) {
-            ws->polled = nextchan;
-        }
+        t = thread_unblock_one_disabled(handle, &ws->waiting_threads, NULL);
+        assert_disabled(t == NULL); // shouldn't see a remote thread
     }
+}
 
-    /* ------------ STATE MACHINERY; RUNS WHILE DISABLED ------------ */
-check_for_events: ;
-    dispatcher_handle_t handle = disp_disable();
+/**
+ * \brief Get next pending event
+ *
+ * Check if there is a pending event that matches current thread and return it.
+ * Pending events are in a pending queue and in a waiting queue.
+ * A pending event then will be removed from a pending/waiting queue and become
+ * unregistered or, if it's persistent, will be re-registered to an idle queue
+ * or a polled queue (UMP channels) of a waitset.
+ * If there's no pending event, block this thread.
+ * If there's a pending event but it doesn't match our thread, don't remove it
+ * from a pending queue and wake up a matching thread.
+ * If there's no matching thread, add it to a waiting queue.
+ *
+ * \param ws Waitset with sources of events
+ * \param retchannel Holder of returned event
+ * \param retclosure Holder of returned closure
+ * \param waitfor Specific event that we're waiting for (can be NULL)
+ * \param handle Dispatcher's handle
+ * \param debug Debug mode (not used)
+ */
 
-    // are there any pending events on the waitset?
-    chan = get_pending_event_disabled(ws);
-    if (chan != NULL) {
-        // if we need to poll, and we have a blocked thread, wake it up to do so
-        if (was_polling && ws->polled != NULL && ws->waiting_threads != NULL) {
-            // start a blocked thread polling
-            struct thread *t;
-            t = thread_unblock_one_disabled(handle, &ws->waiting_threads, NULL);
-            assert_disabled(t == NULL); // shouldn't see a remote thread
-        } else if (was_polling) {
-            // I'm stopping polling, and there is nobody else
-            assert_disabled(ws->polling);
-            ws->polling = false;
+errval_t get_next_event_disabled(struct waitset *ws,
+    struct waitset_chanstate **retchannel, struct event_closure *retclosure,
+    struct waitset_chanstate *waitfor, dispatcher_handle_t handle, bool debug)
+{
+    struct waitset_chanstate * chan;
+
+    for (;;) {
+        chan = get_pending_event_disabled(ws, waitfor); // get our event
+        if (chan) {
+            *retchannel = chan;
+            *retclosure = chan->closure;
+            chan->wait_for = NULL;
+            chan->token = 0;
+            if (chan->persistent)
+                reregister_channel(ws, chan, handle);
+            else
+                waitset_chan_deregister_disabled(chan, handle);
+            wake_up_other_thread(handle, ws);
+            return SYS_ERR_OK;
         }
-        disp_enable(handle);
-
-        *retclosure = chan->closure;
-        return SYS_ERR_OK;
-    }
-
-    // If we got here and there are channels to poll but no-one is polling,
-    // then either we never polled, or we lost a race on the channel we picked.
-    // Either way, we'd better start polling again.
-    if (ws->polled != NULL && (was_polling || !ws->polling)) {
-        if (!was_polling) {
-            ws->polling = true;
+        chan = ws->pending; // check a pending queue
+        if (!chan) { // if nothing then wait
+            thread_block_disabled(handle, &ws->waiting_threads);
+            disp_disable();
+        } else { // something but it's not our event
+            if (!ws->waiting_threads) { // no other thread interested in
+                dequeue(&ws->pending, chan);
+                enqueue(&ws->waiting, chan);
+                chan->state = CHAN_WAITING;
+                chan->waitset = ws;
+            } else {
+                // find a matching thread
+                struct thread *t;
+                for (t = ws->waiting_threads; t; ) {
+                    if (waitset_check_token(chan, t)) { // match found, wake it
+                        ws->waiting_threads = t;
+                        t = thread_unblock_one_disabled(handle,
+                                                    &ws->waiting_threads, chan);
+                        assert_disabled(t == NULL); // shouldn't see a remote thread
+                        break;
+                    }
+                    t = t->next;
+                    if (t == ws->waiting_threads) { // no recipient found
+                        dequeue(&ws->pending, chan);
+                        enqueue(&ws->waiting, chan);
+                        chan->state = CHAN_WAITING;
+                        chan->waitset = ws;
+                        break;
+                    }
+                }
+            }
         }
-        disp_enable(handle);
-        goto polling_loop;
-    }
-
-    // otherwise block awaiting an event
-    chan = thread_block_disabled(handle, &ws->waiting_threads);
-
-    if (chan == NULL) {
-        // not a real event, just a wakeup to get us to start polling!
-        assert(ws->polling);
-        goto polling_loop;
-    } else {
-        *retclosure = chan->closure;
-        return SYS_ERR_OK;
     }
 }
 
@@ -409,58 +395,47 @@ check_for_events: ;
  */
 errval_t get_next_event(struct waitset *ws, struct event_closure *retclosure)
 {
-    return get_next_event_debug(ws, retclosure, false);
+    dispatcher_handle_t handle = disp_disable();
+    struct waitset_chanstate *channel;
+    errval_t err = get_next_event_disabled(ws, &channel, retclosure, NULL,
+                                            handle, false);
+    disp_enable(handle);
+    return err;
 }
 
 
 
 /**
- * \brief Return next event on given waitset, if one is already pending
+ * \brief Check if there is an event pending on given waitset
  *
  * This is essentially a non-blocking variant of get_next_event(). It should be
  * used with great care, to avoid the creation of busy-waiting loops.
  *
  * \param ws Waitset
- * \param retclosure Pointer to storage space for returned event closure
  *
  * \returns LIB_ERR_NO_EVENT if nothing is pending
  */
-errval_t check_for_event(struct waitset *ws, struct event_closure *retclosure)
+static errval_t check_for_event_disabled(struct waitset *ws, dispatcher_handle_t handle)
 {
     struct waitset_chanstate *chan;
-    int pollcount = 0;
-
-    assert(ws != NULL);
-    assert(retclosure != NULL);
 
- recheck: ;
-    // are there any pending events on the waitset?
-    dispatcher_handle_t handle = disp_disable();
-    chan = get_pending_event_disabled(ws);
-    disp_enable(handle);
+    poll_channels_disabled(handle);
+    chan = get_pending_event_disabled(ws, NULL);
     if (chan != NULL) {
-        *retclosure = chan->closure;
         return SYS_ERR_OK;
     }
+    return LIB_ERR_NO_EVENT;
+}
 
-    // if there are no pending events, poll all channels once
-    if (ws->polled != NULL && pollcount++ == 0) {
-        for (chan = ws->polled;
-             chan != NULL && chan->waitset == ws && chan->state == CHAN_POLLED;
-             chan = chan->next) {
-
-            poll_channel(chan);
-            if (ws->pending != NULL) {
-                goto recheck;
-            }
-
-            if (chan->next == ws->polled) { // reached the start of the queue
-                break;
-            }
-        }
-    }
+errval_t check_for_event(struct waitset *ws)
+{
+    errval_t err;
 
-    return LIB_ERR_NO_EVENT;
+    assert(ws != NULL);
+    dispatcher_handle_t handle = disp_disable();
+    err = check_for_event_disabled(ws, handle);
+    disp_enable(handle);
+    return err;
 }
 
 /**
@@ -488,20 +463,59 @@ errval_t event_dispatch(struct waitset *ws)
 errval_t event_dispatch_debug(struct waitset *ws)
 {
     struct event_closure closure;
-    errval_t err = get_next_event_debug(ws, &closure, false);
+    struct waitset_chanstate *channel;
+    dispatcher_handle_t handle = disp_disable();
+    errval_t err = get_next_event_disabled(ws, &channel, &closure, NULL, handle,
+                                            true);
+    disp_enable(handle);
     if (err_is_fail(err)) {
         return err;
     }
 
     assert(closure.handler != NULL);
-//    printf("%s: event_dispatch: %p: \n", disp_name(), closure.handler);
-
-
     closure.handler(closure.arg);
     return SYS_ERR_OK;
 }
 
 /**
+ * \brief Dispatch events until a specific event is received
+ *
+ * Wait for events and dispatch them. If a specific event comes, don't call
+ * a closure, just return.
+ *
+ * \param ws Waitset
+ * \param waitfor Event, that we are waiting for
+ * \param error_var Error variable that can be changed by closures
+ */
+
+errval_t wait_for_channel(struct waitset *ws, struct waitset_chanstate *waitfor,
+                            errval_t *error_var)
+{
+    assert(waitfor->waitset == ws);
+    for (;;) {
+        struct event_closure closure;
+        struct waitset_chanstate *channel;
+
+        dispatcher_handle_t handle = disp_disable();
+        errval_t err = get_next_event_disabled(ws, &channel, &closure, waitfor,
+                                                handle, false);
+        disp_enable(handle);
+        if (err_is_fail(err)) {
+            assert(0);
+            return err;
+        }
+        if (channel == waitfor) {
+            return SYS_ERR_OK;
+        }
+        assert(!channel->wait_for);
+        assert(closure.handler != NULL);
+        closure.handler(closure.arg);
+        if (err_is_fail(*error_var))
+            return *error_var;
+    }
+}
+
+/**
  * \brief check and dispatch next event on given waitset
  *
  * Check if there is any pending activity on some channel, or deferred
@@ -513,14 +527,23 @@ errval_t event_dispatch_debug(struct waitset *ws)
  */
 errval_t event_dispatch_non_block(struct waitset *ws)
 {
-    assert(ws != NULL);
+    struct waitset_chanstate *channel;
     struct event_closure closure;
-    errval_t err = check_for_event(ws, &closure);
 
+    assert(ws != NULL);
+
+    // are there any pending events on the waitset?
+    dispatcher_handle_t handle = disp_disable();
+    errval_t err = check_for_event_disabled(ws, handle);
     if (err_is_fail(err)) {
+        disp_enable(handle);
         return err;
     }
-
+    err = get_next_event_disabled(ws, &channel, &closure, NULL, handle,
+                                            false);
+    if (err_is_fail(err))
+        return err;
+    disp_enable(handle);
     assert(closure.handler != NULL);
     closure.handler(closure.arg);
     return SYS_ERR_OK;
@@ -548,6 +571,9 @@ void waitset_chanstate_init(struct waitset_chanstate *chan,
 #ifndef NDEBUG
     chan->prev = chan->next = NULL;
 #endif
+    chan->persistent = false;
+    chan->token = 0;
+    chan->wait_for = NULL;
 }
 
 /**
@@ -584,6 +610,7 @@ errval_t waitset_chan_register_disabled(struct waitset *ws,
     }
 
     chan->waitset = ws;
+    chan->token = 0;
 
     // channel must not already be registered!
     assert_disabled(chan->next == NULL && chan->prev == NULL);
@@ -596,15 +623,7 @@ errval_t waitset_chan_register_disabled(struct waitset *ws,
     chan->closure = closure;
 
     // enqueue this channel on the waitset's queue of idle channels
-    if (ws->idle == NULL) {
-        chan->next = chan->prev = chan;
-        ws->idle = chan;
-    } else {
-        chan->next = ws->idle;
-        chan->prev = chan->next->prev;
-        chan->next->prev = chan;
-        chan->prev->next = chan;
-    }
+    enqueue(&ws->idle, chan);
     chan->state = CHAN_IDLE;
 
     return SYS_ERR_OK;
@@ -633,6 +652,7 @@ errval_t waitset_chan_register_polled_disabled(struct waitset *ws,
     }
 
     chan->waitset = ws;
+    chan->token = 0;
 
     // channel must not already be registered!
     assert_disabled(chan->next == NULL && chan->prev == NULL);
@@ -642,23 +662,9 @@ errval_t waitset_chan_register_polled_disabled(struct waitset *ws,
     chan->closure = closure;
 
     // enqueue this channel on the waitset's queue of polled channels
-    if (ws->polled == NULL) {
-        chan->next = chan->prev = chan;
-        ws->polled = chan;
-        if (ws->waiting_threads != NULL && !ws->polling) {
-            // start a blocked thread polling
-            ws->polling = true;
-            struct thread *t;
-            t = thread_unblock_one_disabled(handle, &ws->waiting_threads, NULL);
-            assert_disabled(t == NULL); // shouldn't see a remote thread: waitsets are per-dispatcher
-        }
-    } else {
-        chan->next = ws->polled;
-        chan->prev = chan->next->prev;
-        chan->next->prev = chan;
-        chan->prev->next = chan;
-    }
+    enqueue(&ws->polled, chan);
     chan->state = CHAN_POLLED;
+    enqueue_polled(&get_dispatcher_generic(handle)->polled_channels, chan);
 
     return SYS_ERR_OK;
 }
@@ -708,120 +714,6 @@ errval_t waitset_chan_register_polled(struct waitset *ws,
 }
 
 /**
- * \brief Mark an idle channel as polled
- *
- * The given channel will periodically have its poll function called.
- * The channel must already be registered.
- *
- * \param chan Waitset's per-channel state
- */
-errval_t waitset_chan_start_polling(struct waitset_chanstate *chan)
-{
-    errval_t err = SYS_ERR_OK;
-
-    dispatcher_handle_t handle = disp_disable();
-
-    struct waitset *ws = chan->waitset;
-    if (ws == NULL) {
-        err = LIB_ERR_CHAN_NOT_REGISTERED;
-        goto out;
-    }
-
-    assert(chan->state != CHAN_UNREGISTERED);
-    if (chan->state != CHAN_IDLE) {
-        goto out; // no-op if polled or pending
-    }
-
-    // remove from idle queue
-    if (chan->next == chan) {
-        assert(chan->prev == chan);
-        assert(ws->idle == chan);
-        ws->idle = NULL;
-    } else {
-        chan->prev->next = chan->next;
-        chan->next->prev = chan->prev;
-        if (ws->idle == chan) {
-            ws->idle = chan->next;
-        }
-    }
-
-    // enqueue on polled queue
-    if (ws->polled == NULL) {
-        ws->polled = chan;
-        chan->next = chan->prev = chan;
-        if (ws->waiting_threads != NULL && !ws->polling) {
-            // start a blocked thread polling
-            ws->polling = true;
-            struct thread *t;
-            t = thread_unblock_one_disabled(handle, &ws->waiting_threads, NULL);
-            assert(t == NULL); // shouldn't see a remote thread: waitsets are per-dispatcher
-        }
-    } else {
-        chan->next = ws->polled;
-        chan->prev = ws->polled->prev;
-        chan->next->prev = chan;
-        chan->prev->next = chan;
-    }
-    chan->state = CHAN_POLLED;
-
-out:
-    disp_enable(handle);
-    return err;
-}
-
-/**
- * \brief Stop polling the given channel, making it idle again
- *
- * \param chan Waitset's per-channel state
- */
-errval_t waitset_chan_stop_polling(struct waitset_chanstate *chan)
-{
-    errval_t err = SYS_ERR_OK;
-
-    dispatcher_handle_t handle = disp_disable();
-
-    struct waitset *ws = chan->waitset;
-    if (ws == NULL) {
-        err = LIB_ERR_CHAN_NOT_REGISTERED;
-        goto out;
-    }
-
-    assert(chan->state != CHAN_UNREGISTERED);
-    if (chan->state != CHAN_POLLED) {
-        goto out; // no-op if idle or pending
-    }
-
-    // remove from polled queue
-    if (chan->next == chan) {
-        assert(chan->prev == chan);
-        assert(ws->polled == chan);
-        ws->polled = NULL;
-    } else {
-        chan->prev->next = chan->next;
-        chan->next->prev = chan->prev;
-        if (ws->polled == chan) {
-            ws->polled = chan->next;
-        }
-    }
-
-    // enqueue on idle queue
-    if (ws->idle == NULL) {
-        ws->idle = chan;
-        chan->next = chan->prev = chan;
-    } else {
-        chan->next = ws->idle;
-        chan->prev = ws->idle->prev;
-        chan->next->prev = chan;
-        chan->prev->next = chan;
-    }
-    chan->state = CHAN_IDLE;
-
-out:
-    disp_enable(handle);
-    return err;
-}
-
-/**
  * \brief Cancel a previous callback registration
  *
  * Remove the registration for a callback on the given channel.
@@ -829,7 +721,8 @@ out:
  *
  * \param chan Waitset's per-channel state
  */
-errval_t waitset_chan_deregister_disabled(struct waitset_chanstate *chan)
+errval_t waitset_chan_deregister_disabled(struct waitset_chanstate *chan,
+                                          dispatcher_handle_t handle)
 {
     assert_disabled(chan != NULL);
     struct waitset *ws = chan->waitset;
@@ -841,61 +734,29 @@ errval_t waitset_chan_deregister_disabled(struct waitset_chanstate *chan)
     chan->waitset = NULL;
     assert_disabled(chan->next != NULL && chan->prev != NULL);
 
-    if (chan->next == chan) {
-        // only thing in the list: must be the head
-        assert_disabled(chan->prev == chan);
-        switch (chan->state) {
-        case CHAN_IDLE:
-            assert_disabled(chan == ws->idle);
-            ws->idle = NULL;
-            break;
-
-        case CHAN_POLLED:
-            assert_disabled(chan == ws->polled);
-            ws->polled = NULL;
-            break;
-
-        case CHAN_PENDING:
-            assert_disabled(chan == ws->pending);
-            ws->pending = NULL;
-            break;
+    switch (chan->state) {
+    case CHAN_IDLE:
+        dequeue(&ws->idle, chan);
+        break;
 
-        default:
-            assert_disabled(!"invalid channel state in deregister");
-        }
-    } else {
-        assert_disabled(chan->prev != chan);
-        chan->prev->next = chan->next;
-        chan->next->prev = chan->prev;
-        switch (chan->state) {
-        case CHAN_IDLE:
-            if (chan == ws->idle) {
-                ws->idle = chan->next;
-            }
-            break;
+    case CHAN_POLLED:
+        dequeue(&ws->polled, chan);
+        dequeue_polled(&get_dispatcher_generic(handle)->polled_channels, chan);
+        break;
 
-        case CHAN_POLLED:
-            if (chan == ws->polled) {
-                ws->polled = chan->next;
-            }
-            break;
+    case CHAN_PENDING:
+        dequeue(&ws->pending, chan);
+        break;
 
-        case CHAN_PENDING:
-            if (chan == ws->pending) {
-                ws->pending = chan->next;
-            }
-            break;
+    case CHAN_WAITING:
+        dequeue(&ws->waiting, chan);
+        break;
 
-        default:
-            assert_disabled(!"invalid channel state in deregister");
-        }
+    default:
+        assert_disabled(!"invalid channel state in deregister");
     }
     chan->state = CHAN_UNREGISTERED;
-
-#ifndef NDEBUG
-    chan->prev = chan->next = NULL;
-#endif
-
+    chan->wait_for = NULL;
     return SYS_ERR_OK;
 }
 
@@ -910,7 +771,7 @@ errval_t waitset_chan_deregister_disabled(struct waitset_chanstate *chan)
 errval_t waitset_chan_deregister(struct waitset_chanstate *chan)
 {
     dispatcher_handle_t handle = disp_disable();
-    errval_t err = waitset_chan_deregister_disabled(chan);
+    errval_t err = waitset_chan_deregister_disabled(chan, handle);
     disp_enable(handle);
     return err;
 }
@@ -933,75 +794,23 @@ void waitset_chan_migrate(struct waitset_chanstate *chan,
 
     switch(chan->state) {
     case CHAN_IDLE:
-        if (chan->next == chan) {
-            assert(chan->prev == chan);
-            assert(ws->idle == chan);
-            ws->idle = NULL;
-        } else {
-            chan->prev->next = chan->next;
-            chan->next->prev = chan->prev;
-            if (ws->idle == chan) {
-                ws->idle = chan->next;
-            }
-        }
-
-        if (new_ws->idle == NULL) {
-            new_ws->idle = chan;
-            chan->next = chan->prev = chan;
-        } else {
-            chan->next = new_ws->idle;
-            chan->prev = new_ws->idle->prev;
-            chan->next->prev = chan;
-            chan->prev->next = chan;
-        }
+        dequeue(&ws->idle, chan);
+        enqueue(&new_ws->idle, chan);
         break;
 
     case CHAN_POLLED:
-        if (chan->next == chan) {
-            assert(chan->prev == chan);
-            assert(ws->polled == chan);
-            ws->polled = NULL;
-        } else {
-            chan->prev->next = chan->next;
-            chan->next->prev = chan->prev;
-            if (ws->polled == chan) {
-                ws->polled = chan->next;
-            }
-        }
-
-        if (new_ws->polled == NULL) {
-            new_ws->polled = chan;
-            chan->next = chan->prev = chan;
-        } else {
-            chan->next = new_ws->polled;
-            chan->prev = new_ws->polled->prev;
-            chan->next->prev = chan;
-            chan->prev->next = chan;
-        }
+        dequeue(&ws->polled, chan);
+        enqueue(&new_ws->polled, chan);
         break;
 
     case CHAN_PENDING:
-        if (chan->next == chan) {
-            assert(chan->prev == chan);
-            assert(ws->pending == chan);
-            ws->pending = NULL;
-        } else {
-            chan->prev->next = chan->next;
-            chan->next->prev = chan->prev;
-            if (ws->pending == chan) {
-                ws->pending = chan->next;
-            }
-        }
+        dequeue(&ws->pending, chan);
+        enqueue(&new_ws->pending, chan);
+        break;
 
-        if (new_ws->pending == NULL) {
-            new_ws->pending = chan;
-            chan->next = chan->prev = chan;
-        } else {
-            chan->next = new_ws->pending;
-            chan->prev = new_ws->pending->prev;
-            chan->next->prev = chan;
-            chan->prev->next = chan;
-        }
+    case CHAN_WAITING:
+        dequeue(&ws->waiting, chan);
+        enqueue(&new_ws->waiting, chan);
         break;
 
     case CHAN_UNREGISTERED:
@@ -1037,59 +846,26 @@ errval_t waitset_chan_trigger_disabled(struct waitset_chanstate *chan,
     }
 
     // remove from previous queue (either idle or polled)
-    if (chan->next == chan) {
-        assert_disabled(chan->prev == chan);
-        if (chan->state == CHAN_IDLE) {
-            assert_disabled(ws->idle == chan);
-            ws->idle = NULL;
-        } else {
-            assert_disabled(chan->state == CHAN_POLLED);
-            assert_disabled(ws->polled == chan);
-            ws->polled = NULL;
-        }
+    if (chan->state == CHAN_IDLE) {
+        dequeue(&ws->idle, chan);
     } else {
-        chan->prev->next = chan->next;
-        chan->next->prev = chan->prev;
-        if (chan->state == CHAN_IDLE) {
-            if (ws->idle == chan) {
-                ws->idle = chan->next;
-            }
-        } else {
-            assert_disabled(chan->state == CHAN_POLLED);
-            if (ws->polled == chan) {
-                ws->polled = chan->next;
-            }
-        }
+        assert_disabled(chan->state == CHAN_POLLED);
+        dequeue(&ws->polled, chan);
+        dequeue_polled(&get_dispatcher_generic(handle)->polled_channels, chan);
     }
 
+    // else mark channel pending and move to end of pending event queue
+    enqueue(&ws->pending, chan);
+    chan->state = CHAN_PENDING;
+
     // is there a thread blocked on this waitset? if so, awaken it with the event
-    if (ws->waiting_threads != NULL) {
-        chan->waitset = NULL;
-#ifndef NDEBUG
-        chan->prev = chan->next = NULL;
-#endif
-        chan->state = CHAN_UNREGISTERED;
+    struct thread *thread = find_recipient(ws, chan, thread_self());
+    if (thread) {
         struct thread *t;
+        ws->waiting_threads = thread;
         t = thread_unblock_one_disabled(handle, &ws->waiting_threads, chan);
         assert_disabled(t == NULL);
-        return SYS_ERR_OK;
-    }
-
-    // else mark channel pending and move to end of pending event queue
-    chan->state = CHAN_PENDING;
-    if (ws->pending == NULL) {
-        ws->pending = chan;
-        chan->next = chan->prev = chan;
-    } else {
-        chan->next = ws->pending;
-        chan->prev = ws->pending->prev;
-        assert_disabled(ws->pending->next != NULL);
-        assert_disabled(ws->pending->prev != NULL);
-        assert_disabled(chan->prev != NULL);
-        chan->next->prev = chan;
-        chan->prev->next = chan;
     }
-
     return SYS_ERR_OK;
 }
 
@@ -1105,9 +881,9 @@ errval_t waitset_chan_trigger_disabled(struct waitset_chanstate *chan,
  */
 errval_t waitset_chan_trigger(struct waitset_chanstate *chan)
 {
-    dispatcher_handle_t disp = disp_disable();
-    errval_t err = waitset_chan_trigger_disabled(chan, disp);
-    disp_enable(disp);
+    dispatcher_handle_t handle = disp_disable();
+    errval_t err = waitset_chan_trigger_disabled(chan, handle);
+    disp_enable(handle);
     return err;
 }
 
@@ -1141,29 +917,21 @@ errval_t waitset_chan_trigger_closure_disabled(struct waitset *ws,
     // set closure
     chan->closure = closure;
 
+    // mark channel pending and place on end of pending event queue
+    chan->waitset = ws;
+    enqueue(&ws->pending, chan);
+    // if (first)
+    //     ws->pending = chan;
+    chan->state = CHAN_PENDING;
+
     // is there a thread blocked on this waitset? if so, awaken it with the event
-    if (ws->waiting_threads != NULL) {
+    struct thread *thread = find_recipient(ws, chan, thread_self());
+    if (thread) {
         struct thread *t;
+        ws->waiting_threads = thread;
         t = thread_unblock_one_disabled(handle, &ws->waiting_threads, chan);
         assert_disabled(t == NULL);
-        return SYS_ERR_OK;
-    }
-
-    // mark channel pending and place on end of pending event queue
-    chan->waitset = ws;
-    chan->state = CHAN_PENDING;
-    if (ws->pending == NULL) {
-        ws->pending = chan;
-        chan->next = chan->prev = chan;
-    } else {
-        chan->next = ws->pending;
-        chan->prev = ws->pending->prev;
-        chan->next->prev = chan;
-        chan->prev->next = chan;
     }
-
-    assert(ws->pending->prev != NULL && ws->pending->next != NULL);
-
     return SYS_ERR_OK;
 }
 
index c3c95e3..de9088f 100644 (file)
@@ -61,6 +61,7 @@ malloc(size_t nbytes)
                                p += p->s.size;
                                p->s.size = nunits;
                        }
+            p->s.magic = 0xdeadbeef;
                        state->header_freep = prevp;
 #ifdef CONFIG_MALLOC_DEBUG
                        {
@@ -173,6 +174,11 @@ void free(void *ap)
     assert((lvaddr_t)ap >= base && (lvaddr_t)ap < limit);
 #endif
 
+    if (((Header *)ap)[-1].s.magic != 0xdeadbeef) {
+        debug_printf("%s: Trying to free not malloced region: %p\n", __func__, ap);
+        return;
+    }
+    ((Header *)ap)[-1].s.magic = 0;
     MALLOC_LOCK;
     __free_locked(ap);
     lesscore();
index 59fcd5e..eafa458 100644 (file)
@@ -41,11 +41,8 @@ errval_t oct_barrier_enter(const char* name, char** barrier_record, size_t wait_
 {
     errval_t err;
     errval_t exist_err;
-    char* record = NULL;
     char** names = NULL;
     uint64_t mode = 0;
-    uint64_t state = 0;
-    uint64_t fn = 0;
     octopus_trigger_id_t tid;
     size_t current_barriers = 0;
     octopus_trigger_t t = oct_mktrigger(OCT_ERR_NO_RECORD, octopus_BINDING_RPC,
@@ -53,6 +50,10 @@ errval_t oct_barrier_enter(const char* name, char** barrier_record, size_t wait_
 
     err = oct_set_get(SET_SEQUENTIAL, barrier_record,
             "%s_ { barrier: '%s' }", name, name);
+    *barrier_record = strdup(*barrier_record);
+    if (*barrier_record == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
     err = oct_get_names(&names, &current_barriers, "_ { barrier: '%s' }",
             name);
     oct_free_names(names, current_barriers);
@@ -75,8 +76,7 @@ errval_t oct_barrier_enter(const char* name, char** barrier_record, size_t wait_
         }
         if (err_no(err) == OCT_ERR_NO_RECORD) {
             // Wait until barrier record is created
-            err = cl->recv.trigger(cl, &tid, &fn, &mode, &record, &state);
-            free(record);
+            err = cl->recv.trigger(cl, NULL, NULL, &mode, NULL, NULL);
             assert(mode & OCT_REMOVED);
 
             err = SYS_ERR_OK;
@@ -111,12 +111,9 @@ errval_t oct_barrier_leave(const char* barrier_record)
     errval_t err;
     char* rec_name = NULL;
     char* barrier_name = NULL;
-    char* record = NULL;
     char** names = NULL;
     size_t remaining_barriers = 0;
     uint64_t mode = 0;
-    uint64_t state = 0;
-    uint64_t fn = 0;
     octopus_trigger_id_t tid;
     octopus_trigger_t t = oct_mktrigger(SYS_ERR_OK, octopus_BINDING_RPC,
             OCT_ON_DEL, NULL, NULL);
@@ -146,7 +143,7 @@ errval_t oct_barrier_leave(const char* barrier_record)
 
             if (err_is_ok(err)) {
                 // Wait until everyone has left the barrier
-                err = cl->recv.trigger(cl, &tid, &fn, &mode, &record, &state);
+                err = cl->recv.trigger(cl, NULL, NULL, &mode, NULL, NULL);
                 assert(mode & OCT_REMOVED);
             }
             else if (err_no(err) == OCT_ERR_NO_RECORD) {
@@ -165,7 +162,6 @@ errval_t oct_barrier_leave(const char* barrier_record)
     }
 
 out:
-    free(record);
     free(rec_name);
     free(barrier_name);
     return err;
index 5f18792..a4b0e64 100644 (file)
@@ -54,7 +54,6 @@ errval_t oct_get_names(char*** names, size_t* len, const char* query, ...)
     errval_t err = SYS_ERR_OK;
     va_list args;
 
-    char* data = NULL;
     char* buf = NULL;
     *len = 0;
 
@@ -62,21 +61,19 @@ errval_t oct_get_names(char*** names, size_t* len, const char* query, ...)
 
     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
 
-    errval_t error_code;
-    octopus_trigger_id_t tid;
-    err = cl->call_seq.get_names(cl, buf, NOP_TRIGGER, &data,
-            &tid, &error_code);
+    struct octopus_get_names_response__rx_args reply;
+    err = cl->call_seq.get_names(cl, buf, NOP_TRIGGER, reply.output,
+            &reply.tid, &reply.error_code);
     if (err_is_ok(err)) {
-        err = error_code;
+        err = reply.error_code;
     }
 
     if (err_is_ok(err)) {
-        err = oct_parse_names(data, names, len);
+        err = oct_parse_names(reply.output, names, len);
         //qsort(*names, *len, sizeof(char*), cmpstringp);
     }
 
     free(buf);
-    free(data);
     return err;
 }
 
@@ -96,9 +93,7 @@ errval_t oct_get_names(char*** names, size_t* len, const char* query, ...)
 errval_t oct_get(char** data, const char* query, ...)
 {
     assert(query != NULL);
-    errval_t error_code;
     errval_t err = SYS_ERR_OK;
-    octopus_trigger_id_t tid;
     va_list args;
 
     char* buf = NULL;
@@ -106,14 +101,26 @@ errval_t oct_get(char** data, const char* query, ...)
 
     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
     assert(cl != NULL);
-    err = cl->call_seq.get(cl, buf, NOP_TRIGGER, data,
-            &tid, &error_code);
+
+    struct octopus_get_response__rx_args reply;
+    err = cl->call_seq.get(cl, buf, NOP_TRIGGER, reply.output,
+            &reply.tid, &reply.error_code);
 
     if (err_is_ok(err)) {
-        err = error_code;
+        err = reply.error_code;
     }
 
     free(buf);
+
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    if (data) {
+        *data = strdup(reply.output);
+    }
+
+
     return err;
 }
 
@@ -140,12 +147,9 @@ errval_t oct_set(const char* query, ...)
     // Send to Server
     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
 
-    char* record = NULL;
     errval_t error_code;
-    octopus_trigger_id_t tid;
-    err = cl->call_seq.set(cl, buf, SET_DEFAULT, NOP_TRIGGER, false,
-            &record, &tid, &error_code);
-    assert(record == NULL);
+    err = cl->call_seq.set(cl, buf, SET_DEFAULT, NOP_TRIGGER, false, NULL, NULL,
+                           &error_code);
 
     if (err_is_ok(err)) {
         err = error_code;
@@ -179,12 +183,9 @@ errval_t oct_mset(oct_mode_t mode, const char* query, ...)
     // Send to Server
     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
 
-    char* record = NULL;
     errval_t error_code;
-    octopus_trigger_id_t tid;
-    err = cl->call_seq.set(cl, buf, mode, NOP_TRIGGER, false,
-            &record, &tid, &error_code);
-    assert(record == NULL);
+    err = cl->call_seq.set(cl, buf, mode, NOP_TRIGGER, false, NULL, NULL,
+                           &error_code);
 
     if (err_is_ok(err)) {
         err = error_code;
@@ -224,15 +225,23 @@ errval_t oct_set_get(oct_mode_t mode, char** record, const char* query, ...)
 
     // Send to Server
     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
-    errval_t error_code;
-    octopus_trigger_id_t tid;
-    err = cl->call_seq.set(cl, buf, mode, NOP_TRIGGER, true, record,
-            &tid, &error_code);
+    struct octopus_set_response__rx_args reply;
+    err = cl->call_seq.set(cl, buf, mode, NOP_TRIGGER, true, reply.record,
+                           &reply.tid, &reply.error_code);
     if (err_is_ok(err)) {
-        err = error_code;
+        err = reply.error_code;
     }
 
     free(buf);
+
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    if (record) {
+        *record = strdup(reply.record);
+    }
+
     return err;
 }
 
@@ -250,17 +259,24 @@ errval_t oct_set_get(oct_mode_t mode, char** record, const char* query, ...)
 errval_t oct_get_with_idcap(char **data, struct capref idcap)
 {
     assert(!capref_is_null(idcap));
-    errval_t error_code;
     errval_t err = SYS_ERR_OK;
-    octopus_trigger_id_t tid;
 
     struct octopus_thc_client_binding_t *cl = oct_get_thc_client();
     assert(cl != NULL);
-    err = cl->call_seq.get_with_idcap(cl, idcap, NOP_TRIGGER, data, &tid,
-                                      &error_code);
+    struct octopus_get_with_idcap_response__rx_args reply;
+    err = cl->call_seq.get_with_idcap(cl, idcap, NOP_TRIGGER, reply.output,
+                                      &reply.tid, &reply.error_code);
 
     if (err_is_ok(err)) {
-        err = error_code;
+        err = reply.error_code;
+    }
+
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    if (data) {
+        *data = strdup(reply.output);
     }
 
     return err;
@@ -292,12 +308,9 @@ errval_t oct_set_with_idcap(struct capref idcap, const char *attributes, ...)
     // Send to Server
     struct octopus_thc_client_binding_t *cl = oct_get_thc_client();
 
-    char *record = NULL;
     errval_t error_code;
-    octopus_trigger_id_t tid;
     err = cl->call_seq.set_with_idcap(cl, idcap, buf, SET_DEFAULT, NOP_TRIGGER,
-                                      false, &record, &tid, &error_code);
-    assert(record == NULL);
+                                      false, NULL, NULL, &error_code);
 
     if (err_is_ok(err)) {
         err = error_code;
@@ -332,8 +345,7 @@ errval_t oct_del(const char* query, ...)
 
     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
     errval_t error_code;
-    octopus_trigger_id_t tid;
-    err = cl->call_seq.del(cl, buf, NOP_TRIGGER, &tid, &error_code);
+    err = cl->call_seq.del(cl, buf, NOP_TRIGGER, NULL, &error_code);
     if (err_is_ok(err)) {
         err = error_code;
     }
@@ -364,8 +376,7 @@ errval_t oct_exists(const char* query, ...)
 
     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
     errval_t error_code;
-    octopus_trigger_id_t tid;
-    err = cl->call_seq.exists(cl, buf, NOP_TRIGGER, &tid, &error_code);
+    err = cl->call_seq.exists(cl, buf, NOP_TRIGGER, NULL, &error_code);
     if (err_is_ok(err)) {
         err = error_code;
     }
@@ -396,12 +407,20 @@ errval_t oct_wait_for(char** record, const char *query, ...)
 
     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
 
-    errval_t error_code;
-    err = cl->call_seq.wait_for(cl, buf, record, &error_code);
+    struct octopus_wait_for_response__rx_args reply;
+    err = cl->call_seq.wait_for(cl, buf, reply.record, &reply.error_code);
+    if (err_is_fail(err)) {
+        goto out;
+    }
+    err = reply.error_code;
+
     if (err_is_fail(err)) {
         goto out;
     }
-    err = error_code;
+
+    if (record) {
+        *record = strdup(reply.record);
+    }
 
 out:
     free(buf);
index 8101a32..fad5e1b 100644 (file)
@@ -47,14 +47,11 @@ errval_t oct_lock(const char* lock_name, char** lock_record)
     errval_t err = SYS_ERR_OK;
     errval_t exist_err;
     char** names = NULL;
-    char* record = NULL;
     char* name = NULL;
     size_t len = 0;
     size_t i = 0;
     bool found = false;
     uint64_t mode = 0;
-    uint64_t state = 0;
-    uint64_t fn = 0;
     octopus_trigger_id_t tid;
     octopus_trigger_t t = oct_mktrigger(SYS_ERR_OK, octopus_BINDING_RPC,
             OCT_ON_DEL, NULL, NULL);
@@ -64,6 +61,8 @@ errval_t oct_lock(const char* lock_name, char** lock_record)
     if (err_is_fail(err)) {
         goto out;
     }
+    /// XXX why is there a strdup ?
+    *lock_record = strdup(*lock_record);
     err = oct_read(*lock_record, "%s", &name);
     if (err_is_fail(err)) {
         goto out;
@@ -101,9 +100,8 @@ errval_t oct_lock(const char* lock_name, char** lock_record)
             }
 
             if (err_is_ok(exist_err)) {
-                err = cl->recv.trigger(cl, &tid, &fn, &mode, &record, &state);
+                err = cl->recv.trigger(cl, &tid, NULL, &mode, NULL, NULL);
                 assert(err_is_ok(err));
-                free(record);
                 assert(mode & OCT_REMOVED);
             }
             else if (err_no(exist_err) != OCT_ERR_NO_RECORD) {
index a76e49d..7269dc6 100644 (file)
@@ -46,7 +46,6 @@ void subscription_handler(struct octopus_binding *b, subscription_t id,
     else {
         fprintf(stderr, "Incoming subscription(%"PRIu64") for %s with unset handler function.",
                 id, record);
-        free(record);
     }
 }
 
index 3548891..10386e2 100644 (file)
@@ -88,8 +88,6 @@ errval_t oct_sem_post(uint32_t id)
 errval_t oct_sem_wait(uint32_t id)
 {
     errval_t err = SYS_ERR_OK;
-    char* result = NULL;
-    octopus_trigger_id_t tid;
     octopus_trigger_t t = oct_mktrigger(OCT_ERR_NO_RECORD,
             octopus_BINDING_RPC, OCT_ON_SET, NULL, NULL);
     struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
@@ -103,12 +101,11 @@ errval_t oct_sem_wait(uint32_t id)
     // XXX: The current implementation suffers from a herd effect,
     // may be worth it to use locks for this critical section
     while (1) {
-        cl->call_seq.get(cl, query, t, &result, &tid, &err);
+        struct octopus_get_response__rx_args reply;
+        cl->call_seq.get(cl, query, t, reply.output, &reply.tid, &err);
 
         if (err_is_ok(err)) {
-            errval_t del_err = oct_del(result);
-            free(result);
-            result = NULL;
+            errval_t del_err = oct_del(reply.output);
 
             if (err_is_ok(del_err)) {
                 break; // Decreased successfully
@@ -123,17 +120,13 @@ errval_t oct_sem_wait(uint32_t id)
         }
         else if (err_no(err) == OCT_ERR_NO_RECORD) {
             // No record found, wait until one is posted
-            char* trigger_result = NULL;
-            uint64_t fn, mode, state;
-            cl->recv.trigger(cl, &tid, &fn, &mode, &trigger_result, &state);
-            free(trigger_result);
+            cl->recv.trigger(cl, NULL, NULL, NULL, NULL, NULL);
         }
         else {
             break; // Unexpected error
         }
     }
 
-    free(result);
     return err;
 }
 
index 86ef222..695837b 100644 (file)
@@ -41,7 +41,6 @@ void trigger_handler(struct octopus_binding* b, octopus_trigger_id_t id,
     else {
         fprintf(stderr, "Incoming trigger(%"PRIu64") for %s with unset handler function.",
                 id, record);
-        free(record);
     }
 }
 
@@ -101,9 +100,7 @@ errval_t oct_trigger_existing_and_watch(const char* query,
         trigger_handler_fn event_handler, void* state,
         octopus_trigger_id_t* tid)
 {
-    errval_t error_code;
     char** names = NULL;
-    char* output = NULL;
     char* record = NULL; // freed by cpu_change_event
     size_t len = 0;
     octopus_trigger_t t = oct_mktrigger(0, octopus_BINDING_EVENT,
@@ -111,16 +108,18 @@ errval_t oct_trigger_existing_and_watch(const char* query,
 
     // Get current cores registered in system
     struct octopus_thc_client_binding_t* rpc = oct_get_thc_client();
+
+    struct octopus_get_names_response__rx_args reply;
     errval_t err = rpc->call_seq.get_names(rpc, query,
-            t, &output, tid, &error_code);
+            t, reply.output, &reply.tid, &reply.error_code);
     if (err_is_fail(err)) {
         goto out;
     }
-    err = error_code;
+    err = reply.error_code;
 
     switch(err_no(err)) {
     case SYS_ERR_OK:
-        err = oct_parse_names(output, &names, &len);
+        err = oct_parse_names(reply.output, &names, &len);
         if (err_is_fail(err)) {
             goto out;
         }
@@ -134,12 +133,10 @@ errval_t oct_trigger_existing_and_watch(const char* query,
                 break;
 
             case OCT_ERR_NO_RECORD:
-                assert(record == NULL);
                 break;
 
             default:
                 DEBUG_ERR(err, "Unable to retrieve core record for %s", names[i]);
-                assert(record == NULL);
                 break;
             }
         }
@@ -155,7 +152,6 @@ errval_t oct_trigger_existing_and_watch(const char* query,
 
 out:
     oct_free_names(names, len);
-    free(output);
 
     return err;
 }
index e12256a..68637f8 100644 (file)
@@ -70,8 +70,6 @@ void get_cap_handler(struct octopus_binding *b, char *key)
     ns->cap = cap;
     ns->error = reterr;
     ns->reply(b, ns);
-
-    free(key);
 }
 
 static void put_cap_reply(struct octopus_binding *b,
@@ -100,8 +98,9 @@ void put_cap_handler(struct octopus_binding *b, char *key,
         reterr = OCT_ERR_CAP_OVERWRITE;
         err = cap_delete(cap);
         assert(err_is_ok(err));
-        free(key);
     } else {
+        /* we need to make our own copy of the key */
+        key = strdup(key);
         int r = capdb->d.put_capability(&capdb->d, key, cap);
         assert(r == 0);
     }
@@ -147,8 +146,6 @@ void remove_cap_handler(struct octopus_binding *b, char *key)
     assert(err_is_ok(err));
     ns->error = reterr;
     ns->reply(b, ns);
-
-    free(key);
 }
 
 errval_t init_capstorage(void)
index 8087a56..8ec6f1b 100644 (file)
@@ -238,7 +238,6 @@ out:
     drs->reply(b, drs);
 
     free_ast(ast);
-    free(query);
 }
 
 static void get_names_reply(struct octopus_binding* b,
@@ -286,7 +285,6 @@ out:
     drs->reply(b, drs);
 
     free_ast(ast);
-    free(query);
 }
 
 static void set_reply(struct octopus_binding* b, struct oct_reply_state* drs)
@@ -344,7 +342,6 @@ out:
     drs->reply(b, drs);
 
     free_ast(ast);
-    free(query);
 }
 
 static errval_t build_query_with_idcap(char **query_p, struct capref idcap,
@@ -494,7 +491,6 @@ out:
     drs->reply(b, drs);
 
     free_ast(ast);
-    free(attributes);
     if (query != NULL) {
         free(query);
     }
@@ -550,7 +546,6 @@ out:
     drs->reply(b, drs);
 
     free_ast(ast);
-    free(query);
 }
 
 static void exists_reply(struct octopus_binding* b, struct oct_reply_state* drs)
@@ -595,7 +590,6 @@ out:
     drs->reply(b, drs);
 
     free_ast(ast);
-    free(query);
 }
 
 static void wait_for_reply(struct octopus_binding* b, struct oct_reply_state* drs)
@@ -634,7 +628,6 @@ void wait_for_handler(struct octopus_binding* b, char* query) {
     if (err_is_ok(err)) {
         err = get_record(ast, &drs->query_state);
         if (err_no(err) == OCT_ERR_NO_RECORD) {
-            debug_printf("waiting for: %s\n", query);
             uint64_t wid;
             set_watch_err = set_watch(b, ast, OCT_ON_SET, drs, &wid);
         }
@@ -651,7 +644,6 @@ out:
     }
 
     free_ast(ast);
-    free(query);
 }
 
 static void subscribe_reply(struct octopus_binding* b,
@@ -697,7 +689,6 @@ out:
     drs->reply(b, drs);
 
     free_ast(ast);
-    free(query);
 }
 
 static void unsubscribe_reply(struct octopus_binding* b,
@@ -862,7 +853,7 @@ void publish_handler(struct octopus_binding *b, char* record)
 out2:
     free_ast(ast);
 out1:
-    free(record);
+    return;
 }
 
 void get_identifier(struct octopus_binding* b)
index 1d99dd9..85a8ed9 100644 (file)
@@ -80,18 +80,18 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
                                          interrupt_handler_fn reloc_handler,
                                          void *reloc_handler_arg)
 {
-    pci_caps_per_bar_t *caps_per_bar = NULL;
+    pci_caps_per_bar_t caps_per_bar;
     uint8_t nbars;
     errval_t err, msgerr;
 
     err = pci_client->vtbl.
         init_pci_device(pci_client, class, subclass, prog_if, vendor,
                         device, bus, dev, fun, &msgerr,
-                        &nbars, &caps_per_bar);
+                        &nbars, caps_per_bar, caps_per_bar + 1, caps_per_bar + 2,
+                        caps_per_bar + 3, caps_per_bar + 4, caps_per_bar + 5);
     if (err_is_fail(err)) {
         return err;
     } else if (err_is_fail(msgerr)) {
-        free(caps_per_bar);
         return msgerr;
     }
 
@@ -164,7 +164,7 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
     for (int nb = 0; nb < nbars; nb++) {
         struct device_mem *bar = &bars[nb];
 
-        int ncaps = (*caps_per_bar)[nb];
+        int ncaps = (caps_per_bar)[nb];
         if (ncaps != 0) {
             bar->nr_caps = ncaps;
             bar->frame_cap = malloc(ncaps * sizeof(struct capref)); // FIXME: leak
@@ -215,7 +215,6 @@ errval_t pci_register_driver_movable_irq(pci_driver_init_fn init_func, uint32_t
     err = SYS_ERR_OK;
 
  out:
-    free(caps_per_bar);
     return err;
 }
 
index fb0de68..6e9a04a 100644 (file)
@@ -55,7 +55,6 @@ struct dirent *readdir(DIR* dir)
     }
 
     strncpy(dir->dirent.d_name, name, sizeof(dir->dirent.d_name));
-    free(name);
     dir->dirent.d_name[sizeof(dir->dirent.d_name) - 1] = '\0';
     return &dir->dirent;
 }
index 477a439..6d42f60 100644 (file)
@@ -464,15 +464,15 @@ iref_t posixcompat_pts_get_iref(int fd)
 static errval_t allocate_unique_number(uint32_t *np)
 {
     errval_t err;
-    char *record;
-    octopus_trigger_id_t tid;
 
     struct octopus_rpc_client *oc = get_octopus_rpc_client();
 
+    struct octopus_set_response__rx_args reply;
+
     /* request a system-wide unique number at octopus */
     char *query = PTY_PTS_OCTOPUS_PREFIX;
-    oc->vtbl.set(oc, query, SET_SEQUENTIAL, NOP_TRIGGER, true, &record, &tid,
-                 &err);
+    oc->vtbl.set(oc, query, SET_SEQUENTIAL, NOP_TRIGGER, true, reply.record,
+                 &reply.tid, &err);
     if (err_is_fail(err)) {
         goto finish;
     }
@@ -481,11 +481,10 @@ static errval_t allocate_unique_number(uint32_t *np)
      * Octpus returns the record in the form 'ptypts0 {}'. Extract unique
      * number.
      */
-    int ret = sscanf(record, PTY_PTS_OCTOPUS_PREFIX "%" PRIu32, np);
+    int ret = sscanf(reply.record, PTY_PTS_OCTOPUS_PREFIX "%" PRIu32, np);
     assert(ret == 1);
 
 finish:
-    free(record);
     return err;
 }
 
index 51e875a..852f0dd 100644 (file)
@@ -75,15 +75,47 @@ errval_t skb_client_connect(void)
 }
 
 /* ------------------------- evaluate ------------------------------ */
-errval_t skb_evaluate(char *query, char **result, char **str_error, int32_t *int_error)
+errval_t skb_evaluate(char *query, char **ret_result, char **ret_str_error, int32_t *int_error)
 {
     errval_t err;
     struct skb_state *skb_state = get_skb_state();
 
-    err = skb_state->skb->vtbl.run(skb_state->skb, query, result, str_error,
-                                   int_error);
+    // allocate memory for holding the response data
+    char *result = NULL;
+    if (ret_result) {
+        result = malloc(skb__run_response_output_MAX_ARGUMENT_SIZE);
+        if (result == NULL) {
+            return LIB_ERR_MALLOC_FAIL;
+        }
+    }
+    char *str_error = NULL;
+    if (ret_str_error) {
+        str_error = malloc(skb__run_response_str_error_MAX_ARGUMENT_SIZE);
+        if (str_error == NULL) {
+            if (result) {
+                free(result);
+            }
+            return LIB_ERR_MALLOC_FAIL;
+        }
+    }
+    err = skb_state->skb->vtbl.run(skb_state->skb, query, result,
+                                   str_error, int_error);
     if (err_is_fail(err)) {
+        if (result) {
+            free(result);
+        }
+        if (str_error) {
+            free(str_error);
+        }
         return err_push(err, SKB_ERR_RUN);
     }
+
+    if (ret_result) {
+        *ret_result = result;
+    }
+    if (ret_str_error) {
+        *ret_str_error = str_error;
+    }
+
     return SYS_ERR_OK;
 }
index 323bf8e..f1532df 100644 (file)
 #include <string.h>
 #include <barrelfish/barrelfish.h>
 #include <skb/skb.h>
+#include <if/skb_rpcclient_defs.h>
+#include <barrelfish/core_state_arch.h>
 #include "skb_debug.h"
 
-#define BUFFER_SIZE SKB_REPLY_BUF_SIZE
-#define OUTPUT_SIZE SKB_REPLY_BUF_SIZE
+#define BUFFER_SIZE skb__run_call_input_MAX_ARGUMENT_SIZE
+#define OUTPUT_SIZE skb__run_response_output_MAX_ARGUMENT_SIZE
 
 /* XXX: The following static chars make the skb connection not thread
    safe and we probably don't want to put them in the per dispatcher
    corestate as they are so big. */
-static char buffer[BUFFER_SIZE];
-static char output[OUTPUT_SIZE];
-static char error_output[OUTPUT_SIZE];
+static char buffer[skb__run_call_input_MAX_ARGUMENT_SIZE + 1];
+static char output[skb__run_response_output_MAX_ARGUMENT_SIZE + 1];
+static char error_output[skb__run_response_str_error_MAX_ARGUMENT_SIZE + 1];
 static int error_code;
 
 int skb_read_error_code(void)
@@ -46,20 +48,19 @@ char *skb_get_error_output(void)
 
 errval_t skb_execute(char *goal)
 {
-    int32_t error;
-    char *result, *error_out;
-    errval_t err = skb_evaluate(goal, &result, &error_out, &error);
+    errval_t err;
+    struct skb_state *skb_state = get_skb_state();
+
+    err = skb_state->skb->vtbl.run(skb_state->skb, goal, output,
+            error_output, &error_code);
     if (err_is_fail(err)) {
-        return err_push(err, SKB_ERR_EVALUATE);
+        return err_push(err, SKB_ERR_RUN);
     }
-    error_code = error;
-    strncpy(output, result, OUTPUT_SIZE);
-    strncpy(error_output, error_out, OUTPUT_SIZE);
-    free(result);
-    free(error_out);
-    if (error != 0) {
+
+    if (error_code != 0) {
         return err_push(err, SKB_ERR_EXECUTION);
     }
+
     return err;
 }
 
index 7a21ae4..31cd742 100644 (file)
@@ -259,15 +259,13 @@ errval_t spawn_symval_lookup(const char *binary,
         }
     }
 
-    char* record = NULL;
-    octopus_trigger_id_t tid;
-    errval_t error_code;
+    struct octopus_get_response__rx_args reply;
     err = r->vtbl.get(r, omp_entry, NOP_TRIGGER,
-                      &record, &tid, &error_code);
+                      reply.output, &reply.tid, &reply.error_code);
     if (err_is_fail(err)) {
         goto out;
     }
-    err = error_code;
+    err = reply.error_code;
     if (err_is_fail(err)) {
         if (err_no(err) == OCT_ERR_NO_RECORD) {
             err = err_push(err, LIB_ERR_NAMESERVICE_UNKNOWN_NAME);
@@ -277,7 +275,7 @@ errval_t spawn_symval_lookup(const char *binary,
 
     uint64_t addr = 0;
     char *symname = NULL;
-    err = oct_read(record, "_ { sym: %s, addr: %d }", &symname, &addr);
+    err = oct_read(reply.output, "_ { sym: %s, addr: %d }", &symname, &addr);
     if (err_is_fail(err) || symname == NULL) {
         err = err_push(err, LIB_ERR_NAMESERVICE_INVALID_NAME);
         goto out;
@@ -289,7 +287,7 @@ errval_t spawn_symval_lookup(const char *binary,
         *ret_name = strdup(symname);
     }
 
-    out: free(record);
+    out:
     free(omp_entry);
     return err;
 }
@@ -336,19 +334,17 @@ errval_t spawn_symval_register(const char *binary,
         }
     }
 
-    char* ret = NULL;
     octopus_trigger_id_t tid;
     errval_t error_code;
     err = r->vtbl.set(r, record, 0, NOP_TRIGGER,
-                      0, &ret, &tid, &error_code);
+                      0, NULL, &tid, &error_code);
     if (err_is_fail(err)) {
         goto out;
     }
     err = error_code;
 
 out: 
-       free(record);
-       
+    free(record);
     return err;
 }
 
index 9f4be43..10babde 100644 (file)
@@ -269,9 +269,7 @@ errval_t term_client_blocking_write(struct term_client *client,
     }
 
     /* Make a copy of characters, since the output filters might modify them. */
-    outdata = malloc(length);
-    assert(outdata != NULL);
-    memcpy(outdata, data, length);
+    outdata = memdup(data, length);
 
     /* tell user how much we've written (before applying filters) */
     *written = length;
@@ -340,7 +338,7 @@ errval_t term_client_blocking_config(struct term_client *client,
                 term_filter_id_t id = term_client_add_input_filter(client, term_filter_cr2lf);
                 client->cr2lf_id = id;
             }
-            
+
             return SYS_ERR_OK;
         }
         break;
@@ -370,7 +368,7 @@ errval_t term_client_blocking_config(struct term_client *client,
 
 }
 
-errval_t term_client_blocking_tcgetattr(struct term_client *client, 
+errval_t term_client_blocking_tcgetattr(struct term_client *client,
                                         struct termios* t)
 {
     if (client->cr2lf_id > 0) {
@@ -383,7 +381,7 @@ errval_t term_client_blocking_tcgetattr(struct term_client *client,
     return SYS_ERR_OK;
 }
 
-errval_t term_client_blocking_tcsetattr(struct term_client *client, 
+errval_t term_client_blocking_tcsetattr(struct term_client *client,
                                         const struct termios* t)
 {
     errval_t err = term_client_blocking_config(client, TerminalConfig_ECHO, (t->c_lflag & ECHO) > 0);
@@ -472,16 +470,15 @@ static errval_t get_irefs(struct capref session_id, iref_t *in_iref,
     struct octopus_rpc_client *r = get_octopus_rpc_client();
     assert(r != NULL);
 
-    char *record;
-    errval_t error_code;
-    octopus_trigger_id_t tid;
-    err = r->vtbl.get_with_idcap(r, session_id, NOP_TRIGGER, &record, &tid,
-                                 &error_code);
+    struct octopus_get_with_idcap_response__rx_args reply;
+
+    err = r->vtbl.get_with_idcap(r, session_id, NOP_TRIGGER, reply.output, &reply.tid,
+                                 &reply.error_code);
     if (err_is_fail(err)) {
         err_push(err, TERM_ERR_LOOKUP_SESSION_RECORD);
         goto out;
     }
-    err = error_code;
+    err = reply.error_code;
     if (err_is_fail(err)) {
         err_push(err, TERM_ERR_LOOKUP_SESSION_RECORD);
         goto out;
@@ -495,7 +492,7 @@ static errval_t get_irefs(struct capref session_id, iref_t *in_iref,
     int64_t conf_oct;
     // oct_read can only parse 64-bit values, we need to parse the irefs as 64bit
     // then cast to 32bit
-    err = oct_read(record, "_ { session_iref: %d, in_iref: %d, out_iref: %d, "
+    err = oct_read(reply.output, "_ { session_iref: %d, in_iref: %d, out_iref: %d, "
                    "conf_iref: %d }", &session_oct, &in_oct, &out_oct,
                     &conf_oct);
     //iref_t session_iref = (iref_t)session_oct;
@@ -517,7 +514,6 @@ static errval_t get_irefs(struct capref session_id, iref_t *in_iref,
                "\n", *in_iref, *out_iref, *conf_iref);
 
 out:
-    free(record);
     return err;
 }
 
@@ -554,9 +550,7 @@ static errval_t handle_echo(struct term_client *client, char *data,
      * Make a copy of the data, since the echo filters might modify it and the
      * modification should not be seen by the application.
      */
-    echodata = malloc(length);
-    assert(echodata != NULL);
-    memcpy(echodata, data, length);
+    echodata = memdup(data, length);
 
     /* apply echo filters */
     term_filter_apply(client->echo_filters, &echodata, &length);
@@ -607,22 +601,25 @@ static void in_characters_handler(struct terminal_binding *b, char *data,
 {
     struct term_client *client = b->st;
 
+
+    char *my_data = memdup(data, length);
+
     if (client->non_blocking_read) {
         assert(client->chars_cb != NULL);
 
         /* handle triggers */
-        handle_triggers(client, data, length);
+        handle_triggers(client, my_data, length);
 
         /* filter input */
-        term_filter_apply(client->input_filters, &data, &length);
+        term_filter_apply(client->input_filters, &my_data, &length);
 
         /* call user supplied chars_cb */
-        client->chars_cb(client->st, data, length);
+        client->chars_cb(client->st, my_data, length);
     } else {
         assert(client->readbuf == NULL);
 
-        client->readbuf = data;
-        client->readbuf_pos = data;
+        client->readbuf = my_data;
+        client->readbuf_pos = my_data;
         client->readbuf_len = length;
     }
 }
index 0f10ebb..af687c1 100644 (file)
@@ -154,12 +154,12 @@ usb_error_t usb_lib_init(uint8_t init_config)
 
     uint32_t ret_status;
 
-    uint8_t *tmp;
+    uint8_t tmp[2048];
     size_t length;
 
     /* connect with the USB Manager */
     err = usb_manager.vtbl.connect(&usb_manager, usb_driver_iref, init_config,
-            &ret_status, &tmp, &length);
+            &ret_status, tmp, &length);
 
     if (((usb_error_t) ret_status) != USB_ERR_OK) {
         debug_printf("libusb: ERROR connecting to the USB manager\n");
@@ -180,7 +180,6 @@ usb_error_t usb_lib_init(uint8_t init_config)
 
     /*
      * initialize the devices with the descriptors
-     * Do not free the tmp, since the data is still used by the descriptors
      */
     usb_device_init(tmp);
 
index 9de085d..0df5afc 100644 (file)
@@ -647,14 +647,14 @@ usb_error_t usb_do_request_read(struct usb_device_request *req,
 {\r
     errval_t err;\r
     uint32_t ret_status = 0;\r
-    uint8_t *data = NULL;\r
+    uint8_t data[2048];\r
     size_t length = 0;\r
     usb_error_t ret;\r
 \r
     USB_DEBUG_IDC("libusb: usb_do_request_read()\n");\r
 \r
     err = usb_manager.vtbl.request_read(&usb_manager, (uint8_t*) req,\r
-            sizeof(*req), (uint8_t **) &data, &length, &ret_status);\r
+            sizeof(*req), data, &length, &ret_status);\r
 \r
     *ret_length = length;\r
 \r
@@ -670,7 +670,7 @@ usb_error_t usb_do_request_read(struct usb_device_request *req,
 \r
     USB_DEBUG_IDC("libusb: usb_do_request_read() got data (len=%i)\n", *ret_length);\r
 \r
-    *ret_data = (void *) data;\r
+    *ret_data = memdup(data, sizeof(data));\r
 \r
     return (ret);\r
 }\r
index 03f16b5..d8683a5 100644 (file)
@@ -304,23 +304,20 @@ static void ahci_mgmt_bind_cb(void *st, errval_t err, struct ahci_mgmt_binding *
 
     ahci_mgmt_bound = true;
 
-    // populate list
-    uint8_t *port_ids;
-    size_t len;
-
-    err = ahci_mgmt_rpc.vtbl.list(&ahci_mgmt_rpc, &port_ids, &len);
+    struct ahci_mgmt_list_response__rx_args reply;
+    err = ahci_mgmt_rpc.vtbl.list(&ahci_mgmt_rpc, reply.port_ids, &reply.len);
     assert(err_is_ok(err));
 
-    for (size_t i = 0; i < len; i++) {
-        uint8_t *data;
-        size_t identifylen = 0;
+    for (size_t i = 0; i < reply.len; i++) {
+        struct ahci_mgmt_identify_response__rx_args identify_reply;
         err = ahci_mgmt_rpc.vtbl.identify(&ahci_mgmt_rpc,
-                port_ids[i], &data, &identifylen);
+                reply.port_ids[i], identify_reply.identify_data,
+                &identify_reply.data_len);
         assert(err_is_ok(err));
-        assert(identifylen == 512);
+        assert(identify_reply.data_len == 512);
 
         ata_identify_t identify;
-        ata_identify_initialize(&identify, (void *)data);
+        ata_identify_initialize(&identify, (void *)identify_reply.identify_data );
 
         //char buf[8192];
         //ata_identify_pr(buf, 8192, &identify);
@@ -340,7 +337,7 @@ static void ahci_mgmt_bind_cb(void *st, errval_t err, struct ahci_mgmt_binding *
                 port_ids[i], sectors, sector_size);
 
         struct ahci_handle *handle = calloc(1, sizeof(struct ahci_handle));
-        handle->port_num = port_ids[i];
+        handle->port_num = reply.port_ids[i];
 
         struct blockdev_entry *newentry = calloc(1, sizeof(struct blockdev_entry));
         newentry->open = false;
index c51ca3d..e62b3f7 100644 (file)
@@ -163,11 +163,8 @@ errval_t blockdevfs_ata_read(void *handle, size_t pos, void *buffer,
 
     //VFS_BLK_DEBUG("bdfs_ahci: read begin: %zu -> %zu\n", bytes, aligned_bytes);
 
-    uint8_t *data;
     err = h->ata_rw28_rpc.vtbl.read_dma(&h->ata_rw28_rpc,
-            aligned_bytes, blockpos, &data, bytes_read);
-    memcpy(buffer, data, *bytes_read);
-    free(data);
+            aligned_bytes, blockpos, buffer, bytes_read);
 
     return err;
 }
@@ -203,25 +200,23 @@ static void ahci_mgmt_bind_cb(void *st, errval_t err, struct ahci_mgmt_binding *
     ahci_mgmt_bound = true;
 
     // populate list
-    uint8_t *port_ids;
-    size_t len;
-
-    err = ahci_mgmt_rpc.vtbl.list(&ahci_mgmt_rpc, &port_ids, &len);
+    struct ahci_mgmt_list_response__rx_args reply;
+    err = ahci_mgmt_rpc.vtbl.list(&ahci_mgmt_rpc, reply.port_ids, &reply.len);
     assert(err_is_ok(err));
 
-    for (size_t i = 0; i < len; i++) {
+    for (size_t i = 0; i < reply.len; i++) {
         if (i > 9) {
             break;
         }
-        uint8_t *data;
-        size_t identifylen = 0;
-        err = ahci_mgmt_rpc.vtbl.identify(&ahci_mgmt_rpc,
-                port_ids[i], &data, &identifylen);
+        struct ahci_mgmt_identify_response__rx_args identify_reply;
+        err = ahci_mgmt_rpc.vtbl.identify(&ahci_mgmt_rpc, reply.port_ids[i],
+                                          identify_reply.identify_data,
+                                          &identify_reply.data_len);
         assert(err_is_ok(err));
-        assert(identifylen == 512);
+        assert(identify_reply.data_len == 512);
 
         ata_identify_t identify;
-        ata_identify_initialize(&identify, (void *)data);
+        ata_identify_initialize(&identify, (void *)identify_reply.identify_data);
 
         //char buf[8192];
         //ata_identify_pr(buf, 8192, &identify);
@@ -241,7 +236,7 @@ static void ahci_mgmt_bind_cb(void *st, errval_t err, struct ahci_mgmt_binding *
                 port_ids[i], sectors, sector_size);
 
         struct ata_handle *handle = calloc(1, sizeof(struct ata_handle));
-        handle->port_num = port_ids[i];
+        handle->port_num = reply.port_ids[i];
 
         struct blockdev_entry *newentry = calloc(1, sizeof(struct blockdev_entry));
         newentry->open = false;
index e838d11..20d6dd6 100644 (file)
@@ -170,8 +170,9 @@ acquire_or_read(struct fat_mount *mount, struct fs_cache *cache,
     }
     else if (err == FS_CACHE_NOTPRESENT) {
         size_t read_size;
+        data_ = malloc(size);
         err = mount->ata_rw28_rpc.vtbl.read_dma(&mount->ata_rw28_rpc,
-                size, block, &data_, &read_size);
+                size, block, data_, &read_size);
         if (err_is_fail(err)) {
             return err;
         }
@@ -1190,12 +1191,11 @@ vfs_fat_mount(const char *uri, void **retst, struct vfs_ops **retops)
 
     FAT_DEBUG("ata_rw28 initialized.\n");
 #endif
-
-    // read data from fat boot sector
-    uint8_t *data;
     size_t size;
+    // read data from fat boot sector
+    uint8_t *data = malloc(ata_rw28__read_dma_block_response_buffer_MAX_ARGUMENT_SIZE);
     err = mount->ata_rw28_rpc.vtbl.read_dma_block(&mount->ata_rw28_rpc,
-            mount->startblock, &data, &size);
+            mount->startblock, mount->bootsec_data, &size);
     if (err_is_fail(err)) {
         goto bootsec_read_failed;
     }
@@ -1213,8 +1213,7 @@ vfs_fat_mount(const char *uri, void **retst, struct vfs_ops **retops)
     }
     FAT_DEBUG("end sector 0 dump");
 #endif
-    memcpy(mount->bootsec_data, data, size);
-    free(data);
+
     data = NULL;
 
     if (memcmp(mount->bootsec_data+0x1FE, "\x55\xAA", 2) != 0) {
@@ -1295,28 +1294,29 @@ vfs_fat_mount(const char *uri, void **retst, struct vfs_ops **retops)
                     mount->block_count);
             goto fs_check_failed;
         }
+        struct ata_rw28_read_dma_block_response__rx_args reply;
         mount->ata_rw28_rpc.vtbl.read_dma_block(&mount->ata_rw28_rpc,
-                mount->startblock + fs_info_sector, &data, &size);
-        if (memcmp(data+0, "RRaA", 4) != 0 ||
-            memcmp(data+0x1e4, "rrAa", 4) != 0)
+                mount->startblock + fs_info_sector, reply.buffer ,
+                &reply.buffer_size);
+        if (memcmp(reply.buffer+0, "RRaA", 4) != 0 ||
+            memcmp(reply.buffer+0x1e4, "rrAa", 4) != 0)
         {
             FAT_DEBUG_F("File System Information Sector signatures do not match,"
-                    " %"PRIx32", %"PRIx32, *(uint32_t*)(data+0),
-                    *(uint32_t*)(data+0x1e4));
+                    " %"PRIx32", %"PRIx32, *(uint32_t*)(reply.buffer+0),
+                    *(uint32_t*)(reply.buffer+0x1e4));
             goto fs_check_failed;
         }
-        if (memcmp(data+0x1fe, "\x55\xAA", 2) != 0) {
+        if (memcmp(reply.buffer+0x1fe, "\x55\xAA", 2) != 0) {
             FAT_DEBUG("File System Information Sector check bytes do not match");
             goto fs_check_failed;
         }
 #ifdef FAT_DEBUG_ENABLED
         FAT_DEBUG("dumping FSIS");
-        printf("nr of free clusters: %"PRIu32"\n", *(uint32_t*)(data+0x1e8));
+        printf("nr of free clusters: %"PRIu32"\n", *(uint32_t*)(reply.buffer+0x1e8));
         printf("most recently allocated cluster: %"PRIu32"\n",
-                *(uint32_t*)(data+0x1ec));
+                *(uint32_t*)(reply.buffer+0x1ec));
         printf("----------------\n");
 #endif
-        free(data);
         data = NULL;
     }
 
index 203fac8..d4b7a5e 100644 (file)
@@ -236,16 +236,13 @@ static errval_t read(void *st, vfs_handle_t handle, void *buffer, size_t bytes,
 
     assert(!h->isdir);
 
-    uint8_t *mybuf = NULL;
-
 restart:
     err = cl->rpc.vtbl.read(&cl->rpc, h->fh, h->pos, bytes,
-                            &msgerr, &mybuf, bytes_read);
+                            &msgerr, buffer, bytes_read);
     if (err_is_fail(err)) {
         DEBUG_ERR(err, "transport error in read");
         return err;
     } else if (err_is_fail(msgerr)) {
-        assert(mybuf == NULL);
         if (err_no(msgerr) == FS_ERR_INVALID_FH && !restarts++) {
             // revalidate handle and try again
             msgerr = resolve_path(cl, h->path, &h->fh, NULL, NULL);
@@ -258,8 +255,6 @@ restart:
     }
 
     h->pos += *bytes_read;
-    memcpy(buffer, mybuf, *bytes_read);
-    free(mybuf);
 
     if (*bytes_read < bytes) { // XXX: this can only mean EOF for ramfs
         return VFS_ERR_EOF;
@@ -586,23 +581,21 @@ static errval_t dir_read_next(void *st, vfs_handle_t inhandle, char **retname,
 {
     struct ramfs_handle *h = inhandle;
     struct ramfs_client *cl = st;
-    char *name;
-    trivfs_fsize_t size;
-    bool isdir;
-    errval_t err, msgerr;
+
+    errval_t err;
     int restarts = 0;
 
     assert(h->isdir);
 
+    struct trivfs_readdir_response__rx_args reply;
 restart:
     err = cl->rpc.vtbl.readdir(&cl->rpc, h->fh, h->pos,
-                               &msgerr, &name, &isdir, &size);
+                               &reply.err, reply.name, &reply.isdir, &reply.size);
     if (err_is_fail(err)) {
         DEBUG_ERR(err, "transport error in readdir");
         return err;
-    } else if (err_is_fail(msgerr)) {
-        assert(name == NULL);
-        if (err_no(msgerr) == FS_ERR_INVALID_FH && !restarts++) {
+    } else if (err_is_fail(reply.err)) {
+        if (err_no(reply.err) == FS_ERR_INVALID_FH && !restarts++) {
             // revalidate handle and try again
             if (h->fh == cl->rootfh) { // XXX: revalidate root
                 err = cl->rpc.vtbl.getroot(&cl->rpc, &cl->rootfh);
@@ -612,27 +605,27 @@ restart:
                 h->fh = cl->rootfh;
                 goto restart;
             } else {
-                msgerr = resolve_path(cl, h->path, &h->fh, NULL, NULL);
-                if (err_is_ok(msgerr)) {
+                reply.err = resolve_path(cl, h->path, &h->fh, NULL, NULL);
+                if (err_is_ok(reply.err)) {
                     goto restart;
                 }
             }
         }
-        if (err_no(msgerr) != FS_ERR_INDEX_BOUNDS) {
-            DEBUG_ERR(msgerr, "server error in readdir");
+        if (err_no(reply.err) != FS_ERR_INDEX_BOUNDS) {
+            DEBUG_ERR(reply.err, "server error in readdir");
         }
-        return msgerr;
+        return reply.err;
     }
 
     h->pos++;
 
     if (retname != NULL) {
-        *retname = name;
+        *retname = strdup(reply.name);
     }
 
     if (info != NULL) {
-        info->type = isdir ? VFS_DIRECTORY : VFS_FILE;
-        info->size = size;
+        info->type = reply.isdir ? VFS_DIRECTORY : VFS_FILE;
+        info->size = reply.size;
     }
 
     return SYS_ERR_OK;
index 8226ef6..d3f8855 100644 (file)
@@ -101,14 +101,12 @@ errval_t xeon_phi_domain_lookup(const char *iface,
         return LIB_ERR_NAMESERVICE_NOT_BOUND;
     }
 
-    char* record = NULL;
-    octopus_trigger_id_t tid;
-    errval_t error_code;
-    err = r->vtbl.get(r, iface, NOP_TRIGGER, &record, &tid, &error_code);
+    struct octopus_get_response__rx_args reply;
+    err = r->vtbl.get(r, iface, NOP_TRIGGER, reply.output, &reply.tid, &reply.error_code);
     if (err_is_fail(err)) {
         goto out;
     }
-    err = error_code;
+    err = reply.error_code;
     if (err_is_fail(err)) {
         if (err_no(err) == OCT_ERR_NO_RECORD) {
             err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID);
@@ -117,7 +115,7 @@ errval_t xeon_phi_domain_lookup(const char *iface,
     }
 
     xphi_dom_id_t domid = 0;
-    err = oct_read(record, "_ { domid: %d }", &domid);
+    err = oct_read(reply.output, "_ { domid: %d }", &domid);
     if (err_is_fail(err) || domid == 0) {
         err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID);
         goto out;
@@ -127,8 +125,7 @@ errval_t xeon_phi_domain_lookup(const char *iface,
         *retdomid = domid;
     }
 
-    out: free(record);
-
+    out:
     return err;
 #endif
 }
@@ -152,13 +149,12 @@ errval_t xeon_phi_domain_blocking_lookup(const char *iface,
         return LIB_ERR_NAMESERVICE_NOT_BOUND;
     }
 
-    char* record = NULL;
-    errval_t error_code;
-    err = r->vtbl.wait_for(r, iface, &record, &error_code);
+    struct octopus_wait_for_response__rx_args reply;
+    err = r->vtbl.wait_for(r, iface, reply.record, &reply.error_code);
     if (err_is_fail(err)) {
         goto out;
     }
-    err = error_code;
+    err = reply.error_code;
     if (err_is_fail(err)) {
         if (err_no(err) == OCT_ERR_NO_RECORD) {
             err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID);
@@ -167,7 +163,7 @@ errval_t xeon_phi_domain_blocking_lookup(const char *iface,
     }
 
     xphi_dom_id_t domid = 0;
-    err = oct_read(record, "_ { domid: %d }", &domid);
+    err = oct_read(reply.record, "_ { domid: %d }", &domid);
     if (err_is_fail(err)) {
         err = err_push(err, XEON_PHI_ERR_CLIENT_DOMAIN_VOID);
         goto out;
@@ -177,7 +173,6 @@ errval_t xeon_phi_domain_blocking_lookup(const char *iface,
     }
 
     out:
-    free(record);
     return err;
 #endif
 }
@@ -210,10 +205,9 @@ errval_t xeon_phi_domain_register(const char *iface,
     }
     snprintf(record, len+1, format, iface, domid);
 
-    char* ret = NULL;
     octopus_trigger_id_t tid;
     errval_t error_code;
-    err = r->vtbl.set(r, record, 0, NOP_TRIGGER, 0, &ret, &tid, &error_code);
+    err = r->vtbl.set(r, record, 0, NOP_TRIGGER, 0, NULL, &tid, &error_code);
     if (err_is_fail(err)) {
         goto out;
     }
index 68878fb..4edd309 100644 (file)
@@ -330,7 +330,7 @@ rpc_arg rpcargs n = listToMaybe $ filter ((== n) . rpc_arg_var_name . rpc_arg_va
     where rpc_arg_var (RPCArgIn _ v) = v
           rpc_arg_var (RPCArgOut _ v) = v
           rpc_arg_var_name (Name n) = n
-          rpc_arg_var_name (DynamicArray n _) = n
+          rpc_arg_var_name (DynamicArray n _ _) = n
 
 get_meta_arg :: String -> String -> [(String, [(String, MetaArgument)])] -> Maybe MetaArgument
 get_meta_arg nspc n metaargs = (lookup nspc metaargs) >>= (lookup n)
@@ -373,7 +373,7 @@ rpc_dma_args types rpc@(RPC name rpcargs metaargs) =
               meta_arg_dma_size
               ]
           dma_dyn_arg_size = case rpc_arg rpcargs $ rpc_dma_arg_name rpc of
-              Just (RPCArgIn (Builtin UInt8) (DynamicArray _ l)) -> Just $ C.Variable l
+              Just (RPCArgIn (Builtin UInt8) (DynamicArray _ l _)) -> Just $ C.Variable l
               _                                                  -> Nothing
           dma_arg_type_size = case lookup_typeref types $ rpc_arg_type $ fromJust $ rpc_arg rpcargs $ rpc_dma_arg_name rpc of
               TArray (Builtin UInt8) _ length -> Just $ C.NumConstant length
@@ -440,7 +440,7 @@ cc_rx_fn ifn types msg@(RPC name rpcargs metaargs) =
         pr_region_var = C.Variable "completed_st" `C.DerefField` "dma_region"
         output_arg_expr :: Maybe Direction -> MessageArgument -> [C.Expr]
         output_arg_expr _ (Arg (Builtin ErrVal) (Name "status")) = [C.Variable "SYS_ERR_OK"]
-        output_arg_expr (Just RX) (Arg (Builtin UInt8) (DynamicArray _ _)) = [C.Variable dma_data_name, dma_size]
+        output_arg_expr (Just RX) (Arg (Builtin UInt8) (DynamicArray _ _ _)) = [C.Variable dma_data_name, dma_size]
         output_arg_expr _ arg = error ("unrecoginized output argument " ++ (show arg))
 
         dma_args = rpc_dma_args types msg
index 41e3fbc..d14ec0c 100644 (file)
@@ -177,7 +177,7 @@ array, without its associated length bound.
 
 > nameOf :: Variable -> String
 > nameOf (Name s) = s
-> nameOf (DynamicArray s _) = s
+> nameOf (DynamicArray s _ _) = s
 
 
 Conversely, when marshaling or unmarshaling dynamic arrays, we need to
@@ -185,7 +185,7 @@ pass the @length@ parameter.
 
 > listOfArgs :: String -> Variable -> String
 > listOfArgs dereference (Name s) = dereference ++ s
-> listOfArgs dereference (DynamicArray name length) = dereference ++ name ++ ", " ++ length
+> listOfArgs dereference (DynamicArray name length _) = dereference ++ name ++ ", " ++ length
 
 
 > callNameOf :: MessageDef -> String
index b6a37f9..f2e4b47 100644 (file)
@@ -1,4 +1,4 @@
-{- 
+{-
    BackendCommon: Common code used by most backends
 
   Part of Flounder: a message passing IDL for Barrelfish
@@ -48,7 +48,12 @@ intf_frameinfo_type ifn = ifscope ifn "frameinfo"
 -- Variable used to refer to a continuation
 intf_frameinfo_var = "_frameinfo"
 
+-- name of the maximum message size define
+msg_arg_size_name :: String -> String
+msg_arg_size_name ifname = ifscope ifname "_MAX_MESSAGE_SIZE"
 
+arg_size_name :: String -> String -> String -> String
+arg_size_name ifname fname argn= ifscope ifname ("_" ++ fname ++ "_" ++ argn ++ "_MAX_ARGUMENT_SIZE")
 
 -- Name of the bind continuation function type for an interface type
 intf_bind_cont_type :: String -> String
@@ -74,6 +79,9 @@ msg_sig_type ifn m@(RPC _ _ _) _ = idscope ifn (msg_name m) "rpc_method_fn"
 msg_sig_type ifn m TX = idscope ifn (msg_name m) "tx_method_fn"
 msg_sig_type ifn m RX =  idscope ifn (msg_name m) "rx_method_fn"
 
+msg_sig_type_rpc_rx :: String -> MessageDef -> String
+msg_sig_type_rpc_rx ifn m@(RPC _ _ _) = idscope ifn (msg_name m) "rpc_rx_method_fn"
+
 -- Name of a given message definition
 msg_name :: MessageDef -> String
 msg_name (Message _ n _ _) = n
@@ -88,12 +96,14 @@ rpc_call_name n = n ++ "_call"
 rpc_resp_name n = n ++ "_response"
 
 -- Name of the struct holding message args for SAR
-msg_argstruct_name :: String -> String -> String
-msg_argstruct_name ifn n = idscope ifn n "args"
+msg_argstruct_name :: Direction -> String -> String -> String
+msg_argstruct_name TX ifn n = idscope ifn n "tx_args"
+msg_argstruct_name RX ifn n = idscope ifn n "rx_args"
 
 -- Name of the union type holding all the arguments for a message
-binding_arg_union_type :: String -> String
-binding_arg_union_type ifn = ifscope ifn "arg_union"
+binding_arg_union_type :: Direction -> String -> String
+binding_arg_union_type TX ifn = ifscope ifn "tx_arg_union"
+binding_arg_union_type RX ifn = ifscope ifn "rx_arg_union"
 
 -- Name of the C type for a concrete flounder type, struct, or enum
 type_c_struct, type_c_enum :: String -> String -> String
@@ -127,11 +137,14 @@ type_c_type_dir TX ifn tr = case type_c_type ifn tr of
 type_c_type_dir RX ifn tr = type_c_type ifn tr
 
 -- Array types in the msg args struct should only be pointers to the storage
-type_c_type_msgstruct :: String -> [TypeDef] -> TypeRef -> C.TypeSpec
-type_c_type_msgstruct ifn typedefs t
+type_c_type_msgstruct :: Direction -> String -> [TypeDef] -> TypeRef -> C.TypeSpec
+type_c_type_msgstruct TX ifn typedefs t
     = case lookup_typeref typedefs t of
         TArray tr n _ -> C.Ptr $ type_c_type ifn t
         _ -> type_c_type ifn t
+type_c_type_msgstruct RX ifn typedefs t
+    = case lookup_typeref typedefs t of
+        _ -> type_c_type ifn t
 
 -- Name of the struct type for the method vtable
 intf_vtbl_type :: String -> Direction -> String
@@ -152,6 +165,13 @@ register_send_fn_type ifn = ifscope ifn "register_send_fn"
 change_waitset_fn_type ifn = ifscope ifn "change_waitset_fn"
 control_fn_type ifn = ifscope ifn "control_fn"
 error_handler_fn_type ifn = ifscope ifn "error_handler_fn"
+receive_next_fn_type ifn = ifscope ifn "receive_next_fn"
+get_receiving_chanstate_fn_type ifn = ifscope ifn "get_receiving_chanstate_fn"
+
+-- Name of the type of a message handler
+msg_handler_fn_name :: String -> MessageDef -> String
+msg_handler_fn_name ifn m = idscope ifn (msg_name m) "handler_fn"
+
 
 
 ------------------------------------------------------------------------
@@ -206,35 +226,50 @@ partition_rpc_args (first:rest) = case first of
 msg_argdecl :: Direction -> String -> MessageArgument -> [C.Param]
 msg_argdecl dir ifn (Arg tr (Name n)) =
     [ C.Param (type_c_type_dir dir ifn tr) n ]
-msg_argdecl RX ifn (Arg tr (DynamicArray n l)) =
+msg_argdecl dir ifn (Arg tr (StringArray n l)) =
+    [ C.Param (type_c_type_dir dir ifn tr) n ]
+msg_argdecl RX ifn (Arg tr (DynamicArray n l _)) =
     [ C.Param (C.Ptr $ type_c_type_dir RX ifn tr) n,
       C.Param (type_c_type_dir RX ifn size) l ]
-msg_argdecl TX ifn (Arg tr (DynamicArray n l)) =
+msg_argdecl TX ifn (Arg tr (DynamicArray n l _)) =
     [ C.Param (C.Ptr $ C.ConstT $ type_c_type_dir TX ifn tr) n,
       C.Param (type_c_type_dir TX ifn size) l ]
 
-msg_argstructdecl :: String -> [TypeDef] -> MessageArgument -> [C.Param]
-msg_argstructdecl ifn typedefs (Arg tr (Name n)) =
-    [ C.Param (type_c_type_msgstruct ifn typedefs tr) n ]
-msg_argstructdecl ifn typedefs a = msg_argdecl RX ifn a
 
-rpc_argdecl :: String -> RPCArgument -> [C.Param]
-rpc_argdecl ifn (RPCArgIn tr v) = msg_argdecl TX ifn (Arg tr v)
-rpc_argdecl ifn (RPCArgOut tr (Name n)) = [ C.Param (C.Ptr $ type_c_type ifn tr) n ]
-rpc_argdecl ifn (RPCArgOut tr (DynamicArray n l)) =
-    [ C.Param (C.Ptr $ C.Ptr $ type_c_type ifn tr) n,
+msg_argstructdecl :: Direction -> String -> [TypeDef] -> MessageArgument -> [C.Param]
+msg_argstructdecl dir ifn typedefs (Arg tr (Name n)) =
+    [ C.Param (type_c_type_msgstruct dir ifn typedefs tr) n ]
+msg_argstructdecl RX ifn typedefs (Arg tr (StringArray n maxlen)) =
+    [ C.Param (C.Array maxlen $ C.TypeName "char") (n)]
+msg_argstructdecl TX ifn typedefs (Arg tr (StringArray n maxlen)) =
+    [ C.Param (type_c_type_dir TX ifn tr) n ]
+msg_argstructdecl RX ifn typedefs (Arg tr (DynamicArray n l maxlen)) =
+    [ C.Param (C.Array maxlen $ type_c_type ifn tr) (n),
+      C.Param (type_c_type ifn size) l ]
+msg_argstructdecl TX ifn typedefs (Arg tr (DynamicArray n l maxlen)) =
+    [ C.Param (C.Ptr $ C.ConstT $ type_c_type_dir TX ifn tr) n,
+      C.Param (type_c_type ifn size) l ]
+
+
+rpc_argdecl :: Direction -> String -> RPCArgument -> [C.Param]
+rpc_argdecl dir ifn (RPCArgIn tr v) = msg_argdecl dir ifn (Arg tr v)
+rpc_argdecl dir ifn (RPCArgOut tr (Name n)) = [ C.Param (C.Ptr $ type_c_type ifn tr) n ]
+rpc_argdecl dir ifn (RPCArgOut tr (StringArray n _)) = [ C.Param (type_c_type ifn tr) n ]
+rpc_argdecl dir ifn (RPCArgOut tr (DynamicArray n l _)) =
+    [ C.Param (C.Ptr $ type_c_type ifn tr) n,
       C.Param (C.Ptr $ type_c_type ifn size) l ]
 
 -- XXX: kludge wrapper to pass array types by reference in RPC
-rpc_argdecl2 :: String -> [TypeDef] -> RPCArgument -> [C.Param]
-rpc_argdecl2 ifn typedefs arg@(RPCArgOut tr (Name n))
+rpc_argdecl2 :: Direction -> String -> [TypeDef] -> RPCArgument -> [C.Param]
+rpc_argdecl2 dir ifn typedefs arg@(RPCArgOut tr (Name n))
     = case lookup_typeref typedefs tr of
-      TArray _ _ _ -> [ C.Param (C.Ptr $ C.Ptr $ type_c_type ifn tr) n ]
-      _ -> rpc_argdecl ifn arg
-rpc_argdecl2 ifn _ arg = rpc_argdecl ifn arg
+      TArray _ _ _ -> [ C.Param (type_c_type ifn tr) n ]
+      _ -> rpc_argdecl dir ifn arg
+rpc_argdecl2 dir ifn _ arg = rpc_argdecl dir ifn arg
 
 -- binding parameter for a function
 binding_param ifname = C.Param (C.Ptr $ C.Struct $ intf_bind_type ifname) intf_bind_var
+binding_param2 ifname = C.Param (C.Ptr $ C.Struct $ intf_bind_type ifname) (intf_bind_var ++ "_")
 
 
 --
@@ -244,7 +279,10 @@ binding_struct_init :: String -> String -> C.Expr -> C.Expr ->  C.Expr -> [C.Stm
 binding_struct_init drv ifn binding_var waitset_ex tx_vtbl_ex = [
     C.Ex $ C.Assignment (C.FieldOf binding_var "st") (C.Variable "NULL"),
     C.Ex $ C.Assignment (C.FieldOf binding_var "waitset") waitset_ex,
+    C.Ex $ C.Assignment (C.FieldOf binding_var "send_waitset") (C.Variable "NULL"),
     C.Ex $ C.Call "event_mutex_init" [C.AddressOf $ C.FieldOf binding_var "mutex", waitset_ex],
+    C.Ex $ C.Call "thread_mutex_init" [C.AddressOf $ C.FieldOf binding_var "rxtx_mutex"],
+    C.Ex $ C.Call "thread_mutex_init" [C.AddressOf $ C.FieldOf binding_var "send_mutex"],
     C.Ex $ C.Assignment (C.FieldOf binding_var "can_send")
                                 (C.Variable $ can_send_fn_name drv ifn),
     C.Ex $ C.Assignment (C.FieldOf binding_var "register_send")
@@ -255,6 +293,12 @@ binding_struct_init drv ifn binding_var waitset_ex tx_vtbl_ex = [
     C.Ex $ C.Call "memset" [C.AddressOf $ C.FieldOf binding_var "rx_vtbl",
                             C.NumConstant 0,
                             C.Call "sizeof" [C.FieldOf binding_var "rx_vtbl"]],
+    C.Ex $ C.Call "memset" [C.AddressOf $ C.FieldOf binding_var "message_rx_vtbl",
+                            C.NumConstant 0,
+                            C.Call "sizeof" [C.FieldOf binding_var "message_rx_vtbl"]],
+    C.Ex $ C.Call "memset" [C.AddressOf $ C.FieldOf binding_var "rpc_rx_vtbl",
+                            C.NumConstant 0,
+                            C.Call "sizeof" [C.FieldOf binding_var "rpc_rx_vtbl"]],
     C.Ex $ C.Call "flounder_support_waitset_chanstate_init"
             [C.AddressOf $ C.FieldOf binding_var "register_chanstate"],
     C.Ex $ C.Call "flounder_support_waitset_chanstate_init"
@@ -263,7 +307,8 @@ binding_struct_init drv ifn binding_var waitset_ex tx_vtbl_ex = [
         [C.Ex $ C.Assignment (C.FieldOf binding_var f) (C.NumConstant 0)
          | f <- ["tx_msgnum", "rx_msgnum", "tx_msg_fragment", "rx_msg_fragment",
                  "tx_str_pos", "rx_str_pos", "tx_str_len", "rx_str_len"]],
-    C.Ex $ C.Assignment (C.FieldOf binding_var "bind_cont") (C.Variable "NULL")]
+    C.Ex $ C.Assignment (C.FieldOf binding_var "incoming_token") (C.NumConstant 0),
+    C.Ex $ C.Assignment (C.FieldOf binding_var "outgoing_token") (C.NumConstant 0)]
 
 binding_struct_destroy :: String -> C.Expr -> [C.Stmt]
 binding_struct_destroy ifn binding_var
@@ -337,7 +382,7 @@ register_txcont cont_ex = [
     C.If (C.Binary C.NotEquals (cont_ex `C.FieldOf` "handler") (C.Variable "NULL"))
         [localvar (C.TypeName "errval_t") "_err" Nothing,
          C.Ex $ C.Assignment errvar $ C.Call "flounder_support_register"
-            [bindvar `C.DerefField` "waitset",
+            [C.Variable "send_waitset",
              C.AddressOf $ bindvar `C.DerefField` "tx_cont_chanstate",
              cont_ex,
              C.Variable "false"],
@@ -345,13 +390,31 @@ register_txcont cont_ex = [
          C.If (C.Call "err_is_fail" [errvar])
             [C.If (C.Binary C.Equals (C.Call "err_no" [errvar])
                                      (C.Variable "LIB_ERR_CHAN_ALREADY_REGISTERED"))
-                [C.Return $ C.Variable "FLOUNDER_ERR_TX_BUSY"]
-                [C.Ex $ C.Call "assert" [C.Unary C.Not $ C.StringConstant "shouldn't happen"],
+                [C.Ex $ C.Call "thread_mutex_unlock" [C.AddressOf $ C.DerefField bindvar "send_mutex"],
+                 C.Ex $ C.Call "assert" [C.Binary C.NotEquals (cont_ex `C.FieldOf` "handler") (C.Variable "blocking_cont")],
+                 C.Return $ C.Variable "FLOUNDER_ERR_TX_BUSY"]
+                [C.Ex $ C.Call "thread_mutex_unlock" [C.AddressOf $ C.DerefField bindvar "send_mutex"],
+                 C.Ex $ C.Call "assert" [C.Unary C.Not $ C.StringConstant "shouldn't happen"],
                  C.Return $ errvar] ] []
          ] []
     ] where
         errvar = C.Variable "_err"
 
+block_sending :: C.Expr -> [C.Stmt]
+block_sending cont_ex = [
+    C.If (C.Binary C.Equals (cont_ex `C.FieldOf` "handler") (C.Variable "blocking_cont"))
+        [C.If (C.Binary C.Equals binding_error (C.Variable "SYS_ERR_OK")) [
+            C.Ex $ C.Assignment binding_error $ C.Call "wait_for_channel"
+                [C.Variable "send_waitset", tx_cont_chanstate, C.AddressOf binding_error]
+            ] [
+            C.Ex $ C.Call "flounder_support_deregister_chan" [tx_cont_chanstate]
+            ]
+        ] []
+    ] where
+        errvar = C.Variable "_err"
+        mask = C.CallInd (C.DerefField bindvar "get_receiving_chanstate") [bindvar]
+        tx_cont_chanstate = C.AddressOf $ bindvar `C.DerefField` "tx_cont_chanstate"
+
 -- starting a send: just a debug hook
 start_send :: String -> String -> String -> [MessageArgument] -> [C.Stmt]
 start_send drvn ifn mn msgargs
@@ -384,13 +447,17 @@ start_recv drvn ifn typedefs mn msgargs
         _ -> False
 
 -- finished recv: debug, run handler and clean up
-finished_recv :: String -> String -> [TypeDef] -> String -> [MessageArgument] -> [C.Stmt]
-finished_recv drvn ifn typedefs mn msgargs
-    = [C.Ex $ C.Call "FL_DEBUG" [C.StringConstant $
+finished_recv :: String -> String -> [TypeDef] ->  MessageType -> String -> [MessageArgument] -> [C.Stmt]
+finished_recv drvn ifn typedefs mtype mn msgargs
+    = [ C.Ex $ C.Call "FL_DEBUG" [C.StringConstant $
                                  drvn ++ " RX " ++ ifn ++ "." ++ mn ++ "\n"],
-       C.Ex $ C.Call "assert" [C.Binary C.NotEquals handler (C.Variable "NULL")],
-       C.Ex $ C.CallInd handler (bindvar:args),
-       C.Ex $ C.Assignment rx_msgnum_field (C.NumConstant 0)]
+        C.If (C.Binary C.NotEquals handler (C.Variable "NULL"))
+            [C.Ex $ C.Assignment (C.FieldOf message_chanstate "token") binding_incoming_token,
+             C.Ex $ C.CallInd handler (bindvar:args)]
+            [C.Ex $ C.Assignment (C.FieldOf message_chanstate "token") binding_incoming_token,
+             C.Ex $ C.Call "flounder_support_trigger_chan" [C.AddressOf message_chanstate],
+             C.Ex $ C.Assignment (C.Variable "no_register") (C.NumConstant 1)],
+        C.Ex $ C.Assignment rx_msgnum_field (C.NumConstant 0)]
     where
         rx_msgnum_field = C.DerefField bindvar "rx_msgnum"
         handler = C.DerefField bindvar "rx_vtbl" `C.FieldOf` mn
@@ -398,12 +465,100 @@ finished_recv drvn ifn typedefs mn msgargs
         mkargs tr (Name n) = case lookup_typeref typedefs tr of
           TArray _ _ _ -> [C.DerefPtr $ rx_union_elem mn n]
           _ -> [rx_union_elem mn n]
-        mkargs _ (DynamicArray n l) = [rx_union_elem mn n, rx_union_elem mn l]
+        mkargs _ (StringArray n l) = [rx_union_elem mn n]
+        mkargs _ (DynamicArray n l _) = [rx_union_elem mn n, rx_union_elem mn l]
+        binding_incoming_token = C.DerefField bindvar "incoming_token"
+        message_chanstate = C.SubscriptOf (C.DerefField bindvar "message_chanstate") (C.Variable $ msg_enum_elem_name ifn mn)
+
+finished_recv_nocall :: String -> String -> [TypeDef] ->  MessageType -> String -> [MessageArgument] -> [C.Stmt]
+finished_recv_nocall drvn ifn typedefs mtype mn msgargs
+    = [ C.Ex $ C.Call "FL_DEBUG" [C.StringConstant $
+                                 drvn ++ " RX " ++ ifn ++ "." ++ mn ++ "\n"],
+        C.If (C.Binary C.NotEquals handler (C.Variable "NULL"))
+            [C.Ex $ C.Assignment (C.Variable "call_msgnum") (C.Variable $ msg_enum_elem_name ifn mn)]
+            [C.Ex $ C.Assignment (C.FieldOf message_chanstate "token") binding_incoming_token,
+             C.Ex $ C.Call "flounder_support_trigger_chan" [C.AddressOf message_chanstate],
+             C.Ex $ C.Assignment (C.Variable "no_register") (C.NumConstant 1)],
+        C.Ex $ C.Assignment rx_msgnum_field (C.NumConstant 0)]
+    where
+        rx_msgnum_field = C.DerefField bindvar "rx_msgnum"
+        handler = C.DerefField bindvar "rx_vtbl" `C.FieldOf` mn
+        binding_incoming_token = C.DerefField bindvar "incoming_token"
+        message_chanstate = C.SubscriptOf (C.DerefField bindvar "message_chanstate") (C.Variable $ msg_enum_elem_name ifn mn)
+
+-- call callback, directly from a receiving handler
+call_handler :: String -> String -> [TypeDef] ->  MessageType -> String -> [MessageArgument] -> [C.Stmt]
+call_handler drvn ifn typedefs mtype mn msgargs
+    =   [C.Ex $ C.CallInd handler (bindvar:args)]
+    where
+        handler = C.DerefField bindvar "rx_vtbl" `C.FieldOf` mn
+        args = concat [mkargs tr a | Arg tr a <- msgargs]
+        mkargs tr (Name n) = case lookup_typeref typedefs tr of
+          TArray _ _ _ -> [C.DerefPtr $ rx_union_elem mn n]
+          _ -> [rx_union_elem mn n]
+        mkargs _ (StringArray n l) = [rx_union_elem mn n]
+        mkargs _ (DynamicArray n l _) = [rx_union_elem mn n, rx_union_elem mn l]
+
+-- call callback, from a message handler
+call_message_handler_msgargs :: String -> String -> [TypeDef] -> [MessageArgument] -> [C.Stmt]
+call_message_handler_msgargs ifn mn typedefs msgargs
+        = [C.Ex $ C.CallInd handler (bindvar:args)]
+    where
+        handler = C.DerefField bindvar "message_rx_vtbl" `C.FieldOf` mn
+        args = concat [mkargs a | Arg tr a <- msgargs]
+        mkargs (Name n) = [local_rx_union_elem mn n]
+        mkargs (StringArray n l) = [local_rx_union_elem mn n]
+        mkargs (DynamicArray n l _) = [local_rx_union_elem mn n, local_rx_union_elem mn l]
+
+-- call callback, from a rpc handler
+call_message_handler_rpcargs :: String -> String -> [TypeDef] -> [RPCArgument] -> [C.Stmt]
+call_message_handler_rpcargs ifn mn typedefs msgargs
+        = [C.Ex $ C.Call "assert" [handler],
+        C.Ex $ C.CallInd handler (bindvar:args)]
+    where
+        handler = C.DerefField bindvar "message_rx_vtbl" `C.FieldOf` (rpc_call_name mn)
+        args = concat [mkargs a | RPCArgIn tr a <- msgargs]
+        mkargs (Name n) = [local_rx_union_elem mn n]
+        mkargs (StringArray n l) = [local_rx_union_elem mn n]
+        mkargs (DynamicArray n l _) = [local_rx_union_elem mn n, local_rx_union_elem mn l]
+
+-- call rpc callback
+call_rpc_handler :: String -> String -> [TypeDef] -> [RPCArgument] -> [C.Stmt]
+call_rpc_handler ifn mn typedefs msgargs
+        = [C.Ex $ C.CallInd handler (bindvar:args)]
+    where
+        handler = C.DerefField bindvar "rpc_rx_vtbl" `C.FieldOf` (rpc_call_name mn)
+        args = concat [mkargs a | a <- msgargs]
+        mkargs (RPCArgIn _ (Name n)) = [local_rx_union_elem mn n]
+        mkargs (RPCArgIn _ (StringArray n l)) = [local_rx_union_elem mn n]
+        mkargs (RPCArgIn _ (DynamicArray n l _)) = [local_rx_union_elem mn n, local_rx_union_elem mn l]
+        mkargs (RPCArgOut tr (Name n)) = case lookup_typeref typedefs tr of
+          TArray _ _ _ -> [C.DerefPtr $ local_tx_union_elem mn n]
+          _ -> [C.AddressOf $ local_tx_union_elem mn n]
+        mkargs (RPCArgOut _ (StringArray n l)) = [local_tx_union_elem mn n]
+        mkargs (RPCArgOut _ (DynamicArray n l _)) = [local_tx_union_elem mn n, C.AddressOf $ local_tx_union_elem mn l]
+
+-- send response
+send_response :: String -> String -> [TypeDef] -> [RPCArgument] -> [C.Stmt]
+send_response ifn mn typedefs msgargs
+        = [C.Ex $ C.Call "assert" [handler],
+        C.Ex $ C.Assignment errvar $ C.CallInd handler (bindvar:cont:args),
+        C.Ex $ C.Call "assert" [C.Call "err_is_ok" [errvar]]]
+    where
+        handler = C.DerefField bindvar "tx_vtbl" `C.FieldOf` (rpc_resp_name mn)
+        args = concat [mkargs tr a | RPCArgOut tr a <- msgargs]
+        mkargs tr (Name n) = case lookup_typeref typedefs tr of
+          TArray _ _ _ -> [C.DerefPtr $ local_tx_union_elem mn n]
+          _ -> [local_tx_union_elem mn n]
+        mkargs _ (StringArray n l) = [local_tx_union_elem mn n]
+        mkargs _ (DynamicArray n l _) = [local_tx_union_elem mn n, local_tx_union_elem mn l]
+        cont = C.Variable "BLOCKING_CONT"
 
 tx_arg_assignment :: String -> [TypeDef] -> String -> MessageArgument -> C.Stmt
 tx_arg_assignment ifn typedefs mn (Arg tr v) = case v of
     Name an -> C.Ex $ C.Assignment (tx_union_elem mn an) (srcarg an)
-    DynamicArray an len -> C.StmtList [
+    StringArray an _ -> C.Ex $ C.Assignment (tx_union_elem mn an) ((C.Variable an))
+    DynamicArray an len _ -> C.StmtList [
         C.Ex $ C.Assignment (tx_union_elem mn an) (C.Cast (C.Ptr typespec) (C.Variable an)),
         C.Ex $ C.Assignment (tx_union_elem mn len) (C.Variable len)]
     where
@@ -418,6 +573,70 @@ tx_arg_assignment ifn typedefs mn (Arg tr v) = case v of
               _ -> C.Variable an
 
 
+-- extracts the size of the arguemnts of a message
+extract_msg_size :: MessageArgument -> Integer
+extract_msg_size (Arg tr (Name an)) = 0
+extract_msg_size (Arg tr (StringArray an maxlen)) = maxlen
+extract_msg_size (Arg tr (DynamicArray an len maxlen)) = maxlen
+
+-- extracts the size of the arguemnts of an RPC (in)
+extract_rpc_size_in :: RPCArgument -> Integer
+extract_rpc_size_in (RPCArgIn tr (Name an)) = 0
+extract_rpc_size_in (RPCArgIn tr (StringArray an maxlen)) = maxlen
+extract_rpc_size_in (RPCArgIn tr (DynamicArray an len maxlen)) = maxlen
+
+-- extracts the size of the arguemnts of an RPC (out)
+extract_rpc_size_out :: RPCArgument -> Integer
+extract_rpc_size_out (RPCArgOut tr (Name an)) = 0
+extract_rpc_size_out (RPCArgOut tr (StringArray an maxlen)) = maxlen
+extract_rpc_size_out (RPCArgOut tr (DynamicArray an len maxlen)) = maxlen
+
+-- extract the size of arguemnts
+msg_arg_extract_length :: MessageDef -> Integer
+msg_arg_extract_length (RPC n [] _) = 0
+msg_arg_extract_length (RPC n args _) = maximum [ sum $ [ extract_rpc_size_in arg | arg <- args], sum $ [ extract_rpc_size_out arg | arg <- args]]
+msg_arg_extract_length (Message mtype n [] _) = 0
+msg_arg_extract_length (Message mtype n args _) = sum $ [ extract_msg_size arg | arg <- args]
+
+
+
+-- checks the size of the MSG arguments
+tx_fn_arg_check_size :: String -> [TypeDef] -> String -> MessageArgument -> C.Stmt
+tx_fn_arg_check_size ifn typedefs mn (Arg tr v) = case v of
+    Name an -> C.SComment (an ++ " has a base type. no length check")
+    StringArray an maxlen -> C.StmtList [
+        C.SComment ("checking datalength of " ++ an),
+        C.If (C.Binary C.And (C.Variable an)
+              (C.Binary C.GreaterThanEq (C.Call "strlen" [C.Variable an]) (C.Binary C.Minus (C.NumConstant maxlen) (C.NumConstant 1)))) [
+            C.Return (C.Variable "FLOUNDER_ERR_TX_MSG_SIZE")
+        ] []
+        ]
+    DynamicArray an len maxlen -> C.StmtList [
+        C.SComment ("checking datalength of " ++ an),
+        C.If (C.Binary C.GreaterThanEq (C.Variable len) (C.NumConstant maxlen)) [
+            C.Return (C.Variable "FLOUNDER_ERR_TX_MSG_SIZE")
+        ] []
+        ]
+
+-- checks the size of the RPC arguments
+tx_fn_arg_check_size_rpc :: String -> [TypeDef] -> String -> RPCArgument -> C.Stmt
+tx_fn_arg_check_size_rpc ifn typedefs mn (RPCArgIn tr v) = case v of
+    Name an -> C.SComment (an ++ " has a base type. no length check")
+    StringArray an maxlen -> C.StmtList [
+        C.SComment ("checking datalength of " ++ an),
+        C.If (C.Binary C.GreaterThanEq (C.Call "strlen" [C.Variable an]) (C.Binary C.Minus (C.NumConstant maxlen) (C.NumConstant 1))) [
+            C.Return (C.Variable "FLOUNDER_ERR_TX_MSG_SIZE")
+        ] []
+        ]
+    DynamicArray an len maxlen -> C.StmtList [
+        C.SComment ("checking datalength of " ++ an),
+        C.If (C.Binary C.GreaterThanEq (C.Variable len) (C.NumConstant maxlen)) [
+            C.Return (C.Variable "FLOUNDER_ERR_TX_MSG_SIZE")
+        ] []
+        ]
+tx_fn_arg_check_size_rpc ifn typedefs mn (RPCArgOut tr v) = C.SComment (" Is out arg")
+
+
 tx_union_elem :: String -> String -> C.Expr
 tx_union_elem mn fn
    = bindvar `C.DerefField` "tx_union" `C.FieldOf` mn `C.FieldOf` fn
@@ -426,11 +645,26 @@ rx_union_elem :: String -> String -> C.Expr
 rx_union_elem mn fn
    = bindvar `C.DerefField` "rx_union" `C.FieldOf` mn `C.FieldOf` fn
 
+local_rx_union_elem :: String -> String -> C.Expr
+local_rx_union_elem mn fn
+   = (C.Variable "arguments") `C.FieldOf` fn
+
+local_tx_union_elem :: String -> String -> C.Expr
+local_tx_union_elem mn fn
+   = (C.Variable "result") `C.FieldOf` fn
+
 -- misc common bits of C
 localvar = C.VarDecl C.NoScope C.NonConst
 errvar = C.Variable "err"
 bindvar = C.Variable intf_bind_var
-report_user_err ex = C.Ex $ C.CallInd (C.DerefField bindvar "error_handler") [bindvar, ex]
+binding_error = C.DerefField bindvar "error"
+clear_error = C.Ex $ C.Assignment binding_error (C.Variable "SYS_ERR_OK")
+report_user_err ex = C.StmtList [
+    C.Ex $ C.Assignment (C.DerefField bindvar "error") ex,
+    C.If (C.DerefField bindvar "error_handler") [
+        C.Ex $ C.CallInd (C.DerefField bindvar "error_handler") [bindvar, ex]
+    ] []]
+
 report_user_tx_err ex = C.StmtList [
     report_user_err ex,
     C.Ex $ C.Assignment tx_msgnum_field (C.NumConstant 0),
index e9f4809..5e28366 100644 (file)
@@ -72,7 +72,7 @@ pp_expr (DerefField e s) = (pp_par_expr e) ++ "->" ++ s
 pp_expr (Assignment e1 e2) = (pp_expr e1) ++ " = " ++ (pp_par_expr e2)
 pp_expr (Unary o e) = (pp_unop o) ++ (pp_par_expr e)
 pp_expr (Binary o e1 e2)
-    = (pp_par_expr e1) ++" " ++ (pp_binop o) ++ " "++(pp_par_expr e2)
+    = "(" ++ (pp_par_expr e1) ++" " ++ (pp_binop o) ++ " "++(pp_par_expr e2) ++ ")"
 pp_expr (Ternary e1 e2 e3)
     = (pp_par_expr e1) ++ " ? " ++ (pp_par_expr e2) ++ " : " ++ (pp_par_expr e3)
 pp_expr (FieldOf e s) = (pp_par_expr e) ++ "." ++ s
index 675cda4..47bf7b7 100644 (file)
@@ -1,4 +1,4 @@
-{- 
+{-
    GCBackend: Flounder stub generator for generic code
 
   Part of Flounder: a message passing IDL for Barrelfish
@@ -16,8 +16,9 @@ module GCBackend where
 import Data.Char
 
 import qualified CAbsSyntax as C
-import Syntax (Interface (Interface))
-import GHBackend (flounder_backends, export_fn_name, bind_fn_name, accept_fn_name, connect_fn_name)
+import Syntax (Interface (Interface), MessageDef(Message, RPC), TypeDef, MessageType(MMessage, MCall, MResponse), RPCArgument(RPCArgIn, RPCArgOut))
+import GHBackend (flounder_backends, export_fn_name, bind_fn_name, accept_fn_name, connect_fn_name, connect_handlers_fn_name, disconnect_handlers_fn_name)
+import qualified Backend
 import BackendCommon
 import LMP (lmp_bind_type, lmp_bind_fn_name)
 import qualified UMP (bind_type, bind_fn_name)
@@ -37,7 +38,7 @@ compile infile outfile interface =
     unlines $ C.pp_unit $ stub_body infile interface
 
 stub_body :: String -> Interface -> C.Unit
-stub_body infile (Interface ifn descr _) = C.UnitList [
+stub_body infile (Interface ifn descr decls) = C.UnitList [
     intf_preamble infile ifn descr,
     C.Blank,
 
@@ -62,6 +63,122 @@ stub_body infile (Interface ifn descr _) = C.UnitList [
     connect_fn_def ifn]
 
 
+compile_message_handlers :: String -> String -> Interface -> String
+compile_message_handlers infile outfile interface =
+    unlines $ C.pp_unit $ stub_body_message_handlers infile interface
+
+stub_body_message_handlers :: String -> Interface -> C.Unit
+stub_body_message_handlers infile (Interface ifn descr decls) = C.UnitList [
+    intf_preamble infile ifn descr,
+    C.Blank,
+
+    C.Include C.Standard "barrelfish/barrelfish.h",
+    C.Include C.Standard "flounder/flounder_support.h",
+    C.Include C.Standard ("if/" ++ ifn ++ "_defs.h"),
+    C.Blank,
+
+    C.MultiComment [ "Message handlers" ],
+    C.UnitList [ msg_handler ifn m types | m@(Message MMessage _ _ _) <- messages ],
+    C.UnitList [ msg_handler ifn m types | m@(Message MResponse _ _ _) <- messages ],
+    C.UnitList [ msg_handler ifn m types | m <- rpcs ],
+    C.Blank,
+
+    C.MultiComment [ "Connect handlers function" ],
+    connect_handlers_fn_def ifn messages,
+    C.Blank,
+
+    C.MultiComment [ "Disconnect handlers function" ],
+    disconnect_handlers_fn_def ifn messages,
+    C.Blank]
+
+    where
+        (types, messagedecls) = Backend.partitionTypesMessages decls
+        messages = rpcs_to_msgs messagedecls
+        rpcs = [m | m@(RPC _ _ _) <- messagedecls]
+
+
+msg_handler :: String -> MessageDef -> [TypeDef] -> C.Unit
+msg_handler ifname msg@(Message _ mn args _) types = C.FunctionDef C.Static (C.TypeName "void") name [C.Param (C.Ptr C.Void) "arg"] [
+    localvar (C.Ptr $ C.Struct $ intf_bind_type ifname)
+        intf_bind_var (Just $ C.Variable "arg"),
+    localvar (C.TypeName "errval_t") "err" Nothing,
+    if null args then C.SBlank else localvar (C.Struct $ msg_argstruct_name RX ifname mn) "arguments" (Just (bindvar `C.DerefField` "rx_union" `C.FieldOf` mn)),
+    C.SBlank,
+
+    C.Ex $ C.Assignment errvar $ C.CallInd receive_next [bindvar],
+    C.Ex $ C.Call "assert" [C.Call "err_is_ok" [errvar]],
+    C.StmtList $ call_message_handler_msgargs ifname mn types args
+    ]
+    where
+        name = msg_handler_fn_name ifname msg
+        receive_next = C.DerefField bindvar "receive_next"
+
+msg_handler ifname msg@(RPC mn args a) types = C.FunctionDef C.Static (C.TypeName "void") name [C.Param (C.Ptr C.Void) "arg"] [
+    localvar (C.Ptr $ C.Struct $ intf_bind_type ifname)
+        intf_bind_var (Just $ C.Variable "arg"),
+    localvar (C.TypeName "errval_t") "err" Nothing,
+    if null in_args then C.SBlank else localvar (C.Struct $ msg_argstruct_name RX ifname (rpc_call_name mn)) "arguments" (Just (bindvar `C.DerefField` "rx_union" `C.FieldOf` (rpc_call_name mn))),
+    localvar (C.TypeName "uint32_t") "token" (Just $ binding_incoming_token),
+    C.SBlank,
+
+    C.Ex $ C.Assignment errvar $ C.CallInd receive_next [bindvar],
+    C.Ex $ C.Call "assert" [C.Call "err_is_ok" [errvar]],
+    C.If (rpc_rx_handler) [
+        if null out_args then C.SBlank else localvar (C.Struct $ msg_argstruct_name RX ifname (rpc_resp_name mn)) "result" Nothing,
+        C.StmtList $ call_rpc_handler ifname mn types args,
+        C.Ex $ C.Call "thread_set_outgoing_token" [C.Binary C.BitwiseAnd (C.Variable "token") (C.Variable "~1" )],
+        C.StmtList $ send_response ifname mn types args
+        ] [
+        C.StmtList $ call_message_handler_rpcargs ifname mn types args
+        ]
+    ]
+    where
+        name = msg_handler_fn_name ifname (RPC (rpc_call_name mn) args a)
+        receive_next = C.DerefField bindvar "receive_next"
+        rpc_rx_handler = C.DerefField bindvar "rpc_rx_vtbl" `C.FieldOf` (rpc_call_name mn)
+        in_args = [a | RPCArgIn tr a <- args]
+        out_args = [a | RPCArgOut tr a <- args]
+        tx_handler = C.DerefField bindvar "tx_vtbl" `C.FieldOf` (rpc_resp_name mn)
+        binding_outgoing_token = C.DerefField bindvar "outgoing_token"
+        binding_incoming_token = C.DerefField bindvar "incoming_token"
+
+connect_handlers_fn_def :: String -> [MessageDef] -> C.Unit
+connect_handlers_fn_def n messages =
+    C.FunctionDef C.Static (C.TypeName "errval_t") (connect_handlers_fn_name n)
+        [C.Param (C.Ptr $ C.Struct $ intf_bind_type n) intf_bind_var] [
+        localvar (C.TypeName "errval_t") "err" Nothing,
+
+        C.StmtList [connect_handler n m | m <- messages],
+        C.Return $ C.Variable "SYS_ERR_OK"
+    ]
+
+connect_handler :: String -> MessageDef -> C.Stmt
+connect_handler n msg@(Message _ mn _ _) = C.StmtList [
+    C.Ex $ C.Call "flounder_support_waitset_chanstate_init_persistent" [message_chanstate],
+    C.Ex $ C.Assignment errvar $ C.Call "flounder_support_register" [waitset, message_chanstate, closure, C.Variable "false"],
+    C.Ex $ C.Call "assert" [C.Call "err_is_ok" [errvar]]
+    ]
+    where
+        waitset = bindvar `C.DerefField` "waitset"
+        message_chanstate = C.Binary C.Plus (C.DerefField bindvar "message_chanstate") (C.Variable $ msg_enum_elem_name n mn)
+        closure = C.StructConstant "event_closure"
+           [("handler", C.Variable $ msg_handler_fn_name n msg), ("arg", bindvar)]
+
+disconnect_handlers_fn_def :: String -> [MessageDef] -> C.Unit
+disconnect_handlers_fn_def n messages =
+    C.FunctionDef C.Static (C.TypeName "errval_t") (disconnect_handlers_fn_name n)
+        [C.Param (C.Ptr $ C.Struct $ intf_bind_type n) intf_bind_var] [
+        C.StmtList [disconnect_handler n m | m <- messages],
+        C.Return $ C.Variable "SYS_ERR_OK"
+    ]
+
+disconnect_handler :: String -> MessageDef -> C.Stmt
+disconnect_handler n msg@(Message _ mn _ _) = C.StmtList [
+    C.Ex $ C.Call "flounder_support_deregister_chan" [message_chanstate]
+    ]
+    where
+        message_chanstate = C.Binary C.Plus (C.DerefField bindvar "message_chanstate") (C.Variable $ msg_enum_elem_name n mn)
+
 export_fn_def :: String -> C.Unit
 export_fn_def n =
     C.FunctionDef C.NoScope (C.TypeName "errval_t") (export_fn_name n) params [
@@ -180,6 +297,7 @@ bind_cont_def ifn fn_name backends =
             [C.Ex $ C.Call "assert" [C.Unary C.Not $ C.StringConstant "invalid state"]],
         C.SBlank,
         C.Label "out",
+        C.Ex $ C.Call (connect_handlers_fn_name ifn) [C.Variable intf_bind_var],
         C.Ex $ C.CallInd (C.Cast (C.Ptr $ C.TypeName $ intf_bind_cont_type ifn)
                                 (bindst `C.DerefField` "callback"))
                         [bindst `C.DerefField` "st", errvar, C.Variable intf_bind_var],
index 807b546..d6bfa68 100644 (file)
@@ -1,4 +1,4 @@
-{- 
+{-
    GHBackend: Flounder stub generator for generic header files
 
   Part of Flounder: a message passing IDL for Barrelfish
@@ -27,6 +27,11 @@ connect_fn_name n = ifscope n "connect"
 export_fn_name n = ifscope n "export"
 bind_fn_name n = ifscope n "bind"
 
+connect_handlers_fn_name n = ifscope n "connect_handlers"
+disconnect_handlers_fn_name n = ifscope n "disconnect_handlers"
+
+rpc_rx_vtbl_type ifn = ifscope ifn "rpc_rx_vtbl"
+
 ------------------------------------------------------------------------
 -- Language mapping: Create the generic header file for the interface
 ------------------------------------------------------------------------
@@ -50,11 +55,13 @@ intf_header_body infile interface@(Interface name descr decls) =
     let
         (types, messagedecls) = Backend.partitionTypesMessages decls
         messages = rpcs_to_msgs messagedecls
+        rpcs = [m | m@(RPC _ _ _) <- messagedecls]
     in
       [ intf_preamble infile name descr,
         C.Blank,
 
         C.Include C.Standard "flounder/flounder.h",
+        C.Include C.Standard "flounder/flounder_support.h",
         C.Blank,
 
         C.MultiComment [ "Concrete type definitions" ],
@@ -72,6 +79,8 @@ intf_header_body infile interface@(Interface name descr decls) =
         change_waitset_fn_typedef name,
         control_fn_typedef name,
         error_handler_fn_typedef name,
+        receive_next_fn_typedef name,
+        get_receiving_chanstate_fn_typedef name,
         C.Blank,
 
         C.MultiComment [ "Enumeration for message numbers" ],
@@ -86,12 +95,30 @@ intf_header_body infile interface@(Interface name descr decls) =
         C.UnitList [ msg_signature RX name m | m <- messages ],
         C.Blank,
 
-        C.MultiComment [ "Struct type for holding the args for each msg" ],
-        C.UnitList [ msg_argstruct name types m | m <- messages ],
+        C.MultiComment [ "RPC RX function signatures" ],
+        C.UnitList [ msg_signature_rpc_rx name types (binding_param name) m
+                    | m <- rpcs ],
+        C.Blank,
+
+        C.MultiComment [ "Struct type for holding the RX args for each msg" ],
+        C.UnitList [ msg_argstruct RX name types m | m <- messages ],
+        C.Blank,
+
+        C.MultiComment [ "Struct type for holding the TX args for each msg" ],
+        C.UnitList [ msg_argstruct TX name types m | m <- messages ],
+        C.Blank,
+
+        C.MultiComment [ "Union type for all message arguments" ],
+        intf_union RX name messages,
         C.Blank,
 
         C.MultiComment [ "Union type for all message arguments" ],
-        intf_union name messages,
+        intf_union TX name messages,
+        C.Blank,
+
+        C.MultiComment [ "Maximum Transfer Size" ],
+        msg_arg_sizes name types messages,
+        msg_arg_size name types messages,
         C.Blank,
 
         C.MultiComment [ "VTable struct definition for the interface (transmit)" ],
@@ -102,6 +129,10 @@ intf_header_body infile interface@(Interface name descr decls) =
         intf_vtbl name RX messages,
         C.Blank,
 
+        C.MultiComment [ "VTable struct definition for the rpc interface (receive)" ],
+        rpc_rx_vtbl_decl name rpcs,
+        C.Blank,
+
         C.MultiComment [ "Incoming connect callback type" ],
         connect_callback_fn name,
         C.Blank,
@@ -175,36 +206,80 @@ msg_signature_generic dirn ifname typedefs firstparam m = case dirn of
     params = [ firstparam ] ++ opt_continuation ++ concat payload
     payload = case m of
         Message _ _ args _ -> [ msg_argdecl dirn ifname a | a <- args ]
-        RPC s args _       -> [ rpc_argdecl2 ifname typedefs a | a <- args ]
+        RPC s args _       -> [ rpc_argdecl2 TX ifname typedefs a | a <- args ]
 
 msg_signature :: Direction -> String -> MessageDef -> C.Unit
 msg_signature dir ifn = msg_signature_generic dir ifn [] (binding_param ifn)
 
+msg_signature_rpc_rx :: String -> [TypeDef] -> C.Param -> MessageDef -> C.Unit
+msg_signature_rpc_rx ifname typedefs firstparam m@(RPC s args _) = C.TypeDef (C.Function C.NoScope (C.TypeName "errval_t") params) name
+  where
+    name = msg_sig_type_rpc_rx ifname m
+    params = [ firstparam ] ++ concat payload
+    payload = [rpc_argdecl2 RX ifname typedefs a | a <- args]
+
+rpc_rx_vtbl_decl :: String -> [MessageDef] -> C.Unit
+rpc_rx_vtbl_decl n ml =
+    C.StructDecl (rpc_rx_vtbl_type n) [ param n m | m <- ml ]
+    where
+        param ifn m = C.Param (C.Ptr $ C.TypeName $ msg_sig_type_rpc_rx ifn m) ((msg_name m) ++ "_call")
 
 --
--- Generate a struct to hold the arguments of a message while it's being sent.
+-- Get the maximum size of the arguments
 --
-msg_argstruct :: String -> [TypeDef] -> MessageDef -> C.Unit
-msg_argstruct ifname typedefs m@(RPC n args _) =
-    C.StructDecl (msg_argstruct_name ifname n)
-         (concat [ rpc_argdecl ifname a | a <- args ])
-msg_argstruct ifname typedefs m@(Message _ n [] _) = C.NoOp
-msg_argstruct ifname typedefs m@(Message _ n args _) =
-    let tn = msg_argstruct_name ifname n
-    in
-      C.StructDecl tn (concat [ msg_argstructdecl ifname typedefs a
-                               | a <- args ])
 
+msg_arg_size :: String -> [TypeDef] -> [MessageDef] -> C.Unit
+msg_arg_size ifname typedefs messages = C.Define (msg_arg_size_name ifname) []
+                 (C.pp_expr (C.SizeOfT $ C.Union $ binding_arg_union_type RX ifname))
+
+msg_arg_sizes :: String -> [TypeDef] -> [MessageDef] -> C.Unit
+msg_arg_sizes ifname typedefs messages =
+    C.UnitList [ C.UnitList $ define_msg_arg_size ifname m | m <- messages ]
+
+-- extracts the size of the arguemnts of a message
+define_msg_size :: String -> String-> MessageArgument -> C.Unit
+define_msg_size ifn fn (Arg tr (Name an)) = C.NoOp
+define_msg_size ifn fn (Arg tr (StringArray an maxlen)) = C.Define (arg_size_name ifn fn an) [] (show maxlen)
+define_msg_size ifn fn (Arg tr (DynamicArray an len maxlen)) = C.Define (arg_size_name ifn fn an) [] (show maxlen)
+
+
+-- extracts the size of the arguemnts of an RPC (out)
+define_rpc_size :: String -> String-> RPCArgument -> C.Unit
+define_rpc_size ifn fn (RPCArgOut tr (Name an)) = C.NoOp
+define_rpc_size ifn fn (RPCArgIn _ _) = C.NoOp
+define_rpc_size ifn fn (RPCArgOut tr (StringArray an maxlen)) = C.Define (arg_size_name ifn fn an) [] (show maxlen)
+define_rpc_size ifn fn (RPCArgOut tr (DynamicArray an len maxlen)) = C.Define (arg_size_name ifn fn an) [] (show maxlen)
+
+-- extract the size of arguemnts
+define_msg_arg_size :: String-> MessageDef -> [C.Unit]
+define_msg_arg_size ifn (RPC n [] _) = []
+define_msg_arg_size ifn (RPC n args _) = [define_rpc_size ifn n arg | arg <- args]
+define_msg_arg_size ifn (Message mtype n [] _) = []
+define_msg_arg_size ifn (Message mtype n args _) = [define_msg_size ifn n arg | arg <- args]
+
+
+
+--
+-- Generate a struct to hold the arguments of a message while it's being sent.
+--
+msg_argstruct :: Direction -> String -> [TypeDef] -> MessageDef -> C.Unit
+msg_argstruct dir ifname typedefs m@(RPC n args _) =
+    C.StructDecl (msg_argstruct_name dir ifname n)
+                    (concat [ rpc_argdecl TX ifname a | a <- args ])
+msg_argstruct dir ifname typedefs m@(Message _ n [] _) = C.NoOp
+msg_argstruct dir ifname typedefs m@(Message _ n args _) =
+              C.StructDecl (msg_argstruct_name dir ifname n)
+                    (concat [ msg_argstructdecl dir ifname typedefs a | a <- args ])
 --
 -- Generate a union of all the above
 --
-intf_union :: String -> [MessageDef] -> C.Unit
-intf_union ifn msgs =
-    C.UnionDecl (binding_arg_union_type ifn)
-         ([ C.Param (C.Struct $ msg_argstruct_name ifn n) n
+intf_union :: Direction -> String -> [MessageDef] -> C.Unit
+intf_union dir ifn msgs =
+    C.UnionDecl (binding_arg_union_type dir ifn)
+         ([ C.Param (C.Struct $ msg_argstruct_name dir ifn n) n
             | m@(Message _ n a _) <- msgs, 0 /= length a ]
           ++
-          [ C.Param (C.Struct $ msg_argstruct_name ifn n) n
+          [ C.Param (C.Struct $ msg_argstruct_name dir ifn n) n
             | m@(RPC n a _) <- msgs, 0 /= length a ]
          )
 
@@ -229,7 +304,7 @@ binding_struct n ml = C.StructDecl (intf_bind_type n) fields
         C.Param (C.Ptr C.Void) "st",
         C.ParamBlank,
 
-        C.ParamComment "Waitset used for receive handlers and send continuations",
+        C.ParamComment "Waitset used for receive handlers",
         C.Param (C.Ptr $ C.Struct "waitset") "waitset",
         C.ParamBlank,
 
@@ -261,17 +336,40 @@ binding_struct n ml = C.StructDecl (intf_bind_type n) fields
         C.Param (C.Ptr $ C.TypeName $ error_handler_fn_type n) "error_handler",
         C.ParamBlank,
 
+        C.ParamComment "receive next message",
+        C.Param (C.Ptr $ C.TypeName $ receive_next_fn_type n) "receive_next",
+        C.ParamBlank,
+
+        C.ParamComment "get receiving chanstate",
+        C.Param (C.Ptr $ C.TypeName $ get_receiving_chanstate_fn_type n) "get_receiving_chanstate",
+        C.ParamBlank,
+
         C.ParamComment "Message send functions (filled in by binding)",
         C.Param (C.Struct $ intf_vtbl_type n TX) "tx_vtbl",
         C.ParamBlank,
 
-        C.ParamComment "Incoming message handlers (filled in by user)",
+        C.ParamComment "Incoming message handlers, direct (filled in by user)",
         C.Param (C.Struct $ intf_vtbl_type n RX) "rx_vtbl",
         C.ParamBlank,
 
+        C.ParamComment "Incoming message handlers, indirect (filled in by user)",
+        C.Param (C.Struct $ intf_vtbl_type n RX) "message_rx_vtbl",
+        C.ParamBlank,
+
+        C.ParamComment "Incoming message rpc handlers (filled in by user)",
+        C.Param (C.Struct $ rpc_rx_vtbl_type n) "rpc_rx_vtbl",
+        C.ParamBlank,
+
+        C.ParamComment "Message channels",
+        C.Param (C.Array (toInteger ((length ml) + 3)) (C.Struct "waitset_chanstate")) "message_chanstate",
+
+        C.ParamComment "Waitset used for send continuations",
+        C.Param (C.Ptr $ C.Struct "waitset") "send_waitset",
+        C.ParamBlank,
+
         C.ParamComment "Private state belonging to the binding implementation",
-        C.Param (C.Union $ binding_arg_union_type n) "tx_union",
-        C.Param (C.Union $ binding_arg_union_type n) "rx_union",
+        C.Param (C.Union $ binding_arg_union_type TX n) "tx_union",
+        C.Param (C.Union $ binding_arg_union_type RX n) "rx_union",
         C.Param (C.Struct "waitset_chanstate") "register_chanstate",
         C.Param (C.Struct "waitset_chanstate") "tx_cont_chanstate",
         C.Param (C.Enum $ msg_enum_name n) "tx_msgnum",
@@ -283,7 +381,13 @@ binding_struct n ml = C.StructDecl (intf_bind_type n) fields
         C.Param (C.TypeName "size_t") "tx_str_len",
         C.Param (C.TypeName "size_t") "rx_str_len",
         C.Param (C.Struct "event_queue_node") "event_qnode",
-        C.Param (C.Ptr $ C.TypeName $ intf_bind_cont_type n) "bind_cont"]
+        C.Param (C.Ptr $ C.TypeName $ intf_bind_cont_type n) "bind_cont",
+        C.Param (C.TypeName "uint32_t") "incoming_token",
+        C.Param (C.TypeName "uint32_t") "outgoing_token",
+        C.Param (C.Struct "thread_mutex") "rxtx_mutex",
+        C.Param (C.Struct "thread_mutex") "send_mutex",
+        C.Param (C.TypeName "errval_t") "error"
+        ]
 
 --
 -- Generate the binding structure
@@ -399,6 +503,22 @@ error_handler_fn_typedef n =
       params = [ binding_param n,
                  C.Param (C.TypeName "errval_t") "err" ]
 
+receive_next_fn_typedef :: String -> C.Unit
+receive_next_fn_typedef n =
+    C.TypeDef
+        (C.Function C.NoScope (C.TypeName "errval_t") params)
+        (receive_next_fn_type n)
+    where
+        params = [binding_param n]
+
+get_receiving_chanstate_fn_typedef :: String -> C.Unit
+get_receiving_chanstate_fn_typedef n =
+    C.TypeDef
+        (C.Function C.NoScope (C.Ptr $ C.Struct "waitset_chanstate") params)
+        (get_receiving_chanstate_fn_type n)
+    where
+        params = [binding_param n]
+
 bind_function :: String -> C.Unit
 bind_function n =
     C.GVarDecl C.Extern C.NonConst
@@ -451,7 +571,8 @@ tx_wrapper ifn (Message _ mn args _)
     payload_params = [ msg_argdecl TX ifn a | a <- args ]
     payload_args = map C.Variable $ concat $ map mkargs args
     mkargs (Arg _ (Name an)) = [an]
-    mkargs (Arg _ (DynamicArray an al)) = [an, al]
+    mkargs (Arg _ (StringArray an _)) = [an]
+    mkargs (Arg _ (DynamicArray an al _)) = [an, al]
 
 --
 -- Include the right files for different backends
index 221a788..22818bc 100644 (file)
@@ -1,4 +1,4 @@
-{- 
+{-
    LMP.hs: Flounder stub generator for local message passing.
 
   Part of Flounder: a message passing IDL for Barrelfish
@@ -65,6 +65,8 @@ rx_handler_name ifn = ifscope ifn "lmp_rx_handler"
 -- Names of the control functions
 change_waitset_fn_name ifn = ifscope ifn "lmp_change_waitset"
 control_fn_name ifn = ifscope ifn "lmp_control"
+receive_next_fn_name ifn = ifscope ifn "lmp_receive_next"
+get_receiving_chanstate_fn_name ifn = ifscope ifn "lmp_get_receiving_chanstate"
 
 ------------------------------------------------------------------------
 -- Language mapping: Create the header file for this interconnect driver
@@ -199,6 +201,8 @@ lmp_stub_body arch infile intf@(Interface ifn descr decls) = C.UnitList [
     default_error_handler_fn_def drvname ifn,
     change_waitset_fn_def ifn,
     control_fn_def ifn,
+    receive_next_fn_def ifn,
+    get_receiving_chanstate_fn_def ifn,
 
     C.MultiComment [ "Functions to initialise/destroy the binding state" ],
     lmp_init_fn ifn,
@@ -224,6 +228,8 @@ lmp_init_fn ifn = C.FunctionDef C.NoScope C.Void (lmp_init_fn_name ifn) params [
     C.Ex $ C.Call "lmp_chan_init" [C.AddressOf $ C.DerefField lmp_bind_var "chan"],
     C.Ex $ C.Assignment (common_field "change_waitset") (C.Variable $ change_waitset_fn_name ifn),
     C.Ex $ C.Assignment (common_field "control") (C.Variable $ control_fn_name ifn),
+    C.Ex $ C.Assignment (common_field "receive_next") (C.Variable $ receive_next_fn_name ifn),
+    C.Ex $ C.Assignment (common_field "get_receiving_chanstate") (C.Variable $ get_receiving_chanstate_fn_name ifn),
     C.Ex $ C.Assignment
             (C.DerefField lmp_bind_var "flags")
             (C.Variable "LMP_SEND_FLAGS_DEFAULT") ]
@@ -362,6 +368,9 @@ lmp_connect_handler_fn ifn = C.FunctionDef C.NoScope (C.TypeName "errval_t")
          C.Return $ errvar] [],
     C.SBlank,
 
+    C.Ex $ C.Call (connect_handlers_fn_name ifn) [C.Variable intf_bind_var],
+    C.SBlank,
+
     C.SComment "register for receive",
     C.Ex $ C.Assignment errvar $ C.Call "lmp_chan_register_recv"
         [chanaddr, C.DerefField bindvar "waitset",
@@ -393,6 +402,7 @@ change_waitset_fn_def ifn =
         C.Ex $ C.Call "flounder_support_migrate_notify" [register_chanstate, C.Variable "ws"],
         C.Ex $ C.Call "flounder_support_migrate_notify" [tx_cont_chanstate, C.Variable "ws"],
         C.SBlank,
+        C.Ex $ C.Call (disconnect_handlers_fn_name ifn) [bindvar],
 
         C.SComment "change waitset on binding",
         C.Ex $ C.Assignment
@@ -400,6 +410,8 @@ change_waitset_fn_def ifn =
             (C.Variable "ws"),
         C.SBlank,
 
+        C.Ex $ C.Call (connect_handlers_fn_name ifn) [bindvar],
+
         C.SComment "Migrate send and receive notifications",
         C.Ex $ C.Call "lmp_chan_migrate_recv" [chanaddr, C.Variable "ws"],
         C.Ex $ C.Call "lmp_chan_migrate_send" [chanaddr, C.Variable "ws"],
@@ -432,6 +444,38 @@ control_fn_def ifn =
         params = [C.Param (C.Ptr $ C.Struct $ intf_bind_type ifn) intf_bind_var,
                   C.Param (C.TypeName "idc_control_t") "control"]
 
+receive_next_fn_def :: String -> C.Unit
+receive_next_fn_def ifn =
+    C.FunctionDef C.Static (C.TypeName "errval_t") (receive_next_fn_name ifn) params [
+        localvar (C.TypeName "errval_t") "err" Nothing,
+        localvar (C.Ptr $ C.Struct $ lmp_bind_type ifn)
+            lmp_bind_var_name (Just $ C.Cast (C.Ptr C.Void) $ C.Variable intf_bind_var),
+        localvar (C.Struct "event_closure") "recv_closure"
+            (Just $ C.StructConstant "event_closure" [
+                ("handler", C.Variable $ rx_handler_name ifn),
+                ("arg", C.Variable intf_bind_var)]),
+        C.SBlank,
+        C.SComment "register for another receive notification",
+        C.Ex $ C.Assignment errvar $ C.Call "lmp_chan_register_recv"
+            [chanaddr, C.DerefField bindvar "waitset", C.Variable "recv_closure"],
+        C.Ex $ C.Call "assert" [C.Call "err_is_ok" [errvar]],
+        C.Return $ C.Variable "SYS_ERR_OK"
+    ]
+    where
+        params = [C.Param (C.Ptr $ C.Struct $ intf_bind_type ifn) intf_bind_var]
+        chanaddr = C.AddressOf $ C.DerefField lmp_bind_var "chan"
+
+get_receiving_chanstate_fn_def :: String -> C.Unit
+get_receiving_chanstate_fn_def ifn =
+    C.FunctionDef C.Static (C.Ptr $ C.Struct "waitset_chanstate") (get_receiving_chanstate_fn_name ifn) params [
+        localvar (C.Ptr $ C.Struct $ lmp_bind_type ifn)
+            lmp_bind_var_name (Just $ C.Cast (C.Ptr C.Void) $ C.Variable intf_bind_var),
+        C.SBlank,
+        C.Return $ C.Call "lmp_chan_get_receiving_channel" [C.AddressOf $ C.DerefField lmp_bind_var "chan"]
+    ]
+    where
+        params = [C.Param (C.Ptr $ C.Struct $ intf_bind_type ifn) intf_bind_var]
+
 handler_preamble :: String -> C.Stmt
 handler_preamble ifn = C.StmtList
     [C.SComment "Get the binding state from our argument pointer",
@@ -535,21 +579,29 @@ tx_handler_case arch ifn mn (LMPMsgFragment (OverflowFragment (BufferFragment _
         pos_arg = C.AddressOf $ C.DerefField bindvar "tx_str_pos"
 
 tx_fn :: String -> [TypeDef] -> MessageDef -> C.Unit
-tx_fn ifn typedefs msg@(Message _ n args _) =
+tx_fn ifn typedefs msg@(Message mtype n args _) =
     C.FunctionDef C.Static (C.TypeName "errval_t") (tx_fn_name ifn n) params body
     where
         params = [binding_param ifn, cont_param] ++ (
                     concat [ msg_argdecl TX ifn a | a <- args ])
         cont_param = C.Param (C.Struct "event_closure") intf_cont_var
         body = [
+            -- check size of message
+            C.StmtList [ tx_fn_arg_check_size ifn typedefs n a | a <- args ],
             C.SComment "check that we can accept an outgoing message",
+            C.Ex $ C.Call "thread_mutex_lock" [C.AddressOf $ C.DerefField bindvar "send_mutex"],
+            localvar (C.Ptr $ C.Struct "waitset") "send_waitset" (Just $ C.DerefField bindvar "waitset"),
+            C.Ex $ C.Assignment binding_error (C.Variable "SYS_ERR_OK"),
             C.If (C.Binary C.NotEquals tx_msgnum_field (C.NumConstant 0))
-                [C.Return $ C.Variable "FLOUNDER_ERR_TX_BUSY"] [],
+                [C.Ex $ C.Call "thread_mutex_unlock" [C.AddressOf $ C.DerefField bindvar "send_mutex"],
+                 C.Return $ C.Variable "FLOUNDER_ERR_TX_BUSY"] [],
             C.SBlank,
             C.SComment "register send continuation",
             C.StmtList $ register_txcont (C.Variable intf_cont_var),
             C.SBlank,
             C.SComment "store message number and arguments",
+            C.Ex $ C.Assignment binding_outgoing_token (C.Binary C.BitwiseAnd binding_incoming_token (C.Variable "~1" )),
+            C.Ex $ C.Call "thread_get_outgoing_token" [C.AddressOf binding_outgoing_token],
             C.Ex $ C.Assignment tx_msgnum_field (C.Variable $ msg_enum_elem_name ifn n),
             C.Ex $ C.Assignment tx_msgfrag_field (C.NumConstant 0),
             C.StmtList [ tx_arg_assignment ifn typedefs n a | a <- args ],
@@ -557,11 +609,15 @@ tx_fn ifn typedefs msg@(Message _ n args _) =
             C.SBlank,
             C.SComment "try to send!",
             C.Ex $ C.Call (tx_handler_name ifn n) [C.Variable intf_bind_var],
+            C.StmtList $ block_sending (C.Variable intf_cont_var),
+            C.Ex $ C.Call "thread_mutex_unlock" [C.AddressOf $ C.DerefField bindvar "send_mutex"],
             C.SBlank,
-            C.Return $ C.Variable "SYS_ERR_OK"
+            C.Return binding_error
             ]
         tx_msgnum_field = C.DerefField bindvar "tx_msgnum"
         tx_msgfrag_field = C.DerefField bindvar "tx_msg_fragment"
+        binding_incoming_token = C.DerefField bindvar "incoming_token"
+        binding_outgoing_token = C.DerefField bindvar "outgoing_token"
 
 tx_vtbl :: String -> [MessageDef] -> C.Unit
 tx_vtbl ifn ml =
@@ -575,6 +631,7 @@ rx_handler arch ifn typedefs msgdefs msgs =
         handler_preamble ifn,
         localvar (C.Struct "lmp_recv_msg") "msg" (Just $ C.Variable "LMP_RECV_MSG_INIT"),
         localvar (C.Struct "capref") "cap" Nothing,
+        localvar (C.TypeName "int") "__attribute__ ((unused)) no_register" (Just $ C.NumConstant 0),
 
         -- declare closure for retry
         localvar (C.Struct "event_closure") "recv_closure"
@@ -583,6 +640,8 @@ rx_handler arch ifn typedefs msgdefs msgs =
                 ("arg", C.Variable "arg")]),
         C.SBlank,
 
+        C.If (C.Unary C.Not $ C.Call "lmp_chan_can_recv" [chanaddr]) [C.Goto "out"] [],
+
         C.DoWhile (C.Call "err_is_ok" [errvar]) [
 
         C.SComment "try to retrieve a message from the channel",
@@ -596,7 +655,8 @@ rx_handler arch ifn typedefs msgdefs msgs =
             -- if err_is_fail, check err_no
             [C.If (C.Binary C.Equals (C.Call "err_no" [errvar]) (C.Variable "LIB_ERR_NO_LMP_MSG"))
                 [C.SComment "no message",
-                 C.Break]
+                 C.Ex $ C.Assignment errvar $ C.Variable "SYS_ERR_OK",
+                 C.Continue]
                 [C.SComment "real error",
                  report_user_err $ C.Call "err_push" [errvar, C.Variable "LIB_ERR_LMP_CHAN_RECV"],
                  C.ReturnVoid]
@@ -634,10 +694,12 @@ rx_handler arch ifn typedefs msgdefs msgs =
         ], -- end of the while(1) loop
 
         C.Label "out",
-        C.SComment "re-register for another receive notification",
-        C.Ex $ C.Assignment errvar $ C.Call "lmp_chan_register_recv"
-            [chanaddr, C.DerefField bindvar "waitset", C.Variable "recv_closure"],
-        C.Ex $ C.Call "assert" [C.Call "err_is_ok" [errvar]]
+        C.If (C.Unary C.Not (C.Variable "no_register"))
+            [C.SComment "re-register for another receive notification",
+            C.Ex $ C.Assignment errvar $ C.Call "lmp_chan_register_recv"
+                [chanaddr, C.DerefField bindvar "waitset", C.Variable "recv_closure"],
+            C.Ex $ C.Call "assert" [C.Call "err_is_ok" [errvar]]]
+            []
         ]
     where
         chanaddr = C.AddressOf $ C.DerefField lmp_bind_var "chan"
@@ -647,6 +709,7 @@ rx_handler arch ifn typedefs msgdefs msgs =
         msgnum_bits = bitsizeof_argfieldfrag arch MsgCode
         rx_msgnum_field = C.DerefField bindvar "rx_msgnum"
         rx_msgfrag_field = C.DerefField bindvar "rx_msg_fragment"
+        binding_incoming_token = C.DerefField bindvar "incoming_token"
 
         msgnum_cases = [C.Case (C.Variable $ msg_enum_elem_name ifn mn) (msgnum_case msgdef msg)
                             | (msgdef, msg@(LMPMsgSpec mn _)) <- zip msgdefs msgs]
@@ -703,11 +766,12 @@ rx_handler arch ifn typedefs msgdefs msgs =
                 ],
             C.Break]
             where
-                args = [msg_arg, string_arg, pos_arg, len_arg]
+                args = [msg_arg, string_arg, pos_arg, len_arg, maxsize]
                 msg_arg = C.AddressOf $ C.Variable "msg"
-                string_arg = C.AddressOf $ argfield_expr RX mn af
+                string_arg = argfield_expr RX mn af
                 pos_arg = C.AddressOf $ C.DerefField bindvar "rx_str_pos"
                 len_arg = C.AddressOf $ C.DerefField bindvar "rx_str_len"
+                maxsize = C.SizeOf $ string_arg
 
         msgfrag_case msg@(Message _ mn _ _) (LMPMsgFragment (OverflowFragment (BufferFragment _ afn afl)) _) isLast = [
             C.Ex $ C.Assignment errvar (C.Call "flounder_stub_lmp_recv_buf" args),
@@ -722,11 +786,12 @@ rx_handler arch ifn typedefs msgdefs msgs =
                 ],
             C.Break]
             where
-                args = [msg_arg, buf_arg, len_arg, pos_arg]
+                args = [msg_arg, buf_arg, len_arg, pos_arg, maxsize]
                 msg_arg = C.AddressOf $ C.Variable "msg"
-                buf_arg = C.Cast (C.Ptr $ C.Ptr C.Void) $ C.AddressOf $ argfield_expr RX mn afn
+                buf_arg = C.Cast (C.Ptr C.Void) $ argfield_expr RX mn afn
                 len_arg = C.AddressOf $ argfield_expr RX mn afl
                 pos_arg = C.AddressOf $ C.DerefField bindvar "rx_str_pos"
+                maxsize = C.SizeOf $ argfield_expr RX mn afn
 
         msgfrag_case_prolog :: MessageDef -> Bool -> C.Stmt
         -- intermediate fragment
@@ -734,5 +799,10 @@ rx_handler arch ifn typedefs msgdefs msgs =
             = C.Ex $ C.PostInc $ C.DerefField bindvar "rx_msg_fragment"
 
         -- last fragment: call handler and zero message number
-        msgfrag_case_prolog (Message _ mn msgargs _) True
-            = C.StmtList $ finished_recv drvname ifn typedefs mn msgargs
+        msgfrag_case_prolog (Message mtype mn msgargs _) True
+            = C.StmtList [
+                C.StmtList $ (finished_recv drvname ifn typedefs mtype mn msgargs),
+                                                               C.Goto "out"
+            ]
+            where
+                lmp_chan = C.AddressOf $ C.DerefField lmp_bind_var "chan"
index be847cb..0c0e086 100644 (file)
@@ -1,4 +1,4 @@
-{- 
+{-
    Loopback.hs: Flounder stub generator for dummy loopback stubs
 
   Part of Flounder: a message passing IDL for Barrelfish
@@ -175,9 +175,9 @@ tx_fn ifn msg@(Message _ mn args _) =
             C.Return $ C.Variable "SYS_ERR_OK"
             ]
 
-        arrayargs = [a | a@(Arg _ (DynamicArray _ _)) <- args]
+        arrayargs = [a | a@(Arg _ (DynamicArray _ _ _)) <- args]
 
-        copyarray (Arg tr (DynamicArray n l)) = [
+        copyarray (Arg tr (DynamicArray n l _)) = [
             localvar array_type (array_copy_name n)
                 $ Just $ C.Call "malloc" [size],
             C.If (C.Binary C.Equals copyvar (C.Variable "NULL"))
@@ -191,7 +191,7 @@ tx_fn ifn msg@(Message _ mn args _) =
 
         -- string and array arguments need special treatment
         mkvars (Arg (Builtin String) (Name n)) = [C.Call "strdup" [C.Variable n]]
-        mkvars (Arg _ (DynamicArray n l)) = [C.Variable $ array_copy_name n, C.Variable l]
+        mkvars (Arg _ (DynamicArray n l _)) = [C.Variable $ array_copy_name n, C.Variable l]
         mkvars (Arg _ (Name n)) = [C.Variable n]
 
         array_copy_name n = "_copy_of_" ++ n
index 1610161..dcc3940 100644 (file)
@@ -22,6 +22,7 @@
 > import System.FilePath.Posix
 > import Data.Maybe
 > import Control.Monad
+> import Data.Eq
 
 > import Text.ParserCombinators.Parsec as Parsec
 > import qualified Parser
 
 > data Target = GenericHeader
 >            | GenericCode
+>            | MessageHandlers
 >            | LMP_Header
 >            | LMP_Stub
 >            | UMP_Header
 >            | UMP_Stub
 >            | UMP_IPI_Header
 >            | UMP_IPI_Stub
->           | Multihop_Stub
+>               | Multihop_Stub
 >            | Multihop_Header
 >            | Loopback_Header
 >            | Loopback_Stub
@@ -61,7 +63,7 @@
 >            | THCStubs
 >            | AHCI_Header
 >            | AHCI_Stub
->            deriving (Show)
+>   deriving (Show, Eq)
 
 > data Options = Options {
 >     optTargets :: [Target],
@@ -74,6 +76,7 @@
 > generator :: Options -> Target -> String -> String -> Syntax.Interface -> String
 > generator _ GenericHeader = GHBackend.compile
 > generator _ GenericCode = GCBackend.compile
+> generator _ MessageHandlers = GCBa