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