1 /*
2 * Copyright (c) 2009 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Author: Steven Dake (sdake@redhat.com)
7 *
8 * libqb is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 2.1 of the License, or
11 * (at your option) any later version.
12 *
13 * libqb is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with libqb. If not, see <http://www.gnu.org/licenses/>.
20 */
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <errno.h>
25 #include <assert.h>
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/time.h>
31 #include <time.h>
32 #include <signal.h>
33
34 #include <qb/qbdefs.h>
35 #include <qb/qbutil.h>
36 #include <qb/qbipcc.h>
37
38 #define ITERATIONS 10000000
39 #define THREADS 4
40
41 struct bm_ctx {
42 qb_ipcc_connection_t *conn;
43 qb_util_stopwatch_t *sw;
44 float mbs;
45 float secs;
46 int32_t multi;
47 uint32_t counter;
48 };
49
50 static void bm_start(struct bm_ctx *ctx)
51 {
52 qb_util_stopwatch_start(ctx->sw);
53 }
54
55 static void bm_finish(struct bm_ctx *ctx, const char *operation, int32_t size)
56 {
57 qb_util_stopwatch_stop(ctx->sw);
|
(1) Event zero_return: |
Function call "qb_util_stopwatch_sec_elapsed_get(ctx->sw)" returns 0.0. [details] |
|
(2) Event assign: |
Assigning: "ctx->secs" = "qb_util_stopwatch_sec_elapsed_get(ctx->sw)". |
| Also see events: |
[divide_by_zero] |
58 ctx->secs = qb_util_stopwatch_sec_elapsed_get(ctx->sw);
59
|
(3) Event divide_by_zero: |
In expression "(float)ctx->counter * size / ctx->secs", division by expression "ctx->secs" which may be zero results in either +infinity, -infinity, or NaN. |
| Also see events: |
[zero_return][assign] |
60 ctx->mbs =
61 ((((float)ctx->counter) * size) / ctx->secs) / (1024.0 *
62 1024.0);
63 }
64
65 static void bmc_connect(struct bm_ctx *ctx)
66 {
67 ctx->sw = qb_util_stopwatch_create();
68 ctx->conn = qb_ipcc_connect("bm1", QB_MAX(1000 * (100 + THREADS),
69 1024*1024));
70 if (ctx->conn == NULL) {
71 perror("qb_ipcc_connect");
72 exit(-1);
73 }
74 }
75
76 static void bmc_disconnect(struct bm_ctx *ctx)
77 {
78 qb_ipcc_disconnect(ctx->conn);
79 qb_util_stopwatch_free(ctx->sw);
80 }
81
82 struct my_req {
83 struct qb_ipc_request_header hdr;
84 char message[1024 * 1024];
85 };
86
87 static struct my_req request;
88
89 static int32_t bmc_send_nozc(struct bm_ctx *ctx, uint32_t size)
90 {
91 struct qb_ipc_response_header res_header;
92 int32_t res;
93
94 request.hdr.id = QB_IPC_MSG_USER_START + 3;
95 request.hdr.size = sizeof(struct qb_ipc_request_header) + size;
96
97 repeat_send:
98 res = qb_ipcc_send(ctx->conn, &request, request.hdr.size);
99 if (res < 0) {
100 if (res == -EAGAIN) {
101 goto repeat_send;
102 } else if (res == -EINVAL || res == -EINTR) {
103 perror("qb_ipcc_send");
104 return -1;
105 } else {
106 errno = -res;
107 perror("qb_ipcc_send");
108 goto repeat_send;
109 }
110 }
111
112 res = qb_ipcc_recv(ctx->conn, &res_header,
113 sizeof(struct qb_ipc_response_header), -1);
114 if (res == -EINTR) {
115 return -1;
116 }
117 if (res < 0) {
118 perror("qb_ipcc_recv");
119 }
120 assert(res == sizeof(struct qb_ipc_response_header));
121 assert(res_header.id == 13);
122 assert(res_header.size == sizeof(struct qb_ipc_response_header));
123 return 0;
124 }
125
126 uint32_t alarm_notice = 0;
127 static void sigalrm_handler(int32_t num)
128 {
129 alarm_notice = 1;
130 }
131
132 static void *benchmark(void *ctx)
133 {
134 struct bm_ctx *bm_ctx = (struct bm_ctx *)ctx;
135 int32_t res;
136
137 bmc_connect(bm_ctx);
138
139 bm_start(bm_ctx);
140 for (;;) {
141 bm_ctx->counter++;
142 res = bmc_send_nozc(bm_ctx, 1000 * bm_ctx->multi);
143 if (alarm_notice || res == -1) {
144 bm_finish(bm_ctx, "send_nozc", 1000 * bm_ctx->multi);
145 bmc_disconnect(bm_ctx);
146 return (NULL);
147 }
148 }
149 }
150
151
152 int32_t main(void)
153 {
154 struct bm_ctx bm_ctx[THREADS];
155 pthread_t threads[THREADS];
156 pthread_attr_t thread_attr[THREADS];
157 int32_t i, j;
158 float total_mbs;
159 void *retval;
160
161 for (i = 0; i < THREADS; i++) {
162 bm_ctx[i].mbs = 0;
163 }
164 signal(SIGALRM, sigalrm_handler);
165 for (j = 0; j < 500; j++) {
166 alarm_notice = 0;
167 alarm(3);
168 for (i = 0; i < THREADS; i++) {
169 bm_ctx[i].multi = j + 100;
170 bm_ctx[i].counter = 0;
171 pthread_attr_init(&thread_attr[i]);
172
173 pthread_attr_setdetachstate(&thread_attr[i],
174 PTHREAD_CREATE_JOINABLE);
175 pthread_create(&threads[i], &thread_attr[i], benchmark,
176 &bm_ctx[i]);
177 }
178 for (i = 0; i < THREADS; i++) {
179 pthread_join(threads[i], &retval);
180 }
181 total_mbs = 0;
182 for (i = 0; i < THREADS; i++) {
183 total_mbs = total_mbs + bm_ctx[i].mbs;
184 }
185 printf("%d ", 1000 * bm_ctx[0].multi);
186 printf("%9.3f\n", total_mbs);
187 }
188 return EXIT_SUCCESS;
189 }
190