• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2004, QUALCOMM Inc. All rights reserved.
3  * Created by:  abisain REMOVE-THIS AT qualcomm DOT com
4  * This file is licensed under the GPL license.  For the full content
5  * of this license, see the COPYING file at the top level of this
6  * source tree.
7  *
8  * Test that pthread_barrier_wait()
9  * shall wakeup a high priority thread even when a low priority thread
10  * is running
11  *
12  * Steps:
13  * 1. Create a barrier object
14  * 2. Create a high priority thread and make it wait on the barrier
15  * 3. Create a low priority thread and let it busy-loop
16  * 4. Both low and high prio threads run on same CPU
17  * 5. Call the final barrier_wait from main
18  * 6. Check that the higher priority thread got woken up
19  *    and preempted low priority thread
20  */
21 
22 #define _XOPEN_SOURCE 600
23 #include "affinity.h"
24 #include <pthread.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <sys/time.h>
29 #include "posixtest.h"
30 #include "safe_helpers.h"
31 
32 #define TEST "5-4"
33 #define AREA "scheduler"
34 #define ERROR_PREFIX "unexpected error: " AREA " " TEST ": "
35 
36 #define HIGH_PRIORITY 10
37 #define LOW_PRIORITY 5
38 #define RUNTIME 5
39 
40 pthread_barrier_t barrier;
41 static volatile int woken_up;
42 static volatile int low_done;
43 
timediff(struct timespec t2,struct timespec t1)44 float timediff(struct timespec t2, struct timespec t1)
45 {
46 	float diff = t2.tv_sec - t1.tv_sec;
47 	diff += (t2.tv_nsec - t1.tv_nsec) / 1000000000.0;
48 	return diff;
49 }
50 
my_pthread_barrier_wait(pthread_barrier_t * p)51 int my_pthread_barrier_wait(pthread_barrier_t *p)
52 {
53 	int rc;
54 
55 	rc = pthread_barrier_wait(p);
56 	if (rc == PTHREAD_BARRIER_SERIAL_THREAD)
57 		rc = 0;
58 	return rc;
59 }
60 
hi_prio_thread(void * tmp)61 void *hi_prio_thread(void *tmp)
62 {
63 	struct sched_param param;
64 	int policy;
65 
66 	(void) tmp;
67 	set_affinity_single();
68 
69 	SAFE_PFUNC(pthread_getschedparam(pthread_self(), &policy, &param));
70 	if (policy != SCHED_RR || param.sched_priority != HIGH_PRIORITY) {
71 		printf("Error: the policy or priority not correct\n");
72 		exit(PTS_UNRESOLVED);
73 	}
74 
75 	SAFE_PFUNC(my_pthread_barrier_wait(&barrier));
76 
77 	/* This variable is unprotected because the scheduling removes
78 	 * the contention
79 	 */
80 	if (!low_done)
81 		woken_up = 1;
82 
83 	pthread_exit(NULL);
84 }
85 
low_prio_thread(void * tmp)86 void *low_prio_thread(void *tmp)
87 {
88 	struct timespec start_timespec, current_timespec;
89 	struct sched_param param;
90 	int policy;
91 
92 	(void) tmp;
93 	set_affinity_single();
94 
95 	SAFE_PFUNC(pthread_getschedparam(pthread_self(), &policy, &param));
96 	if (policy != SCHED_RR || param.sched_priority != LOW_PRIORITY) {
97 		printf("Error: the policy or priority not correct\n");
98 		exit(PTS_UNRESOLVED);
99 	}
100 
101 	clock_gettime(CLOCK_REALTIME, &start_timespec);
102 	while (!woken_up) {
103 		clock_gettime(CLOCK_REALTIME, &current_timespec);
104 		if (timediff(current_timespec, start_timespec) > RUNTIME)
105 			break;
106 	}
107 	low_done = 1;
108 
109 	pthread_exit(NULL);
110 }
111 
main()112 int main()
113 {
114 	pthread_t high_id, low_id;
115 	pthread_attr_t high_attr;
116 	struct sched_param param;
117 
118 	SAFE_PFUNC(pthread_barrier_init(&barrier, NULL, 2));
119 
120 	/* Create the higher priority */
121 	SAFE_PFUNC(pthread_attr_init(&high_attr));
122 	SAFE_PFUNC(pthread_attr_setinheritsched(&high_attr, PTHREAD_EXPLICIT_SCHED));
123 	SAFE_PFUNC(pthread_attr_setschedpolicy(&high_attr, SCHED_RR));
124 	param.sched_priority = HIGH_PRIORITY;
125 	SAFE_PFUNC(pthread_attr_setschedparam(&high_attr, &param));
126 	SAFE_PFUNC(pthread_create(&high_id, &high_attr, hi_prio_thread, NULL));
127 
128 	/* run main with same priority as low prio thread */
129 	param.sched_priority = LOW_PRIORITY;
130 	SAFE_PFUNC(pthread_setschedparam(pthread_self(), SCHED_RR, &param));
131 
132 	/* Create the low priority thread (inherits sched policy from main) */
133 	SAFE_PFUNC(pthread_create(&low_id, NULL, low_prio_thread, NULL));
134 
135 	sleep(1);
136 	SAFE_PFUNC(my_pthread_barrier_wait(&barrier));
137 
138 	/* Wait for the threads to exit */
139 	SAFE_PFUNC(pthread_join(low_id, NULL));
140 	if (!woken_up) {
141 		printf("High priority was not woken up. Test FAILED\n");
142 		exit(PTS_FAIL);
143 	}
144 	SAFE_PFUNC(pthread_join(high_id, NULL));
145 
146 	printf("Test PASSED\n");
147 	exit(PTS_PASS);
148 }
149