mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-27 21:14:44 +08:00
92dd8dd4d0
Move prctl tests from Documentation/prctl to selftests/prctl. Remove prctl from Makefile to move the test. Update prctl Makefile to work under selftests. prctl will not be run as part of selftests suite and will not be included in install targets. They can be built separately for now. Acked-by: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
98 lines
1.7 KiB
C
98 lines
1.7 KiB
C
/*
|
|
* Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
|
|
*
|
|
* Tests if the control register is updated correctly
|
|
* at context switches
|
|
*
|
|
* Warning: this test will cause a very high load for a few seconds
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <inttypes.h>
|
|
#include <wait.h>
|
|
|
|
|
|
#include <sys/prctl.h>
|
|
#include <linux/prctl.h>
|
|
|
|
/* Get/set the process' ability to use the timestamp counter instruction */
|
|
#ifndef PR_GET_TSC
|
|
#define PR_GET_TSC 25
|
|
#define PR_SET_TSC 26
|
|
# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
|
|
# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
|
|
#endif
|
|
|
|
static uint64_t rdtsc(void)
|
|
{
|
|
uint32_t lo, hi;
|
|
/* We cannot use "=A", since this would use %rax on x86_64 */
|
|
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
|
|
return (uint64_t)hi << 32 | lo;
|
|
}
|
|
|
|
static void sigsegv_expect(int sig)
|
|
{
|
|
/* */
|
|
}
|
|
|
|
static void segvtask(void)
|
|
{
|
|
if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
|
|
{
|
|
perror("prctl");
|
|
exit(0);
|
|
}
|
|
signal(SIGSEGV, sigsegv_expect);
|
|
alarm(10);
|
|
rdtsc();
|
|
fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
|
|
exit(0);
|
|
}
|
|
|
|
|
|
static void sigsegv_fail(int sig)
|
|
{
|
|
fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
|
|
exit(0);
|
|
}
|
|
|
|
static void rdtsctask(void)
|
|
{
|
|
if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
|
|
{
|
|
perror("prctl");
|
|
exit(0);
|
|
}
|
|
signal(SIGSEGV, sigsegv_fail);
|
|
alarm(10);
|
|
for(;;) rdtsc();
|
|
}
|
|
|
|
|
|
int main(void)
|
|
{
|
|
int n_tasks = 100, i;
|
|
|
|
fprintf(stderr, "[No further output means we're allright]\n");
|
|
|
|
for (i=0; i<n_tasks; i++)
|
|
if (fork() == 0)
|
|
{
|
|
if (i & 1)
|
|
segvtask();
|
|
else
|
|
rdtsctask();
|
|
}
|
|
|
|
for (i=0; i<n_tasks; i++)
|
|
wait(NULL);
|
|
|
|
exit(0);
|
|
}
|
|
|