Test "mcexec additional options (h, m, n, O, stack-premap)" on arm64

Change-Id: I85d5deb0433cc1208e4b6837dcc6d6dc2a7b7b52
This commit is contained in:
Shiratori, Takehiro
2018-11-23 16:03:33 +09:00
committed by Masamichi Takagi
parent dc1f96fee3
commit 00395d68d4
13 changed files with 866 additions and 0 deletions

View File

@ -0,0 +1,28 @@
# Makefile COPYRIGHT FUJITSU LIMITED 2018
CC = gcc
TARGET = extend_heap node_bind allow_oversubscribe stack_premap
LDFLAGS =
all: $(TARGET)
extend_heap: extend_heap.c
$(CC) -o $@ $^ $(LDFLAGS)
node_bind: node_bind.c
$(CC) -o $@ $^ $(LDFLAGS) -lnuma
allow_oversubscribe: allow_oversubscribe.c
$(CC) -o $@ $^ $(LDFLAGS)
stack_premap: stack_premap.c
$(CC) -o $@ $^ $(LDFLAGS)
test: all
./run_extend_heap.sh
./run_node_bind.sh
./run_nr_partitions.sh
./run_allow_oversubscribe.sh
./run_stack_premap.sh
clean:
rm -f $(TARGET)

View File

@ -0,0 +1,74 @@
/* README COPYRIGHT FUJITSU LIMITED 2018 */
mcexecへの追加実装オプションテストセットREADME
(1) テストの実行方法
以下の手順でテストを実行する
1. $HOME/.mck_test_configを用意する
当該ファイルは、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを
$HOMEにコピーし、適宜編集する
2. configのページサイズ変数群の定義を環境に合わせる(デフォルトでは64K-page設定が有効)
3. make testを実行する
(2) テスト項目詳細
【-h オプション】
TEST001 "-h xxK"指定のヒープ拡張確認(サイズはページサイズより小さい値)
TEST002 "-h xxM"指定のヒープ拡張確認(サイズはラージページサイズより小さい値)
TEST003 "-h 1G"指定のヒープ拡張確認
TEST004 "-h xxk"指定のヒープ拡張確認(サイズはページサイズより大きく、ラージページサイズより小さい値)
TEST005 "-h xxm"指定のヒープ拡張確認(サイズはラージページサイズより大きい値)
TEST006 "-h 2g"指定のヒープ拡張確認
TEST007 "-h xx"指定のヒープ拡張確認(サイズはノーマルページサイズ)
TEST008 "-h xx"指定のヒープ拡張確認(サイズはラージページサイズ)
【-m オプション】
TEST009 任意のMcKernelに含むnodeを-mで指定する
TEST010 HOST上には存在するが、McKernelには割り当たっていないnodeを-mで指定する
TEST011 「-」を含む指定を行い、連続したnodeを割り当てる
TEST012 「,」で区切った指定を行い、nodeを割り当てる
TEST013 「!」を使用し、指定除外を含むnodeを割り当てる
TEST014 「+」を使用したnode指定を含むnodeを割り当てる
TEST015 allを指定したnodeを割り当てる
TEST016 存在しないnode番号を指定する
【-n オプション】
TEST017 -n 2を指定して、任意のa.outを実行して動作することを確認する
TEST018 -n 4(McKernel割り当てコア数と同一)を指定して、任意のa.outを実行して動作することを確認する
TEST019 McKernel割り当てコア数より大きい数値を指定して、エラーになることを確認する
TEST020 数値以外を含む文字列を指定して、エラーになることを確認する
【-O オプション】
TEST021 mcreboot.shの-Oオプション無効時、McKernelコア数を越えるforkがEINVALで失敗すること
TEST022 mcreboot.shの-Oオプション有効時、McKernelコア数を越えるforkが成功すること
【-s(--stack-premap) オプション】
TEST023 "-s xxK"指定のpremap領域確認(サイズはページサイズより小さい値)
TEST024 "-s xxM"指定のpremap領域確認(サイズはラージページサイズより小さい値)
TEST025 "-s 1G"指定のpremap領域確認
TEST026 "--stack-premap xxk"指定のpremap領域確認(サイズはページサイズより大きく、ラージページサイズより小さい値)
TEST027 "--stack-premap xxm"指定のpremap領域確認(サイズはラージページサイズより大きい値)
TEST028 "--stack-premap 2g"指定のpremap領域確認
TEST029 "-s xx"指定のpremap領域確認(サイズはノーマルページサイズ)
TEST030 max指定値がsize指定値よりも小さい場合、max値分でpremapする事を確認
(3) 実行結果ログ
result.logファイル内に実行時のログを記載する。
実行に利用したIHK/McKernelは、IA版における下記の版数相当の
arm64版移植IHK/McKernelである。
IHK
commit d6fcbee8cb91f9ec4b49f97c918e696ac0335aaf
Author: Shiratori, Takehiro <fj0300es@aa.jp.fujitsu.com>
Date: Tue Oct 16 16:25:33 2018 +0900
McKernel
commit 6f9fef2b13447c74c36d15cf5ebd186f8395ccca
Author: Ken Sato <ken.sato.ty@hitachi-solutions.com>
Date: Tue Sep 25 10:05:41 2018 +0900
(4) 備考
本テストセットは一部IHK/McKernelの実装挙動を期待としてテスト項目を作成しているため、
全ての項目がHOST-Linux上でもOKになるとは限らない。
以上。

