1 /* 2 * 3 * Copyright (c) Novell Inc. 2011 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms in version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 * Author: Peter W. Morreale <pmorreale AT novell DOT com> 19 * Date: 11/08/2011 20 */ 21 22 #include "affinity.h" 23 24 #include <stdio.h> 25 #include <sys/wait.h> 26 #include <errno.h> 27 #include <string.h> 28 #include <signal.h> 29 #include <pthread.h> 30 #include <sched.h> 31 #include <signal.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include "posixtest.h" 35 36 37 #define ERR_LOG(l, rc) printf("Failed: %s rc: %d errno: %s\n", \ 38 l, rc, strerror(errno)) 39 40 static int child_busy(int fd) 41 { 42 int rc; 43 44 /* suicide if sched_yield fails */ 45 alarm(4); 46 47 /* Tell the parent we're ready */ 48 write(fd, "go", 2); 49 50 for (;;) { 51 rc = sched_yield(); 52 if (rc) { 53 ERR_LOG("child: sched_yield", rc); 54 exit(1); 55 } 56 } 57 58 /* should not get here */ 59 exit(2); 60 } 61 62 int main(void) 63 { 64 int pid; 65 int rc; 66 int pfd[2]; 67 int status = PTS_UNRESOLVED; 68 int s; 69 struct sched_param sp; 70 char buf[8]; 71 72 /* Set up a pipe, for synching. */ 73 rc = pipe(pfd); 74 if (rc) { 75 ERR_LOG("pipe", rc); 76 return status; 77 } 78 79 /* get in FIFO */ 80 sp.sched_priority = sched_get_priority_min(SCHED_FIFO); 81 rc = sched_setscheduler(getpid(), SCHED_FIFO, &sp); 82 if (rc) { 83 ERR_LOG("sched_setscheduler", rc); 84 return status; 85 } 86 87 /* Must only use a single CPU */ 88 rc = set_affinity_single(); 89 if (rc) { 90 ERR_LOG("set_affinity_single", rc); 91 return status; 92 } 93 94 pid = fork(); 95 if (pid == 0) 96 child_busy(pfd[1]); 97 98 if (pid < 0) { 99 ERR_LOG("fork", rc); 100 return status; 101 } 102 103 /* wait for child */ 104 rc = read(pfd[0], buf, sizeof(buf)); 105 if (rc != 2) { 106 kill(pid, SIGTERM); 107 waitpid(pid, NULL, 0); 108 ERR_LOG("read", rc); 109 return status; 110 } 111 112 /* Can only get here if sched_yield works. */ 113 kill(pid, SIGTERM); 114 waitpid(pid, &s, 0); 115 116 status = PTS_PASS; 117 if (WIFSIGNALED(s)) { 118 s = WTERMSIG(s); 119 if (s != SIGTERM) { 120 printf("Failed: kill signal: %d, should be: %d\n", 121 s, SIGTERM); 122 status = PTS_FAIL; 123 } 124 } else if (WIFEXITED(s)) { 125 printf("Failed: child prematurely exited with: %d\n", 126 WEXITSTATUS(s)); 127 status = PTS_FAIL; 128 } 129 130 if (status == PTS_PASS) 131 printf("Test PASSED\n"); 132 133 return status; 134 } 135