Hi,
As a toy exercise I'm trying to write a very simple custom pager which simply allocates memory from RAM to handle page faults.  When I try to handle the fault I get a region conflict exception.  Can someone tell me why??  I think I am missing something fundamental here.

Thanks
Daniel

----

#include <base/printf.h>
#include <base/sleep.h>
#include <base/rpc_server.h>
#include <cap_session/connection.h>
#include <dataspace/client.h>
#include <rom_session/connection.h>
#include <rm_session/connection.h>
#include <ram_session/connection.h>
#include <root/component.h>
#include <util/avl_string.h>
#include <util/misc_math.h>
#include <assert.h>

#define PAGE_SIZE 4096

using namespace Genode;

namespace Test
{

  /**
   * Example pager class
   *
   * @return
   */
  class Pager : public Thread<8192>
    {
  private:

    Signal_receiver _receiver;

  public:

    Signal_receiver *signal_receiver() { return &_receiver; }
   
    void entry();
    };

  /**
   * Example backing store class - this one uses physical memory
   *
   */
  class Physical_backing_store : public Signal_context
  {
  private:
    Rm_connection _rm;
    size_t _size;

  public:
    // ctor
    Physical_backing_store(size_t size): _rm(0,_size) {
      _size = size;
      assert(_size > 0);
    }

    virtual ~Physical_backing_store() {
    }

    /**
     * Page fault handler.
     *
     */
    void handle_fault()
    {
      Rm_session::State state = _rm.state();

      printf("Test::Physical_backing_store:: rm session state is %s, pf_addr=0x%lx\n",
             state.type == Rm_session::READ_FAULT  ? "READ_FAULT"  :
             state.type == Rm_session::WRITE_FAULT ? "WRITE_FAULT" :
             state.type == Rm_session::EXEC_FAULT  ? "EXEC_FAULT"  : "READY",
             state.addr);

      if (state.type == Rm_session::READY)
        return;
     
      try {

        Dataspace_capability _ds;
        try {
          _ds = env()->ram_session()->alloc(PAGE_SIZE);
        }
        catch(...) { PERR("Actual page allocation failed.\n"); }

        _rm.attach_at(_ds, state.addr & ~(PAGE_SIZE - 1));

        PDBG("attached data space OK!\n");
      }
      catch (Genode::Rm_session::Region_conflict) {
        PERR("Region conflict - this should not happen\n");
      }
      catch (Genode::Rm_session::Out_of_metadata) {
        PERR("Out of meta data!\n");
      }
      catch(...) {
        PERR("Something else caused attach to fail in fault handler.\n");
      }

      return;
    }
   
    Rm_connection *rm() { return &_rm; }
    Dataspace_capability ds() { return _rm.dataspace(); }

        void connect_pager(Pager& _pager) {
      /* connect pager signal receiver to the fault handler */
      _rm.fault_handler(_pager.signal_receiver()->manage(this));
    }

  };


  /**
   * Entry point for pager thread.
   *
   */
  void Pager::entry()
  {
    printf("Pager thread started OK.\n");

    while (true) {
      try {
        Signal signal = _receiver.wait_for_signal();

        for (int i = 0; i < signal.num(); i++) {
          static_cast<Physical_backing_store *>(signal.context())->handle_fault();
        }
      } catch (...) {
        PDBG("unexpected error while waiting for signal");
      }
    }
  }


}

int main()
{
  Genode::printf("Test-pager example. ;-))\n");

  Test::Pager _pager;

  /* start pager thread */
  _pager.start();

  /* create dataspace etc. */
  try {

    enum { MANAGED_DS_SIZE = 64*1024*1024 };
    Test::Physical_backing_store bs(MANAGED_DS_SIZE);

    /* connect pager to fault handler */
    bs.connect_pager(_pager);

    /* attach to dataspace */
    char * addr = (char*) env()->rm_session()->attach(bs.ds());
    assert(addr);

    /* trigger read fault */
    printf("!!!Triggering fault...\n");
    printf("%c%c%c\n",addr[0],addr[1],addr[2]);
         
    printf("Fault handled OK.\n");

  }
  catch(...) {
    PERR("Something failed ????.\n");
  }

  printf("test-pager completed.\n");
  Genode::sleep_forever();
  return 0;
}