Philippe Berthault | 1 Aug 2006 12:45
Picon

Virtual CPUs functions

Hello,

I'm working on the vpcu patch of Michel Ponceau because he is in 
vacation for a long time.

Michel has proposed to add 3 APIs to libvirt:
  - virDomainSetVcpus
  - virDomainPinVcpu
  - virDomainGetVcpus

I've seen in libvirt mail archives that there was a problem with the 
virDomainGetVcpus API because the virCpuInfo structure contains a CPU 
map for only 256 physical CPUs.

Your proposition to remove cpumap field from virCpuInfo structure and 
add it as parameter to the virDomainGetVcpus API isn't valid for the 
following reason:

The virDomainGetVcpus API fills an array of virCpuInfo structures (one 
virCpuInfo for one VCPU) but cpumap is for one VCPU, not for all VCPUs 
at whole. Your proposition can work only if cpumap is a array of array 
of characters and if maplen is also an array of integers. This is very 
complicated solution and not elegant.

I've also seen that you make a mistake in your proposition because you 
compute the cpuMapLen from the number of virtual CPUs but the cpumap is 
related to physical CPUs, not virtual CPUs.

So, in conclusion, I propose, as you, to remove cpumap field of the 
virCpuInfo structure but to add an API to retrieve the CPU map of one 
(Continue reading)

Daniel Veillard | 1 Aug 2006 14:00
Picon
Favicon
Gravatar

Re: Virtual CPUs functions

On Tue, Aug 01, 2006 at 12:45:18PM +0200, Philippe Berthault wrote:
> Hello,
> 
> I'm working on the vpcu patch of Michel Ponceau because he is in 
> vacation for a long time.
> 
> Michel has proposed to add 3 APIs to libvirt:
>  - virDomainSetVcpus
>  - virDomainPinVcpu
>  - virDomainGetVcpus
> 
> I've seen in libvirt mail archives that there was a problem with the 
> virDomainGetVcpus API because the virCpuInfo structure contains a CPU 
> map for only 256 physical CPUs.

  right

> Your proposition to remove cpumap field from virCpuInfo structure and 
> add it as parameter to the virDomainGetVcpus API isn't valid for the 
> following reason:
> 
> The virDomainGetVcpus API fills an array of virCpuInfo structures (one 
> virCpuInfo for one VCPU) but cpumap is for one VCPU, not for all VCPUs 
> at whole.

  The char * cpumap in the latest proposal is not the same a before.

> Your proposition can work only if cpumap is a array of array 
> of characters

(Continue reading)

Philippe Berthault | 1 Aug 2006 17:06
Picon

Re: Virtual CPU functions

I've tried to illustrate an exemple of virDomainGetVcpus API with a 2 
dimensional cpumaps array.
If you are agree with this, I can modify the patch of Michel Ponceau in 
this sense before the end of this week.

I've proposed the virDomainGetCpus API to be in accordance with the 
virDomainPinVcpu which is per vpcu and not per domain as 
virDomainGetVcpus API.
The virDomainPinVcpu API is'nt symmetrical with virDomainGetVcpus and 
must be called N times to perform the CPU mapping of a domain which 
isn't very satisfying.
Another complaint against the virDomainPinVcpu versus virDomainGetVcpus 
API is that the cpumap parameter hasn't the same meaning in these two 
APIs. This point requires to duplicate macro for bit manipulations on 
these maps.

Philippe Berthault
______________________________________________________________________

virConnectPtr pConn;
virDomainPtr pDomain;
virNodeInfo nodeInfo;
virDomainInfo domInfo;
virVcpuInfoPtr pVcpuInfos;
int nbPhysCpus;
unsigned char *cpuMaps[]; /* 1st dimension = per virtual cpu, 2nd 
dimension = per physical cpu */
int oneCpuMapLen;
int vcpu, cpu;

(Continue reading)

Daniel Veillard | 1 Aug 2006 17:44
Picon
Favicon
Gravatar

Re: Re: Virtual CPU functions

On Tue, Aug 01, 2006 at 05:06:59PM +0200, Philippe Berthault wrote:
> I've tried to illustrate an exemple of virDomainGetVcpus API with a 2 
> dimensional cpumaps array.

  Hum, right, the best is probably to go down to some examples at this
point.

> If you are agree with this, I can modify the patch of Michel Ponceau in 
> this sense before the end of this week.

  That would be good, even though I can't garantee the proposed API won't
change, that would allow more people to work on the code.

> I've proposed the virDomainGetCpus API to be in accordance with the 
> virDomainPinVcpu which is per vpcu and not per domain as 
> virDomainGetVcpus API.

  I wonder how people are most likely to use those APIs. Building scenarios
