kernel: do not drop RAM caps
authorSimon Gerber <simon.gerber@inf.ethz.ch>
Thu, 6 Aug 2015 14:02:42 +0000 (16:02 +0200)
committerSimon Gerber <simon.gerber@inf.ethz.ch>
Thu, 6 Aug 2015 14:05:06 +0000 (16:05 +0200)
When deleting last copy of a RAM-derived cap without going through the monitor
it is possible that the monitor endpoint is already occupied.  If that's the
case we used to just leak the reclaimed RAM cap.  This patch changes the
behaviour in that case to return SYS_ERR_RETRY_THROUGH_MONITOR which then
provides a free slot to put the freshly created RAM cap.

Signed-off-by: Simon Gerber <simon.gerber@inf.ethz.ch>

kernel/cap_delete.c
kernel/dispatch.c
kernel/include/dispatch.h

index 56dfcf2..fd5c11a 100644 (file)
@@ -253,6 +253,16 @@ cleanup_last(struct cte *cte, struct cte *ret_ram_cap)
         }
     }
 
+    // have cap to return to monitor but no allocated slot and no room in
+    // monitor channel; have user retry over monitor rpc interface
+    if (ram.bits > 0 &&
+        !ret_ram_cap &&
+        err_is_fail(lmp_can_deliver_payload(&monitor_ep, len)))
+    {
+        return SYS_ERR_RETRY_THROUGH_MONITOR;
+    }
+
+
     err = cleanup_copy(cte);
     if (err_is_fail(err)) {
         return err;
@@ -279,7 +289,7 @@ cleanup_last(struct cte *cte, struct cte *ret_ram_cap)
             memset(&ramcte, 0, sizeof(ramcte));
             ramcte.cap.u.ram = ram;
             ramcte.cap.type = ObjType_RAM;
-            TRACE_CAP_MSG("reclaimed", ret_ram_cap);
+            TRACE_CAP_MSG("reclaimed", &ramcte);
 #endif
             // XXX: This looks pretty ugly. We need an interface.
             err = lmp_deliver_payload(&monitor_ep, NULL,
index 4b1fb56..c7950d4 100644 (file)
@@ -355,8 +355,8 @@ static errval_t lmp_transfer_cap(struct capability *ep, struct dcb *send,
  * \param ep     Endpoint capability to send to
  * \param payload_len Length (in number of words) of payload
  */
-static errval_t lmp_can_deliver_payload(struct capability *ep,
-                                        size_t payload_len)
+errval_t lmp_can_deliver_payload(struct capability *ep,
+                                 size_t payload_len)
 {
     assert(ep != NULL);
     assert(ep->type == ObjType_EndPoint);
index 361a83c..fbef4ca 100644 (file)
@@ -72,6 +72,8 @@ static inline const char *get_disp_name(struct dcb *dcb)
 extern struct dcb *dcb_current, *fpu_dcb;
 
 void dispatch(struct dcb *dcb) __attribute__ ((noreturn));
+errval_t lmp_can_deliver_payload(struct capability *ep,
+                                 size_t payload_len);
 errval_t lmp_deliver_payload(struct capability *ep, struct dcb *send,
                              uintptr_t *payload, size_t payload_len,
                              bool captransfer);