View File

@ -0,0 +1,71 @@
/* allow_oversubscribe.c COPYRIGHT FUJITSU LIMITED 2018 */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#define PROG "/usr/bin/date"
static int
do_fork(int proc_num)
{
int i;
for (i = 0; i < proc_num; i += 1) {
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
return -1;
}
else if (0 == pid) {
printf("%d: in child (%d/%d)\n",
getpid(), (i+1), proc_num);
execl(PROG, PROG, NULL);
exit(0);
/* NOTREACHED */
}
}
return 0;
}
static int
do_wait(int proc_num)
{
pid_t mypid = getpid();
int i;
printf("%d: in parent\n", mypid);
for (i = 0; i < proc_num; i += 1) {
int status;
pid_t pid = waitpid(-1, &status, 0);
if (pid < 0) {
perror("waitpid failed");
return -1;
}
printf("%d: waited %d (%d/%d)\n",
mypid, pid, (i+1), proc_num);
}
printf("%d: all done\n", mypid);
return 0;
}
int
main(int argc, char *argv[])
{
int result = 0;
int proc_num = atoi(argv[1]);
if (do_fork(proc_num)) {
result = -1;
}
if (do_wait(proc_num)) {
result = -1;
}
return result;
}

View File

@ -0,0 +1,29 @@
## config COPYRIGHT FUJITSU LIMITED 2018 ##
## set size pattern
## 64K-page
PGSZ="$((64*1024))"
NEAR_PGSZ_LOW="63K"
NEAR_PGSZ_LOW_VAL="$((63*1024))"
NEAR_PGSZ_HIGH="65k"
NEAR_PGSZ_HIGH_VAL="$((65*1024))"
LPGSZ="$((512*1024*1024))"
NEAR_LPGSZ_LOW="511M"
NEAR_LPGSZ_LOW_VAL="$((511*1024*1024))"
NEAR_LPGSZ_HIGH="513m"
NEAR_LPGSZ_HIGH_VAL="$((513*1024*1024))"
## 4K-page
# PGSZ="$((4*1024))"
# NEAR_PGSZ_LOW="3K"
# NEAR_PGSZ_LOW_VAL="$((3*1024))"
# NEAR_PGSZ_HIGH="5k"
# NEAR_PGSZ_HIGH_VAL="$((5*1024))"
#
# LPGSZ="$((2*1024*1024))"
# NEAR_LPGSZ_LOW="1M"
# NEAR_LPGSZ_LOW_VAL="$((1024*1024))"
# NEAR_LPGSZ_HIGH="3m"
# NEAR_LPGSZ_HIGH_VAL="$((3*1024*1024))"

View File