like:
    - physical CPU is to be locked to serve only VCPU N in domain D
    - domain A and domain B should be served by disjoint physical CPUs sets
    - monitoring 
 are the most common uses I would guess but I may be wrong.
First would require:
    - virDomainPinVcpu I guess
Second would require:
    - virDomainGetCpus and a number of calls to limit to sets :-\
The last one is likely to require getting full maps, and since it is likely 
to be called frequently the cheapest the better

(Continue reading)

Philippe Berthault | 1 Aug 2006 19:05
Picon

Re: Re: Virtual CPU functions

Daniel Veillard a écrit :
On Tue, Aug 01, 2006 at 05:06:59PM +0200, Philippe Berthault wrote:
I've tried to illustrate an exemple of virDomainGetVcpus API with a 2 dimensional cpumaps array.
Hum, right, the best is probably to go down to some examples at this point.
If you are agree with this, I can modify the patch of Michel Ponceau in this sense before the end of this week.
That would be good, even though I can't garantee the proposed API won't change, that would allow more people to work on the code.
I've proposed the virDomainGetCpus API to be in accordance with the virDomainPinVcpu which is per vpcu and not per domain as virDomainGetVcpus API.
I wonder how people are most likely to use those APIs. Building scenarios like: - physical CPU is to be locked to serve only VCPU N in domain D - domain A and domain B should be served by disjoint physical CPUs sets - monitoring are the most common uses I would guess but I may be wrong. First would require: - virDomainPinVcpu I guess Second would require: - virDomainGetCpus and a number of calls to limit to sets :-\ The last one is likely to require getting full maps, and since it is likely to be called frequently the cheapest the better If people who expressed interest on the list about VCPU function could express their principal use case it may help getting the APIs right.
About third point (monitoring): I think the virDomainGetVcpus API isn't adequate for this purpose. It would be better to have an API (to be defined) which give the state of all physical CPUs because it's the hardware resources we need to monitor, not the virtual ones. The virDomainGetVcpus API permits to obtain the relation vcpu->physical_cpu(s) but for monitoring usage, it's not interesting. It would be better to have an API which give the reverse relation : physical_cpu->vpcu(s) independently of domains and give the physical CPU usage. With the virDomainGetVcpus API, it's impossible to determine if a physical cpu is underused or overused and it's this information we need to know for monitoring and for load-balancing.

The virDomainPinVcpu API is'nt symmetrical with virDomainGetVcpus and must be called N times to perform the CPU mapping of a domain which isn't very satisfying. Another complaint against the virDomainPinVcpu versus virDomainGetVcpus API is that the cpumap parameter hasn't the same meaning in these two APIs. This point requires to duplicate macro for bit manipulations on these maps.
Yes those are good points. There is an orthogonality decision on the API, access could be done by VCPU or by CPU, if you provide one at a time kind of accesses and of the wrong kind you may hit API problems really fast.
Philippe Berthault ______________________________________________________________________ virConnectPtr pConn; virDomainPtr pDomain; virNodeInfo nodeInfo; virDomainInfo domInfo; virVcpuInfoPtr pVcpuInfos; int nbPhysCpus; unsigned char *cpuMaps[]; /* 1st dimension = per virtual cpu, 2nd dimension = per physical cpu */ int oneCpuMapLen; int vcpu, cpu; #define CPU_USABLE(maps,vcpu,cpu) (maps[vcpu][((cpu) / 8)] & (1 >> ((cpu) % 8)))
Hum, I don't think the array code is right here, it is basically a one dimention array, so maps[][] won't do what you expect.
... virNodeGetInfo(pConn, &nodeInfo); nbPhysCpus = nodeInfo.cpus; /* ? or ? */ nbPhysCpus = nodeInfo.nodes * nodeInfo.sockets * nodeInfo.cores * nodeInfo.threads; virDomainGetInfo(pDomain, &domInfo); pVcpuInfos = malloc(sizeof(virVcpuInfo)*domInfo.nrVirtCpu); oneCpuMapLen = (nbPhysCpus + 7) / 8; cpuMaps = calloc(domInfo.nrVirtCpu, oneCpuMapLen); virDomainGetVcpus(pDomain, pVcpuInfos, domInfo.nrVirtCpu, cpuMaps, oneCpuMapLen); for (vcpu = 0; vcpu < domInfo.nrVirtCpu; vcpu++) { for (cpu = 0; cpu < nbPhysCpus; cpu++) { int byteCpu = cpu / 8; int bitCpu = cpu % 8; int mask = 1 >> bitCpu; /* lowest CPU number is least significant bit as M.Ponceau said */
int cpuUsable = cpuMaps[vcpu][byteCpu] & mask; ... /* or */ int cpuUsable = CPU_USABLE(cpuMaps, vcpu, cpu); ...
both are wrong IMHO :-) one need to compute the index based on domInfo.nrVirtCpu
I don't understand why you think both are wrong. The first 'for' loop index is based on domInfo.nrVirtCpu.
if (cpuUsable) { printf("The physical cpu #%d is usable by virtual cpu #%d of domain #%s\n", cpu, vcpu, virDomainGetName(pDomain)); } } }
I'm tempted to say: - let's collect use case - post the code you have - distinguish the problem of getting low level access in the library right and getting the API right those are separate thanks, Daniel

