1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2001-2016. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 /* to test multiple threads in ei */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26
27 #ifdef __WIN32__
28 #include <winsock2.h>
29 #include <windows.h>
30 #include <process.h>
31 #else
32 #include <pthread.h>
33 #include <sys/socket.h>
34 #include <unistd.h>
35 #endif
36
37 #include "ei.h"
38
39 /*
40 A small einode.
41 To be called from the test case ei_accept_SUITE:multi_thread
42 usage: einode <cookie> <n> <destnode>
43
44 - start threads 0..n-1
45 - in each thread
46 - connect to destnode
47 - send a message ("ei0".."ei<n-1>") to mth0..mth<n-1> on destnode
48 - shutdown gracefully
49 */
50
51 static const char* cookie, * desthost;
52
53 #ifndef SD_SEND
54 #ifdef SHUTWR
55 #define SD_SEND SHUT_WR
56 #else
57 #define SD_SEND 1
58 #endif
59 #endif
60
61 #ifndef __WIN32__
62 #define closesocket(fd) close(fd)
63 #endif
64
65 #ifdef __WIN32__
66 static DWORD WINAPI
67 #else
68 static void*
69 #endif
einode_thread(void * num)70 einode_thread(void* num)
71 {
72 int n = (int)num;
73 ei_cnode ec;
74 char myname[100], destname[100];
75 int r, fd;
76
77 sprintf(myname, "ei%d", n);
78 sprintf(destname, "mth%d", n);
79 printf("thread %d (%s %s) connecting\n", n, myname, destname);
80 r = ei_connect_init(&ec, myname, cookie, 0);
81 fd = ei_connect(&ec, (char*)desthost);
82 if (r == 0 && fd >= 0) {
83 ei_x_buff x;
84 ei_x_new_with_version(&x);
85 ei_x_encode_string(&x, myname);
86 ei_reg_send(&ec, fd, destname, x.buff, x.index);
87 ei_x_free(&x);
88 //SleepEx(100);
89 shutdown(fd, SD_SEND);
90 closesocket(fd);
91 } else {
92 printf("coudn't connect fd %d r %d\n", fd, r); // DebugBreak();
93 }
94 printf("done thread %d\n", n);
95 return 0;
96 }
97
main(int argc,char * argv[])98 int main(int argc, char *argv[])
99 {
100 int i, n, no_threads;
101 #ifdef __WIN32__
102 HANDLE threads[100];
103 #else
104 pthread_t threads[100];
105 #endif
106
107 if (argc < 3)
108 exit(1);
109
110 ei_init();
111
112 cookie = argv[1];
113 n = atoi(argv[2]);
114 if (n > 100)
115 exit(2);
116 desthost = argv[3];
117 no_threads = argv[4] != NULL && strcmp(argv[4], "nothreads") == 0;
118 for (i = 0; i < n; ++i) {
119 if (!no_threads) {
120 #ifdef __WIN32__
121 unsigned tid;
122 threads[i] = (HANDLE)_beginthreadex(NULL, 0, einode_thread,
123 (void*)i, 0, &tid);
124 #else
125 pthread_create(&threads[i], NULL, einode_thread, (void*)i);
126 #endif
127 } else
128 einode_thread((void*)i);
129 }
130 if (!no_threads)
131 for (i = 0; i < n; ++i) {
132 #ifdef __WIN32__
133 if (WaitForSingleObject(threads[i], INFINITE) != WAIT_OBJECT_0)
134 #else
135 if (pthread_join(threads[i], NULL) != 0)
136 #endif
137 printf("bad wait thread %d\n", i);
138 }
139 printf("ok\n");
140 return 0;
141 }
142