* perfmon3 interface overview [not found] <7c86c4470809231432j4231cfa4g7dd158a7fe9c9277@mail.gmail.com> @ 2008-09-25 21:48 ` stephane eranian 2008-10-03 6:17 ` David Gibson 2008-10-03 14:44 ` stephane eranian 1 sibling, 1 reply; 15+ messages in thread From: stephane eranian @ 2008-09-25 21:48 UTC (permalink / raw) To: linux-kernel Hello, A few months ago, I started posting on this list a highly simplified version of the perfmon2 version which was providing only per-thread counting on X86 processors. The feedback I got was generally positive but people raised two more issues: - too many system calls for a single subsystem (12 calls) - how to ensure syscalls could be extended without necessarily adding new ones. Since then, I have been working hard on addressing those two issues, in other words redesign of the perfmon2 syscall API. This message is to announce that I now have a new proposal for the API. As expected it is called perfmon3 and it addresses the two issues above while allowing backward compatibility with the existing v2.81 version through a user level glue layer which could be implemented by a library such as libpfm. The new API now has 8 system calls in its fully-featured version. Many data structures shared with user level have been abandoned in favor of explicit syscall parameters. Each syscall has a flags parameters which allows the syscalls to be extended with new parameters when we need them. Most structures passed to the kernel have reserved fields for future extensions. The initial patchset will only support per-thread counting as I did previously. However, here I am presenting the details for the fully featured version so people can get a feel for it. For each call I show the old way and the new way. Note that when the syscall is shown twice with a different number of parameters, this variation is handled by the user library. The kernel implements the full call. This is the same technique used for the open(2) syscall. I) session creation With v2.81: int pfm_create_context(pfarg_ctx_t *ctx, char *smpl_name, void *smpl_arg, size_t smpl_size); With v3.0: int pfm_create_session(int flags); int pfm_create_session(int flags, char *smpl_name, void *smpl_arg, size_t smpl_size); New Flags: PFM_FL_SMPL_FMT : indicate using sampling format and that 3 additional parameters are passed The pfarg_ctx_t structure has been abandoned. The flags parameter is used very much like for the open(2) syscall to indicate that additional (optional) parameters are passed. All v2.81 flags are preserved. The call still returns the file descriptor uniquely identifying the session. Just like with context, a session can either be monitoring a thread or a CPU. II) programming the registers With v2.81: int pfm_write_pmcs(int fd, pfarg_pmc_t *pmds, int n); int pfm_write_pmds(int fd, pfarg_pmd_t *pmcs, int n); int pfm_read_pmds(int fd, parg_pmd_t *pmds, int n); With v3.0: int pfm_write_pmrs(int fd, int flags, pfarg_pmr_t *pmrs, int n); int pfm_write_pmrs(int fd, int flags, pfarg_pmr_t *pmrs, int n, pfarg_pmd_attr_t *pmas); int pfm_read_pmrs(int fd, int flags, pfarg_pmr_t *pmrs, int n); int pfm_read_pmrs(int fd, int flags, parg_pmr_t *pmrs, int n, pfarg_pmd_attr_t *pmas); New structures: typedef struct { u16 reg_num; u16 reg_set; u32 reg_flags; u64 reg_value; } pfarg_pmr_t; typedef struct { u64 reg_long_reset; u64 reg_short_reset; u64 reg_random_mask; u64 reg_smpl_pmds[PFM_PMD_BV]; u64 reg_reset_pmds[PFM_PMD_BV]; u64 reg_ovfl_swcnt; u64 reg_smpl_eventid; u64 reg_last_value; u64 reg_reserved[8]; } pfarg_pmd_t; New flags: PFM_RWFL_PMD : pmrs contains PMD register descriptions PFM_RWFL_PMC : pmrs contains PMC register descriptions PFM_RWFL_PMD_ATTR: PFM_RWFL_PMD + attributes We now use only 2 system calls to read and write the PMU registers. This is possible because we are sharing the same register description data structure, pfarg_pmr_t. They key attributes of each register are encapsulated into this structure. Additional PMD attributes related to sampling and multiplexing are off-loaded into another optional structure, pfarg_pmd_attr_t. This structure becomes optional and is only looked at by the kernel if the PFM_RWFL_PMD_ATTR flag is passed. For all counting applications, using pfarg_pmr_t is enough. The nice side effect of this split is that the cost of reading and writing PMD register is now reduced because we have less data to copy in and out of the kernel. Unlike suggested by some people, I have not merged the notions of PMD and PMC registers. I think it is cleaner to separate them out. It also makes it much easier to provide backward compatibility with v2.81. III) attaching and detaching With v2.81: int pfm_load_context(int fd, pfarg_load_t *load); int pfm_unload_context(int fd); With v3.0: int pfm_attach_session(int fd, int flags, int target); int pfm_detach_session(int fd, int flags); The pfarg_load_t structure has been abandoned. The information about what to attach to is passed as a parameter to the syscall in "target". It can either be a thread id or a CPU id. There are currently no flags defined for either call. Note that we have lost the ability to specify which event set is to be activated first. There was no actual use of this option anyway. Some people have suggested that I use 'unsigned long' instead of 'int' for target. I am not against it. IV) starting and stopping With v2.81: int pfm_start(int fd, pfarg_start_t *st); int pfm_stop(int fd); int pfm_restart(int fd); With v3.0: int pfm_start_session(int fd, int flags); int pfm_stop_session(int fd, int flags); New flags: PFM_STFL_RESTART: resume monitoring after an overflow notification The pfarg_start_t structure has been abandoned. The pfm_restart() syscall has been merged with pfm_start() by using the PFM_STFL_RESTART flag. It is not possible to just use pfm_start_session() and internally determine what to do because this is dependent on the sampling format. We have lost the ability to specify on which event set to start. I don't think this option was ever used. V) event set and multiplexing With v2.81: int pfm_create_evtsets(int fd, pfarg_setdesc_t *s, int n); int pfm_getinfo_evtsets(int fd, pfarg_setinfo_t *s, int n); int pfm_delete_evtsets(int fd, pfarg_setdesc_t *s, int n); With v3.0: int pfm_create_sets(int fd, int flags, pfarg_setdesc_t *s, int n); int pfm_getinfo_sets(int fd, int flags, pfarg_setinfo_t *s, int n); We have kept the same data structures and simply added a flags parameters to provide for extensibility of the calls. We have removed pfm_delete_evtsets() because it was not used by a lot of applications. We could add it back later if there is a good reason for it , something stronger than saying it needs to be there for symmetry. The code for v3.0 has been uploaded into the perfmon GIT tree at kernel.org. It is located in the perfmon3 branch. I am hoping this will lift the last remaining issues and we will be able to start merging perfmon3 into mainline. Thanks. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-09-25 21:48 ` perfmon3 interface overview stephane eranian @ 2008-10-03 6:17 ` David Gibson [not found] ` <7c86c4470810030354x6984372akfe18761da7504a0c@mail.gmail.com> 0 siblings, 1 reply; 15+ messages in thread From: David Gibson @ 2008-10-03 6:17 UTC (permalink / raw) To: eranian; +Cc: linux-kernel On Thu, Sep 25, 2008 at 11:48:27PM +0200, stephane eranian wrote: > Hello, > > A few months ago, I started posting on this list a highly simplified version > of the perfmon2 version which was providing only per-thread counting on X86 > processors. > > The feedback I got was generally positive but people raised two more issues: > > - too many system calls for a single subsystem (12 calls) > > - how to ensure syscalls could be extended without necessarily > adding new ones. > > > Since then, I have been working hard on addressing those two issues, > in other words redesign of the perfmon2 syscall API. This message is > to announce that I now have a new proposal for the API. As expected > it is called perfmon3 and it addresses the two issues above while > allowing backward compatibility with the existing v2.81 version > through a user level glue layer which could be implemented by a > library such as libpfm. > The new API now has 8 system calls in its fully-featured > version. Many data structures shared with user level have been > abandoned in favor of explicit syscall parameters. Each syscall has Ah, excellent, big structures passed through an interface are often a pain to deal with, so I'm glad these are going. > a flags parameters which allows the syscalls to be extended with new > parameters when we need them. Most structures passed to the kernel > have reserved fields for future extensions. > > The initial patchset will only support per-thread counting as I did > previously. However, here I am presenting the details for the fully > featured version so people can get a feel for it. For each call I > show the old way and the new way. > > Note that when the syscall is shown twice with a different number of > parameters, this variation is handled by the user library. The > kernel implements the full call. This is the same technique used for > the open(2) syscall. I, at least, like the changes that have been made here. I do have a few suggestions for further simplifications along the same lines though, see below. [snip] > II) programming the registers > > With v2.81: > int pfm_write_pmcs(int fd, pfarg_pmc_t *pmds, int n); > int pfm_write_pmds(int fd, pfarg_pmd_t *pmcs, int n); > int pfm_read_pmds(int fd, parg_pmd_t *pmds, int n); > > With v3.0: > int pfm_write_pmrs(int fd, int flags, pfarg_pmr_t *pmrs, int n); > int pfm_write_pmrs(int fd, int flags, pfarg_pmr_t *pmrs, int n, > pfarg_pmd_attr_t *pmas); > > int pfm_read_pmrs(int fd, int flags, pfarg_pmr_t *pmrs, int n); > int pfm_read_pmrs(int fd, int flags, parg_pmr_t *pmrs, int n, > pfarg_pmd_attr_t *pmas); I would suggest adding 'type' and 'size' (int) parameters, and folding the pmrs and pmas arrays into one freeform array. 'size' gives the size in bytes of the array elements, 'type' selects the structure of each array element. This means: - if you ever have some sort of registers to access that are neither PMCs nor PMDs, you can access those two, using a new type value. - if a new method of operation wants to supply different information for PMCs or PMDs, you can define a new structure and type value (one obvious example would be a minimal (num,value) only structure for minimum latency on simple applications). - an explicit size value means things can marshal / copy / whatnot the parameters without having to know what size each type implies - the code will stay valid when new types / structures are defined. [snip] > III) attaching and detaching > > With v2.81: > int pfm_load_context(int fd, pfarg_load_t *load); > int pfm_unload_context(int fd); > > With v3.0: > int pfm_attach_session(int fd, int flags, int target); > int pfm_detach_session(int fd, int flags); Couldn't you get rid of one more syscall here by making detach a special case of attach with a special "null" value for target, or a special flag? > IV) starting and stopping > > With v2.81: > int pfm_start(int fd, pfarg_start_t *st); > int pfm_stop(int fd); > int pfm_restart(int fd); > > With v3.0: > int pfm_start_session(int fd, int flags); > int pfm_stop_session(int fd, int flags); Likewise, couldn't you cut this down by one more syscall by making it int pfm_set_session_state(int fd, int flags); and having a 'RUNNING' flag, which selects start or stop behaviour? -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <7c86c4470810030354x6984372akfe18761da7504a0c@mail.gmail.com>]
* Re: perfmon3 interface overview [not found] ` <7c86c4470810030354x6984372akfe18761da7504a0c@mail.gmail.com> @ 2008-10-03 10:58 ` stephane eranian 2008-10-03 11:12 ` stephane eranian 2008-10-05 5:53 ` David Gibson 0 siblings, 2 replies; 15+ messages in thread From: stephane eranian @ 2008-10-03 10:58 UTC (permalink / raw) To: David Gibson, eranian, linux-kernel; +Cc: perfmon2-devel David, On Fri, Oct 3, 2008 at 8:17 AM, David Gibson <david@gibson.dropbear.id.au> wrote: > > > The new API now has 8 system calls in its fully-featured > > version. Many data structures shared with user level have been > > abandoned in favor of explicit syscall parameters. Each syscall has > > Ah, excellent, big structures passed through an interface are often a > pain to deal with, so I'm glad these are going. Thanks. > > > I, at least, like the changes that have been made here. I do have a > few suggestions for further simplifications along the same lines > though, see below. > > [snip] > > II) programming the registers > > > > With v2.81: > > int pfm_write_pmcs(int fd, pfarg_pmc_t *pmds, int n); > > int pfm_write_pmds(int fd, pfarg_pmd_t *pmcs, int n); > > int pfm_read_pmds(int fd, parg_pmd_t *pmds, int n); > > > > With v3.0: > > int pfm_write_pmrs(int fd, int flags, pfarg_pmr_t *pmrs, int n); > > int pfm_write_pmrs(int fd, int flags, pfarg_pmr_t *pmrs, int n, > > pfarg_pmd_attr_t *pmas); > > > > int pfm_read_pmrs(int fd, int flags, pfarg_pmr_t *pmrs, int n); > > int pfm_read_pmrs(int fd, int flags, parg_pmr_t *pmrs, int n, > > pfarg_pmd_attr_t *pmas); > > I would suggest adding 'type' and 'size' (int) parameters, and folding > the pmrs and pmas arrays into one freeform array. 'size' gives the > size in bytes of the array elements, 'type' selects the structure of > each array element. This means: > - if you ever have some sort of registers to access that are > neither PMCs nor PMDs, you can access those two, using a new type > value. > - if a new method of operation wants to supply different > information for PMCs or PMDs, you can define a new structure and type > value (one obvious example would be a minimal (num,value) only > structure for minimum latency on simple applications). > - an explicit size value means things can marshal / copy / > whatnot the parameters without having to know what size each type > implies - the code will stay valid when new types / structures are > defined. So you are suggesting something along the lines: int pfm_read_pmrs(int fd, int flags, int type, void *tab, size_t sz); int pfm_write_pmrs(int fd, int flags, int type, void *tab, size_t sz); I have already introduced a type flag (PFM_RWFL_PMD, PFM_RWFL_PMC). Why separate the type into its own parameter? As for the freeform array, isn't that what people do not like because of void * and thus weak type checking? I will look at switching to size instead of count. I think it does make sense. > > [snip] > > III) attaching and detaching > > > > With v2.81: > > int pfm_load_context(int fd, pfarg_load_t *load); > > int pfm_unload_context(int fd); > > > > With v3.0: > > int pfm_attach_session(int fd, int flags, int target); > > int pfm_detach_session(int fd, int flags); > > Couldn't you get rid of one more syscall here by making detach a > special case of attach with a special "null" value for target, or a > special flag? We could combine the two and use the flag field to indicate attach/detach. The target is not a pointer but an int. Some people suggested I use an unsigned long instead. In anycase, we could not use 0 to indicate "detach" because CPU0 is a valid choice for system-wide. Thus we would have to pick another value to mean "nothing", e.g, -1. > IV) starting and stopping > > With v2.81: > int pfm_start(int fd, pfarg_start_t *st); > int pfm_stop(int fd); > int pfm_restart(int fd); > > With v3.0: > int pfm_start_session(int fd, int flags); > int pfm_stop_session(int fd, int flags); > Likewise, couldn't you cut this down by one more syscall by making it > int pfm_set_session_state(int fd, int flags); > and having a 'RUNNING' flag, which selects start or stop behaviour? That one we can certainly do. That's a good idea. Thanks for your feedback, keep it coming. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-03 10:58 ` stephane eranian @ 2008-10-03 11:12 ` stephane eranian 2008-10-04 6:05 ` David Gibson 2008-10-05 5:53 ` David Gibson 1 sibling, 1 reply; 15+ messages in thread From: stephane eranian @ 2008-10-03 11:12 UTC (permalink / raw) To: David Gibson, eranian, linux-kernel; +Cc: perfmon2-devel David, >> [snip] >> > III) attaching and detaching >> > >> > With v2.81: >> > int pfm_load_context(int fd, pfarg_load_t *load); >> > int pfm_unload_context(int fd); >> > >> > With v3.0: >> > int pfm_attach_session(int fd, int flags, int target); >> > int pfm_detach_session(int fd, int flags); >> >> Couldn't you get rid of one more syscall here by making detach a >> special case of attach with a special "null" value for target, or a >> special flag? > > > We could combine the two and use the flag field to indicate attach/detach. > The target is not a pointer but an int. Some people suggested I use an > unsigned long instead. In anycase, we could not use 0 to indicate "detach" > because CPU0 is a valid choice for system-wide. Thus we would have to > pick another value to mean "nothing", e.g, -1. > > > IV) starting and stopping > > > > With v2.81: > > int pfm_start(int fd, pfarg_start_t *st); > > int pfm_stop(int fd); > > int pfm_restart(int fd); > > > > With v3.0: > > int pfm_start_session(int fd, int flags); > > int pfm_stop_session(int fd, int flags); > >> Likewise, couldn't you cut this down by one more syscall by making it >> int pfm_set_session_state(int fd, int flags); >> and having a 'RUNNING' flag, which selects start or stop behaviour? > > That one we can certainly do. That's a good idea. Some more thoughts on this. If we wanted to go even further, we could combine start/stop, attach/detach into a single syscall: int pfm_control_session(int fd, int flags, int target); With flags: PFM_CTFL_START : start monitoring PFM_CTFL_STOP : stop monitoring PFM_CTFL_RESTART: resume after overflow notification PFM_CTFL_ATTACH: attach to thread or cpu designated by 'target' PFM_CTFL_DETACH: detach session But then, this is a form of ioctl() which people don't like.... ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-03 11:12 ` stephane eranian @ 2008-10-04 6:05 ` David Gibson 2008-10-04 7:20 ` stephane eranian 0 siblings, 1 reply; 15+ messages in thread From: David Gibson @ 2008-10-04 6:05 UTC (permalink / raw) To: eranian; +Cc: linux-kernel, perfmon2-devel On Fri, Oct 03, 2008 at 01:12:09PM +0200, stephane eranian wrote: > David, > >> [snip] > >> > III) attaching and detaching > >> > > >> > With v2.81: > >> > int pfm_load_context(int fd, pfarg_load_t *load); > >> > int pfm_unload_context(int fd); > >> > > >> > With v3.0: > >> > int pfm_attach_session(int fd, int flags, int target); > >> > int pfm_detach_session(int fd, int flags); > >> > >> Couldn't you get rid of one more syscall here by making detach a > >> special case of attach with a special "null" value for target, or a > >> special flag? > > > > > > We could combine the two and use the flag field to indicate attach/detach. > > The target is not a pointer but an int. Some people suggested I use an > > unsigned long instead. In anycase, we could not use 0 to indicate "detach" > > because CPU0 is a valid choice for system-wide. Thus we would have to > > pick another value to mean "nothing", e.g, -1. > > > > > IV) starting and stopping > > > > > > With v2.81: > > > int pfm_start(int fd, pfarg_start_t *st); > > > int pfm_stop(int fd); > > > int pfm_restart(int fd); > > > > > > With v3.0: > > > int pfm_start_session(int fd, int flags); > > > int pfm_stop_session(int fd, int flags); > > > >> Likewise, couldn't you cut this down by one more syscall by making it > >> int pfm_set_session_state(int fd, int flags); > >> and having a 'RUNNING' flag, which selects start or stop behaviour? > > > > That one we can certainly do. That's a good idea. > > Some more thoughts on this. > > If we wanted to go even further, we could combine start/stop, attach/detach > into a single syscall: Well, you could. But the attach/detach take a parameter which start/stop don't, making it a less obvious merge to make. > int pfm_control_session(int fd, int flags, int target); > With flags: > PFM_CTFL_START : start monitoring > PFM_CTFL_STOP : stop monitoring > PFM_CTFL_RESTART: resume after overflow notification > > PFM_CTFL_ATTACH: attach to thread or cpu designated by 'target' > PFM_CTFL_DETACH: detach session > > But then, this is a form of ioctl() which people don't like.... -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-04 6:05 ` David Gibson @ 2008-10-04 7:20 ` stephane eranian 2008-10-05 5:44 ` David Gibson 0 siblings, 1 reply; 15+ messages in thread From: stephane eranian @ 2008-10-04 7:20 UTC (permalink / raw) To: David Gibson, eranian, linux-kernel, perfmon2-devel David, On Sat, Oct 4, 2008 at 8:05 AM, David Gibson <david@gibson.dropbear.id.au> wrote: >> >> If we wanted to go even further, we could combine start/stop, attach/detach >> into a single syscall: > > Well, you could. But the attach/detach take a parameter which > start/stop don't, making it a less obvious merge to make. > Unless you make the 3rd argument optional and hide this in a user library. This is how this is handled for pfm_create_session() for instance. The library would define this as follows: int pfm_control_session(int fd, int flags, ...); Based upon flags, it would use va_arg() to get to the 3rd argument and pass it to the syscall which implements the version below. A dummy value would be passed with the flags is not equal to PFM_CTFL_ATTACH. >> int pfm_control_session(int fd, int flags, int target); >> With flags: >> PFM_CTFL_START : start monitoring >> PFM_CTFL_STOP : stop monitoring >> PFM_CTFL_RESTART: resume after overflow notification >> >> PFM_CTFL_ATTACH: attach to thread or cpu designated by 'target' >> PFM_CTFL_DETACH: detach session >> ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-04 7:20 ` stephane eranian @ 2008-10-05 5:44 ` David Gibson 0 siblings, 0 replies; 15+ messages in thread From: David Gibson @ 2008-10-05 5:44 UTC (permalink / raw) To: eranian; +Cc: linux-kernel, perfmon2-devel On Sat, Oct 04, 2008 at 09:20:00AM +0200, stephane eranian wrote: > David, > > On Sat, Oct 4, 2008 at 8:05 AM, David Gibson > <david@gibson.dropbear.id.au> wrote: > >> > >> If we wanted to go even further, we could combine start/stop, attach/detach > >> into a single syscall: > > > > Well, you could. But the attach/detach take a parameter which > > start/stop don't, making it a less obvious merge to make. > > > Unless you make the 3rd argument optional and hide this in a > user library. This is how this is handled for pfm_create_session() > for instance. The library would define this as follows: > > int pfm_control_session(int fd, int flags, ...); > > Based upon flags, it would use va_arg() to get to the 3rd argument and > pass it to the syscall which implements the version below. A dummy value > would be passed with the flags is not equal to PFM_CTFL_ATTACH. Yeah, that's what I'm saying. You could do it, but it feels like you're forcing it, at least to me. As you say it starts to look a bit like ioctl() again. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-03 10:58 ` stephane eranian 2008-10-03 11:12 ` stephane eranian @ 2008-10-05 5:53 ` David Gibson 2008-10-05 21:23 ` stephane eranian 1 sibling, 1 reply; 15+ messages in thread From: David Gibson @ 2008-10-05 5:53 UTC (permalink / raw) To: eranian; +Cc: linux-kernel, perfmon2-devel On Fri, Oct 03, 2008 at 12:58:12PM +0200, stephane eranian wrote: > David, > > On Fri, Oct 3, 2008 at 8:17 AM, David Gibson > <david@gibson.dropbear.id.au> wrote: > > > > > The new API now has 8 system calls in its fully-featured > > > version. Many data structures shared with user level have been > > > abandoned in favor of explicit syscall parameters. Each syscall has > > > > Ah, excellent, big structures passed through an interface are often a > > pain to deal with, so I'm glad these are going. [snip] > So you are suggesting something along the lines: > > int pfm_read_pmrs(int fd, int flags, int type, void *tab, size_t sz); > int pfm_write_pmrs(int fd, int flags, int type, void *tab, size_t sz); Uh.. maybe.. there are actually several possible variants all of which would meet the general idea I had in mind. > I have already introduced a type flag (PFM_RWFL_PMD, PFM_RWFL_PMC). > Why separate the type into its own parameter? Combining the type into the flags is certainly a possibility. I was just a bit worried that if you eventually have enough actual flag flags, in addition to the type values, you might start running out of bits. > As for the freeform array, isn't that what people do not like because > of void * > and thus weak type checking? Yeah; this is an interesting tradeoff of flexibility versus predictability. Actually, what I originally had in mind was seperately passing both 'n' and a per-element size. That provides a bit more defined structure to the void * - it must be an array of n identical, fixed-size elements. The internal structure of each element is defined only by type, but it is assumed to contain no pointers to further chained structures (i.e. its safe for wrapper code to do shallow copies of the array). > I will look at switching to size instead of count. I think it does > make sense. Yeah. As I said I was originally thinking of keeping the 'n' parameter, and adding an element size parameter. But just having an overall size is also a possibility - it gives less definition to the internal structure but at least things can marshal or copy the whole array parameter without having to know its internals. [snip] > > > III) attaching and detaching > > > > > > With v2.81: > > > int pfm_load_context(int fd, pfarg_load_t *load); > > > int pfm_unload_context(int fd); > > > > > > With v3.0: > > > int pfm_attach_session(int fd, int flags, int target); > > > int pfm_detach_session(int fd, int flags); > > > > Couldn't you get rid of one more syscall here by making detach a > > special case of attach with a special "null" value for target, or a > > special flag? > > We could combine the two and use the flag field to indicate attach/detach. > The target is not a pointer but an int. Some people suggested I use an > unsigned long instead. In anycase, we could not use 0 to indicate "detach" > because CPU0 is a valid choice for system-wide. Thus we would have to > pick another value to mean "nothing", e.g, -1. Sorry, I didn't express myself well. I realise it's an integer, and didn't mean an actual NULL, but as you say a special integer value with a function similar to NULL. -1 is the most obvious choice. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-05 5:53 ` David Gibson @ 2008-10-05 21:23 ` stephane eranian 2008-10-07 3:56 ` David Gibson 2008-10-07 9:24 ` [perfmon2] " Arnd Bergmann 0 siblings, 2 replies; 15+ messages in thread From: stephane eranian @ 2008-10-05 21:23 UTC (permalink / raw) To: David Gibson, eranian, linux-kernel, perfmon2-devel David, On Sun, Oct 5, 2008 at 7:53 AM, David Gibson <david@gibson.dropbear.id.au> wrote: > [snip] >> So you are suggesting something along the lines: >> >> int pfm_read_pmrs(int fd, int flags, int type, void *tab, size_t sz); >> int pfm_write_pmrs(int fd, int flags, int type, void *tab, size_t sz); > > Uh.. maybe.. there are actually several possible variants all of which > would meet the general idea I had in mind. > >> I have already introduced a type flag (PFM_RWFL_PMD, PFM_RWFL_PMC). >> Why separate the type into its own parameter? > > Combining the type into the flags is certainly a possibility. I was > just a bit worried that if you eventually have enough actual flag > flags, in addition to the type values, you might start running out of > bits. > I see, so you were just decoupling to double the number of available bits. I guess we have a minimum of 32 bits. It seems overkill to support up to 32 'types'. We could force flags to uint64_t. But then we would have to do the same for all other syscalls to be consistent. Defining flags as long won't work because of 32-bit vs. 64-bit ABI compatibility issues. >> As for the freeform array, isn't that what people do not like because >> of void * >> and thus weak type checking? > > Yeah; this is an interesting tradeoff of flexibility versus > predictability. Actually, what I originally had in mind was > seperately passing both 'n' and a per-element size. That provides a > bit more defined structure to the void * - it must be an array of n > identical, fixed-size elements. The internal structure of each > element is defined only by type, but it is assumed to contain no > pointers to further chained structures (i.e. its safe for wrapper code > to do shallow copies of the array). > Ok, that reminds me of the API of calloc(). It certainly forces you to think it terms of 'array of elements'. Yet it can be perverted very easily with the number of elements at 1. >> I will look at switching to size instead of count. I think it does >> make sense. > > Yeah. As I said I was originally thinking of keeping the 'n' > parameter, and adding an element size parameter. But just having an > overall size is also a possibility - it gives less definition to the > internal structure but at least things can marshal or copy the whole > array parameter without having to know its internals. > Yes, that it true. It also simplifies the checking on size. With count we had to check for multiply overflow because internall we had to check the size anyway. > [snip] >> > > III) attaching and detaching >> > > >> > > With v2.81: >> > > int pfm_load_context(int fd, pfarg_load_t *load); >> > > int pfm_unload_context(int fd); >> > > >> > > With v3.0: >> > > int pfm_attach_session(int fd, int flags, int target); >> > > int pfm_detach_session(int fd, int flags); >> > >> > Couldn't you get rid of one more syscall here by making detach a >> > special case of attach with a special "null" value for target, or a >> > special flag? >> >> We could combine the two and use the flag field to indicate attach/detach. >> The target is not a pointer but an int. Some people suggested I use an >> unsigned long instead. In anycase, we could not use 0 to indicate "detach" >> because CPU0 is a valid choice for system-wide. Thus we would have to >> pick another value to mean "nothing", e.g, -1. > > Sorry, I didn't express myself well. I realise it's an integer, and > didn't mean an actual NULL, but as you say a special integer value > with a function similar to NULL. -1 is the most obvious choice. > Yes, -1 would work. If I summarize our discussion. It seems we can define the API as follows: int pfm_create_session(int fd, uint64_t flags, pfarg_sinfo_t *sif, [ char *smpl_name, void *smpl_arg, size_t arg_size]); int pfm_read_pmrs(int fd, uint64_t flags, void *tab, size_t sz); int pfm_write_pmrs(int fd, uint64_t flags, void *tab, size_t sz); int pfm_attach_session(int fd, uint64_t flags, int target); /* attach, detach with target=-1 */ int pfm_control_session(int fd, uint64_t flags); /* for start/stop */ int pfm_control_sets(int fd, uint64_t flags, void *sets, size_t sz); Does this look reasonable? ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-05 21:23 ` stephane eranian @ 2008-10-07 3:56 ` David Gibson 2008-10-07 9:46 ` stephane eranian 2008-10-07 9:24 ` [perfmon2] " Arnd Bergmann 1 sibling, 1 reply; 15+ messages in thread From: David Gibson @ 2008-10-07 3:56 UTC (permalink / raw) To: eranian; +Cc: linux-kernel, perfmon2-devel On Sun, Oct 05, 2008 at 11:23:15PM +0200, stephane eranian wrote: > David, > > On Sun, Oct 5, 2008 at 7:53 AM, David Gibson > <david@gibson.dropbear.id.au> wrote: > > [snip] > >> So you are suggesting something along the lines: > >> > >> int pfm_read_pmrs(int fd, int flags, int type, void *tab, size_t sz); > >> int pfm_write_pmrs(int fd, int flags, int type, void *tab, size_t sz); > > > > Uh.. maybe.. there are actually several possible variants all of which > > would meet the general idea I had in mind. > > > >> I have already introduced a type flag (PFM_RWFL_PMD, PFM_RWFL_PMC). > >> Why separate the type into its own parameter? > > > > Combining the type into the flags is certainly a possibility. I was > > just a bit worried that if you eventually have enough actual flag > > flags, in addition to the type values, you might start running out of > > bits. > > > I see, so you were just decoupling to double the number of available bits. > I guess we have a minimum of 32 bits. It seems overkill to support up to > 32 'types'. We could force flags to uint64_t. But then we would have to do > the same for all other syscalls to be consistent. Defining flags as long > won't work because of 32-bit vs. 64-bit ABI compatibility issues. I guess so. I guess there's also the possibility that you might later have some flags that can apply to many of the syscalls, and it would be nice to have them in a standard bit position for all calls. That might make bit allocation a bit interesting if you're squeezing type into the same field. My opinion is not really strong either way though. > >> As for the freeform array, isn't that what people do not like because > >> of void * > >> and thus weak type checking? > > > > Yeah; this is an interesting tradeoff of flexibility versus > > predictability. Actually, what I originally had in mind was > > seperately passing both 'n' and a per-element size. That provides a > > bit more defined structure to the void * - it must be an array of n > > identical, fixed-size elements. The internal structure of each > > element is defined only by type, but it is assumed to contain no > > pointers to further chained structures (i.e. its safe for wrapper code > > to do shallow copies of the array). > > Ok, that reminds me of the API of calloc(). It certainly forces you to > think it terms of 'array of elements'. Yet it can be perverted very easily > with the number of elements at 1. That's true. Like I say, it's a tradeoff. > >> I will look at switching to size instead of count. I think it does > >> make sense. > > > > Yeah. As I said I was originally thinking of keeping the 'n' > > parameter, and adding an element size parameter. But just having an > > overall size is also a possibility - it gives less definition to the > > internal structure but at least things can marshal or copy the whole > > array parameter without having to know its internals. > > > Yes, that it true. It also simplifies the checking on size. With count > we had to check for multiply overflow because internall we had to > check the size anyway. That's a nice extra bonus, yes. > > [snip] > >> > > III) attaching and detaching > >> > > > >> > > With v2.81: > >> > > int pfm_load_context(int fd, pfarg_load_t *load); > >> > > int pfm_unload_context(int fd); > >> > > > >> > > With v3.0: > >> > > int pfm_attach_session(int fd, int flags, int target); > >> > > int pfm_detach_session(int fd, int flags); > >> > > >> > Couldn't you get rid of one more syscall here by making detach a > >> > special case of attach with a special "null" value for target, or a > >> > special flag? > >> > >> We could combine the two and use the flag field to indicate attach/detach. > >> The target is not a pointer but an int. Some people suggested I use an > >> unsigned long instead. In anycase, we could not use 0 to indicate "detach" > >> because CPU0 is a valid choice for system-wide. Thus we would have to > >> pick another value to mean "nothing", e.g, -1. > > > > Sorry, I didn't express myself well. I realise it's an integer, and > > didn't mean an actual NULL, but as you say a special integer value > > with a function similar to NULL. -1 is the most obvious choice. > > > Yes, -1 would work. > > If I summarize our discussion. It seems we can define the API as follows: > > int pfm_create_session(int fd, uint64_t flags, pfarg_sinfo_t *sif, > [ char *smpl_name, void *smpl_arg, size_t arg_size]); > int pfm_read_pmrs(int fd, uint64_t flags, void *tab, size_t sz); > int pfm_write_pmrs(int fd, uint64_t flags, void *tab, size_t sz); > int pfm_attach_session(int fd, uint64_t flags, int target); /* > attach, detach with target=-1 */ > int pfm_control_session(int fd, uint64_t flags); /* for start/stop */ Unless you have other functions in mind for this, I'd suggest a name that's a little less generic here. pfm_set_running() maybe. > int pfm_control_sets(int fd, uint64_t flags, void *sets, size_t > sz); Hrm. This now has identical signature to the {read,write}_pmrs. I wonder if these could be sensibly combined. Maybe have pfm_get_info(), pfm_set_info() which can get/set control structures for several different namespaces: PMCs PMDs and now event sets. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-07 3:56 ` David Gibson @ 2008-10-07 9:46 ` stephane eranian 2008-10-08 0:53 ` David Gibson 0 siblings, 1 reply; 15+ messages in thread From: stephane eranian @ 2008-10-07 9:46 UTC (permalink / raw) To: David Gibson, eranian, linux-kernel, perfmon2-devel David, On Tue, Oct 7, 2008 at 5:56 AM, David Gibson <david@gibson.dropbear.id.au> wrote: > On Sun, Oct 05, 2008 at 11:23:15PM +0200, stephane eranian wrote: >> I see, so you were just decoupling to double the number of available bits. >> I guess we have a minimum of 32 bits. It seems overkill to support up to >> 32 'types'. We could force flags to uint64_t. But then we would have to do >> the same for all other syscalls to be consistent. Defining flags as long >> won't work because of 32-bit vs. 64-bit ABI compatibility issues. > > I guess so. I guess there's also the possibility that you might later > have some flags that can apply to many of the syscalls, and it would > be nice to have them in a standard bit position for all calls. That > might make bit allocation a bit interesting if you're squeezing type > into the same field. > I can see that for subsets of the calls, e.g., read and write of registers. It is not clear to me what kind of 'service' would apply to all calls. As Corey suggested yesteday, the flags for read and write operations are not just single bit. A portion of the 64 bits, 8 in his proposal, are used to encode the 'type' of register (PMD, PMC, PMD_ATTR). That simplifies checking for valid bits in this portion of flags. OTOH, if I go back to your original proposal: int pfm_write_pmrs(int fd, int flags, int type, void *v, size_t); The 'type' field would have the same encoding as proposed by Corey. 32 bits would be plentyful for types. Flags could remain at 32-bits across the board, thereby avoiding the problems outlined by Arnd in his follow-up message. Separating the type also makes it look less like an ioctl(). So I think we should go with that proposal. [snip] >> >> If I summarize our discussion. It seems we can define the API as follows: >> >> int pfm_create_session(int fd, uint64_t flags, pfarg_sinfo_t *sif, >> [ char *smpl_name, void *smpl_arg, size_t arg_size]); >> int pfm_read_pmrs(int fd, uint64_t flags, void *tab, size_t sz); >> int pfm_write_pmrs(int fd, uint64_t flags, void *tab, size_t sz); >> int pfm_attach_session(int fd, uint64_t flags, int target); /* >> attach, detach with target=-1 */ >> int pfm_control_session(int fd, uint64_t flags); /* for start/stop */ > > Unless you have other functions in mind for this, I'd suggest a name > that's a little less generic here. pfm_set_running() maybe. > What about pfm_set_state() or pfm_set_session_state()? >> int pfm_control_sets(int fd, uint64_t flags, void *sets, size_t >> sz); > > Hrm. This now has identical signature to the {read,write}_pmrs. I > wonder if these could be sensibly combined. Maybe have > pfm_get_info(), pfm_set_info() which can get/set control structures > for several different namespaces: PMCs PMDs and now event sets. > I think this would be too generic as it would be mixing very different data types. This is not the case for pfm_write_pmrs() and pfm_read_pmrs() because you are always passing 'register descriptions'. There is a fundamental difference between pfm_control_sets() and pfm_write_pmrs()/pfm_read_pmrs(). For the latter, the 'action' is hardcoded in the name of the syscall, i.e., read or write, what varies is whether or not we are passing PMD or PMC. For the former, the 'action', i.e., create new set or get info about a set, is hardcoded in the flags, and it determines the type of structure passed in the third argument. In that sense, pfm_control_sets() has more the look and feel of ioctl(), but as David points out in his follow-up message, the difference is that we have size and that provides a basis for sanity checking in the kernel, unlike ioctl() which only has 'flags'. In summary, here is the current proposal: int pfm_create_session(int fd, int flags, pfarg_sinfo_t *sif, [ char *smpl_name, void *smpl_arg, size_t arg_size]); int pfm_read_pmrs(int fd, int flags, int type, void *tab, size_t sz); int pfm_write_pmrs(int fd, int flags, int type, void *tab, size_t sz); int pfm_attach_session(int fd, int flags, int target); /* detach with target=-1 */ int pfm_set_session_state(int fd, int flags); /* for start/stop */ int pfm_control_sets(int fd, int flags, void *sets, size_t sz); ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-07 9:46 ` stephane eranian @ 2008-10-08 0:53 ` David Gibson 2008-10-08 10:09 ` stephane eranian 0 siblings, 1 reply; 15+ messages in thread From: David Gibson @ 2008-10-08 0:53 UTC (permalink / raw) To: eranian; +Cc: linux-kernel, perfmon2-devel On Tue, Oct 07, 2008 at 11:46:53AM +0200, stephane eranian wrote: > David, > > On Tue, Oct 7, 2008 at 5:56 AM, David Gibson > <david@gibson.dropbear.id.au> wrote: > > On Sun, Oct 05, 2008 at 11:23:15PM +0200, stephane eranian wrote: > >> I see, so you were just decoupling to double the number of available bits. > >> I guess we have a minimum of 32 bits. It seems overkill to support up to > >> 32 'types'. We could force flags to uint64_t. But then we would have to do > >> the same for all other syscalls to be consistent. Defining flags as long > >> won't work because of 32-bit vs. 64-bit ABI compatibility issues. > > > > I guess so. I guess there's also the possibility that you might later > > have some flags that can apply to many of the syscalls, and it would > > be nice to have them in a standard bit position for all calls. That > > might make bit allocation a bit interesting if you're squeezing type > > into the same field. > > > I can see that for subsets of the calls, e.g., read and write of registers. > It is not clear to me what kind of 'service' would apply to all calls. > > As Corey suggested yesteday, the flags for read and write operations > are not just single bit. A portion of the 64 bits, 8 in his proposal, are used > to encode the 'type' of register (PMD, PMC, PMD_ATTR). That simplifies > checking for valid bits in this portion of flags. Yes, that was always what I had in mind if flags and type were combined. > OTOH, if I go back to your original proposal: > int pfm_write_pmrs(int fd, int flags, int type, void *v, size_t); > > The 'type' field would have the same encoding as proposed by Corey. > 32 bits would be plentyful for types. Flags could remain at 32-bits > across the board, thereby avoiding the problems outlined by Arnd > in his follow-up message. Separating the type also makes it look > less like an ioctl(). So I think we should go with that proposal. Works for me. > [snip] > >> > >> If I summarize our discussion. It seems we can define the API as follows: > >> > >> int pfm_create_session(int fd, uint64_t flags, pfarg_sinfo_t *sif, > >> [ char *smpl_name, void *smpl_arg, size_t arg_size]); > >> int pfm_read_pmrs(int fd, uint64_t flags, void *tab, size_t sz); > >> int pfm_write_pmrs(int fd, uint64_t flags, void *tab, size_t sz); > >> int pfm_attach_session(int fd, uint64_t flags, int target); /* > >> attach, detach with target=-1 */ > >> int pfm_control_session(int fd, uint64_t flags); /* for start/stop */ > > > > Unless you have other functions in mind for this, I'd suggest a name > > that's a little less generic here. pfm_set_running() maybe. > > > What about pfm_set_state() or pfm_set_session_state()? I guess so. > >> int pfm_control_sets(int fd, uint64_t flags, void *sets, size_t > >> sz); > > > > Hrm. This now has identical signature to the {read,write}_pmrs. I > > wonder if these could be sensibly combined. Maybe have > > pfm_get_info(), pfm_set_info() which can get/set control structures > > for several different namespaces: PMCs PMDs and now event sets. > > > I think this would be too generic as it would be mixing very different > data types. This is not the case for pfm_write_pmrs() and pfm_read_pmrs() > because you are always passing 'register descriptions'. > > There is a fundamental difference between pfm_control_sets() and > pfm_write_pmrs()/pfm_read_pmrs(). For the latter, the 'action' is hardcoded > in the name of the syscall, i.e., read or write, what varies is whether or not > we are passing PMD or PMC. For the former, the 'action', i.e., create new > set or get info about a set, is hardcoded in the flags, and it determines the Uh.. I was assuming if combined we'd drop the selecting flag from control_sets() and instead make the pfm_read_stuff() call be the get_info() equivalent when used on the eventsets space and pfm_write_stuff() be the create/modify sets call. The fact that the structure is different for read/write in this case is a bit funny. In fact it would probably be best to have different 'type' fields for read and write too (EVTSET_INFOm only usable for reads , and EVTSET_CONTROL only for writes, maybe). I'm not dead-set on combining these calls, but it seems to me we've already just about made the read/write calls into a read/write array of control structures in some namespace call, which pretty much is what the event set call is too. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview 2008-10-08 0:53 ` David Gibson @ 2008-10-08 10:09 ` stephane eranian 0 siblings, 0 replies; 15+ messages in thread From: stephane eranian @ 2008-10-08 10:09 UTC (permalink / raw) To: David Gibson, eranian, linux-kernel, perfmon2-devel David, On Wed, Oct 8, 2008 at 2:53 AM, David Gibson <david@gibson.dropbear.id.au> wrote: David, >> >> int pfm_control_sets(int fd, uint64_t flags, void *sets, size_t >> >> sz); >> > >> > Hrm. This now has identical signature to the {read,write}_pmrs. I >> > wonder if these could be sensibly combined. Maybe have >> > pfm_get_info(), pfm_set_info() which can get/set control structures >> > for several different namespaces: PMCs PMDs and now event sets. >> > >> I think this would be too generic as it would be mixing very different >> data types. This is not the case for pfm_write_pmrs() and pfm_read_pmrs() >> because you are always passing 'register descriptions'. >> >> There is a fundamental difference between pfm_control_sets() and >> pfm_write_pmrs()/pfm_read_pmrs(). For the latter, the 'action' is hardcoded >> in the name of the syscall, i.e., read or write, what varies is whether or not >> we are passing PMD or PMC. For the former, the 'action', i.e., create new >> set or get info about a set, is hardcoded in the flags, and it determines the > > Uh.. I was assuming if combined we'd drop the selecting flag from > control_sets() and instead make the pfm_read_stuff() call be the > get_info() equivalent when used on the eventsets space and > pfm_write_stuff() be the create/modify sets call. > There is something I'd like o clarify about event sets. People may be wondering why we need a separate call to create new event sets. Why not create the sets when the session is created, e.g., 'create a session with 5 sets'. There are several reasons for not doing this. Each set has some attributes which describes how and when to switch to another set. Switching can be done based on timeout or based on the number of overflows of counters, each chosen on a per set basis, i.e,, it is possible to combine overflow and timeout switching. Furthermore, the timeout is defined per set and can thus vary from one set to the other. Overflow switching is controlled by a threshold passed as an attribute to the PMD registers. If we were to create sets with the sessions, it would be more than a matter of passing the number of sets. We would actually have to pass the set attributes (pfarg_set_desc_t) and a size parameter. We could do this in v3.0 but it would have to work incrementally as initially we won't support event sets in mainline. The call would look as follows: int pfm_create_session(int flags, pfarg_sinfo_t *sif); int pfm_create_session(int flags, pfarg_sinfo_t *sif, char *smpl_name, void *smpl_arg, size_t arg_size); int pfm_create_session(int flags, pfarg_sinfo_t *sif, char *smpl_name, void *smpl_arg, size_t arg_size, pfarg_set_desc_t *s, size_t sz); I think this call is a bit too complicated. It does a lot of things. Furthermore, you lose the ability to add sets on the fly. Deleting may be possible via another call. So my inclination is to keep this as a separate call. By default, one set is created (set0), with no switching attribute. It is possible to change the attributes by recreating the set. That means, unless you need more sets, you have nothing to do. > The fact that the structure is different for read/write in this case > is a bit funny. In fact it would probably be best to have different > 'type' fields for read and write too (EVTSET_INFOm only usable for > reads , and EVTSET_CONTROL only for writes, maybe). > > > I'm not dead-set on combining these calls, but it seems to me we've > already just about made the read/write calls into a read/write array > of control structures in some namespace call, which pretty much is > what the event set call is too. > I see, you are pushing it a bit further here. If I understand, you're saying: int pfm_read_session(int fd, int flags, int type, void *t, size_t sz); int pfm_write_session(int fd, int flags, int type, void *t, size_t sz); Where type could be: PFM_RWFL_PMD : write simplified pmds registers (pfarg_pmr_t) PFM_RWFL_PMD_ATTR: read or write pmds registers with extended attributes. PFM_RWFL_PMC : write pmcs register (pfarg_pmr_t), note: this is for writing only. PFM_RWFL_SETINFO : read set information (pfarg_set_info_t). Only supported by pfm_read_session PFM_RWFL_CREATSET: create new event sets (pfarg_set_desc_t). Only supported by pfm_write_session I am a bit worried this is too generic, especially for creating sets. Yet it offers the advantage of being very compact and extensible. I'd like to combine pfarg_set_info_t and pfarg_set_desc_t if possible, even if some fields are used in only one of the calls. In summary, here is the current proposal: int pfm_create_session(int flags, pfarg_sinfo_t *sif, [char *smpl_name, void *smpl_arg, size_t arg_sz]); int pfm_read_session(int fd, int flags, int type, void *t, size_t sz); int pfm_write_session(int fd, int flags, int type, void *t, size_t sz); int pfm_attach_session((int fd, int flags, int target); /* target = -1 for detach */ int pfm_set_state_session(int fd, int flags); No other calls are necessary to support event sets and multiplexing. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [perfmon2] perfmon3 interface overview 2008-10-05 21:23 ` stephane eranian 2008-10-07 3:56 ` David Gibson @ 2008-10-07 9:24 ` Arnd Bergmann 1 sibling, 0 replies; 15+ messages in thread From: Arnd Bergmann @ 2008-10-07 9:24 UTC (permalink / raw) To: perfmon2-devel, eranian; +Cc: David Gibson, linux-kernel On Sunday 05 October 2008, stephane eranian wrote: > If I summarize our discussion. It seems we can define the API as follows: > > int pfm_create_session(int fd, uint64_t flags, pfarg_sinfo_t *sif, > [ char *smpl_name, void *smpl_arg, size_t arg_size]); > int pfm_read_pmrs(int fd, uint64_t flags, void *tab, size_t sz); > int pfm_write_pmrs(int fd, uint64_t flags, void *tab, size_t sz); > int pfm_attach_session(int fd, uint64_t flags, int target); /* > attach, detach with target=-1 */ > int pfm_control_session(int fd, uint64_t flags); /* for start/stop */ > int pfm_control_sets(int fd, uint64_t flags, void *sets, size_t sz); There are two problems with uint64_t arguments to system calls: 1. You have to mandate the use of stdint.h before including the perfmon header file. This is a minor problem as long as all callers go through libpfm, but you can avoid it entirely by using the kernel __u32 instead of uint32_t style types everywhere in your interface. 2. The calling conventions for passing 64 bit values on 32 bit architecture are complex, every architecture enforces different rules here. On the syscall interface, bettwe always use native types like 'unsigned long' instead of '__u64'. This is different from the case where you pass a pointer to data, in which case a '__u64 *' is much preferred over a 'unsigned long *'. I did not understand the reason for going to a 64 bit flags parameter, but I think that you would do everyone a favour if you can instead use two 32-bit flags or a unsigned long flags parameter. Arnd <>< ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: perfmon3 interface overview [not found] <7c86c4470809231432j4231cfa4g7dd158a7fe9c9277@mail.gmail.com> 2008-09-25 21:48 ` perfmon3 interface overview stephane eranian @ 2008-10-03 14:44 ` stephane eranian 1 sibling, 0 replies; 15+ messages in thread From: stephane eranian @ 2008-10-03 14:44 UTC (permalink / raw) To: perfmon2-devel; +Cc: linux-kernel, David Gibson Hello, Based on the comments from David Gibson, here is another version of the v3.0 API. This one collapses the system calls to the maximum while still providing a lot of flexbility. We are down to 5 system calls from 12. Of course, each syscall has more of an ioctl()-style to it but types of actions are still well separated. I) session creation With v2.81: int pfm_create_context(pfarg_ctx_t *ctx, char *smpl_name, void *smpl_arg, size_t smpl_size); With v3.0: int pfm_create_session(int flags, pfarg_sinfo_t *sif); int pfm_create_session(int flags, pfarg_sinfo_t *sif, char *smpl_name, void *smpl_arg, size_t smpl_size); Flags: PFM_FL_SMPL_FMT : using sampling format (3 extra params passed) PFM_FL_SYSTEM_WIDE : create a system-wide (cpu-wide) session PFM_FL_OVFL_NO_MSG : do not send overflow message (just signal) typedef { __u64 sif_avail_pmcs[PFM_PMC_BV];/* out: available PMCs */ __u64 sif_avail_pmds[PFM_PMD_BV];/* out: available PMDs */ __u64 sif_reserved1[4]; /* for future use */ } pfarg_sinfo_t; The sinfo structure is systematically returned. It contains bitmasks showing which registers are available to the session. The PMU may be shared with other subsystems, so tools cannot assume they have access to all registers. Furthermore, some registers may not be available to both types of sessions (per-thread, system-wide). If PFM_FL_SMPL_FMT is present, then the kernel expects the extra 3 paramters to describe which kernel sampling format to use, and its optional parameters. II) programming the registers With v2.81: int pfm_write_pmcs(int fd, pfarg_pmc_t *pmds, int n); int pfm_write_pmds(int fd, pfarg_pmd_t *pmcs, int n); int pfm_read_pmds(int fd, parg_pmd_t *pmds, int n); With v3.0: int pfm_write_pmrs(int fd, int flags, void *pmrs, size_t sz); int pfm_read_pmrs(int fd, int flags, void **pmrs, size_t sz); New structures: typedef struct { u16 reg_num; u16 reg_set; u32 reg_flags; u64 reg_value; } pfarg_pmr_t; typedef struct { u16 reg_num; u16 reg_set; u32 reg_flags; u64 reg_value; u64 reg_long_reset; u64 reg_short_reset; u64 reg_random_mask; u64 reg_smpl_pmds[PFM_PMD_BV]; u64 reg_reset_pmds[PFM_PMD_BV]; u64 reg_ovfl_swcnt; u64 reg_smpl_eventid; u64 reg_last_value; u64 reg_reserved[8]; } pfarg_pmd_attr_t; New flags: PFM_RWFL_PMD : passing simplified PMD registers in pfarg_pmr_t PFM_RWFL_PMC : passing PMD registers in pfarg_pmr_t PFM_RWFL_PMD_ATTR: passing full PMD registers in pfarg_pmd_attr_t We now use only 2 system calls to read and write the PMU registers. The vector is now void *. That gives us the ability to pass new types of structure in the future if we have to. Also we now use size instead of count. The calls provides two modes for passing PMD registers. A simplified mode used mostly for counting where no attributes are passed. A full mode, where extended attributes are passed for kernel-level sampling and multiplexing. That way, counting sessions do not pay the price of copying in/out the large set of attributes. There is only one mode to pass PMC registers. III) attaching/detaching, starting/stopping With v2.81: int pfm_load_context(int fd, pfarg_load_t *load); int pfm_unload_context(int fd); int pfm_start(int fd, pfarg_start_t *st); int pfm_stop(int fd); int pfm_restart(int fd); With v3.0: int pfm_control_session(int fd, int flags, int target); New flags: PFM_CTFL_START: start monitoring PFM_CTFL_STOP : stop monitoring PFM_CTFL_RESTART: resume monitoring after a notification PFM_CTFL_ATTACH: attach to thread or CPU designated by 'target' PFM_CTFL_DETACH: detach from thread or CPU (target not used) This is a combined syscall, because all those operations have something in common, they control the state of the session. V) event set and multiplexing With v2.81: int pfm_create_evtsets(int fd, pfarg_setdesc_t *s, int n); int pfm_getinfo_evtsets(int fd, pfarg_setinfo_t *s, int n); int pfm_delete_evtsets(int fd, pfarg_setdesc_t *s, int n); With v3.0: int pfm_control_sets(int fd, int flags, void *s, size_t sz; typedef struct { __u16 set_id; /* which set */ __u16 set_reserved1; /* for future use */ __u32 set_flags; /* SETFL flags */ __u64 set_timeout; /* switch timeout in nsecs */ __u64 reserved[6]; /* for future use */ } pfarg_set_desc; typedef struct { __u16 set_id; /* which set */ __u16 set_reserved1; /* for future use */ __u32 set_reserved2; /* for future use */ __u64 set_ovfl_pmds[PFM_PMD_BV];/* out: last ovfl PMDs */ __u64 set_runs; /* out: #times the set was active */ __u64 set_timeout; /* out: leftover timeout (nsecs) */ __u64 set_duration; /* out: time set was active in nsecs */ __u64 set_reserved3[4]; /* for future use */ } pfarg_set_info; New flags: PFM_STFL_CREAT : create new event sets using pfarg_set_desc_t PFM_STFL_INFO : get info about event sets using pfarg_set_info_t Here again we combine syscall because they all control events sets. The pfm_delete_evtsets() has no equivalent, but it could easily be added if we have a strong need for it. Any opinions on this revised v3.0 interface? Thanks ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2008-10-08 10:09 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <7c86c4470809231432j4231cfa4g7dd158a7fe9c9277@mail.gmail.com>
2008-09-25 21:48 ` perfmon3 interface overview stephane eranian
2008-10-03 6:17 ` David Gibson
[not found] ` <7c86c4470810030354x6984372akfe18761da7504a0c@mail.gmail.com>
2008-10-03 10:58 ` stephane eranian
2008-10-03 11:12 ` stephane eranian
2008-10-04 6:05 ` David Gibson
2008-10-04 7:20 ` stephane eranian
2008-10-05 5:44 ` David Gibson
2008-10-05 5:53 ` David Gibson
2008-10-05 21:23 ` stephane eranian
2008-10-07 3:56 ` David Gibson
2008-10-07 9:46 ` stephane eranian
2008-10-08 0:53 ` David Gibson
2008-10-08 10:09 ` stephane eranian
2008-10-07 9:24 ` [perfmon2] " Arnd Bergmann
2008-10-03 14:44 ` stephane eranian
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
Powered by JetHome