<div>
Daniel Veillard a &eacute;crit&nbsp;:
<blockquote cite="mid20060801154428.GB32349 <at> redhat.com" type="cite">
  On Tue, Aug 01, 2006 at 05:06:59PM +0200, Philippe Berthault wrote:

  <blockquote type="cite">
    I've tried to illustrate an exemple of virDomainGetVcpus API with a 2 
dimensional cpumaps array.

  </blockquote>

  Hum, right, the best is probably to go down to some examples at this
point.

  
  <blockquote type="cite">
    If you are agree with this, I can modify the patch of Michel Ponceau in 
this sense before the end of this week.

  </blockquote>

  That would be good, even though I can't garantee the proposed API won't
change, that would allow more people to work on the code.

  
  <blockquote type="cite">
    I've proposed the virDomainGetCpus API to be in accordance with the 
virDomainPinVcpu which is per vpcu and not per domain as 
virDomainGetVcpus API.

  </blockquote>

  I wonder how people are most likely to use those APIs. Building scenarios
like:
    - physical CPU is to be locked to serve only VCPU N in domain D
    - domain A and domain B should be served by disjoint physical CPUs sets
    - monitoring 
 are the most common uses I would guess but I may be wrong.
First would require:
    - virDomainPinVcpu I guess
Second would require:
    - virDomainGetCpus and a number of calls to limit to sets :-\
The last one is likely to require getting full maps, and since it is likely 
to be called frequently the cheapest the better

  If people who expressed interest on the list about VCPU function could
express their principal use case it may help getting the APIs right.

  
</blockquote>
About third point (monitoring): I think the virDomainGetVcpus API isn't
adequate for this purpose. It would be better to have an API (to be
defined) which give the state of all physical CPUs because it's the
hardware resources we need to monitor, not the virtual ones. The
virDomainGetVcpus API permits to obtain the relation
vcpu-&gt;physical_cpu(s) but for monitoring usage, it's not
interesting. It would be better to have an API which give the reverse
relation : physical_cpu-&gt;vpcu(s) independently of domains and give
the physical CPU usage. With the virDomainGetVcpus API, it's impossible
to determine if a physical cpu is underused or overused and it's this
information we need to know for monitoring and for load-balancing.<br><br><blockquote cite="mid20060801154428.GB32349 <at> redhat.com" type="cite">

  <blockquote type="cite">
    The virDomainPinVcpu API is'nt symmetrical with virDomainGetVcpus and 
must be called N times to perform the CPU mapping of a domain which 
isn't very satisfying.
Another complaint against the virDomainPinVcpu versus virDomainGetVcpus 
API is that the cpumap parameter hasn't the same meaning in these two 
APIs. This point requires to duplicate macro for bit manipulations on 
these maps.

  </blockquote>

  Yes those are good points. There is an orthogonality decision on the
API, access could be done by VCPU or by CPU, if you provide one at a time
kind of accesses and of the wrong kind you may hit API problems really fast.

  
  <blockquote type="cite">
    Philippe Berthault
______________________________________________________________________

virConnectPtr pConn;
virDomainPtr pDomain;
virNodeInfo nodeInfo;
virDomainInfo domInfo;
virVcpuInfoPtr pVcpuInfos;
int nbPhysCpus;
unsigned char *cpuMaps[]; /* 1st dimension = per virtual cpu, 2nd 
dimension = per physical cpu */
int oneCpuMapLen;
int vcpu, cpu;

#define CPU_USABLE(maps,vcpu,cpu) (maps[vcpu][((cpu) / 8)] &amp; (1 &gt;&gt; 
((cpu) % 8)))

  </blockquote>

  Hum, I don't think the array code is right here, it is basically a one
dimention array, so maps[][] won't do what you expect.

  
  <blockquote type="cite">
    ...
virNodeGetInfo(pConn, &amp;nodeInfo);

nbPhysCpus = nodeInfo.cpus;
/* ? or ? */
nbPhysCpus = nodeInfo.nodes * nodeInfo.sockets * nodeInfo.cores * 
nodeInfo.threads;

virDomainGetInfo(pDomain, &amp;domInfo);
pVcpuInfos = malloc(sizeof(virVcpuInfo)*domInfo.nrVirtCpu);

oneCpuMapLen = (nbPhysCpus + 7) / 8;
cpuMaps = calloc(domInfo.nrVirtCpu, oneCpuMapLen);

virDomainGetVcpus(pDomain, pVcpuInfos, domInfo.nrVirtCpu, cpuMaps, 
oneCpuMapLen);
for (vcpu = 0; vcpu &lt; domInfo.nrVirtCpu; vcpu++) {
   for (cpu = 0; cpu &lt; nbPhysCpus; cpu++) {
       int byteCpu = cpu / 8;
       int bitCpu = cpu % 8;
       int mask = 1 &gt;&gt; bitCpu; /* lowest CPU number is least 
significant bit as M.Ponceau said */

  </blockquote>

  
  <blockquote type="cite">
           int cpuUsable = cpuMaps[vcpu][byteCpu] &amp; mask;
       ...
       /* or */
       int cpuUsable = CPU_USABLE(cpuMaps, vcpu, cpu);
       ...

  </blockquote>

    both are wrong IMHO :-)
one need to compute the index based on domInfo.nrVirtCpu

  
</blockquote>
I don't understand why you think both are wrong. The first 'for' loop
index is based on domInfo.nrVirtCpu.<br><blockquote cite="mid20060801154428.GB32349 <at> redhat.com" type="cite">

  <blockquote type="cite">
           if (cpuUsable) {
           printf("The physical cpu #%d is usable by virtual cpu #%d of 
domain #%s\n",
                  cpu, vcpu, virDomainGetName(pDomain));
       }
   }
}

  </blockquote>

  I'm tempted to say:
    - let's collect use case
    - post the code you have
    - distinguish the problem of getting low level access in the library right
      and getting the API right those are separate

 thanks,

Daniel

  
</blockquote>
<br>
</div>
Daniel Veillard | 1 Aug 2006 21:29
Picon
Favicon
Gravatar

Re: Re: Virtual CPU functions

On Tue, Aug 01, 2006 at 07:05:49PM +0200, Philippe Berthault wrote:
>>unsigned char *cpuMaps[]; /* 1st dimension = per virtual cpu, 2nd
>>dimension = per physical cpu */
...
> >>virDomainGetVcpus(pDomain, pVcpuInfos, domInfo.nrVirtCpu, cpuMaps, 
> >>oneCpuMapLen);
> >>for (vcpu = 0; vcpu < domInfo.nrVirtCpu; vcpu++) {
> >>   for (cpu = 0; cpu < nbPhysCpus; cpu++) {
> >>       int byteCpu = cpu / 8;
> >>       int bitCpu = cpu % 8;
> >>       int mask = 1 >> bitCpu; /* lowest CPU number is least 
> >>significant bit as M.Ponceau said */
> >>    
> >
> >  
> >>       int cpuUsable = cpuMaps[vcpu][byteCpu] & mask;
> >>       ...
> >>       /* or */
> >>       int cpuUsable = CPU_USABLE(cpuMaps, vcpu, cpu);
> >>       ...
> >>    
> >
> >    both are wrong IMHO :-)
> >one need to compute the index based on domInfo.nrVirtCpu
> >
> >  
> I don't understand why you think both are wrong. The first 'for' loop 
> index is based on domInfo.nrVirtCpu.

  Just a C implem nitpick, but that can lead to interesting debugging
sessions (I think I got beaten by that a couple of time).
  Nowhere the compiler can guess that you're accessing a 2 dimentional array
with a row of length domInfo.nrVirtCpu, it's a one dimension array so I
think cpuMaps[vcpu][byteCpu] is equivalent to cpuMaps[vcpu + byteCpu] there
and unless I misunderstood both case that won't work as expected. This is
also why I suggested a macro this can of code is easy to get wrong.

Daniel

--

-- 
Daniel Veillard      | Red Hat http://redhat.com/
veillard <at> redhat.com  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

Philippe Berthault | 2 Aug 2006 09:48
Picon

Re: Re: Virtual CPU functions


> Just a C implem nitpick, but that can lead to interesting debugging
> sessions (I think I got beaten by that a couple of time).
>   Nowhere the compiler can guess that you're accessing a 2 dimentional array
> with a row of length domInfo.nrVirtCpu, it's a one dimension array so I
> think cpuMaps[vcpu][byteCpu] is equivalent to cpuMaps[vcpu + byteCpu] there
> and unless I misunderstood both case that won't work as expected. This is
> also why I suggested a macro this can of code is easy to get wrong.
>
> Daniel
OK, you are right. ;-)
Thanks.

