By Shirou [F.a.w] WAKAYAMA
Pentium Counter
thanks for ngt and tsuboi.
pentium counter は,RDTSC (Real Time-Stamp Counter)命令によって読むこ
とができる 64 ビットのタイムスタンプのことです.このカウンタは CPU が
リセットされてから何ステップ経過したかを cycle 単位で数えています.
さて,その pentium counter ですが,FreeBSD では
% sysctl machdep.tsc_freq
で値がかえってくれば,そのマシンでは pentium カウンタがとれます.かえっ
てくる値は CPU クロックの値です.
# ちなみに athlon ではかえってこない.
で,プログラム的にどー取るかというと,
#define readTSC(x) __asm __volatile(".byte 0x0f, 0x31" : "=A" (x))
とか宣言しておいて,x に 64 bit な変数(たとえば int64_t)をつっこんでや
ると取れると思います.
## ちなみに athlon だと machdep.tsc_freq は取れないので,CPU のクロッ
## クは自分で調べないと駄目.
### CPUの実クロック数の調べ方としては、boot -vで起動することで、
### boot message(dmesg中にも)に TSC clockと、値が表示されるようになります。
### FreeBSD-4.7Sで確認。 thanks > nobuo
#### でも、これだと、いちいち再起動しなきゃいけないので、他の方法があれ
#### ばいいなぁ。
これで得られるのは cycle 数なので,時間をはかる始点と終点の cycle 数を
引いて,CPU クロック(Hz)でわらなければならない.
これで出てくる値が実際に始点から終点までにかかった時間(ナノ秒)となる.
測定をする時,gettimeofday はやめましょう :-)
以下にプログラム例を書きます。
#define CPUHZ 600025023 ←sysctl machdep.tsc_freqの値
#define PENCNT_TO_NSEC(count, clock) (((count)*1000*1000*1000)/(clock))
#define PENCNT_TO_USEC(count, clock) (((count)*1000*1000)/(clock))
#define PENCNT_TO_MSEC(count, clock) (((count)*1000)/(clock))
#define PENCNT_TO_SEC(count, clock) ((count)/(clock))
#define readTSC(x) __asm __volatile(".byte 0x0f, 0x31" : "=A" (x))
以上をヘッダファイルに記述します。
unsigned long long start_count, cur_count,count;
readTSC(start_count);
/*
ここに処理を記述。
*/
readTSC(cur_count);
count = cur_count - start_count;
fprintf (stderr,
"start %d end %d\n"
,(int)start_count,(int)cur_count);
fprintf (stderr, "PENCNT %d nsec(%d/%d)\n",
(int)PENCNT_TO_NSEC(count, CPUHZ),(int)count, (int)CPUHZ);
fprintf (stderr, "PENCNT %d usec(%d/%d)\n",
(int)PENCNT_TO_USEC(count, CPUHZ),(int)count, (int)CPUHZ);
fprintf (stderr, "PENCNT %d msec(%d/%d)\n",
(int)PENCNT_TO_MSEC(count, CPUHZ),(int)count, (int)CPUHZ);
fprintf (stderr, "PENCNT %d sec(%d/%d)\n",
(int)PENCNT_TO_SEC(count, CPUHZ),(int)count, (int)CPUHZ);
などとします。
Address already in use
thanks for gon.
Address already in use ... とかなって「休憩だ!」とならないためには...
set setsockopt SO_REUSEADDR !!
FD INIT_FD;
int one = 1;
/* Create Socket */
if ( (INIT_FD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == ERR ) {
perror("[init_socket()] socket");
return (ERR);
}
setsockopt(INIT_FD, SOL_SOCKET,SO_REUSEADDR,(char *) &one,sizeof(int));
setsockopt(INIT_FD, SOL_SOCKET,SO_USELOOPBACK,(char *) &one,sizeof(int))
デバグメッセージ
thanks for gon.
/* Debug Level */
#define DEBUGLEVEL 4
void dbprintf __P((short, char *, ...));
/*---------------------------------------------------------------------*
* debug printf
*---------------------------------------------------------------------*/
#include <stdio.h>
#include <stdarg.h>
void
dbprintf(short dblev, char *fmt, ...)
{
if ( dblev <= DEBUGLEVEL ) {
va_list argp;
fprintf(stderr, "##DEBUG L=%hd## ", dblev);
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
fprintf(stderr, "\n");
fflush(stderr);
}
return;
}
で,
#define DBG_INFO 1
...
とやっておいて
dbprintf(DBG_INFO,"print = %d",i);
とかすればいいわけですよね.
レベル段階表示より,個別にデバッグ表示させたいときには
char で bitmask かけた方がいいですね.
あとは,上の中で if() でフィルタかけているところを
マクロでかけられたらかっこいい.
だれかやってみない?
可変長マクロ
thanks for furu.
GNU Cにおけるマクロは,関数とほぼ同様に,可変個数の引数を受け取ること
ができます.マクロの定義構文は関数の定義に使われる。
#define eprintf(format, args...) fprintf(stderr, format, ##args)
詳しくは,
http://www.asahi-net.or.jp/~wg5k-ickw/html/online/gcc-2.95.1/gcc_3.html#SEC32
です.
getopt
引数解析にはgetoptを。
int getopt(int argc, char * const *argv, const char *optstring);
optstringには、解析したい引数を全部書きます。"h:"のように、:をつけると、
その引数に対する引数をとることができます。また、"ab:"とすれば、-aと、-b
と-bのargを取り出してくれます。
なお、getoptは --helpなどのような複数文字の引数は扱えません。
#include <stdio.h>
#include <unistd.h> // for getopt
int
main(int argc, char **argv){
int c;
while((c = getopt(argc, argv, "h:m:p:")) != EOF){
switch(c){
case 'h':
printf("%c:%s\n",optopt,optarg);
break;
case 'm':
printf("%c:%s\n",optopt,optarg);
break;
case 'p':
printf("%c:%s\n",optopt,optarg);
break;
case '?':
printf("%s: illegal option -- %c\n",argv[0],optopt);
usage();
break;
}
}
return 0;
}