1 /**************************************\r
2 * file : synchtest2.c\r
3 **************************************\r
4 * * FILE: synchtest2.c\r
5 * \r
6 * DESCRIPTION: netapi user space transport\r
7 * library test application - more synchtest\r
8 * \r
9 * REVISION HISTORY: rev 0.0.1 \r
10 *\r
11 * Copyright (c) Texas Instruments Incorporated 2010-2011\r
12 * \r
13 * Redistribution and use in source and binary forms, with or without \r
14 * modification, are permitted provided that the following conditions \r
15 * are met:\r
16 *\r
17 * Redistributions of source code must retain the above copyright \r
18 * notice, this list of conditions and the following disclaimer.\r
19 *\r
20 * Redistributions in binary form must reproduce the above copyright\r
21 * notice, this list of conditions and the following disclaimer in the \r
22 * documentation and/or other materials provided with the \r
23 * distribution.\r
24 *\r
25 * Neither the name of Texas Instruments Incorporated nor the names of\r
26 * its contributors may be used to endorse or promote products derived\r
27 * from this software without specific prior written permission.\r
28 *\r
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \r
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
40 ******************************************************************************/\r
41 \r
42 #include <stdio.h>\r
43 #include <pthread.h>\r
44 #include <unistd.h>\r
45 #include <stdlib.h>\r
46 #include <sched.h>\r
47 #include <linux/unistd.h>\r
48 #include <sys/syscall.h>\r
49 #include <errno.h>\r
50 \r
51 #include "netsync.h"\r
52 #include "netapi_util.h"\r
53 //#define INC_TO 1000000 // one million.\r
54 #define INC_TO 10000 // one million...\r
55 \r
56 NETAPI_ATOMIC64_T global_int=NETAPI_ATOMIC_INIT64(0LL) ;\r
57 __thread blah=0;\r
58 int blah2=0;\r
59 NETAPI_SPINLOCK_T spin_test;\r
60 \r
61 pid_t gettid( void )\r
62 {\r
63 return syscall( __NR_gettid );\r
64 }\r
65 \r
66 void *thread_routine( void *arg )\r
67 {\r
68 int i;\r
69 int proc_num = (int)(long)arg;\r
70 cpu_set_t set;\r
71 int v1, v2,v3;\r
72 \r
73 #if 0\r
74 CPU_ZERO( &set );\r
75 CPU_SET( proc_num, &set );\r
76 \r
77 if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))\r
78 {\r
79 perror( "sched_setaffinity" );\r
80 return NULL;\r
81 }\r
82 #endif\r
83 \r
84 for (i = 0; i < INC_TO; i++)\r
85 {\r
86 \r
87 v1 = netapi_timing_start(); \r
88 netapi_atomic_add64(&global_int,1LL);\r
89 v1= netapi_timing_stop() - v1;\r
90 sched_yield();\r
91 v2 = netapi_timing_start(); \r
92 blah+=1; \r
93 v2= netapi_timing_stop() - v2;\r
94 \r
95 v3 = netapi_timing_start(); \r
96 blah2+=1; \r
97 v3= netapi_timing_stop() - v3;\r
98 if(i<10) { printf("thread %d -> a64 costs %d, tls costs %d simple++ costs %d\n", proc_num,v1,v2,v3);}\r
99 sched_yield();\r
100 }\r
101 printf("thead %d -> blah=%d\n",proc_num, blah);\r
102 \r
103 printf("now try spin lock test. i'm thread %d, about to grab lock \n", proc_num);\r
104 \r
105 //now we try the synch_lock_and_test\r
106 v1 = netapi_timing_start();\r
107 netapi_spinlock_lock(&spin_test);\r
108 v2 = netapi_timing_stop();\r
109 printf("i'm thread %d. I've locked it, val= %d, it took cycles=%d to get it\ngoing to sleep..",proc_num,spin_test,v2-v1);\r
110 sleep(1);\r
111 printf(" i'm back. i'm thread %d. i'm unlocking now\n",proc_num); \r
112 netapi_spinlock_unlock(&spin_test);\r
113 return NULL;\r
114 }\r
115 \r
116 int main()\r
117 {\r
118 int procs = 0;\r
119 int i;\r
120 pthread_t *thrs;\r
121 printf("at start up\n");\r
122 \r
123 // Getting number of CPUs\r
124 procs = (int)sysconf( _SC_NPROCESSORS_ONLN );\r
125 if (procs < 0)\r
126 {\r
127 perror( "sysconf" );\r
128 return -1;\r
129 }\r
130 printf(" num cpus = %d\n",procs);\r
131 if (procs==1) {procs+=1; printf("adding 2nd 'core' \n");}\r
132 thrs = malloc( sizeof( pthread_t ) * procs );\r
133 if (thrs == NULL)\r
134 {\r
135 perror( "malloc" );\r
136 return -1;\r
137 }\r
138 \r
139 //initialize spinlock\r
140 netapi_spinlock_init(&spin_test);\r
141 printf( "Starting %d threads...\n", procs );\r
142 \r
143 for (i = 0; i < procs; i++)\r
144 {\r
145 if (pthread_create( &thrs[i], NULL, thread_routine,\r
146 (void *)(long)i ))\r
147 {\r
148 perror( "pthread_create" );\r
149 procs = i;\r
150 break;\r
151 }\r
152 }\r
153 \r
154 for (i = 0; i < procs; i++)\r
155 pthread_join( thrs[i], NULL );\r
156 \r
157 free( thrs );\r
158 \r
159 printf( "global_int value is: %lld bare global_int is %d\n",\r
160 global_int.val, blah2 );\r
161 printf( "Expected value is: %d\n", INC_TO * procs );\r
162 \r
163 return 0;\r
164 }\r