2014/10/08(水)memory test
メモリテストプログラム
いわゆるPCのmemtestがそう。PCとは異なるアーキテクチャでも、特に組込み危機でも必要となるでしょう。
この記事は、メモ代わりに記載するだけで本体に価値はありません・・・。
(オフラインで資料を作る際に参考にさせていただいた時のメモ)
メモリテストの目的や達成目標を明確にすることで、必要十分なものを選択しましょう。
(過去の踏襲…とか、非論理的なシゴトは決してしないように、なぁ。)
参考
メモリテストに関するよい記事
http://www.barrgroup.com/Embedded-Systems/How-To/Memory-Test-Suite-C掲示板には20年の職人が来ている
http://stackoverflow.com/questions/3729544/free-implementation-of-march-memory-testing-algorithm>Memory testing with cache >Permalink Submitted by krishnakoyalmannam on Thu, 2011-05-19 02:00. When you are testing external DDR2 memory on a multicore system, with a shared Level 2 Cache, each core could be assigned a dedicated section of memory to test and all the cores memory tests in parallel. This causes the L2 cache to result in more cache miss than cache hit, thereby resulting in increased DRAM bus transactions, which could be very useful during HW Board BringUp. And yes, the ground bounce and cross-talk tests do check for signal integrity problems. There is also MARCH-B and MARCH-C memory testing algorithms that sweep memory with random patterns in one direction and sweep in the reverse direction, so, a cache flush would be required before starting the reverse sweep. And finally, an XOR test to uncover memory cell faults, would make the suite of memory tests quite comprehensive providing greater coverage.
マーチアルゴリズム:LSIテスト用だなぁ
http://www.ece.uc.edu/~wjone/http://www.ece.uc.edu/~wjone/Memory.pdf
2013/01/08(火)sigprocmaskの検証
#include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/syscall.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <pthread.h> #include <signal.h> #define gettid() syscall(SYS_gettid) // 0: sigprocmask at process, 1:thr1, #define DF_CHGMASK_ID 2 //#define DF_USE_PTHREADMASK //#define DF_INITIAL_MASK (SIGSEGV) //#define DF_INITIAL_MASK (SIGABRT) #define DF_INITIAL_MASK (12) void abt_handler(int n, siginfo_t *pSigInf, void *pContext) { struct sigaction sa; printf("I am dead...[%d][parent:%d][tid=%d][thread_id=%ld]", getpid(), getppid(), gettid(), (long)pthread_self()); memset(&sa,0,sizeof(struct sigaction)); //_exit(1); sigemptyset(&sa.sa_mask); // sa.sa_flags |= SA_SIGINFO ; sa.sa_handler = SIG_DFL; // sigaction(SIGABRT,&sa,NULL); // raise(SIGABRT); } void register_handler() { struct sigaction sa; memset(&sa,0,sizeof(struct sigaction)); sigemptyset(&sa.sa_mask); sa.sa_flags |= SA_SIGINFO ; sa.sa_sigaction = abt_handler; // sigaction(SIGABRT,&sa,NULL); sigaction( 12,&sa,NULL); } struct st_signals_st { int signo; const char *pcSignal ; } st_signals[] = { {SIGHUP, "SIGHUP"}, {SIGINT, "SIGINT"}, {SIGQUIT, "SIGQUIT"}, {SIGILL, "SIGILL"}, {SIGTRAP, "SIGTRAP"}, {SIGABRT, "SIGABRT"}, {SIGIOT, "SIGIOT"}, {SIGBUS, "SIGBUS"}, {SIGFPE, "SIGFPE"}, {SIGKILL, "SIGKILL"}, {SIGUSR1, "SIGUSR1"}, {SIGSEGV, "SIGSEGV"}, {SIGUSR2, "SIGUSR2"}, {SIGPIPE, "SIGPIPE"}, {SIGALRM, "SIGALRM"}, {SIGTERM, "SIGTERM"}, {SIGSTKFLT, "SIGSTKFLT"}, {SIGCHLD, "SIGCHLD"}, {SIGCONT, "SIGCONT"}, {SIGSTOP, "SIGSTOP"}, {SIGTSTP, "SIGTSTP"}, {SIGTTIN, "SIGTTIN"}, {SIGTTOU, "SIGTTOU"}, {SIGURG, "SIGURG"}, {SIGXCPU, "SIGXCPU"}, {SIGXFSZ, "SIGXFSZ"}, {SIGVTALRM, "SIGVTALRM"}, {SIGPROF, "SIGPROF"}, {SIGWINCH, "SIGWINCH"}, {SIGIO, "SIGIO"}, {SIGPOLL, "SIGPOLL"}, {SIGPWR, "SIGPWR"}, {SIGSYS, "SIGSYS"}, {0, NULL} } ; void dump_sigmask(const char* pMsg, sigset_t* sig_mask) { struct st_signals_st* pStSignal = st_signals ; int i; puts(pMsg); while( pStSignal->pcSignal ){ if (sigismember( sig_mask, pStSignal->signo )) { putchar('1'); } else { putchar('0'); } pStSignal++; } putchar('_'); for (i=SIGRTMIN; i<=SIGRTMAX; i++) { if (sigismember( sig_mask, i )) { putchar('1'); } else { putchar('0'); } } puts(""); return ; } void* thr1(void* arg) { sigset_t sig_mask ; sleep(1); printf("[%d/ppid=%d/tid=%d/self=%ld] wakeup thr1!\n", getpid(), getppid(), gettid(), (long)pthread_self()); pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask); dump_sigmask("thr1", &sig_mask); #if (DF_CHGMASK_ID==1) sigfillset(&sig_mask); #ifdef DF_USE_PTHREADMASK if (pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) { #else if (sigprocmask(SIG_SETMASK, &sig_mask, NULL)) { #endif perror ("main(): failure set..."); } #endif sleep(4); pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask); dump_sigmask("thr1", &sig_mask); #if (DF_CHGMASK_ID==1) sigemptyset(&sig_mask); #ifdef DF_USE_PTHREADMASK if (pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) { #else if (sigprocmask(SIG_SETMASK, &sig_mask, NULL)) { #endif perror ("main(): failure set..."); } #endif sleep(4); pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask); dump_sigmask("thr1", &sig_mask); sleep(10); } void* thr2(void* arg) { sigset_t sig_mask ; register_handler(); // sigaddset(&sig_mask, DF_INITIAL_MASK) ; sigemptyset(&sig_mask); sigaddset(&sig_mask, 12) ; #ifdef DF_USE_PTHREADMASK if (pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL)) { #else if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) { #endif perror ("thr2(): Dead set..."); } sleep(2); printf("[%d/ppid=%d/tid=%d/self=%ld] wakeup thr2!\n", getpid(), getppid(), gettid(), (long)pthread_self()); pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask); dump_sigmask("thr2", &sig_mask); sleep(4); pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask); dump_sigmask("thr2", &sig_mask); sleep(4); pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask); dump_sigmask("thr2", &sig_mask); system("echo thr2 is spawn $$ ; sleep 17"); sleep(3); } int main(int argc, char *argv[]) { int status=0; int fd; pthread_t child[2]; sigset_t sig_mask ; sigfillset(&sig_mask); if (sigprocmask(SIG_BLOCK, &sig_mask, NULL)) { perror ("main(): Dead set..."); } /* sigaddset(&sig_mask, DF_INITIAL_MASK) ; if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) { perror ("main(): Dead set..."); } */ // register_handler(); if (sigprocmask(SIG_UNBLOCK, NULL, &sig_mask)) { perror ("main(): Dead get..."); } dump_sigmask("main", &sig_mask); /* スレッド生成 */ pthread_create(&child[0], NULL, thr1, NULL ); pthread_create(&child[1], NULL, thr2, NULL ); sleep(4); #if (DF_CHGMASK_ID==0) sigemptyset(&sig_mask); if (sigprocmask(SIG_SETMASK, &sig_mask, NULL)) { perror ("main(): failure set..."); } #endif if (sigprocmask(SIG_UNBLOCK, NULL, &sig_mask)) { perror ("main(): Dead get..."); } dump_sigmask("main", &sig_mask); sleep(4); #if (DF_CHGMASK_ID==0) sigfillset(&sig_mask); if (sigprocmask(SIG_SETMASK, &sig_mask, NULL)) { perror ("main(): failure set..."); } #endif if (sigprocmask(SIG_UNBLOCK, NULL, &sig_mask)) { perror ("main(): Dead get..."); } dump_sigmask("main", &sig_mask); sleep(4); if (sigprocmask(SIG_UNBLOCK, NULL, &sig_mask)) { perror ("main(): Dead get..."); } dump_sigmask("main", &sig_mask); status = pthread_join(child[0], NULL); if (status<0) { printf("pthread_join(0) returns: %d\n", status); } status = pthread_join(child[1], NULL); if (status<0) { printf("pthread_join(0) returns: %d\n", status); } return 0; }
2013/01/08(火)sigactionを触ってみる。
backtraceを取れるか確認する(PwerPC 32bitでのみ確認)
glibcに、backtrace()函数があって、便利だなぁ、と。自分で書かなくて良いんだねぇ。組み込みRTOSで触ってた何か、は、スタックを手動で追っていたわ~。
コレも自動化しすぎて、スタックと思ったアドレスが別空間だとSIGSEGVでおちるけどな…
/* * sigaction sample program for powerpc32 * You can add more informations in segv_handler(). * In this fucntion, you have pointer of stacks, regs, contexts... * If we can allow increase size of binary, we can continu using backtrace_symbols()/backtrace_symbols_fd(). * Please refer man-pages, info-pages and a lot of WEB-pages B) * * Author: 30/Aug./2012 YNK * NOTE: Don't use '=O2' because optimization makes no 'bl' instructions to call function. */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <execinfo.h> #include <linux/sysctl.h> #include <sys/ucontext.h> int (*func_ptr)() = (void *)0x1234567; int func1(); int func2(); void segv_handler(int n, siginfo_t *pSigInf, void *pContext); int main(int argc,char ** argv) { struct sigaction sa; memset(&sa,0,sizeof(struct sigaction)); sigemptyset(&sa.sa_mask); sa.sa_flags |= SA_SIGINFO ; sa.sa_sigaction = segv_handler; sigaction(SIGSEGV,&sa,NULL); func1(); return 0; } int func1() { func2(); return 0; } int func2() { *(int*)0xBAD2DEAD = 2; func_ptr(); return 0; } void segv_handler(int n, siginfo_t *pSigInf, void *pContext) { int cnt, i; void **arr = alloca(256 * sizeof(void *)); ucontext_t* pCon = (ucontext_t *)pContext; printf("*** segmentation fault! (No=%d)\n", n); printf(" An errno value: %d\n", pSigInf->si_errno ); printf(" Signal code : %d\n", pSigInf->si_code ); printf(" access address : %p\n", pSigInf->si_addr ); // struct defined in ptrace.h for(i=0;i<32;i++) { printf("GPRS%2d: 0x%08X\n", i, pCon->uc_mcontext.regs->gpr[i]); } printf("NIP=0x%08X MSR=0x%08X\n", pCon->uc_mcontext.regs->nip, pCon->uc_mcontext.regs->msr ); printf("\n\n *** backtrace address ***\n"); cnt = backtrace(arr, 256); for(i=0;i<cnt;i++) { printf("\t%3d: 0x%08X\n", i, arr[i]); } /* if included symbolx(compile with "-r dynamic") */ backtrace_symbols_fd(arr, cnt, 2); abort(); }