Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /* threadtest.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  *		by: john stultz (johnstul@us.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *		(C) Copyright IBM 2004, 2005, 2006, 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *		Licensed under the GPLv2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  To build:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *	$ gcc threadtest.c -o threadtest -lrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *   This program is free software: you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *   it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *   the Free Software Foundation, either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *   (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *   This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *   GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <sys/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <pthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include "../kselftest.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) /* serializes shared list access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) /* serializes console output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define MAX_THREADS 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define LISTSIZE 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) int done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) struct timespec global_list[LISTSIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) int listcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) void checklist(struct timespec *list, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct timespec *a, *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	/* scan the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	for (i = 0; i < size-1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		a = &list[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		b = &list[i+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		/* look for any time inconsistencies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		if ((b->tv_sec <= a->tv_sec) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 			(b->tv_nsec < a->tv_nsec)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 			/* flag other threads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 			done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			/*serialize printing to avoid junky output*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 			pthread_mutex_lock(&print_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			/* dump the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 			printf("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 			for (j = 0; j < size; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 				if (j == i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 					printf("---------------\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 				printf("%lu:%lu\n", list[j].tv_sec, list[j].tv_nsec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 				if (j == i+1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 					printf("---------------\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			printf("[FAILED]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 			pthread_mutex_unlock(&print_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) /* The shared thread shares a global list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  * that each thread fills while holding the lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * This stresses clock syncronization across cpus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) void *shared_thread(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	while (!done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		/* protect the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		pthread_mutex_lock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		/* see if we're ready to check the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		if (listcount >= LISTSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			checklist(global_list, LISTSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			listcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		clock_gettime(CLOCK_MONOTONIC, &global_list[listcount++]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		pthread_mutex_unlock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* Each independent thread fills in its own
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)  * list. This stresses clock_gettime() lock contention.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) void *independent_thread(void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct timespec my_list[LISTSIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	while (!done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		/* fill the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		for (count = 0; count < LISTSIZE; count++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			clock_gettime(CLOCK_MONOTONIC, &my_list[count]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		checklist(my_list, LISTSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define DEFAULT_THREAD_COUNT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define DEFAULT_RUNTIME 30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	int thread_count, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	time_t start, now, runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	char buf[255];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	pthread_t pth[MAX_THREADS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	int opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	void *tret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	void *(*thread)(void *) = shared_thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	thread_count = DEFAULT_THREAD_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	runtime = DEFAULT_RUNTIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	/* Process arguments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	while ((opt = getopt(argc, argv, "t:n:i")) != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		switch (opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 			runtime = atoi(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			thread_count = atoi(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			thread = independent_thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			printf("using independent threads\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			printf("Usage: %s [-t <secs>] [-n <numthreads>] [-i]\n", argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			printf("	-t: time to run\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			printf("	-n: number of threads\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			printf("	-i: use independent threads\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (thread_count > MAX_THREADS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		thread_count = MAX_THREADS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	setbuf(stdout, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	start = time(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	strftime(buf, 255, "%a, %d %b %Y %T %z", localtime(&start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	printf("%s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	printf("Testing consistency with %i threads for %ld seconds: ", thread_count, runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	fflush(stdout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	/* spawn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	for (i = 0; i < thread_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		pthread_create(&pth[i], 0, thread, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	while (time(&now) < start + runtime) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		sleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		if (done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			strftime(buf, 255, "%a, %d %b %Y %T %z", localtime(&now));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			printf("%s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	printf("[OK]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	/* wait */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	for (i = 0; i < thread_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		pthread_join(pth[i], &tret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	/* die */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		ksft_exit_fail();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	return ksft_exit_pass();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }