Merge tag 'powerpc-4.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[cascardo/linux.git] / tools / testing / selftests / powerpc / signal / signal.c
1 /*
2  * Copyright 2016, Cyril Bur, IBM Corp.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version
7  * 2 of the License, or (at your option) any later version.
8  *
9  * Sending one self a signal should always get delivered.
10  */
11
12 #include <signal.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 #include <unistd.h>
19
20 #include <altivec.h>
21
22 #include "utils.h"
23
24 #define MAX_ATTEMPT 500000
25 #define TIMEOUT 5
26
27 extern long signal_self(pid_t pid, int sig);
28
29 static sig_atomic_t signaled;
30 static sig_atomic_t fail;
31
32 static void signal_handler(int sig)
33 {
34         if (sig == SIGUSR1)
35                 signaled = 1;
36         else
37                 fail = 1;
38 }
39
40 static int test_signal()
41 {
42         int i;
43         struct sigaction act;
44         pid_t ppid = getpid();
45         pid_t pid;
46
47         act.sa_handler = signal_handler;
48         act.sa_flags = 0;
49         sigemptyset(&act.sa_mask);
50         if (sigaction(SIGUSR1, &act, NULL) < 0) {
51                 perror("sigaction SIGUSR1");
52                 exit(1);
53         }
54         if (sigaction(SIGALRM, &act, NULL) < 0) {
55                 perror("sigaction SIGALRM");
56                 exit(1);
57         }
58
59         /* Don't do this for MAX_ATTEMPT, its simply too long */
60         for(i  = 0; i < 1000; i++) {
61                 pid = fork();
62                 if (pid == -1) {
63                         perror("fork");
64                         exit(1);
65                 }
66                 if (pid == 0) {
67                         signal_self(ppid, SIGUSR1);
68                         exit(1);
69                 } else {
70                         alarm(0); /* Disable any pending */
71                         alarm(2);
72                         while (!signaled && !fail)
73                                 asm volatile("": : :"memory");
74                         if (!signaled) {
75                                 fprintf(stderr, "Didn't get signal from child\n");
76                                 FAIL_IF(1); /* For the line number */
77                         }
78                         /* Otherwise we'll loop too fast and fork() will eventually fail */
79                         waitpid(pid, NULL, 0);
80                 }
81         }
82
83         for (i = 0; i < MAX_ATTEMPT; i++) {
84                 long rc;
85
86                 alarm(0); /* Disable any pending */
87                 signaled = 0;
88                 alarm(TIMEOUT);
89                 rc = signal_self(ppid, SIGUSR1);
90                 if (rc) {
91                         fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
92                                         i, fail, rc);
93                         FAIL_IF(1); /* For the line number */
94                 }
95                 while (!signaled && !fail)
96                         asm volatile("": : :"memory");
97                 if (!signaled) {
98                         fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
99                                         i, fail, rc);
100                         FAIL_IF(1); /* For the line number */
101                 }
102         }
103
104         return 0;
105 }
106
107 int main(void)
108 {
109         test_harness_set_timeout(300);
110         return test_harness(test_signal, "signal");
111 }