Re: [patch 4/5] x86, ptrace: new ptrace BTS API

2007-12-14 Thread Ingo Molnar

* Markus Metzger <[EMAIL PROTECTED]> wrote:

> Here's the new ptrace BTS API that supports two different overflow 
> handling mechanisms (wrap-around and buffer-full-signal) to support 
> two different use cases (debugging and profiling).
> 
> It further combines buffer allocation and configuration.
> 
> Opens:
> - memory rlimit
> - overflow signal
> 
> What would be the right signal to use?

i think we tend to have such signal targets configurable (like in the 
POSIX timers APIs) - or we could use SIGIO. I've Cc:-ed Ulrich - maybe 
he has some specific ideas how to structure this.

Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[patch 4/5] x86, ptrace: new ptrace BTS API

2007-12-14 Thread Markus Metzger
Here's the new ptrace BTS API that supports two different overflow handling 
mechanisms (wrap-around and buffer-full-signal) to support two different use 
cases (debugging and profiling).

It further combines buffer allocation and configuration.


Opens:
- memory rlimit
- overflow signal

What would be the right signal to use?


Signed-off-by: Markus Metzger <[EMAIL PROTECTED]>
---

Index: linux-2.6-x86/arch/x86/kernel/ds.c
===
--- linux-2.6-x86.orig/arch/x86/kernel/ds.c 2007-12-14 15:31:48.%N +0100
+++ linux-2.6-x86/arch/x86/kernel/ds.c  2007-12-14 15:31:48.%N +0100
@@ -177,18 +177,20 @@
 }
 
 
-int ds_allocate(void **dsp, size_t bts_size_in_records)
+int ds_allocate(void **dsp, size_t bts_size_in_bytes)
 {
-   size_t bts_size_in_bytes = 0;
-   void *bts = 0;
-   void *ds = 0;
+   size_t bts_size_in_records;
+   void *bts;
+   void *ds;
 
if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts)
return -EOPNOTSUPP;
 
-   if (bts_size_in_records < 0)
+   if (bts_size_in_bytes < 0)
return -EINVAL;
 
+   bts_size_in_records =
+   bts_size_in_bytes / ds_cfg.sizeof_bts;
bts_size_in_bytes =
bts_size_in_records * ds_cfg.sizeof_bts;
 
@@ -233,9 +235,21 @@
if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts)
return -EOPNOTSUPP;
 
+   if (!ds)
+   return 0;
+
size_in_bytes =
get_bts_absolute_maximum(ds) -
get_bts_buffer_base(ds);
+   return size_in_bytes;
+}
+
+int ds_get_bts_end(void *ds)
+{
+   size_t size_in_bytes = ds_get_bts_size(ds);
+
+   if (size_in_bytes <= 0)
+   return size_in_bytes;
 
return size_in_bytes / ds_cfg.sizeof_bts;
 }
@@ -254,6 +268,38 @@
return index_offset_in_bytes / ds_cfg.sizeof_bts;
 }
 
+int ds_set_overflow(void *ds, int method)
+{
+   switch (method) {
+   case DS_O_SIGNAL:
+   return -EOPNOTSUPP;
+   case DS_O_WRAP:
+   return 0;
+   default:
+   return -EINVAL;
+   }
+}
+
+int ds_get_overflow(void *ds)
+{
+   return DS_O_WRAP;
+}
+
+int ds_clear(void *ds)
+{
+   int bts_size = ds_get_bts_size(ds);
+   void *bts_base;
+
+   if (bts_size <= 0)
+   return bts_size;
+
+   bts_base = get_bts_buffer_base(ds);
+   memset(bts_base, 0, bts_size);
+
+   set_bts_index(ds, bts_base);
+   return 0;
+}
+
 int ds_read_bts(void *ds, size_t index, struct bts_struct *out)
 {
void *bts;
Index: linux-2.6-x86/arch/x86/kernel/ptrace.c
===
--- linux-2.6-x86.orig/arch/x86/kernel/ptrace.c 2007-12-14 15:31:48.%N +0100
+++ linux-2.6-x86/arch/x86/kernel/ptrace.c  2007-12-14 17:32:40.%N +0100
@@ -33,12 +33,6 @@
 
 
 /*
- * The maximal size of a BTS buffer per traced task in number of BTS
- * records.
- */
-#define PTRACE_BTS_BUFFER_MAX 4000
-
-/*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
  */
@@ -466,17 +460,12 @@
return 0;
 }
 
