1/*
2 * Copyright (c) 2002, Intel Corporation. All rights reserved.
3 * Created by:  bing.wei.liu REMOVE-THIS AT intel 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_mutex_lock()
9 *   shall lock the mutex object referenced by 'mutex'.  If the mutex is
10 *   already locked, the calling thread shall block until the mutex becomes
11 *   available. This operation shall return with the mutex object referenced
12 *   by 'mutex' in the locked state with the calling thread as its owner.
13
14 * Steps:
15 *   -- Initialize a mutex to protect a global variable 'value'
16 *   -- Create N threads. Each is looped M times to acquire the mutex,
17 *      increase the value, and then release the mutex.
18 *   -- Check if the value has increased properly (M*N); a broken mutex
19 *      implementation may cause lost augments.
20 *
21 */
22
23#define _XOPEN_SOURCE 600
24
25#include <pthread.h>
26#include <stdio.h>
27#include <unistd.h>
28#include "posixtest.h"
29
30#define    THREAD_NUM  	5
31#define    LOOPS     	4
32
33void *f1(void *parm);
34
35pthread_mutex_t    mutex = PTHREAD_MUTEX_INITIALIZER;
36int                value;	/* value protected by mutex */
37
38int main()
39{
40  	int                   i, rc;
41  	pthread_attr_t        pta;
42  	pthread_t             threads[THREAD_NUM];
43  	//pthread_t  	      self = pthread_self();
44
45  	pthread_attr_init(&pta);
46  	pthread_attr_setdetachstate(&pta, PTHREAD_CREATE_JOINABLE);
47
48  	/* Create threads */
49  	fprintf(stderr,"Creating %d threads\n", THREAD_NUM);
50  	for (i=0; i<THREAD_NUM; ++i)
51    		rc = pthread_create(&threads[i], &pta, f1, NULL);
52
53	/* Wait to join all threads */
54  	for (i=0; i<THREAD_NUM; ++i)
55    		pthread_join(threads[i], NULL);
56  	pthread_attr_destroy(&pta);
57  	pthread_mutex_destroy(&mutex);
58
59  	/* Check if the final value is as expected */
60  	if(value != (THREAD_NUM) * LOOPS) {
61	  	fprintf(stderr,"Using %d threads and each loops %d times\n", THREAD_NUM, LOOPS);
62    		fprintf(stderr,"Final value must be %d instead of %d\n", (THREAD_NUM)*LOOPS, value);
63		printf("Test FAILED\n");
64		return PTS_FAIL;
65  	}
66
67	printf("Test PASSED\n");
68	return PTS_PASS;
69}
70
71void *f1(void *parm)
72{
73  	int   i, tmp;
74  	int   rc = 0;
75  	pthread_t  self = pthread_self();
76
77	/* Loopd M times to acquire the mutex, increase the value,
78	   and then release the mutex. */
79
80  	for (i=0; i<LOOPS; ++i) {
81      		rc = pthread_mutex_lock(&mutex);
82      		if(rc!=0) {
83        		fprintf(stderr,"Error on pthread_mutex_lock(), rc=%d\n", rc);
84			return (void*)(PTS_FAIL);
85      		}
86
87    		tmp = value;
88    		tmp = tmp+1;
89    		fprintf(stderr,"Thread(0x%p) holds the mutex\n",(void*)self);
90    		usleep(1000);	  /* delay the increasement operation */
91    		value = tmp;
92
93      		rc = pthread_mutex_unlock(&mutex);
94      		if(rc!=0) {
95        		fprintf(stderr,"Error on pthread_mutex_unlock(), rc=%d\n", rc);
96 			return (void*)(PTS_UNRESOLVED);
97      		}
98    		sleep(1);
99  	}
100  	pthread_exit(0);
101  	return (void*)(0);
102}
103