@ -0,0 +1,97 @@
/* extend_heap.c COPYRIGHT FUJITSU LIMITED 2018 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
static void show_usage(void)
{
printf("./extend_heap <extend-heap-by(byte)>\n");
}
int main(int argc, char *argv[])
{
FILE *fp = 0;
int result = -1;
unsigned long exheap = 0;
unsigned long start = 0; /* dummy */
unsigned long bf_end = 0;
unsigned long af_end = 0;
char buf[4096];
char *tmp = NULL;
const unsigned long page_size = sysconf(_SC_PAGESIZE);
unsigned long align_size = page_size;
if (argc != 2) {
show_usage();
result = 0;
goto err;
}
exheap = atoll(argv[1]);
/* check default heap-end */
fp = fopen("/proc/self/maps", "r");
if (fp == NULL) {
printf("fopen() failed. %d\n", errno);
goto err;
}
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (strstr(buf, "[heap]")) {
sscanf(buf, "%lx-%lx", &start, &bf_end);
}
}
if (fclose(fp)) {
printf("fclose() failed. %d\n", errno);
goto err;
}
/* heap-end adjustment */
if (brk((void *)bf_end)) {
printf("brk() failed. %d\n", errno);
goto err;
}
/* heap extend 1byte */
if (sbrk(1) == (void *)-1) {
printf("sbrk() failed. %d\n", errno);
goto err;
}
/* check extended heap-end */
fp = fopen("/proc/self/maps", "r");
if (fp == NULL) {
printf("fopen() failed. %d\n", errno);
goto err;
}
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (strstr(buf, "[heap]")) {
sscanf(buf, "%lx-%lx", &start, &af_end);
}
}
if (fclose(fp)) {
printf("fclose() failed. %d\n", errno);
goto err;
}
if (page_size < exheap) {
align_size = page_size / 8 * page_size;
}
if ((af_end - bf_end) < exheap) {
printf("extend size ng.\n");
goto err;
}
if (af_end & (align_size - 1)) {
printf("extend align ng.\n");
goto err;
}
result = 0;
err:
return result;
}

View File

@ -0,0 +1,52 @@
/* node_bind.c COPYRIGHT FUJITSU LIMITED 2018 */
#include <stdio.h>
#include <stdlib.h>
#include <numaif.h>
#include <numa.h>
#include <errno.h>
static void show_usage(void)
{
printf("./node_bind <numa node>\n");
}
int main(int argc, char *argv[])
{
int mode = 0;
int result = -1;
unsigned long mask = 0;
unsigned long exp_mask = 0;
struct bitmask *bind_mask;
if (argc != 2) {
show_usage();
result = 0;
goto err;
}
bind_mask = numa_parse_nodestring_all(argv[1]);
if (bind_mask) {
int node;
for (node = 0; node <= numa_max_possible_node(); ++node) {
if (numa_bitmask_isbitset(bind_mask, node)) {
exp_mask |= (1UL << node);
}
}
}
if (get_mempolicy(&mode, &mask, sizeof(mask) * 8, 0, MPOL_F_NODE)) {
printf("get_mempolicy() failed. %d\n", errno);
goto err;
}
if (mask != exp_mask) {
printf("node_bind mask mismatch, ng. (exp:%lx, mask:%lx)\n",
exp_mask, mask);
goto err;
}
result = 0;
err:
return result;
}

View File

@ -0,0 +1,76 @@
gcc -o extend_heap extend_heap.c
gcc -o node_bind node_bind.c -lnuma
gcc -o allow_oversubscribe allow_oversubscribe.c
gcc -o stack_premap stack_premap.c
./run_extend_heap.sh
mcstop+release.sh ... done
mcreboot.sh -c 4-7 -m 4G@0,4G@1,4G@2,4G@3 ... done
TEST001: OK
TEST002: OK
TEST003: OK
TEST004: OK
TEST005: OK
TEST006: OK
TEST007: OK
TEST008: OK
./run_node_bind.sh
mcstop+release.sh ... done
mcreboot.sh -c 4-7 -m 4G@0,4G@1,4G@2,4G@3 ... done
TEST009: OK
TEST010: OK
TEST011: OK
TEST012: OK
TEST013: OK
TEST014: OK
TEST015: OK
libnuma: Warning: node argument 63 is out of range
libnuma: Warning: node argument 63 is out of range
TEST016: OK
./run_nr_partitions.sh
mcstop+release.sh ... done
mcreboot.sh -c 4-7 -m 4G@0,4G@1,4G@2,4G@3 ... done
TEST017: OK
TEST018: OK
error: nr_processes can't exceed nr. of CPUs
TEST019: OK
error: -n: invalid number of processes
TEST020: OK
./run_allow_oversubscribe.sh
mcstop+release.sh ... done
mcreboot.sh -c 4-7 -m 4G@0,4G@1,4G@2,4G@3 ... done
fork failed: Invalid argument
2018年 11月 21日 水曜日 02:44:04 JST
2018年 11月 21日 水曜日 02:44:04 JST
2018年 11月 21日 水曜日 02:44:04 JST
waitpid failed: No child processes
9907: in parent
9907: waited 9920 (1/4)
9907: waited 9914 (2/4)
9907: waited 9926 (3/4)
TEST021: OK
mcstop+release.sh ... done
mcreboot.sh -c 4-7 -m 4G@0,4G@1,4G@2,4G@3 -O ... done
2018年 11月 21日 水曜日 02:44:18 JST
2018年 11月 21日 水曜日 02:44:18 JST
2018年 11月 21日 水曜日 02:44:18 JST
2018年 11月 21日 水曜日 02:44:18 JST
10076: in parent
10076: waited 10083 (1/4)
10076: waited 10089 (2/4)
10076: waited 10095 (3/4)
10076: waited 10102 (4/4)
10076: all done
TEST022: OK
./run_stack_premap.sh
mcstop+release.sh ... done
mcreboot.sh -c 4-7 -m 4G@0,4G@1,4G@2,4G@3 ... done
TEST023: OK
TEST024: OK
TEST025: OK
TEST026: OK
TEST027: OK
TEST028: OK
TEST029: OK
TEST030: OK

