This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Support ENABLED sdt probe macro


uprobe and utrace are now supported similarly.

uprobe
stap_uprobe_spec add tsk and sdt_sem_address, initialize
stap_uprobe_change increment the semaphore variable using __access_process_vm
systemtap_module_exit decrement all the semaphore variables


utrace
stap_utrace_probe add tsk and sdt_sem_address, initialize
_stp_utrace_probe_cb increment the semaphore variable
systemtap_module_exit decrement all the semaphore variables

session.h add std::map<Dwarf_Addr, derived_probe*> sdt_semaphore_addr;
tapsets.cxx record it
tapsets.cxx allow for uprobe enable variable to be set and unset
tapset-utrace.cxx all for utrace enable variable to be set and unset

Here are some performance results for a looping test:
uprobe and stap
1.06user 11.03system 0:12.17elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+1248outputs (0major+8354minor)pagefaults 0swaps
utrace and stap
0.67user 4.33system 0:05.08elapsed 98%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+1024outputs (0major+7945minor)pagefaults 0swaps
kprobe and stap
1.08user 0.55system 0:01.66elapsed 98%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+936outputs (0major+25594minor)pagefaults 0swaps
uprobe no stap
real 0m0.004s user 0m0.004s sys 0m0.000s
utrace no stap
real 0m0.004s user 0m0.002s sys 0m0.002s
kprobe no stap
real 0m0.003s user 0m0.002s sys 0m0.002s



diff --git a/dtrace.in b/dtrace.in
index 168bfb1..21d313c 100755
--- a/dtrace.in
+++ b/dtrace.in
@@ -17,9 +17,17 @@ from subprocess import call
 from tempfile import mkstemp
 
 class provider:
+    semaphores_def = "\n"
+    # is the type a basic scalar type?
+    def basic_type(self, arg):
+        basic_types = [ "int","int*","long","long*","short","short int","unsigned long","char","char*","float","double" ]
+        split_arg = arg.rsplit(None,1)
+        return (split_arg[0].strip() in basic_types) & (arg.find("[") == -1)
     def typedef_append(self, typedefs,this_probe,arg,c):
         if (add_typedefs):
             split_arg = arg.rsplit(None,1)
+            if (self.basic_type(arg)):
+                return typedefs
             type_name = " %s_arg%d" % (this_probe.replace("__","_"),c)
             if (len(split_arg) > 1):
                 typedefs += ("typedef " + arg.replace(" " + split_arg[1].split("[")[0].lstrip("*"),type_name).strip() + "; ")
@@ -28,11 +36,17 @@ class provider:
                 typedefs += ("typedef " + arg.strip() + type_name + "; ")
                 typedefs += (type_name + type_name + "_v;\n")
         return typedefs
+    def semaphore_def_append(self, this_probe):
+        self.semaphores_def += "__extension__ long %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe)
+    def semaphore_def_write(self, file):
+        file.write(self.semaphores_def)
     def generate(self, provider, header, add_typedefs):
         have_provider = False
         self.f = open(provider)
         self.h = open(header,mode='w')
         self.h.write("/* Generated by the Systemtap dtrace wrapper */\n")
+        if (build_source):
+            self.h.write("\n#define STAP_HAS_SEMAPHORES 1\n\n")
         self.h.write("\n#include <sys/sdt.h>\n\n")
         in_comment = False
         typedefs = ""
@@ -64,6 +78,7 @@ class provider:
                 arg = ""
                 i = 0
                 c = 0
+                self.semaphore_def_append (this_probe)
                 while (i < len(args)):
                     if (args[i:i+1] == ","):
                         args_string = ('%s %s,' % (args_string, arg.strip()))
@@ -91,7 +106,8 @@ class provider:
                     stap_str = stap_str + ",arg%s" % (i);
                     i += 1
                 self.h.write ('/* %s (%s) */\n' % (this_probe_canon,args_string))
-                self.h.write ('#define %s_ENABLED() 1\n' % this_probe_canon)
+                self.h.write ('#define %s_ENABLED() %s_semaphore\n' % (this_probe_canon,this_probe))
+                self.h.write ("__extension__ extern long %s_semaphore __attribute__ ((unused)) __attribute__ ((section (\".probes\")));\n" % (this_probe))
                 self.h.write (define_str + ") \\\n")
                 self.h.write (stap_str + ")\n\n")
             elif (line.find("}") != -1 and have_provider):
