getaffinity/setaffinity and cpu sets.
    Robert Watson 
    rwatson at FreeBSD.org
       
    Thu Feb 21 09:27:43 UTC 2008
    
    
  
On Wed, 20 Feb 2008, Jeff Roberson wrote:
> I also have a 'cpuset' command which can run a new program with a given cpu 
> set, view and modify sets of arbitrary pids.  This is all working and I can 
> supply patches if anyone is interested.  I have to implement 4BSD support 
> before I can commit.
>
> I have a proposal for solaris style processor sets which I think is simple 
> and sufficient for most cases.  It involves the following new syscalls:
>
> int cpuset(void); int setcpuset(pid_t pid, int setid); int getcpuset(pid_t 
> pid);
>
> The notion would be that you can create a new numbered cpuset with cpuset(). 
> You can modify or inspect its affinity with get/setaffinity above and the 
> CPU_WHICH_SET argument.  The cpuset exists as long as there are members of 
> the set.  Sort of like a process group or session.  The {get,set}cpuset 
> calls can inspect or modify the state.
>
> This set would not be modifiable by user processes or by processes in a 
> jail. It would create the restriction that differs between 'avail' and 'sys' 
> above. Processors would be able to directly bind to any processor within the 
> set. Changing the set would apply to all processes in the set. The cpuset 
> would be per-process while the mask is per-thread.  Sets involvement is 
> inherited on fork().
>
> In solaris sets can be named and have a more complete management api.  I'm 
> not really interested in implementing all of that but I believe what I have 
> outlined here would be subset of this and no code/syscalls would be wasted.
>
> Comments?  Objections?  I'm fairly pleased with this arrangement now.
Just to put a few notes from our conversation on IRC in e-mail:
- I think I'd prefer int cpuset(cpuset_t *set), int getcpuset(pid_t, cpuset_t
   *) so that we don't mix up ID's and return values.  More recent interfaces
   tend to do this, I believe, and it means that the prototype, even if not the
   ABI, remains the same if the set identifier changes in the future.
- You don't mention what happens if a process's cpu set changes to preclude a
   CPU the process has a thread with affinity for.  Online, you suggested
   SIGKILL, and I thought maybe a new SIGCPUGONE with a default SIGKILL action
   might be a friendlier model.  We should see what Solaris and others do here
   though.  I like the idea that the affinity is a guarantee in userspace
   because it means that you can rely on it; I'm OK with the idea that your
   thread always runs on the CPUs you have affinity for unless in the
   SIGCPUGONE handler :-).
- It would be nice to be able to use CPU sets in jail as well, suggesting a
   hierarchal model with some sort of tagging so you know what CPU sets were
   created in a jail such that you know whether they can be changed in a jail.
   While I recognize this makes things a lot more tricky, I think we should
   basically be planning more carefully with respect to virtualization when we
   add new interfaces, since it's a widely used feature, and the current set of
   "stragglers" unsupported in Jail is growing rather than shrinking.
- There's still no way to specify an affinity policy rather than explicit
   affinity, but if our CPU set model is sufficiently general, that might be a
   vehicle to do that.  I.e., cpuset_setpolicy() rather than setting a mask.
- In the interests of boring API changes, recent APIs tend to prefix the
   method on the object name.  Have you thought about cpuset_create(),
   cpuset_foo(), etc?  That reduces the chances of interfering with application
   namespaces.  I think, anyway. :-).
I need to ponder the proposal a little more, ideally over a hot beverage this 
morning, and will follow up if I have further thoughts.  Thanks for working on 
this, BTW -- affinity is well-overdue for FreeBSD.
Robert N M Watson
Computer Laboratory
University of Cambridge
    
    
More information about the freebsd-arch
mailing list