-static int ptrace_bts_max_buffer_size(void)
-{
-   return PTRACE_BTS_BUFFER_MAX;
-}
-
-static int ptrace_bts_get_buffer_size(struct task_struct *child)
+static int ptrace_bts_get_size(struct task_struct *child)
 {
if (!child->thread.ds_area_msr)
return -ENXIO;
 
-   return ds_get_bts_size((void *)child->thread.ds_area_msr);
+   return ds_get_bts_index((void *)child->thread.ds_area_msr);
 }
 
 static int ptrace_bts_read_record(struct task_struct *child,
@@ -485,7 +474,7 @@
 {
struct bts_struct ret;
int retval;
-   int bts_size;
+   int bts_end;
int bts_index;
 
if (!child->thread.ds_area_msr)
@@ -494,15 +483,15 @@
if (index < 0)
return -EINVAL;
 
-   bts_size = ds_get_bts_size((void *)child->thread.ds_area_msr);
-   if (bts_size <= index)
+   bts_end = ds_get_bts_end((void *)child->thread.ds_area_msr);
+   if (bts_end <= index)
return -EINVAL;
 
/* translate the ptrace bts index into the ds bts index */
bts_index = ds_get_bts_index((void *)child->thread.ds_area_msr);
bts_index -= (index + 1);
if (bts_index < 0)
-   bts_index += bts_size;
+   bts_index += bts_end;
 
retval = ds_read_bts((void *)child->thread.ds_area_msr,
 bts_index, );
@@ -530,19 +519,97 @@
return sizeof(*in);
 }
 
-static int ptrace_bts_config(struct task_struct *child,
-unsigned long options)
+static int ptrace_bts_clear(struct task_struct *child)
 {
-   unsigned long debugctl_mask = ds_debugctl_mask();
-   int retval;
+   if (!child->thread.ds_area_msr)
+   return -ENXIO;
 
-   retval = ptrace_bts_get_buffer_size(child);
-   if 

[patch 4/5] x86, ptrace: new ptrace BTS API

2007-12-14 Thread Markus Metzger
Here's the new ptrace BTS API that supports two different overflow handling 
mechanisms (wrap-around and buffer-full-signal) to support two different use 
cases (debugging and profiling).

It further combines buffer allocation and configuration.


Opens:
- memory rlimit
- overflow signal

What would be the right signal to use?


Signed-off-by: Markus Metzger [EMAIL PROTECTED]
---

Index: linux-2.6-x86/arch/x86/kernel/ds.c
===
--- linux-2.6-x86.orig/arch/x86/kernel/ds.c 2007-12-14 15:31:48.%N +0100
+++ linux-2.6-x86/arch/x86/kernel/ds.c  2007-12-14 15:31:48.%N +0100
@@ -177,18 +177,20 @@
 }
 
 
-int ds_allocate(void **dsp, size_t bts_size_in_records)
+int ds_allocate(void **dsp, size_t bts_size_in_bytes)
 {
-   size_t bts_size_in_bytes = 0;
-   void *bts = 0;
-   void *ds = 0;
+   size_t bts_size_in_records;
+   void *bts;
+   void *ds;
 
if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts)
return -EOPNOTSUPP;
 
-   if (bts_size_in_records  0)
+   if (bts_size_in_bytes  0)
return -EINVAL;
 
+   bts_size_in_records =
+   bts_size_in_bytes / ds_cfg.sizeof_bts;
bts_size_in_bytes =
bts_size_in_records * ds_cfg.sizeof_bts;
 
@@ -233,9 +235,21 @@
if (!ds_cfg.sizeof_ds || !ds_cfg.sizeof_bts)
return -EOPNOTSUPP;
 
+   if (!ds)
+   return 0;
+
size_in_bytes =
get_bts_absolute_maximum(ds) -
get_bts_buffer_base(ds);
+   return size_in_bytes;
+}
+
+int ds_get_bts_end(void *ds)
+{
+   size_t size_in_bytes = ds_get_bts_size(ds);
+
+   if (size_in_bytes = 0)
+   return size_in_bytes;
 
return size_in_bytes / ds_cfg.sizeof_bts;
 }