View File

@ -0,0 +1,37 @@
#!/bin/sh
## run_allow_oversubscribe.sh COPYRIGHT FUJITSU LIMITED 2018 ##
USELTP=0
USEOSTEST=0
. ../../common.sh
. ./config
result=0
####################
## -O option test ##
####################
${MCEXEC} ./allow_oversubscribe 4
if [ `echo $?` != 0 ]; then
echo "TEST021: OK"
else
echo "TEST021: NG, not -O setting mcexec."
result=-1
fi
BOOTPARAM="${BOOTPARAM} -O"
((${MCSTOP-1})) && mcstop
((${MCREBOOT-1})) && mcreboot
${MCEXEC} ./allow_oversubscribe 4
if [ `echo $?` == 0 ]; then
echo "TEST022: OK"
else
echo "TEST022: NG, -O setting mcexec."
result=-1
fi
exit ${result}

View File

@ -0,0 +1,81 @@
#!/bin/sh
## run_extend_heap.sh COPYRIGHT FUJITSU LIMITED 2018 ##
USELTP=0
USEOSTEST=0
. ../../common.sh
. ./config
result=0
####################
## -h option test ##
####################
${MCEXEC} -h ${NEAR_PGSZ_LOW} ./extend_heap ${NEAR_PGSZ_LOW_VAL}
if [ `echo $?` == 0 ]; then
echo "TEST001: OK"
else
echo "TEST001: NG, -h ${NEAR_PGSZ_LOW} options failed."
result=-1
fi
${MCEXEC} -h ${NEAR_LPGSZ_LOW} ./extend_heap ${NEAR_LPGSZ_LOW_VAL}
if [ `echo $?` == 0 ]; then
echo "TEST002: OK"
else
echo "TEST002: NG, -h ${NEAR_LPGSZ_LOW} options failed."
result=-1
fi
${MCEXEC} -h 1G ./extend_heap $((1024*1024*1024))
if [ `echo $?` == 0 ]; then
echo "TEST003: OK"
else
echo "TEST003: NG, -h 1G options failed."
result=-1
fi
${MCEXEC} -h ${NEAR_PGSZ_HIGH} ./extend_heap ${NEAR_PGSZ_HIGH_VAL}
if [ `echo $?` == 0 ]; then
echo "TEST004: OK"
else
echo "TEST004: NG, -h ${NEAR_PGSZ_HIGH} options failed."
result=-1
fi
${MCEXEC} -h ${NEAR_LPGSZ_HIGH} ./extend_heap ${NEAR_LPGSZ_HIGH_VAL}
if [ `echo $?` == 0 ]; then
echo "TEST005: OK"
else
echo "TEST005: NG, -h ${NEAR_LPGSZ_HIGH} options failed."
result=-1
fi
${MCEXEC} -h 2g ./extend_heap $((2*1024*1024*1024))
if [ `echo $?` == 0 ]; then
echo "TEST006: OK"
else
echo "TEST006: NG, -h 2g options failed."
result=-1
fi
${MCEXEC} -h ${PGSZ} ./extend_heap ${PGSZ}
if [ `echo $?` == 0 ]; then
echo "TEST007: OK"
else
echo "TEST007: NG, -h ${PGSZ} options failed."
result=-1
fi
${MCEXEC} -h ${LPGSZ} ./extend_heap ${LPGSZ}
if [ `echo $?` == 0 ]; then
echo "TEST008: OK"
else
echo "TEST008: NG, -h ${LPGSZ} options failed."
result=-1
fi
exit ${result}

