forked from beagleboard/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/powerpc: Check that signals always get delivered
Signed-off-by: Cyril Bur <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
- Loading branch information
1 parent
8e03bd4
commit ef18633
Showing
5 changed files
with
285 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ SUB_DIRS = alignment \ | |
dscr \ | ||
mm \ | ||
pmu \ | ||
signal \ | ||
primitives \ | ||
stringloops \ | ||
switch_endian \ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
TEST_PROGS := signal signal_tm | ||
|
||
all: $(TEST_PROGS) | ||
|
||
$(TEST_PROGS): ../harness.c ../utils.c signal.S | ||
|
||
CFLAGS += -maltivec | ||
signal_tm: CFLAGS += -mhtm | ||
|
||
include ../../lib.mk | ||
|
||
clean: | ||
rm -f $(TEST_PROGS) *.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* Copyright 2015, Cyril Bur, IBM Corp. | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the License, or (at your option) any later version. | ||
*/ | ||
|
||
#include "../basic_asm.h" | ||
|
||
/* long signal_self(pid_t pid, int sig); */ | ||
FUNC_START(signal_self) | ||
li r0,37 /* sys_kill */ | ||
/* r3 already has our pid in it */ | ||
/* r4 already has signal type in it */ | ||
sc | ||
bc 4,3,1f | ||
subfze r3,r3 | ||
1: blr | ||
FUNC_END(signal_self) | ||
|
||
/* long tm_signal_self(pid_t pid, int sig, int *ret); */ | ||
FUNC_START(tm_signal_self) | ||
PUSH_BASIC_STACK(8) | ||
std r5,STACK_FRAME_PARAM(0)(sp) /* ret */ | ||
tbegin. | ||
beq 1f | ||
tsuspend. | ||
li r0,37 /* sys_kill */ | ||
/* r3 already has our pid in it */ | ||
/* r4 already has signal type in it */ | ||
sc | ||
ld r5,STACK_FRAME_PARAM(0)(sp) /* ret */ | ||
bc 4,3,2f | ||
subfze r3,r3 | ||
2: std r3,0(r5) | ||
tabort. 0 | ||
tresume. /* Be nice to some cleanup, jumps back to tbegin then to 1: */ | ||
/* | ||
* Transaction should be proper doomed and we should never get | ||
* here | ||
*/ | ||
li r3,1 | ||
POP_BASIC_STACK(8) | ||
blr | ||
1: li r3,0 | ||
POP_BASIC_STACK(8) | ||
blr | ||
FUNC_END(tm_signal_self) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* | ||
* Copyright 2016, Cyril Bur, IBM Corp. | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the License, or (at your option) any later version. | ||
* | ||
* Sending one self a signal should always get delivered. | ||
*/ | ||
|
||
#include <signal.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/types.h> | ||
#include <sys/wait.h> | ||
#include <unistd.h> | ||
|
||
#include <altivec.h> | ||
|
||
#include "utils.h" | ||
|
||
#define MAX_ATTEMPT 500000 | ||
#define TIMEOUT 5 | ||
|
||
extern long signal_self(pid_t pid, int sig); | ||
|
||
static sig_atomic_t signaled; | ||
static sig_atomic_t fail; | ||
|
||
static void signal_handler(int sig) | ||
{ | ||
if (sig == SIGUSR1) | ||
signaled = 1; | ||
else | ||
fail = 1; | ||
} | ||
|
||
static int test_signal() | ||
{ | ||
int i; | ||
struct sigaction act; | ||
pid_t ppid = getpid(); | ||
pid_t pid; | ||
|
||
act.sa_handler = signal_handler; | ||
act.sa_flags = 0; | ||
sigemptyset(&act.sa_mask); | ||
if (sigaction(SIGUSR1, &act, NULL) < 0) { | ||
perror("sigaction SIGUSR1"); | ||
exit(1); | ||
} | ||
if (sigaction(SIGALRM, &act, NULL) < 0) { | ||
perror("sigaction SIGALRM"); | ||
exit(1); | ||
} | ||
|
||
/* Don't do this for MAX_ATTEMPT, its simply too long */ | ||
for(i = 0; i < 1000; i++) { | ||
pid = fork(); | ||
if (pid == -1) { | ||
perror("fork"); | ||
exit(1); | ||
} | ||
if (pid == 0) { | ||
signal_self(ppid, SIGUSR1); | ||
exit(1); | ||
} else { | ||
alarm(0); /* Disable any pending */ | ||
alarm(2); | ||
while (!signaled && !fail) | ||
asm volatile("": : :"memory"); | ||
if (!signaled) { | ||
fprintf(stderr, "Didn't get signal from child\n"); | ||
FAIL_IF(1); /* For the line number */ | ||
} | ||
/* Otherwise we'll loop too fast and fork() will eventually fail */ | ||
waitpid(pid, NULL, 0); | ||
} | ||
} | ||
|
||
for (i = 0; i < MAX_ATTEMPT; i++) { | ||
long rc; | ||
|
||
alarm(0); /* Disable any pending */ | ||
signaled = 0; | ||
alarm(TIMEOUT); | ||
rc = signal_self(ppid, SIGUSR1); | ||
if (rc) { | ||
fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx", | ||
i, fail, rc); | ||
FAIL_IF(1); /* For the line number */ | ||
} | ||
while (!signaled && !fail) | ||
asm volatile("": : :"memory"); | ||
if (!signaled) { | ||
fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx", | ||
i, fail, rc); | ||
FAIL_IF(1); /* For the line number */ | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int main(void) | ||
{ | ||
test_harness_set_timeout(300); | ||
return test_harness(test_signal, "signal"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
* Copyright 2016, Cyril Bur, IBM Corp. | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the License, or (at your option) any later version. | ||
* | ||
* Sending one self a signal should always get delivered. | ||
*/ | ||
|
||
#include <errno.h> | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <signal.h> | ||
#include <unistd.h> | ||
|
||
#include <altivec.h> | ||
|
||
#include "utils.h" | ||
#include "../tm/tm.h" | ||
|
||
#define MAX_ATTEMPT 500000 | ||
#define TIMEOUT 10 | ||
|
||
extern long tm_signal_self(pid_t pid, int sig, long *ret); | ||
|
||
static sig_atomic_t signaled; | ||
static sig_atomic_t fail; | ||
|
||
static void signal_handler(int sig) | ||
{ | ||
if (tcheck_active()) { | ||
fail = 2; | ||
return; | ||
} | ||
|
||
if (sig == SIGUSR1) | ||
signaled = 1; | ||
else | ||
fail = 1; | ||
} | ||
|
||
static int test_signal_tm() | ||
{ | ||
int i; | ||
struct sigaction act; | ||
|
||
act.sa_handler = signal_handler; | ||
act.sa_flags = 0; | ||
sigemptyset(&act.sa_mask); | ||
if (sigaction(SIGUSR1, &act, NULL) < 0) { | ||
perror("sigaction SIGUSR1"); | ||
exit(1); | ||
} | ||
if (sigaction(SIGALRM, &act, NULL) < 0) { | ||
perror("sigaction SIGALRM"); | ||
exit(1); | ||
} | ||
|
||
SKIP_IF(!have_htm()); | ||
|
||
for (i = 0; i < MAX_ATTEMPT; i++) { | ||
/* | ||
* If anything bad happens in ASM and we fail to set ret | ||
* because *handwave* TM this will cause failure | ||
*/ | ||
long ret = 0xdead; | ||
long rc = 0xbeef; | ||
|
||
alarm(0); /* Disable any pending */ | ||
signaled = 0; | ||
alarm(TIMEOUT); | ||
FAIL_IF(tcheck_transactional()); | ||
rc = tm_signal_self(getpid(), SIGUSR1, &ret); | ||
if (ret == 0xdead) | ||
/* | ||
* This basically means the transaction aborted before we | ||
* even got to the suspend... this is crazy but it | ||
* happens. | ||
* Yes this also means we might never make forward | ||
* progress... the alarm() will trip eventually... | ||
*/ | ||
continue; | ||
|
||
if (rc || ret) { | ||
/* Ret is actually an errno */ | ||
printf("TEXASR 0x%016lx, TFIAR 0x%016lx\n", | ||
__builtin_get_texasr(), __builtin_get_tfiar()); | ||
fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n", | ||
i, fail, rc, ret); | ||
FAIL_IF(ret); | ||
} | ||
while(!signaled && !fail) | ||
asm volatile("": : :"memory"); | ||
if (!signaled) { | ||
fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n", | ||
i, fail, rc, ret); | ||
FAIL_IF(fail); /* For the line number */ | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int main(void) | ||
{ | ||
return test_harness(test_signal_tm, "signal_tm"); | ||
} |