10dc076565f772bb1953209fb69ea150b494aaa40robbiew/*
20dc076565f772bb1953209fb69ea150b494aaa40robbiew * Copyright (c) 2004, QUALCOMM Inc. All rights reserved.
30dc076565f772bb1953209fb69ea150b494aaa40robbiew * Created by:  abisain REMOVE-THIS AT qualcomm DOT com
40dc076565f772bb1953209fb69ea150b494aaa40robbiew * This file is licensed under the GPL license.  For the full content
50dc076565f772bb1953209fb69ea150b494aaa40robbiew * of this license, see the COPYING file at the top level of this
60dc076565f772bb1953209fb69ea150b494aaa40robbiew * source tree.
7061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek *
80dc076565f772bb1953209fb69ea150b494aaa40robbiew * Test that pthread_cond_broadcast()
90dc076565f772bb1953209fb69ea150b494aaa40robbiew *   shall wakeup a high priority thread even when a low priority thread
100dc076565f772bb1953209fb69ea150b494aaa40robbiew *   is running
110dc076565f772bb1953209fb69ea150b494aaa40robbiew *
120dc076565f772bb1953209fb69ea150b494aaa40robbiew * Steps:
130dc076565f772bb1953209fb69ea150b494aaa40robbiew * 1. Create a condition variable
140dc076565f772bb1953209fb69ea150b494aaa40robbiew * 2. Create a high priority thread and make it wait on the cond
150dc076565f772bb1953209fb69ea150b494aaa40robbiew * 3. Create a low priority thread and let it busy-loop
16dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek * 4. Both low and high prio threads run on same CPU
17dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek * 5. Signal the cond from main and check that high priority thread
18dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek *    got woken up and preempted low priority thread
190dc076565f772bb1953209fb69ea150b494aaa40robbiew */
200dc076565f772bb1953209fb69ea150b494aaa40robbiew
21dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek#include "affinity.h"
220dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <pthread.h>
230dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdio.h>
240dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <stdlib.h>
250dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <unistd.h>
260dc076565f772bb1953209fb69ea150b494aaa40robbiew#include <time.h>
270dc076565f772bb1953209fb69ea150b494aaa40robbiew#include "posixtest.h"
28061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek#include "safe_helpers.h"
290dc076565f772bb1953209fb69ea150b494aaa40robbiew
300dc076565f772bb1953209fb69ea150b494aaa40robbiew#define TEST "5-1"
310dc076565f772bb1953209fb69ea150b494aaa40robbiew#define AREA "scheduler"
320dc076565f772bb1953209fb69ea150b494aaa40robbiew#define ERROR_PREFIX "unexpected error: " AREA " " TEST ": "
330dc076565f772bb1953209fb69ea150b494aaa40robbiew
340dc076565f772bb1953209fb69ea150b494aaa40robbiew#define HIGH_PRIORITY 10
350dc076565f772bb1953209fb69ea150b494aaa40robbiew#define LOW_PRIORITY  5
360dc076565f772bb1953209fb69ea150b494aaa40robbiew#define RUNTIME       5
370dc076565f772bb1953209fb69ea150b494aaa40robbiew#define POLICY        SCHED_RR
380dc076565f772bb1953209fb69ea150b494aaa40robbiew
392c28215423293e443469a07ae7011135d058b671Garrett Cooperpthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
402c28215423293e443469a07ae7011135d058b671Garrett Cooperpthread_cond_t cond = PTHREAD_COND_INITIALIZER;
410dc076565f772bb1953209fb69ea150b494aaa40robbiew
420dc076565f772bb1953209fb69ea150b494aaa40robbiew/* Flags that the threads use to indicate events */
43d9d0e9cc0cd3f5eb5f70d47177a4b9ed4a0de827Jan Stancekstatic volatile int woken_up;
44d9d0e9cc0cd3f5eb5f70d47177a4b9ed4a0de827Jan Stancekstatic volatile int low_done;
450dc076565f772bb1953209fb69ea150b494aaa40robbiew
460dc076565f772bb1953209fb69ea150b494aaa40robbiewfloat timediff(struct timespec t2, struct timespec t1)
470dc076565f772bb1953209fb69ea150b494aaa40robbiew{
480dc076565f772bb1953209fb69ea150b494aaa40robbiew	float diff = t2.tv_sec - t1.tv_sec;
49354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	diff += (t2.tv_nsec - t1.tv_nsec) / 1000000000.0;
500dc076565f772bb1953209fb69ea150b494aaa40robbiew	return diff;
510dc076565f772bb1953209fb69ea150b494aaa40robbiew}
520dc076565f772bb1953209fb69ea150b494aaa40robbiew
53061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancekvoid *hi_prio_thread(void *tmp)
542c28215423293e443469a07ae7011135d058b671Garrett Cooper{
55354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct sched_param param;
56354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int policy;
570dc076565f772bb1953209fb69ea150b494aaa40robbiew
58061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	(void) tmp;
59dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	set_affinity_single();
600dc076565f772bb1953209fb69ea150b494aaa40robbiew
61061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_getschedparam(pthread_self(), &policy, &param));
62df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper	if ((policy != POLICY) || (param.sched_priority != HIGH_PRIORITY)) {
630dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("Error: the policy or priority not correct\n");
640dc076565f772bb1953209fb69ea150b494aaa40robbiew		exit(PTS_UNRESOLVED);
650dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
660dc076565f772bb1953209fb69ea150b494aaa40robbiew
67061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_mutex_lock(&mutex));
680dc076565f772bb1953209fb69ea150b494aaa40robbiew
690dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Block, to be woken up by the signal handler */
70061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_cond_wait(&cond, &mutex));
710dc076565f772bb1953209fb69ea150b494aaa40robbiew
722c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* This variable is unprotected because the scheduling removes
732c28215423293e443469a07ae7011135d058b671Garrett Cooper	 * the contention
740dc076565f772bb1953209fb69ea150b494aaa40robbiew	 */
75d9d0e9cc0cd3f5eb5f70d47177a4b9ed4a0de827Jan Stancek	if (!low_done)
760dc076565f772bb1953209fb69ea150b494aaa40robbiew		woken_up = 1;
770dc076565f772bb1953209fb69ea150b494aaa40robbiew
78061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_mutex_unlock(&mutex));
790dc076565f772bb1953209fb69ea150b494aaa40robbiew	return NULL;
800dc076565f772bb1953209fb69ea150b494aaa40robbiew}
810dc076565f772bb1953209fb69ea150b494aaa40robbiew
82061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancekvoid *low_prio_thread(void *tmp)
830dc076565f772bb1953209fb69ea150b494aaa40robbiew{
84354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct timespec start_time, current_time;
85354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct sched_param param;
86354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int policy;
870dc076565f772bb1953209fb69ea150b494aaa40robbiew
88061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	(void) tmp;
89dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	set_affinity_single();
900dc076565f772bb1953209fb69ea150b494aaa40robbiew
91061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_getschedparam(pthread_self(), &policy, &param));
92df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper	if ((policy != POLICY) || (param.sched_priority != LOW_PRIORITY)) {
930dc076565f772bb1953209fb69ea150b494aaa40robbiew		printf("Error: the policy or priority not correct\n");
940dc076565f772bb1953209fb69ea150b494aaa40robbiew		exit(PTS_UNRESOLVED);
950dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
960dc076565f772bb1953209fb69ea150b494aaa40robbiew
970dc076565f772bb1953209fb69ea150b494aaa40robbiew	clock_gettime(CLOCK_REALTIME, &start_time);
98d9d0e9cc0cd3f5eb5f70d47177a4b9ed4a0de827Jan Stancek	while (!woken_up) {
990dc076565f772bb1953209fb69ea150b494aaa40robbiew		clock_gettime(CLOCK_REALTIME, &current_time);
100df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper		if (timediff(current_time, start_time) > RUNTIME)
1010dc076565f772bb1953209fb69ea150b494aaa40robbiew			break;
1020dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1030dc076565f772bb1953209fb69ea150b494aaa40robbiew	low_done = 1;
1040dc076565f772bb1953209fb69ea150b494aaa40robbiew	return NULL;
1050dc076565f772bb1953209fb69ea150b494aaa40robbiew}
1060dc076565f772bb1953209fb69ea150b494aaa40robbiew
1070dc076565f772bb1953209fb69ea150b494aaa40robbiewint main()
1080dc076565f772bb1953209fb69ea150b494aaa40robbiew{
109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pthread_t high_id, low_id;
110dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	pthread_attr_t high_attr;
111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct sched_param param;
1122c28215423293e443469a07ae7011135d058b671Garrett Cooper
1130dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Create the higher priority thread */
114061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_attr_init(&high_attr));
1150f029d9eea2b580cd4389aecb50f016b7d5fdc04Jan Stancek	SAFE_PFUNC(pthread_attr_setinheritsched(&high_attr, PTHREAD_EXPLICIT_SCHED));
116061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_attr_setschedpolicy(&high_attr, POLICY));
1170dc076565f772bb1953209fb69ea150b494aaa40robbiew	param.sched_priority = HIGH_PRIORITY;
118061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_attr_setschedparam(&high_attr, &param));
119061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_create(&high_id, &high_attr, hi_prio_thread, NULL));
1200dc076565f772bb1953209fb69ea150b494aaa40robbiew
121dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	/* run main with same priority as low prio thread */
1220dc076565f772bb1953209fb69ea150b494aaa40robbiew	param.sched_priority = LOW_PRIORITY;
123dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	SAFE_PFUNC(pthread_setschedparam(pthread_self(), POLICY, &param));
124dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek
125dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	/* Create the low priority thread (inherits sched policy from main) */
126dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	SAFE_PFUNC(pthread_create(&low_id, NULL, low_prio_thread, NULL));
127dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek
128dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	sleep(1);
129dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	SAFE_PFUNC(pthread_cond_broadcast(&cond));
1300dc076565f772bb1953209fb69ea150b494aaa40robbiew
1310dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Wait for the threads to exit */
132061df0771e1e4c42dc6d0f1efabe38b9392de48eJan Stancek	SAFE_PFUNC(pthread_join(low_id, NULL));
133d9d0e9cc0cd3f5eb5f70d47177a4b9ed4a0de827Jan Stancek	if (!woken_up) {
134d9d0e9cc0cd3f5eb5f70d47177a4b9ed4a0de827Jan Stancek		printf("Test FAILED: high priority was not woken up\n");
1350dc076565f772bb1953209fb69ea150b494aaa40robbiew		exit(PTS_FAIL);
1360dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
137dadab74ec5c36fe26ea6ebd788196051e8130da6Jan Stancek	SAFE_PFUNC(pthread_join(high_id, NULL));
1380dc076565f772bb1953209fb69ea150b494aaa40robbiew
139de55e5ac14dc3e683117ae84bad34944fa7c38c6Cyril Hrubis	printf("Test PASSED\n");
1400dc076565f772bb1953209fb69ea150b494aaa40robbiew	exit(PTS_PASS);
141ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
142