10分間カーネルソースリーティング(timeシステムコールその2、というよりシステムコールのマクロ)

今日は帰宅が遅かった。なので、あまりソースを読む時間がとれない。

昨日はtimeシステムコールが何をしていたのかを調べた。
ところで、SYSCALL_DEFINE1って何だろ?これを調べるためにinclude/linux/syscalls.hを覗いてみる。

#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)

さらにSYSCALL_DEFINExを追いかける。

#ifdef CONFIG_FTRACE_SYSCALLS
#define SYSCALL_DEFINEx(x, sname, ...)        \
  static const char *types_##sname[] = {      \
    __SC_STR_TDECL##x(__VA_ARGS__)      \
  };              \
  static const char *args_##sname[] = {     \
    __SC_STR_ADECL##x(__VA_ARGS__)      \
  };              \
  SYSCALL_METADATA(sname, x);       \
  __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#else
#define SYSCALL_DEFINEx(x, sname, ...)        \
  __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
#endif

今度は__SYSCALL_DEFINExを追う。

#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS

#define SYSCALL_DEFINE(name) static inline long SYSC_##name

#define __SYSCALL_DEFINEx(x, name, ...)         \
  asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__));   \
  static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__)); \
  asmlinkage long SyS##name(__SC_LONG##x(__VA_ARGS__))    \
  {               \
    __SC_TEST##x(__VA_ARGS__);        \
    return (long) SYSC##name(__SC_CAST##x(__VA_ARGS__));  \
  }               \
  SYSCALL_ALIAS(sys##name, SyS##name);        \
  static inline long SYSC##name(__SC_DECL##x(__VA_ARGS__))

#else /* CONFIG_HAVE_SYSCALL_WRAPPERS */

#define SYSCALL_DEFINE(name) asmlinkage long sys_##name
#define __SYSCALL_DEFINEx(x, name, ...)         \
  asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))

#endif /* CONFIG_HAVE_SYSCALL_WRAPPERS */

まずは、例によってより簡単なCONFIG_FTRACE_SYSCALLS、CONFIG_HAVE_SYSCALL_WRAPPERS両者が定義されていない場合を追ってみる。

ここまでのところで分かっているマクロを置き換えると

asmlinkage long sys_time(__SC_DECL1(__VA_ARGS__))

となる。

さらに残りの定義を追う。

#define __SC_DECL1(t1, a1)  t1 a1

__VA_ARGS__は可変長引数マクロなので、

asmlinkage long sys_time(__SC_DECL1(__VA_ARGS__))

は最終的に

asmlinkage long sys_time(time_t __user * tloc)

となる。

__userは__CHECKER__マクロの有無によって変化し、__CHECKER__マクロが有効な時はtlocがユーザ空間を指すポインタかどうかのチェックをsparseにより行うためのものである。
(kosakiさん情報ありがとう!)

#ifdef __CHECKER__
# define __user   __attribute__((noderef, address_space(1)))
(中略)
#else
# define __user

やはり、CONFIG_FTRACE_SYSCALLSとCONFIG_HAVE_SYSCALL_WRAPPERSが気になる。名前から察するに何らかのデバッグ機能かな?
この予想の元、ftraceをググってみると、http://www.atmarkit.co.jp/flinux/rensai/watch2009/watch03a.html
という情報が見つかった。
CONFIG_HAVE_SYSCALL_WRAPPERSはググったけれど有用な情報がなさげなので、読んでみるしかあるまい。

ということで、次回はCONFIG_FTRACE_SYSCALLSとCONFIG_HAVE_SYSCALL_WRAPPERSを見てみたい。(他の事に興味が湧いたらごめんね)