Daniel Veillard | 2 Aug 2006 10:10
Picon
Favicon
Gravatar

Re: Re: Virtual CPU functions

On Wed, Aug 02, 2006 at 09:48:35AM +0200, Philippe Berthault wrote:
> 
> >Just a C implem nitpick, but that can lead to interesting debugging
> >sessions (I think I got beaten by that a couple of time).
> >  Nowhere the compiler can guess that you're accessing a 2 dimentional 
> >  array
> >with a row of length domInfo.nrVirtCpu, it's a one dimension array so I
> >think cpuMaps[vcpu][byteCpu] is equivalent to cpuMaps[vcpu + byteCpu] there
> >and unless I misunderstood both case that won't work as expected. This is
> >also why I suggested a macro this can of code is easy to get wrong.
> >
> >Daniel
> OK, you are right. ;-)

  That happens, sometimes, when it's clearly not the case don't hesistate
to yell a bit because I can be stubborn :-)

Daniel

--

-- 
Daniel Veillard      | Red Hat http://redhat.com/
veillard <at> redhat.com  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/

Philippe Berthault | 2 Aug 2006 11:47
Picon

New (last ?) virtual cpu functions proposal

Here the new virtual cpu functions proposal.
What do you think about it ?



/**
 * virVcpuInfo: structure for information about a virtual CPU in a domain.
 */
typedef enum {
    VIR_VCPU_OFFLINE    = 0,    /* the virtual CPU is offline */
    VIR_VCPU_RUNNING    = 1,    /* the virtual CPU is running */
    VIR_VCPU_BLOCKED    = 2,    /* the virtual CPU is blocked on resource */
} virVcpuState;

typedef struct _virVcpuInfo virVcpuInfo;
struct _virVcpuInfo {
    unsigned int number;        /* virtual CPU number */
    int state;                  /* value from virVcpuState */
    unsigned long long cpuTime; /* CPU time used, in nanoseconds */
    int cpu;                    /* real CPU number, or -1 if offline */
};
typedef virVcpuInfo *virVcpuInfoPtr;


/**
 * virDomainSetVcpus:
 * <at> domain: pointer to domain object, or NULL for Domain0
 * <at> nvcpus: the new number of virtual CPUs for this domain
 *
 * Dynamically change the number of virtual CPUs used by the domain.
 * Note that this call may fail if the underlying virtualization hypervisor
 * does not support it or if growing the number is arbitrary limited.
 * This function requires priviledged access to the hypervisor.
 *
 * Returns 0 in case of success, -1 in case of failure.
 */
int virDomainSetVcpus   (virDomainPtr domain,
                         unsigned int nvcpus);


/**
 * virDomainPinVcpu:
 * <at> domain: pointer to domain object, or NULL for Domain0
 * <at> vcpu: virtual CPU number
 * <at> cpumap: pointer to a bit map of real CPUs (in 8-bit bytes).
 *      Each bit set to 1 means that corresponding CPU is usable.
 *      Bytes are stored in little-endian order: CPU0-7, 8-15...
 *      In each byte, lowest CPU number is least significant bit.
 * <at> maplen: number of bytes in cpumap, from 1 up to size of CPU map in
 *      underlying virtualization system (Xen...).
 *      If maplen < size, missing bytes are set to zero.
 *      If maplen > size, failure code is returned.
 *
 * Dynamically change the real CPUs which can be allocated to a virtual CPU.
 * This function requires priviledged access to the hypervisor.
 *
 * Returns 0 in case of success, -1 in case of failure.
 */
int virDomainPinVcpu    (virDomainPtr domain,
                         unsigned int vcpu,
                         unsigned char *cpumap,
                         int maplen);

/* Macros for bit manipulation in cpumap */
#define USE_CPU(cpumap,cpu)     (cpumap[(cpu)/8] |=  (1<<((cpu)%8)))
#define UNUSE_CPU(cpumap,cpu)   (cpumap[(cpu)/8] &= ~(1<<((cpu)%8)))


