trace_kmem_cache_alloc()はどこにいるの?と思ったのでめもです。
まずはこのkmem_cache_alloc_trace()を呼んでいるのはどこかというとslub.cのkmem_cache_alloc()です。あ、うちはslabじゃなくてslubを使ってるのでファイルはslub.cを参照してます(;´∀`)
ソースはこれですね。
2398 void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags) 2399 { 2400 void *ret = slab_alloc(s, gfpflags, _RET_IP_); 2401 2402 trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size, s->size, gfpflags); 2403 2404 return ret; 2405 }
この2402行目のtrace_kmem_cache_alloc()ですが、これは普通にgrepとかしても見つかりません/(^o^)\ Linuxカーネルにかぎらないけどマクロを使って関数とか構造体を定義するパターンありますよね~ trace_kmem_cache_alloc()もそのパターンです。ちなみにNetBSDのmbufもマクロで定義してますね。FreeBSDは違いましたけど。
/* * Definition of "struct mbuf". * Don't change this without understanding how MHLEN/MLEN are defined. */ #define MBUF_DEFINE(name, mhlen, mlen) \ struct name { \ struct m_hdr m_hdr; \ union { \ struct { \ struct pkthdr MH_pkthdr; \ union { \ struct _m_ext MH_ext; \ char MH_databuf[(mhlen)]; \ } MH_dat; \ } MH; \ char M_databuf[(mlen)]; \ } M_dat; \ } /* * The *real* struct mbuf */ MBUF_DEFINE(mbuf, MHLEN, MLEN);
与太話はさておきtrace_kmem_cache_alloc()はどこで定義しているのかというとinclude/trace/events/kmem.hで以下のようになってます。
53 DEFINE_EVENT(kmem_alloc, kmem_cache_alloc, 54 55 TP_PROTO(unsigned long call_site, const void *ptr, 56 size_t bytes_req, size_t bytes_alloc, gfp_t gfp_flags), 57 58 TP_ARGS(call_site, ptr, bytes_req, bytes_alloc, gfp_flags) 59 ); 60
そしてこのマクロ達はどこにあるかというと[http://lxr.free-electrons.com/source/include/linux/tracepoint.h
:title=include/linux/tracepoint.h]にあります。
そしてDEFINE_EVENTマクロを見ていくと最終的に__DECLARE_TRACEマクロにたどり着きます。ホントはCONFIG_TRACEPOINTSが定義されてるかで変わりますけど、CONFIG_TRACEPOINTSが定義されていない場合は空の関数を作るだけなのでCONFIG_TRACEPOINTSアリの場合を見ましょう。。。
155 /* 156 * Make sure the alignment of the structure in the __tracepoints section will 157 * not add unwanted padding between the beginning of the section and the 158 * structure. Force alignment to the same alignment as the section start. 159 */ 160 #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \ 161 extern struct tracepoint __tracepoint_##name; \ 162 static inline void trace_##name(proto) \ 163 { \ 164 if (static_key_false(&__tracepoint_##name.key)) \ 165 __DO_TRACE(&__tracepoint_##name, \ 166 TP_PROTO(data_proto), \ 167 TP_ARGS(data_args), \ 168 TP_CONDITION(cond),,); \ 169 } \ 170 __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args), \ 171 PARAMS(cond), PARAMS(data_proto), PARAMS(data_args)) \ 172 static inline int \ 173 register_trace_##name(void (*probe)(data_proto), void *data) \ 174 { \ 175 return tracepoint_probe_register(#name, (void *)probe, \ 176 data); \ 177 } \ 178 static inline int \ 179 unregister_trace_##name(void (*probe)(data_proto), void *data) \ 180 { \ 181 return tracepoint_probe_unregister(#name, (void *)probe, \ 182 data); \ 183 } \ 184 static inline void \ 185 check_trace_callback_type_##name(void (*cb)(data_proto)) \ 186 { \ 187 }
このマクロを見ると関数名にtrace_が付加されることがわかりますね。
DEFINE_EVENTマクロの2番目の引数がnameでこれをDECLARE_TRACEマクロの一番目の引数として渡します。
379 #define DEFINE_EVENT(template, name, proto, args) \ 380 DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
そうすると、kmem.hではkmem_cache_allocがnameになるので__DECLARE_TRACEマクロによってtrace_kmem_cache_allocという関数が作られるわけです。
ということでLinuxカーネルコードでtrace_xxx()という関数があったらイベントトレーサー用の関数だってことが分かりますね( ´∀`)bグッ!
今回のまとめとしては、普通にgrepしたりctagsやlxr等で見つからない関数や構造体があったらマクロで作られていると考えると良いかと思います。
自分はtrace_kmem_cache_alloc()を探すときにslub.cでincludeしているtrace/events/kmem.hが怪しいんじゃね?というところと名前にtraceがついているのでトレーサー関係だよな~というところから__DECLARE_TRACEマクロにたどり着きました(;´Д`)
そういえば_RET_IP_は予想通りな内容でした。
107 #define _RET_IP_ (unsigned long)__builtin_return_address(0)
( ´Д`)ノ~