View File

@ -0,0 +1,81 @@
#!/bin/sh
## run_node_bind.sh COPYRIGHT FUJITSU LIMITED 2018 ##
USELTP=0
USEOSTEST=0
. ../../common.sh
. ./config
result=0
####################
## -m option test ##
####################
${MCEXEC} -m 1 ./node_bind 1
if [ `echo $?` == 0 ]; then
echo "TEST009: OK"
else
echo "TEST009: NG, -m 1 setting."
result=-1
fi
${MCEXEC} -m 3 ./node_bind 3
if [ `echo $?` == 0 ]; then
echo "TEST010: OK"
else
echo "TEST010: NG, -m out of McKernel node setting."
result=-1
fi
${MCEXEC} -m 0-2 ./node_bind 0-2
if [ `echo $?` == 0 ]; then
echo "TEST011: OK"
else
echo "TEST011: NG, -m 0-2 setting."
result=-1
fi
${MCEXEC} -m 0,2 ./node_bind 0,2
if [ `echo $?` == 0 ]; then
echo "TEST012: OK"
else
echo "TEST012: NG, -m 0,2 setting."
result=-1
fi
${MCEXEC} -m \!0,1,2 ./node_bind \!0,1,2
if [ `echo $?` == 0 ]; then
echo "TEST013: OK"
else
echo "TEST013: NG, -m \!0,1,2 setting."
result=-1
fi
${MCEXEC} -m +0,1 ./node_bind +0,1
if [ `echo $?` == 0 ]; then
echo "TEST014: OK"
else
echo "TEST014: NG, -m +0,1 setting."
result=-1
fi
${MCEXEC} -m all ./node_bind all
if [ `echo $?` == 0 ]; then
echo "TEST015: OK"
else
echo "TEST015: NG, -m all setting."
result=-1
fi
${MCEXEC} -m 63 ./node_bind 63
if [ `echo $?` == 0 ]; then
echo "TEST016: OK"
else
echo "TEST016: NG, -m 63 setting."
result=-1
fi
exit ${result}

View File

@ -0,0 +1,57 @@
#!/bin/sh
## run_nr_partitions.sh COPYRIGHT FUJITSU LIMITED 2018 ##
USELTP=0
USEOSTEST=0
. ../../common.sh
. ./config
result=0
####################
## -n option test ##
####################
${MCEXEC} -n 2 ls > /dev/null &
sleep 1
${MCEXEC} -n 2 ls > /dev/null
if [ `echo $?` == 0 ]; then
echo "TEST017: OK"
else
echo "TEST017: NG, -n 2 setting."
result=-1
fi
${MCEXEC} -n 4 ls > /dev/null &
sleep 1
${MCEXEC} -n 4 ls > /dev/null &
sleep 1
${MCEXEC} -n 4 ls > /dev/null &
sleep 1
${MCEXEC} -n 4 ls > /dev/null
if [ `echo $?` == 0 ]; then
echo "TEST018: OK"
else
echo "TEST018: NG, -n 4 setting."
result=-1
fi
${MCEXEC} -n 8 ls
if [ `echo $?` != 0 ]; then
echo "TEST019: OK"
else
echo "TEST019: NG, -n <over mckcores> setting."
result=-1
fi
${MCEXEC} -n abcde ls
if [ `echo $?` != 0 ]; then
echo "TEST020: OK"
else
echo "TEST020: NG, -n <invalid strings> setting."
result=-1
fi
exit ${result}

View File