/**
 * virDomainGetVcpus:
 * <at> domain: pointer to domain object, or NULL for Domain0
 * <at> info: pointer to an array of virVcpuInfo structures
 * <at> maxinfo: number of structures in info array
 * <at> cpumaps: pointer to a bit map of real CPUs for all vcpus of this domain.
 *      If cpumaps is NULL, then no cpumap information is returned by the API.
 *      It's assumed there is <maxinfo> cpumap in cpumaps.
 *      The memory allocated to cpumaps must be (maxinfo * maplen) bytes.
 *      One cpumap inside cupmaps have the format described in virDomainPinVcpu API.
 * <at> maplen: number of bytes in one cpumap, from 1 up to size of CPU map in
 *      underlying virtualization system (Xen...).
 *
 * Extract information about virtual CPUs of domain, store it in info array.
 *
 * Returns the number of info filled in case of success, -1 in case of failure.
 */
int virDomainGetVcpus   (virDomainPtr domain,
                         virVcpuInfoPtr info,
                         int maxinfo,
                         unsigned char *cpumaps, /* may be NULL */
                         int maplen);

/* Macros for bit testing in cpumaps */
#define CPU_USABLE(cpumaps,maplen,vcpu,cpu) \
    (cpumaps[((vcpu)*(maplen))+((cpu)/8)] & (1<<((cpu)%8)))

/*
 * Macro for copying the cpumap of a vcpu from cupmaps inside a standalone cpumap.
 * This macro is useful in case of using virDomainPinVcpu() after virDomainGetVcpus().
 * cpumap must be previously allocated.
 */
#define COPY_CPUMAP(cpumaps,maplen,vcpu,cpumap) \
    memcpy(cpumap, &(cpumaps[(vcpu)*(maplen)]), (maplen))

