Port changes to release branch
[util-vserver.git] / lib / planetlab.c
index 034c249..879cb5d 100644 (file)
@@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include <errno.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <unistd.h>
 #include <sys/resource.h>
 
@@ -47,14 +48,16 @@ create_context(xid_t ctx, uint32_t flags, uint64_t bcaps, const rspec_t *rspec)
 {
   struct vc_ctx_caps  vc_caps;
   struct vc_ctx_flags  vc_flags;
-  struct vc_set_sched  vc_sched;
   struct vc_rlimit  vc_rlimit;
 
-  /* create context info */
+  /*
+   * Create context info - this sets the STATE_SETUP and STATE_INIT flags.
+   * Don't ever clear the STATE_INIT flag, that makes us the init task.
+   */
   if (vc_ctx_create(ctx) == VC_NOCTX)
     return -1;
 
-  /* set capabilities - these don't take effect until SETUP flags is unset */
+  /* set capabilities - these don't take effect until SETUP flag is unset */
   vc_caps.bcaps = bcaps;
   vc_caps.bmask = ~0ULL;  /* currently unused */
   vc_caps.ccaps = 0;      /* don't want any of these */
@@ -62,21 +65,8 @@ create_context(xid_t ctx, uint32_t flags, uint64_t bcaps, const rspec_t *rspec)
   if (vc_set_ccaps(ctx, &vc_caps))
     return -1;
 
-  /* ignore all flags except SETUP and scheduler flags */
-  vc_flags.mask = VC_VXF_STATE_SETUP | VC_VXF_SCHED_FLAGS;
-  /* don't let user change scheduler flags */
-  vc_flags.flagword = flags & ~VC_VXF_SCHED_FLAGS;  /* SETUP not set */
-
   /* set scheduler parameters */
-  vc_flags.flagword |= rspec->cpu_sched_flags;
-  vc_sched.set_mask = (VC_VXSM_FILL_RATE | VC_VXSM_INTERVAL | VC_VXSM_TOKENS |
-                      VC_VXSM_TOKENS_MIN | VC_VXSM_TOKENS_MAX);
-  vc_sched.fill_rate = rspec->cpu_share;  /* tokens accumulated per interval */
-  vc_sched.interval = 1000;  /* milliseconds */
-  vc_sched.tokens = 100;     /* initial allocation of tokens */
-  vc_sched.tokens_min = 50;  /* need this many tokens to run */
-  vc_sched.tokens_max = 100;  /* max accumulated number of tokens */
-  if (vc_set_sched(ctx, &vc_sched))
+  if (pl_setsched(ctx, rspec->cpu_share, rspec->cpu_sched_flags))
     return -1;
 
   /* set resource limits */
@@ -92,6 +82,9 @@ create_context(xid_t ctx, uint32_t flags, uint64_t bcaps, const rspec_t *rspec)
     return -1;
 
   /* set flags, unset SETUP flag - this allows other processes to migrate */
+  vc_flags.mask = VC_VXF_STATE_SETUP | VC_VXF_SCHED_FLAGS;
+  flags = 0;  /* XXX - ignore flags parameter */
+  vc_flags.flagword = flags | rspec->cpu_sched_flags;  /* SETUP cleared */
   if (vc_set_cflags(ctx, &vc_flags))
     return -1;
 
@@ -141,3 +134,49 @@ pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps, const rspec_t *rspec)
 
   return 0;
 }
+
+/* it's okay for a syscall to fail because the context doesn't exist */
+#define VC_SYSCALL(x)                          \
+do                                             \
+{                                              \
+  if (x)                                       \
+    return errno == ESRCH ? 0 : -1;            \
+}                                              \
+while (0)
+
+
+int
+pl_setsched(xid_t ctx, uint32_t cpu_share, uint32_t cpu_sched_flags)
+{
+  struct vc_set_sched  vc_sched;
+  struct vc_ctx_flags  vc_flags;
+
+  if (cpu_sched_flags & ~VC_VXF_SCHED_FLAGS)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  vc_sched.set_mask = (VC_VXSM_FILL_RATE | VC_VXSM_INTERVAL | VC_VXSM_TOKENS |
+                      VC_VXSM_TOKENS_MIN | VC_VXSM_TOKENS_MAX);
+  vc_sched.fill_rate = cpu_share;  /* tokens accumulated per interval */
+  vc_sched.interval = 1000;  /* milliseconds */
+  vc_sched.tokens = 100;     /* initial allocation of tokens */
+  vc_sched.tokens_min = 50;  /* need this many tokens to run */
+  vc_sched.tokens_max = 100;  /* max accumulated number of tokens */
+
+  VC_SYSCALL(vc_set_sched(ctx, &vc_sched));
+
+  /* get current flag values */
+  VC_SYSCALL(vc_get_cflags(ctx, &vc_flags));
+
+  /* the only flag which ever changes is the SCHED_SHARE bit */
+  if ((vc_flags.flagword ^ cpu_sched_flags) & VC_VXF_SCHED_SHARE)
+    {
+      vc_flags.mask = VC_VXF_SCHED_SHARE;
+      vc_flags.flagword = cpu_sched_flags & VC_VXF_SCHED_FLAGS;
+      VC_SYSCALL(vc_set_cflags(ctx, &vc_flags));
+    }
+
+  return 0;
+}