@ -0,0 +1,81 @@
#!/bin/sh
## run_stack_premap.sh COPYRIGHT FUJITSU LIMITED 2018 ##
USELTP=0
USEOSTEST=0
. ../../common.sh
. ./config
result=0
####################################
## -s(--stack-premap) option test ##
####################################
${MCEXEC} -s ${NEAR_PGSZ_LOW},${LPGSZ} ./stack_premap ${NEAR_PGSZ_LOW_VAL}
if [ `echo $?` == 0 ]; then
echo "TEST023: OK"
else
echo "TEST023: NG, -s ${NEAR_PGSZ_LOW},${LPGSZ} setting."
result=-1
fi
${MCEXEC} -s ${NEAR_LPGSZ_LOW},${LPGSZ} ./stack_premap ${NEAR_LPGSZ_LOW_VAL}
if [ `echo $?` == 0 ]; then
echo "TEST024: OK"
else
echo "TEST024: NG, -s ${NEAR_LPGSZ_LOW},${LPGSZ} setting."
result=-1
fi
${MCEXEC} -s 1G,2G ./stack_premap $((1024*1024*1024))
if [ `echo $?` == 0 ]; then
echo "TEST025: OK"
else
echo "TEST025: NG, -s 1G,2G setting."
result=-1
fi
${MCEXEC} --stack-premap ${NEAR_PGSZ_HIGH},${LPGSZ} ./stack_premap ${NEAR_PGSZ_HIGH_VAL}
if [ `echo $?` == 0 ]; then
echo "TEST026: OK"
else
echo "TEST026: NG, -s ${NEAR_PGSZ_HIGH},${LPGSZ} setting."
result=-1
fi
${MCEXEC} --stack-premap ${NEAR_LPGSZ_HIGH},2g ./stack_premap ${NEAR_LPGSZ_HIGH_VAL}
if [ `echo $?` == 0 ]; then
echo "TEST027: OK"
else
echo "TEST027: NG, -s ${NEAR_LPGSZ_HIGH},2g setting."
result=-1
fi
${MCEXEC} --stack-premap 2g,3g ./stack_premap $((2*1024*1024*1024))
if [ `echo $?` == 0 ]; then
echo "TEST028: OK"
else
echo "TEST028: NG, -s 2g,3g setting."
result=-1
fi
${MCEXEC} -s ${PGSZ},${LPGSZ} ./stack_premap ${PGSZ}
if [ `echo $?` == 0 ]; then
echo "TEST029: OK"
else
echo "TEST029: NG, -s ${PGSZ},${LPGSZ} setting."
result=-1
fi
${MCEXEC} --stack-premap ${LPGSZ},${PGSZ} ./stack_premap ${PGSZ}
if [ `echo $?` == 0 ]; then
echo "TEST030: OK"
else
echo "TEST030: NG, -s ${LPGSZ},${PGSZ} setting."
result=-1
fi
exit ${result}

View File

@ -0,0 +1,102 @@
/* stack_premap.c COPYRIGHT FUJITSU LIMITED 2018 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define PAGEMAP_PRESENT (1UL << 63)
static void show_usage(void)
{
printf("./stack_premap <stack_premap(byte)>\n");
}
int main(int argc, char *argv[])
{
FILE *fp_maps = 0;
FILE *fp_pgmap = 0;
int result = -1;
unsigned long premap = 0;
unsigned long start = 0;
unsigned long end = 0;
char buf[4096];
char *tmp = NULL;
const unsigned long page_size = sysconf(_SC_PAGESIZE);
unsigned long align_size = 0;
unsigned long pagemap = 0;
long offset = 0;
if (argc != 2) {
show_usage();
result = 0;
goto err;
}
premap = atoll(argv[1]);
/* alignment check */
if (premap & (page_size - 1)) {
align_size = ((premap + page_size) & ~(page_size - 1));
} else {
align_size = premap;
}
fp_maps = fopen("/proc/self/maps", "r");
if (fp_maps == NULL) {
printf("fopen() failed. %d\n", errno);
goto err;
}
fp_pgmap = fopen("/proc/self/pagemap", "r");
if (fp_pgmap == NULL) {
printf("fopen() failed. %d\n", errno);
goto maps_close;
}
/* check stack area */
while (fgets(buf, sizeof(buf), fp_maps) != NULL) {
if (strstr(buf, "[stack]")) {
sscanf(buf, "%lx-%lx", &start, &end);
}
}
/* check premapping */
offset = (end - align_size) / page_size * 8;
if (fseek(fp_pgmap, offset, SEEK_SET)) {
printf("fseek() failed. %d\n", errno);
goto pgmap_close;
}
if (fread(&pagemap, 8, 1, fp_pgmap) != 1) {
printf("fread() failed. %d\n", errno);
goto pgmap_close;
}
if (!(pagemap & PAGEMAP_PRESENT)) {
printf("not premapped. (stack(0x%lx-0x%lx), va=0x%lx)\n",
start, end, end - align_size);
goto pgmap_close;
}
result = 0;
pgmap_close:
if (fp_pgmap) {
if (fclose(fp_pgmap)) {
printf("fclose() failed. %d\n", errno);
result = -1;
goto err;
}
}
maps_close:
if (fp_maps) {
if (fclose(fp_maps)) {
printf("fclose() failed. %d\n", errno);
result = -1;
goto err;
}
}
err:
return result;
}