@@ -176,9 +192,17 @@ if (build_header):
 elif (build_source):
     (basename,ext) = os.path.splitext(s_filename)
     basename = os.path.basename(basename)
+
+    # create for semaphore_def_write
+    providers = provider()
+    (d,fn) = mkstemp(suffix=".h",prefix=basename)
+    providers.generate(s_filename, fn, add_typedefs)
+    os.remove(fn)
+
     (d,fn) = mkstemp(suffix=".c",prefix=basename)
     f = open(fn,mode='w')
     f.write("static __dtrace () {}\n")
+    providers.semaphore_def_write(f)
     f.close()
     call(["gcc", "-fPIC", "-I.", "-I@prefix@/include", "-g", "-c", fn, "-o", os.path.basename(filename) + ".o"], shell=False)
     os.remove(fn)
diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h
index f179c2a..6f3aaab 100644
--- a/includes/sys/sdt.h
+++ b/includes/sys/sdt.h
@@ -252,21 +252,31 @@ extern long int syscall (long int __sysno, ...) __THROW;
 # define STAP_GUARD 0x33425250
 # endif
 
+#ifdef STAP_HAS_SEMAPHORES
+#define STAP_SEMAPHORE(probe)			\
+  if ( probe ## _semaphore )
+#else
+#define STAP_SEMAPHORE(probe) ;
+#endif
+
 #include <sys/syscall.h>
 
 #define STAP_PROBE_(probe)			\
+STAP_SEMAPHORE(probe) \
 do {						\
-  STAP_PROBE_DATA(probe,STAP_SYSCALL,0);	\
+  STAP_PROBE_DATA(probe,STAP_GUARD,0);	\
   syscall (STAP_SYSCALL, #probe, STAP_GUARD);	\
  } while (0)
 
 #define STAP_PROBE1_(probe,label,parm1)				\
+STAP_SEMAPHORE(probe) \
 do {								\
   STAP_PROBE_DATA(probe,STAP_GUARD,1);				\
   syscall (STAP_SYSCALL, #probe, STAP_GUARD, (size_t)parm1);	\
  } while (0)
 
 #define STAP_PROBE2_(probe,label,parm1,parm2)				\
+STAP_SEMAPHORE(probe) \
 do {									\
   __extension__ struct {size_t arg1 __attribute__((aligned(8)));	\
 	  size_t arg2 __attribute__((aligned(8)));}			\
@@ -276,16 +286,18 @@ do {									\
  } while (0)
 
 #define STAP_PROBE3_(probe,label,parm1,parm2,parm3)			\
+STAP_SEMAPHORE(probe)  \
 do {									\
   __extension__ struct {size_t arg1 __attribute__((aligned(8)));	\
 	  size_t arg2 __attribute__((aligned(8)));			\
 	  size_t arg3 __attribute__((aligned(8)));}			\
   stap_probe3_args = {(size_t)parm1, (size_t)parm2, (size_t)parm3};	\
   STAP_PROBE_DATA(probe,STAP_GUARD,3);					\
-  syscall (STAP_SYSCALL, #probe, STAP_GUARD, &stap_probe3_args);		\
+  syscall (STAP_SYSCALL, #probe, STAP_GUARD, &stap_probe3_args);	\
  } while (0)
 
 #define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4)		\
+STAP_SEMAPHORE(probe)  \
 do {									\
   __extension__ struct {size_t arg1 __attribute__((aligned(8)));	\
 	  size_t arg2 __attribute__((aligned(8)));			\
@@ -293,10 +305,11 @@ do {									\
 	  size_t arg4 __attribute__((aligned(8)));}			\
   stap_probe4_args = {(size_t)parm1, (size_t)parm2, (size_t)parm3, (size_t)parm4}; \
   STAP_PROBE_DATA(probe,STAP_GUARD,4);					\
-  syscall (STAP_SYSCALL, #probe, STAP_GUARD,&stap_probe4_args);		\
+  syscall (STAP_SYSCALL, #probe, STAP_GUARD,&stap_probe4_args);	\
  } while (0)
 
 #define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5)		\
+STAP_SEMAPHORE(probe)  \
 do {									\
   __extension__ struct {size_t arg1 __attribute__((aligned(8)));			\
 	  size_t arg2 __attribute__((aligned(8)));			\
@@ -310,6 +323,7 @@ do {									\
  } while (0)
 
 #define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6)	\
+STAP_SEMAPHORE(probe)  \
 do {									\
   __extension__ struct {size_t arg1 __attribute__((aligned(8)));			\
 	  size_t arg2 __attribute__((aligned(8)));			\
@@ -324,6 +338,7 @@ do {									\
  } while (0)
 
 #define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \
+STAP_SEMAPHORE(probe)  \
 do {									\
   __extension__ struct {size_t arg1 __attribute__((aligned(8)));			\
 	  size_t arg2 __attribute__((aligned(8)));			\
@@ -339,6 +354,7 @@ do {									\
  } while (0)
 
 #define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \
+STAP_SEMAPHORE(probe)  \
 do {									\
   __extension__ struct {size_t arg1 __attribute__((aligned(8)));			\
 	  size_t arg2 __attribute__((aligned(8)));			\
@@ -355,6 +371,7 @@ do {									\
  } while (0)
 
 #define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \
+STAP_SEMAPHORE(probe)  \
 do {									\
   __extension__ struct {size_t arg1 __attribute__((aligned(8)));			\
 	  size_t arg2 __attribute__((aligned(8)));			\
@@ -372,6 +389,7 @@ do {									\
  } while (0)
 
 #define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \
+STAP_SEMAPHORE(probe)  \
 do {									\
   __extension__ struct {size_t arg1 __attribute__((aligned(8)));			\
 	  size_t arg2 __attribute__((aligned(8)));			\
@@ -385,7 +403,7 @@ do {									\
 	  size_t arg10 __attribute__((aligned(8)));}			\
   stap_probe10_args = {(size_t)parm1, (size_t)parm2, (size_t)parm3, (size_t)parm4, \
 	(size_t)parm5, (size_t)parm6, (size_t)parm7, (size_t)parm8, (size_t)parm9, (size_t)parm10}; \
-  STAP_PROBE_DATA(probe,STAP_GUARD,10);					\
+  STAP_PROBE_DATA(probe,STAP_GUARD,10);				\
   syscall (STAP_SYSCALL, #probe, STAP_GUARD, &stap_probe10_args);		\
  } while (0)
 

diff --git a/session.h b/session.h
index ea91442..861f012 100644
--- a/session.h
+++ b/session.h
@@ -221,6 +221,10 @@ struct systemtap_session
   void print_error_source (std::ostream&, std::string&, const token* tok);
   void print_warning (const std::string& w, const token* tok = 0);
 
+
+  // Location of semaphores to activate sdt probes
+  std::map<Dwarf_Addr, derived_probe*> sdt_semaphore_addr;
+
   // NB: It is very important for all of the above (and below) fields
   // to be cleared in the systemtap_session ctor (elaborate.cxx)
   // and/or main.cxx(main).

diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx
index a07e08b..20bd4de 100644
--- a/tapset-utrace.cxx
+++ b/tapset-utrace.cxx
@@ -716,6 +716,15 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s,
       break;
     }
   s.op->line() << " .engine_attached=0,";
+  map<Dwarf_Addr, derived_probe*>::iterator its;
+  for (its = s.sdt_semaphore_addr.begin();
+       its != s.sdt_semaphore_addr.end();
+       its++)
+    {
+      if (p == ((struct utrace_derived_probe*)(its->second)))
+	s.op->line() << " .sdt_sem_address=(unsigned long)0x" << hex << its->first << dec << "ULL,";
+    }
+  s.op->line() << " .tsk=0,";
   s.op->line() << " },";
 }
 
@@ -750,6 +759,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "struct utrace_engine_ops ops;";
   s.op->newline() << "unsigned long events;";
   s.op->newline() << "int engine_attached;";
+  s.op->newline() << "struct task_struct *tsk;";
+  s.op->newline() << "unsigned long sdt_sem_address;";
   s.op->newline(-1) << "};";
 
 
@@ -872,6 +883,15 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "break;";
   s.op->indent(-1);
   s.op->newline(-1) << "}";
+
+  s.op->newline() << "{";
+  s.op->newline(1) << "size_t sdt_semaphore;";
+  s.op->newline() << "p->tsk = tsk;";
+  s.op->newline() << "__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);";
+  s.op->newline() << "sdt_semaphore += 1;";
+  s.op->newline() << "__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);";
+  s.op->newline(-1) << "}";
+
   s.op->newline(-1) << "}";
 
   // Since this engine could be attached to multiple threads, don't
@@ -1045,6 +1065,26 @@ utrace_derived_probe_group::emit_module_exit (systemtap_session& s)
   s.op->newline() << "stap_utrace_detach_ops(&p->ops);";
   s.op->newline(-1) << "}";
   s.op->newline(-1) << "}";
+
+  int sem_idx = 0;
+  if (! s.sdt_semaphore_addr.empty())
+    for (p_b_path_iterator it = probes_by_path.begin();
+	 it != probes_by_path.end(); it++)
+      {
+	s.op->newline() << "{";
+	s.op->indent(1);
+	s.op->newline() << "size_t sdt_semaphore;";
+	s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {";
+	s.op->newline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];";
+
+	s.op->newline() << "__access_process_vm (p->tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);";
+	s.op->newline() << "sdt_semaphore -= 1;";
+	s.op->newline() << "__access_process_vm (p->tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);";
+	
+	s.op->newline(-1) << "}";
+	s.op->newline(-1) << "}";
+	sem_idx += it->second.size() - 1;
+      }
 }
 
 
diff --git a/tapsets.cxx b/tapsets.cxx
index f91d15d..2b59b89 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -3350,6 +3350,7 @@ private:
 
   probe * base_probe;
   probe_point * base_loc;
+  literal_map_t const & params;
   vector<derived_probe *> & results;
   string mark_name;
 
@@ -3365,6 +3366,7 @@ private:
   bool get_next_probe();
 
   void convert_probe(probe *base);
+  void record_semaphore(vector<derived_probe *> & results);
   void convert_location(probe *base, probe_point *location);
 };
 
@@ -3373,7 +3375,7 @@ sdt_query::sdt_query(probe * base_probe, probe_point * base_loc,
                      dwflpp & dw, literal_map_t const & params,
                      vector<derived_probe *> & results):
   base_query(dw, params), base_probe(base_probe),
-  base_loc(base_loc), results(results)
+  base_loc(base_loc), params(params), results(results)
 {
   assert(get_string_param(params, TOK_MARK, mark_name));
 }
@@ -3415,7 +3417,11 @@ sdt_query::handle_query_module()
       unsigned i = results.size();
 
       if (probe_type == kprobe_type || probe_type == utrace_type)
-        derive_probes(sess, new_base, results);
+	{
+	  derive_probes(sess, new_base, results);
+	  record_semaphore(results);
+	}
+      
       else
         {
           literal_map_t params;
@@ -3428,6 +3434,7 @@ sdt_query::handle_query_module()
           dwarf_query q(new_base, new_location, dw, params, results);
           q.has_mark = true; // enables mid-statement probing
           dw.iterate_over_modules(&query_module, &q);
+	  record_semaphore(results);
         }
 
       if (sess.listing_mode)
@@ -3559,6 +3566,28 @@ sdt_query::get_next_probe()
 
 
 void
+sdt_query::record_semaphore (vector<derived_probe *> & results)
+{
+  int sym_count = dwfl_module_getsymtab(dw.module);
+  assert (sym_count >= 0);
+  for (int i = 0; i < sym_count; i++)
+    {
+      GElf_Sym sym;
+      GElf_Word shndxp;
+      char *sym_str = (char*)dwfl_module_getsym (dw.module, i, &sym, &shndxp);
+      if (strcmp(sym_str, string(probe_name + "_semaphore").c_str()) == 0)
+	{
+	  string process_name;
+	  derived_probe_builder::get_param(params, TOK_PROCESS, process_name);
+          for (unsigned int i = 0; i < results.size(); ++i)
+	      sess.sdt_semaphore_addr.insert(make_pair(sym.st_value, results[i]));
+	  break;
+	}
+    }
+}
+
+
+void
 sdt_query::convert_probe (probe *base)
 {
   block *b = new block;
@@ -3709,7 +3738,6 @@ sdt_query::convert_location (probe *base, probe_point *location)
   base->locations.push_back(location);
 }
 
-
 void
 dwarf_builder::build(systemtap_session & sess,
 		     probe * base,
@@ -4423,6 +4451,8 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline() << "const char *pathname;";
   s.op->newline() << "const char *pp;";
   s.op->newline() << "void (*ph) (struct context*);";
+  s.op->newline() << "unsigned long sdt_sem_address;";
+  s.op->newline() << "struct task_struct *tsk;";
   s.op->newline() << "unsigned return_p:1;";
   s.op->newline(-1) << "} stap_uprobe_specs [] = {";
   s.op->indent(1);
@@ -4442,7 +4472,16 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
       s.op->line() << " .address=(unsigned long)0x" << hex << p->address << dec << "ULL,";
       s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ",";
       s.op->line() << " .ph=&" << p->name << ",";
-      if (p->return_p) s.op->line() << " .return_p=1,";
+  map<Dwarf_Addr, derived_probe*>::iterator its;
+  for (its = s.sdt_semaphore_addr.begin();
+       its != s.sdt_semaphore_addr.end();
+       its++)
+    {
+      if (p->module == ((struct uprobe_derived_probe*)(its->second))->module
+	  && p->address == ((struct uprobe_derived_probe*)(its->second))->address)
+	s.op->line() << " .sdt_sem_address=(unsigned long)0x" << hex << its->first << dec << "ULL,";
+    }
+  if (p->return_p) s.op->line() << " .return_p=1,";
       s.op->line() << " },";
     }
   s.op->newline(-1) << "};";
@@ -4626,6 +4665,16 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
   s.op->newline(-1) << "}";
   s.op->newline(-1) << "}";
 
+  //----------
+  s.op->newline() << "{";
+  s.op->newline(1) << "size_t sdt_semaphore;";
+  s.op->newline() << "sups->tsk = tsk;";
+  s.op->newline() << "__access_process_vm (tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);";
+  s.op->newline() << "sdt_semaphore += 1;";
+  s.op->newline() << "__access_process_vm (tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);";
+  s.op->newline(-1) << "}";
+  //----------
+
   s.op->newline() << "return 0;"; // XXX: or rc?
   s.op->newline(-1) << "}";
   s.op->assert_0_indent();
@@ -4730,6 +4779,16 @@ uprobe_derived_probe_group::emit_module_exit (systemtap_session& s)
   s.op->newline() << "struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
   s.op->newline() << "if (sup->spec_index < 0) continue;"; // free slot
 
+  //----------
+  s.op->newline() << "{";
+  s.op->newline(1) << "size_t sdt_semaphore;";
+  s.op->newline() << "__access_process_vm (sups->tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);";
+  s.op->newline() << "sdt_semaphore -= 1;";
+  s.op->newline() << "__access_process_vm (sups->tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);";
+  s.op->newline(-1) << "}";
+  //----------
+
+
   s.op->newline() << "if (sups->return_p) {";
   s.op->newline(1) << "#ifdef DEBUG_UPROBES";
   s.op->newline() << "printk (KERN_INFO \"-uretprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->up.pid, (void*) sup->up.vaddr);";

diff --git a/translate.cxx b/translate.cxx
index 4a6a10b..3cc4fee 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -5177,6 +5177,8 @@ translate_pass (systemtap_session& s)
       s.op->newline() << "#include <linux/version.h>";
       // s.op->newline() << "#include <linux/compile.h>";
       s.op->newline() << "#include \"loc2c-runtime.h\" ";
+      if (! s.sdt_semaphore_addr.empty())
+	s.op->newline() << "#include \"access_process_vm.h\" ";
 
       // XXX: old 2.6 kernel hack
       s.op->newline() << "#ifndef read_trylock";

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]