1 /*
2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3  *                         University Research and Technology
4  *                         Corporation.  All rights reserved.
5  * Copyright (c) 2004-2005 The University of Tennessee and The University
6  *                         of Tennessee Research Foundation.  All rights
7  *                         reserved.
8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9  *                         University of Stuttgart.  All rights reserved.
10  * Copyright (c) 2004-2005 The Regents of the University of California.
11  *                         All rights reserved.
12  * Copyright (c) 2010      Cisco Systems, Inc.  All rights reserved.
13  * Copyright (c) 2015      Research Organization for Information Science
14  *                         and Technology (RIST). All rights reserved.
15  * $COPYRIGHT$
16  *
17  * Additional copyrights may follow
18  *
19  * $HEADER$
20  */
21 
22 #define OMPI_BUILDING 0
23 #include "opal_config.h"
24 
25 #ifdef HAVE_PTHREAD_H
26 #include <pthread.h>
27 #endif
28 #include <stdlib.h>
29 #include <stdio.h>
30 
31 #include "opal/sys/atomic.h"
32 
33 #define TEST_REPS 500
34 
35 int atomic_verbose = 0;
36 
37 struct start_info {
38     int tid;
39     int count;
40     opal_atomic_lock_t *lock;
41 };
42 
43 static int atomic_spinlock_test(opal_atomic_lock_t *lock, int count, int id);
44 
atomic_spinlock_start(void * arg)45 static void* atomic_spinlock_start(void* arg)
46 {
47     struct start_info *data = (struct start_info*) arg;
48 
49     return (void*) (unsigned long) atomic_spinlock_test(data->lock, data->count,
50                                         data->tid);
51 }
52 
53 static int
atomic_spinlock_test_th(opal_atomic_lock_t * lock,int count,int id,int thr_count)54 atomic_spinlock_test_th(opal_atomic_lock_t *lock, int count, int id, int thr_count)
55 {
56     pthread_t *th;
57     int tid, ret = 0;
58     struct start_info *data;
59 
60     th = (pthread_t *) malloc(thr_count * sizeof(pthread_t));
61     if (!th) { perror("malloc"); exit(EXIT_FAILURE); }
62     data = (struct start_info *) malloc(thr_count * sizeof(struct start_info));
63     if (!th) { perror("malloc"); exit(EXIT_FAILURE); }
64 
65     for (tid = 0; tid < thr_count; tid++) {
66         data[tid].tid = tid;
67         data[tid].count = count;
68         data[tid].lock = lock;
69 
70         if (pthread_create(&th[tid], NULL, atomic_spinlock_start, (void *) &(data[tid])) != 0) {
71             perror("pthread_create");
72             exit(EXIT_FAILURE);
73         }
74     }
75 
76     /* -- wait for the thread set to finish -- */
77     for (tid = 0; tid < thr_count; tid++) {
78         void *thread_return;
79 
80         if (pthread_join(th[tid], &thread_return) != 0) {
81             perror("pthread_join");
82             exit(EXIT_FAILURE);
83         }
84 
85         ret += (int) (unsigned long) thread_return;
86     }
87     free(data);
88     free(th);
89 
90     return ret;
91 }
92 
93 
94 static int
atomic_spinlock_test(opal_atomic_lock_t * lock,int count,int id)95 atomic_spinlock_test(opal_atomic_lock_t *lock, int count, int id)
96 {
97     int i;
98 
99     for (i = 0 ; i < count ; ++i) {
100         opal_atomic_lock(lock);
101         if (atomic_verbose) { printf("id %03d has the lock (lock)\n", id); }
102         opal_atomic_unlock(lock);
103 
104         while (opal_atomic_trylock(lock)) { ; }
105         if (atomic_verbose) { printf("id %03d has the lock (trylock)\n", id); }
106         opal_atomic_unlock(lock);
107     }
108 
109     return 0;
110 }
111 
112 
113 int
main(int argc,char * argv[])114 main(int argc, char *argv[])
115 {
116     int ret = 77;
117     opal_atomic_lock_t lock;
118     int num_threads = 1;
119 
120     if (argc != 2) {
121         printf("*** Incorrect number of arguments.  Skipping test\n");
122         return 77;
123     }
124     num_threads = atoi(argv[1]);
125 
126     opal_atomic_lock_init(&lock, OPAL_ATOMIC_LOCK_UNLOCKED);
127     ret = atomic_spinlock_test_th(&lock, TEST_REPS, 0, num_threads);
128 
129     return ret;
130 }
131