@@ -254,6 +268,38 @@
return index_offset_in_bytes / ds_cfg.sizeof_bts;
 }
 
+int ds_set_overflow(void *ds, int method)
+{
+   switch (method) {
+   case DS_O_SIGNAL:
+   return -EOPNOTSUPP;
+   case DS_O_WRAP:
+   return 0;
+   default:
+   return -EINVAL;
+   }
+}
+
+int ds_get_overflow(void *ds)
+{
+   return DS_O_WRAP;
+}
+
+int ds_clear(void *ds)
+{
+   int bts_size = ds_get_bts_size(ds);
+   void *bts_base;
+
+   if (bts_size = 0)
+   return bts_size;
+
+   bts_base = get_bts_buffer_base(ds);
+   memset(bts_base, 0, bts_size);
+
+   set_bts_index(ds, bts_base);
+   return 0;
+}
+
 int ds_read_bts(void *ds, size_t index, struct bts_struct *out)
 {
void *bts;
Index: linux-2.6-x86/arch/x86/kernel/ptrace.c
===
--- linux-2.6-x86.orig/arch/x86/kernel/ptrace.c 2007-12-14 15:31:48.%N +0100
+++ linux-2.6-x86/arch/x86/kernel/ptrace.c  2007-12-14 17:32:40.%N +0100
@@ -33,12 +33,6 @@
 
 
 /*
- * The maximal size of a BTS buffer per traced task in number of BTS
- * records.
- */
-#define PTRACE_BTS_BUFFER_MAX 4000
-
-/*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
  */
@@ -466,17 +460,12 @@
return 0;
 }
 
-static int ptrace_bts_max_buffer_size(void)
-{
-   return PTRACE_BTS_BUFFER_MAX;
-}
-
-static int ptrace_bts_get_buffer_size(struct task_struct *child)
+static int ptrace_bts_get_size(struct task_struct *child)
 {
if (!child-thread.ds_area_msr)
return -ENXIO;
 
-   return ds_get_bts_size((void *)child-thread.ds_area_msr);
+   return ds_get_bts_index((void *)child-thread.ds_area_msr);
 }
 
 static int ptrace_bts_read_record(struct task_struct *child,
@@ -485,7 +474,7 @@
 {
struct bts_struct ret;
int retval;
-   int bts_size;
+   int bts_end;
int bts_index;
 
if (!child-thread.ds_area_msr)
@@ -494,15 +483,15 @@
if (index  0)
return -EINVAL;
 
-   bts_size = ds_get_bts_size((void *)child-thread.ds_area_msr);
-   if (bts_size = index)
+   bts_end = ds_get_bts_end((void *)child-thread.ds_area_msr);
+   if (bts_end = index)
return -EINVAL;
 
/* translate the ptrace bts index into the ds bts index */
bts_index = ds_get_bts_index((void *)child-thread.ds_area_msr);
bts_index -= (index + 1);
if (bts_index  0)
-   bts_index += bts_size;
+   bts_index += bts_end;
 
retval = ds_read_bts((void *)child-thread.ds_area_msr,
 bts_index, ret);
@@ -530,19 +519,97 @@
return sizeof(*in);
 }
 
-static int ptrace_bts_config(struct task_struct *child,
-unsigned long options)
+static int ptrace_bts_clear(struct task_struct *child)
 {
-   unsigned long debugctl_mask = ds_debugctl_mask();
-   int retval;
+   if (!child-thread.ds_area_msr)
+   return -ENXIO;
 
-   retval = ptrace_bts_get_buffer_size(child);
-   if (retval  0)
- 

Re: [patch 4/5] x86, ptrace: new ptrace BTS API

2007-12-14 Thread Ingo Molnar

* Markus Metzger [EMAIL PROTECTED] wrote:

 Here's the new ptrace BTS API that supports two different overflow 
 handling mechanisms (wrap-around and buffer-full-signal) to support 
 two different use cases (debugging and profiling).
 
 It further combines buffer allocation and configuration.
 
 Opens:
 - memory rlimit
 - overflow signal
 
 What would be the right signal to use?

i think we tend to have such signal targets configurable (like in the 
POSIX timers APIs) - or we could use SIGIO. I've Cc:-ed Ulrich - maybe 
he has some specific ideas how to structure this.

Ingo
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/