<div>
Here the new virtual cpu functions proposal.<br>
What do you think about it ?<br><br><br><br>/**≤br>
&nbsp;* virVcpuInfo: structure for information about a virtual CPU
in a domain.<br>
&nbsp;*/<br>
typedef enum {<br>
&nbsp;&nbsp;&nbsp; VIR_VCPU_OFFLINE&nbsp;&nbsp;&nbsp; = 0,&nbsp;&nbsp;&nbsp; /* the virtual
CPU is offline */<br>
&nbsp;&nbsp;&nbsp; VIR_VCPU_RUNNING&nbsp;&nbsp;&nbsp; = 1,&nbsp;&nbsp;&nbsp; /* the virtual
CPU is running */<br>
&nbsp;&nbsp;&nbsp; VIR_VCPU_BLOCKED&nbsp;&nbsp;&nbsp; = 2,&nbsp;&nbsp;&nbsp; /* the virtual
CPU is blocked on resource */<br>} virVcpuState;<br><br>
typedef struct _virVcpuInfo virVcpuInfo;<br>
struct _virVcpuInfo {<br>
&nbsp;&nbsp;&nbsp; unsigned int number;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* virtual CPU
number */<br>
&nbsp;&nbsp;&nbsp; int state;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* value from
virVcpuState */<br>
&nbsp;&nbsp;&nbsp; unsigned long long cpuTime; /* CPU time
used, in nanoseconds */<br>
&nbsp;&nbsp;&nbsp; int cpu;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* real CPU
number, or -1 if offline */<br>
};<br>
typedef virVcpuInfo *virVcpuInfoPtr;<br><br><br>/**≤br>
&nbsp;* virDomainSetVcpus:<br>
&nbsp;*  <at> domain: pointer to domain object, or NULL for Domain0<br>
&nbsp;*  <at> nvcpus: the new number of virtual CPUs for this domain<br>
&nbsp;*<br>
&nbsp;* Dynamically change the number of virtual CPUs used by the domain.<br>
&nbsp;* Note that this call may fail if the underlying virtualization
hypervisor<br>
&nbsp;* does not support it or if growing the number is arbitrary limited.<br>
&nbsp;* This function requires priviledged access to the hypervisor.<br>
&nbsp;*<br>
&nbsp;* Returns 0 in case of success, -1 in case of failure.<br>
&nbsp;*/<br>
int virDomainSetVcpus&nbsp;&nbsp; (virDomainPtr domain,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int nvcpus);<br><br><br>/**≤br>
&nbsp;* virDomainPinVcpu:<br>
&nbsp;*  <at> domain: pointer to domain object, or NULL for Domain0<br>
&nbsp;*  <at> vcpu: virtual CPU number<br>
&nbsp;*  <at> cpumap: pointer to a bit map of real CPUs (in 8-bit bytes).<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Each bit set to 1 means that corresponding CPU is usable.<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bytes are stored in little-endian order: CPU0-7, 8-15...<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In each byte, lowest CPU number is least significant bit.<br>
&nbsp;*  <at> maplen: number of bytes in cpumap, from 1 up to size of CPU
map in<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; underlying virtualization system (Xen...).<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If maplen &lt; size, missing bytes are set to zero.<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If maplen &gt; size, failure code is returned.<br>
&nbsp;*<br>
&nbsp;* Dynamically change the real CPUs which can be allocated to a virtual
CPU.<br>
&nbsp;* This function requires priviledged access to the hypervisor.<br>
&nbsp;*<br>
&nbsp;* Returns 0 in case of success, -1 in case of failure.<br>
&nbsp;*/<br>
int virDomainPinVcpu&nbsp;&nbsp;&nbsp; (virDomainPtr domain,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int vcpu,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned char *cpumap,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int maplen);<br><br>/* Macros for bit manipulation in cpumap */<br>
#define USE_CPU(cpumap,cpu)&nbsp;&nbsp;&nbsp;&nbsp; (cpumap[(cpu)/8] |=&nbsp;
(1&lt;&lt;((cpu)%8)))<br>
#define UNUSE_CPU(cpumap,cpu)&nbsp;&nbsp; (cpumap[(cpu)/8] &amp;=
~(1&lt;&lt;((cpu)%8)))<br><br><br>/**≤br>
&nbsp;* virDomainGetVcpus:<br>
&nbsp;*  <at> domain: pointer to domain object, or NULL for Domain0<br>
&nbsp;*  <at> info: pointer to an array of virVcpuInfo structures<br>
&nbsp;*  <at> maxinfo: number of structures in info array<br>
&nbsp;*  <at> cpumaps: pointer to a bit map of real CPUs for all vcpus of
this domain.<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If cpumaps is NULL, then no cpumap information is returned by
the API.<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; It's assumed there is &lt;maxinfo&gt; cpumap in cpumaps.<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The memory allocated to cpumaps must be (maxinfo * maplen)
bytes.<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; One cpumap inside cupmaps have the format described in
virDomainPinVcpu API.<br>
&nbsp;*  <at> maplen: number of bytes in one cpumap, from 1 up to size of
CPU map in<br>
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; underlying virtualization system (Xen...).<br>
&nbsp;*<br>
&nbsp;* Extract information about virtual CPUs of domain, store it in info
array.<br>
&nbsp;*<br>
&nbsp;* Returns the number of info filled in case of success, -1 in case of
failure.<br>
&nbsp;*/<br>
int virDomainGetVcpus&nbsp;&nbsp; (virDomainPtr domain,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virVcpuInfoPtr info,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int maxinfo,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned char *cpumaps,
/* may be NULL */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int maplen);<br><br>/* Macros for bit testing in cpumaps */<br>
#define CPU_USABLE(cpumaps,maplen,vcpu,cpu) \<br>
&nbsp;&nbsp;&nbsp; (cpumaps[((vcpu)*(maplen))+((cpu)/8)] &amp; (1&lt;&lt;((cpu)%8)))<br><br>
/*<br>
&nbsp;* Macro for copying the cpumap of a vcpu from cupmaps inside a
standalone cpumap.<br>
&nbsp;* This macro is useful in case of using virDomainPinVcpu() after
virDomainGetVcpus().<br>
&nbsp;* cpumap must be previously allocated.<br>
&nbsp;*/<br>
#define COPY_CPUMAP(cpumaps,maplen,vcpu,cpumap) \<br>
&nbsp;&nbsp;&nbsp; memcpy(cpumap, &amp;(cpumaps[(vcpu)*(maplen)]), (maplen))<br><br>
</div>
Daniel Veillard | 2 Aug 2006 13:13
Picon
Favicon
Gravatar

Re: New (last ?) virtual cpu functions proposal

On Wed, Aug 02, 2006 at 11:47:14AM +0200, Philippe Berthault wrote:
> Here the new virtual cpu functions proposal.
> What do you think about it ?
> 

  looks fine to me, except for some extra '*' showing up around identifiers :-)
I would just add documentations for the parameters of the macros in the final
version but it's a detail.

  thanks !

Daniel

