Home | History | Annotate | Download | only in newlib_tests
      1 /*
      2  * Copyright (c) 2017 Richard Palethorpe <rpalethorpe (at) suse.com>
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 2 of the License, or
      7  * (at your option) any later version.
      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 the
     12  * 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, see <http://www.gnu.org/licenses/>.
     16  */
     17 /* Basic functionality test for tst_fuzzy_sync.h similar to the atomic tests
     18  * (test15.c). One thread writes to the odd indexes of an array while the
     19  * other writes to the even. If the threads are not synchronised then they
     20  * will probably write to the wrong indexes as they share an index variable
     21  * which they should take it in turns to update.
     22  */
     23 
     24 #include <stdlib.h>
     25 #include "tst_test.h"
     26 #include "tst_safe_pthread.h"
     27 #include "tst_fuzzy_sync.h"
     28 
     29 /* LOOPS * 2 + 1 must be less than INT_MAX */
     30 #define LOOPS 0xFFFFFFULL
     31 
     32 static pthread_t thrd;
     33 static volatile char seq[LOOPS * 2 + 1];
     34 static struct tst_fzsync_pair pair = TST_FZSYNC_PAIR_INIT;
     35 static volatile int seq_n;
     36 static volatile int iterations;
     37 
     38 static void *worker(void *v LTP_ATTRIBUTE_UNUSED)
     39 {
     40 	unsigned long long i;
     41 
     42 	for (i = 0; tst_fzsync_wait_update_b(&pair); i++) {
     43 		tst_fzsync_delay_b(&pair);
     44 		tst_fzsync_time_b(&pair);
     45 		if (!tst_fzsync_wait_b(&pair))
     46 			break;
     47 		seq[seq_n] = 'B';
     48 		seq_n = (i + 1) * 2 % (int)LOOPS * 2;
     49 	}
     50 
     51 	if (i > LOOPS * iterations)
     52 		tst_res(TWARN, "Worker performed too many iterations: %lld > %lld",
     53 			i, LOOPS * iterations);
     54 
     55 	return NULL;
     56 }
     57 
     58 static void setup(void)
     59 {
     60 	SAFE_PTHREAD_CREATE(&thrd, NULL, worker, NULL);
     61 }
     62 
     63 static void run(void)
     64 {
     65 	unsigned int i, j, fail = 0;
     66 
     67 	for (i = 0; i < LOOPS; i++) {
     68 		tst_fzsync_wait_update_a(&pair);
     69 		tst_fzsync_delay_a(&pair);
     70 		seq[seq_n] = 'A';
     71 		seq_n = i * 2 + 1;
     72 		tst_fzsync_time_a(&pair);
     73 		if (!tst_fzsync_wait_a(&pair))
     74 			break;
     75 	}
     76 
     77 	tst_res(TINFO, "Checking sequence...");
     78 	for (i = 0; i < LOOPS; i++) {
     79 		j = i * 2;
     80 		if (seq[j] != 'A') {
     81 			tst_res(TFAIL, "Expected A, but found %c at %d",
     82 				seq[j], j);
     83 			fail = 1;
     84 		}
     85 		j = i * 2 + 1;
     86 		if (seq[j] != 'B') {
     87 			tst_res(TFAIL, "Expected A, but found %c at %d",
     88 				seq[j], j);
     89 			fail = 1;
     90 		}
     91 	}
     92 
     93 	if (!fail)
     94 		tst_res(TPASS, "Sequence is correct");
     95 
     96 	if (labs(pair.delay) > 1000)
     97 		tst_res(TFAIL, "Delay is suspiciously large");
     98 
     99 	iterations++;
    100 }
    101 
    102 static void cleanup(void)
    103 {
    104 	tst_fzsync_pair_exit(&pair);
    105 	SAFE_PTHREAD_JOIN(thrd, NULL);
    106 }
    107 
    108 static struct tst_test test = {
    109 	.setup = setup,
    110 	.cleanup = cleanup,
    111 	.test_all = run,
    112 };
    113