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 <stdio.h>
25
26 #ifdef __WIN32__
27 #include <winsock2.h>
28 #include <windows.h>
29 #include <process.h>
30 #else
31 #ifndef VXWORKS
32 #include <pthread.h>
33 #endif
34 #include <sys/socket.h>
35 #endif
36
37 #include "ei.h"
38 #include "erl_interface.h"
39
40 #ifdef VXWORKS
41 #define MAIN cnode
42 #else
43 #define MAIN main
44 #endif
45
46 /*
47 A small einode.
48 To be called from the test case ei_accept_SUITE:multi_thread
49 usage: einode <cookie> <n> <destnode>
50
51 - start threads 0..n-1
52 - in each thread
53 - connect to destnode
54 - send a message ("ei0".."ei<n-1>") to mth0..mth<n-1> on destnode
55 - shutdown gracefully
56 */
57
58 static const char* cookie, * desthost;
59
60 #ifndef SD_SEND
61 #ifdef SHUTWR
62 #define SD_SEND SHUT_WR
63 #else
64 #define SD_SEND 1
65 #endif
66 #endif
67
68 #ifndef __WIN32__
69 #define closesocket(fd) close(fd)
70 #endif
71
72 #ifdef __WIN32__
73 static DWORD WINAPI
74 #else
75 static void*
76 #endif
einode_thread(void * num)77 einode_thread(void* num)
78 {
79 int n = (int)num;
80 ei_cnode ec;
81 char myname[100], destname[100];
82 int r, fd;
83
84 sprintf(myname, "ei%d", n);
85 sprintf(destname, "mth%d", n);
86 printf("thread %d (%s %s) connecting\n", n, myname, destname);
87 r = ei_connect_init(&ec, myname, cookie, 0);
88 fd = ei_connect(&ec, (char*)desthost);
89 if (r == 0 && fd >= 0) {
90 ei_x_buff x;
91 ei_x_new_with_version(&x);
92 ei_x_encode_string(&x, myname);
93 ei_reg_send(&ec, fd, destname, x.buff, x.index);
94 ei_x_free(&x);
95 //SleepEx(100);
96 shutdown(fd, SD_SEND);
97 closesocket(fd);
98 } else {
99 printf("coudn't connect fd %d r %d\n", fd, r); // DebugBreak();
100 }
101 printf("done thread %d\n", n);
102 return 0;
103 }
104
MAIN(int argc,char * argv[])105 MAIN(int argc, char *argv[])
106 {
107 int i, n, no_threads;
108 #ifndef VXWORKS
109 #ifdef __WIN32__
110 HANDLE threads[100];
111 #else
112 pthread_t threads[100];
113 #endif
114 #endif
115
116 if (argc < 3)
117 exit(1);
118
119 erl_init(NULL, 0);
120
121 cookie = argv[1];
122 n = atoi(argv[2]);
123 if (n > 100)
124 exit(2);
125 desthost = argv[3];
126 #ifndef VXWORKS
127 no_threads = argv[4] != NULL && strcmp(argv[4], "nothreads") == 0;
128 #else
129 no_threads = 1;
130 #endif
131 for (i = 0; i < n; ++i) {
132 if (!no_threads) {
133 #ifndef VXWORKS
134 #ifdef __WIN32__
135 unsigned tid;
136 threads[i] = (HANDLE)_beginthreadex(NULL, 0, einode_thread,
137 (void*)i, 0, &tid);
138 #else
139 pthread_create(&threads[i], NULL, einode_thread, (void*)i);
140 #endif
141 #else
142 ;
143 #endif
144 } else
145 einode_thread((void*)i);
146 }
147 if (!no_threads)
148 #ifndef VXWORKS
149 for (i = 0; i < n; ++i) {
150 #ifdef __WIN32__
151 if (WaitForSingleObject(threads[i], INFINITE) != WAIT_OBJECT_0)
152 #else
153 if (pthread_join(threads[i], NULL) != 0)
154 #endif
155 printf("bad wait thread %d\n", i);
156 }
157 #else
158 ;
159 #endif
160 printf("ok\n");
161 return 0;
162 }
163