> 
> /**
> * *virVcpuInfo*: structure for information about a virtual CPU in a domain.
> */
> typedef enum {
>    VIR_VCPU_OFFLINE    = 0,    /* the virtual CPU is offline */
>    VIR_VCPU_RUNNING    = 1,    /* the virtual CPU is running */
>    VIR_VCPU_BLOCKED    = 2,    /* the virtual CPU is blocked on resource */
> *} virVcpuState*;
> 
> typedef struct _virVcpuInfo virVcpuInfo;
> struct _virVcpuInfo {
>    unsigned int number;        /* virtual CPU number */
>    int state;                  /* value from virVcpuState */
>    unsigned long long cpuTime; /* CPU time used, in nanoseconds */
>    int cpu;                    /* real CPU number, or -1 if offline */
> };
> typedef virVcpuInfo **virVcpuInfoPtr*;
> 
> 
> /**
> * *virDomainSetVcpus*:
> *  <at> *domain*: pointer to domain object, or NULL for Domain0
> *  <at> *nvcpus*: the new number of virtual CPUs for this domain
> *
> * Dynamically change the number of virtual CPUs used by the domain.
> * Note that this call may fail if the underlying virtualization hypervisor
> * does not support it or if growing the number is arbitrary limited.
> * This function requires priviledged access to the hypervisor.
> *
> * Returns 0 in case of success, -1 in case of failure.
> */
> int *virDomainSetVcpus*   (virDomainPtr domain,
>                         unsigned int nvcpus);
> 
> 
> /**
> * *virDomainPinVcpu*:
> *  <at> *domain*: pointer to domain object, or NULL for Domain0
> *  <at> *vcpu*: virtual CPU number
> *  <at> *cpumap*: pointer to a bit map of real CPUs (in 8-bit bytes).
> *      Each bit set to 1 means that corresponding CPU is usable.
> *      Bytes are stored in little-endian order: CPU0-7, 8-15...
> *      In each byte, lowest CPU number is least significant bit.
> *  <at> *maplen*: number of bytes in cpumap, from 1 up to size of CPU map in
> *      underlying virtualization system (Xen...).
> *      If maplen < size, missing bytes are set to zero.
> *      If maplen > size, failure code is returned.
> *
> * Dynamically change the real CPUs which can be allocated to a virtual CPU.
> * This function requires priviledged access to the hypervisor.
> *
> * Returns 0 in case of success, -1 in case of failure.
> */
> int *virDomainPinVcpu*    (virDomainPtr domain,
>                         unsigned int vcpu,
>                         unsigned char *cpumap,
>                         int maplen);
> 
> /* Macros for bit manipulation in cpumap */
> #define *USE_CPU*(cpumap,cpu)     (cpumap[(cpu)/8] |=  (1<<((cpu)%8)))
> #define *UNUSE_CPU*(cpumap,cpu)   (cpumap[(cpu)/8] &= ~(1<<((cpu)%8)))
> 
> 
> /**
> * *virDomainGetVcpus*:
> *  <at> *domain*: pointer to domain object, or NULL for Domain0
> *  <at> *info*: pointer to an array of virVcpuInfo structures
> *  <at> *maxinfo*: number of structures in info array
> *  <at> *cpumaps*: pointer to a bit map of real CPUs for all vcpus of this 
> domain.
> *      If cpumaps is NULL, then no cpumap information is returned by 
> the API.
> *      It's assumed there is <maxinfo> cpumap in cpumaps.
> *      The memory allocated to cpumaps must be (maxinfo * maplen) bytes.
> *      One cpumap inside cupmaps have the format described in 
> virDomainPinVcpu API.
> *  <at> *maplen*: number of bytes in one cpumap, from 1 up to size of CPU map in
> *      underlying virtualization system (Xen...).
> *
> * Extract information about virtual CPUs of domain, store it in info array.
> *
> * Returns the number of info filled in case of success, -1 in case of 
> failure.
> */
> int *virDomainGetVcpus*   (virDomainPtr domain,
>                         virVcpuInfoPtr info,
>                         int maxinfo,
>                         unsigned char *cpumaps, /* may be NULL */
>                         int maplen);
> 
> /* Macros for bit testing in cpumaps */
> #define *CPU_USABLE*(cpumaps,maplen,vcpu,cpu) \
>    (cpumaps[((vcpu)*(maplen))+((cpu)/8)] & (1<<((cpu)%8)))
> 
> /*
> * Macro for copying the cpumap of a vcpu from cupmaps inside a 
> standalone cpumap.
> * This macro is useful in case of using virDomainPinVcpu() after 
> virDomainGetVcpus().
> * cpumap must be previously allocated.
> */
> #define *COPY_CPUMAP*(cpumaps,maplen,vcpu,cpumap) \
>    memcpy(cpumap, &(cpumaps[(vcpu)*(maplen)]), (maplen))
> 

> --
> Libvir-list mailing list
> Libvir-list <at> redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list

--

-- 
Daniel Veillard      | Red Hat http://redhat.com/
veillard <at> redhat.com  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/


Gmane