ROSS
tw-util.c
Go to the documentation of this file.
1#include <ross.h>
2#include <stdio.h>
3#include <ctype.h>
4
5/**
6 * Rollback-aware printf, i.e. if the event gets rolled back, undo the printf.
7 * We can'd do that of course so we store the message in a buffer until GVT.
8 */
9int
10tw_output(tw_lp *lp, const char *fmt, ...)
11{
12 int ret = 0;
13 va_list ap;
14 tw_event *cev;
15 tw_out *temp;
16
18 ) {
19 va_start(ap, fmt);
20 vfprintf(stdout, fmt, ap);
21 va_end(ap);
22 return 0;
23 }
24
26 if (!out) {
27 tw_printf(TW_LOC, "kp (%d) has no available output buffers\n", lp->kp->id);
28 tw_printf(TW_LOC, "This event may be rolled back!");
29 va_start(ap, fmt);
30 vfprintf(stdout, fmt, ap);
31 va_end(ap);
32 return 0;
33 }
34
35 cev = lp->pe->cur_event;
36
37 if (cev->out_msgs == 0) {
38 cev->out_msgs = out;
39 }
40 else {
41 // Attach it to the end
42 temp = cev->out_msgs;
43
44 while (temp->next != 0) {
45 temp = temp->next;
46 }
47 temp->next = out;
48 }
49
50 va_start(ap, fmt);
51 ret = vsnprintf(out->message, sizeof(out->message), fmt, ap);
52 va_end(ap);
53 if (ret >= 0 && (unsigned)ret < sizeof(out->message)) {
54 // Should be successful
55 }
56 else {
57 tw_printf(TW_LOC, "Message may be too large?");
58 }
59
60 return ret;
61}
62
63void
64tw_printf(const char *file, int line, const char *fmt, ...)
65{
66 va_list ap;
67
68 va_start(ap, fmt);
69 fprintf(stdout, "%s:%i: ", file, line);
70 vfprintf(stdout, fmt, ap);
71 fprintf(stdout, "\n");
72 fflush(stdout);
73 va_end(ap);
74}
75
76void
77tw_error(const char *file, int line, const char *fmt, ...)
78{
79 va_list ap;
80
81 va_start(ap, fmt);
82 fprintf(stdout, "node: %ld: error: %s:%i: ", g_tw_mynode, file, line);
83 vfprintf(stdout, fmt, ap);
84 fprintf(stdout, "\n");
85 fflush(stdout);
86 fflush(stdout);
87 va_end(ap);
88
90}
91
92void
93tw_warning(const char *file, int line, const char *fmt, ...)
94{
95 va_list ap;
96
97 va_start(ap, fmt);
98 fprintf(stdout, "node: %ld: warning: %s:%i: ", g_tw_mynode, file, line);
99 vfprintf(stdout, fmt, ap);
100 fprintf(stdout, "\n");
101 fflush(stdout);
102 fflush(stdout);
103 va_end(ap);
104}
105
107{
110 char *end_free;
111}__attribute__((aligned(8)));
112
113static struct mem_pool *main_pool;
114
115//static const size_t pool_size = 512 * 1024 - sizeof(struct mem_pool);
116static const size_t pool_size = (512 * 1024) - 32;
117static const size_t pool_align = ROSS_MAX(sizeof(double),sizeof(void*));
118static size_t total_allocated;
119static unsigned malloc_calls;
120static void* my_malloc(size_t len);
121
122void
124 size_t *bytes_alloc,
125 size_t *bytes_wasted)
126{
127 struct mem_pool *p;
128
129 *bytes_alloc = total_allocated;
130 *bytes_wasted = malloc_calls * (sizeof(void*) + sizeof(size_t));
131
132 for (p = main_pool; p; p = p->next_pool)
133 *bytes_wasted += p->end_free - p->next_free;
134}
135
136/* debug version - don't use pool allocator so tools like valgrind can
137 * detect memory bugs */
138#ifdef ROSS_ALLOC_DEBUG
139
140void*
142 const char *file,
143 int line,
144 const char *for_who,
145 size_t e_sz,
146 size_t n)
147{
148 void *r = calloc(e_sz, n);
149 if (!r){
150 tw_error(
151 file, line,
152 "Cannot allocate %lu bytes for %u %s",
153 (unsigned long)e_sz,
154 n,
155 for_who);
156 }
157 return r;
158}
159
160#else
161
162static void*
163pool_alloc(size_t len)
164{
165 struct mem_pool *p;
166 void *r;
167
168 for (p = main_pool; p; p = p->next_pool)
169 if ((unsigned)(p->end_free - p->next_free) >= len)
170 break;
171
172 if (!p) {
173 if (len >= pool_size) {
174 r = my_malloc(len);
175 goto ret;
176 }
177
178 p = (struct mem_pool *) my_malloc(pool_size + 32);
179 if (!p) {
180 r = NULL;
181 goto ret;
182 }
183
184 p->next_pool = main_pool;
185 //p->next_free = (char*)(p + 1);
186 p->next_free = (char *)((size_t)32 + (size_t)p);
187 if( 7 & (size_t)(p->next_free) )
188 printf("pool_alloc: WARNING found pool start address (%p) NOT 8 byte aligned\n", p->next_free);
189 p->end_free = p->next_free + pool_size;
190 main_pool = p;
191 }
192
193 r = p->next_free;
194 p->next_free += len;
195
196 if( 7 & (size_t)r || 7 & (size_t)(p->next_free) )
197 printf("pool_alloc: WARNING found return ptr (%p) or next_free (%p) NOT 8 bytes aligned\n", r, p->next_free );
198
199ret:
200 if (r)
201 total_allocated += len;
202 return r;
203}
204
205void*
207 const char *file,
208 int line,
209 const char *for_who,
210 size_t e_sz,
211 size_t n)
212{
213 void *r;
214
215 if(e_sz & (pool_align - 1))
216 {
217 e_sz += pool_align - (e_sz & (pool_align - 1));
218 // printf("%s:%d:%s: realigned size to %d \n", file, line, for_who, e_sz );
219 }
220
221 e_sz *= n;
222 if (!e_sz)
223 return NULL;
224
225 r = pool_alloc(e_sz);
226 if (!r)
227 tw_error(
228 file, line,
229 "Cannot allocate %lu bytes for %u %s"
230 " (need total of %lu KiB)",
231 (unsigned long)e_sz,
232 n,
233 for_who,
234 (unsigned long)((total_allocated + e_sz) / 1024));
235 memset(r, 0, e_sz);
236 return r;
237}
238
239#endif
240
241#undef malloc
242static void*
243my_malloc(size_t len)
244{
245 malloc_calls++;
246 return malloc(len);
247}
248
249#undef realloc
250
251/**
252 * tw_fprint_binary_array
253 * @brief Prints content of memory into hexadecimal.
254 *
255 * Printing the array "hello world! I'm happy to be here" would produce:
256 *
257 * | 68 65 6c 6c 6f 20 77 6f 72 6c 64 21 20 49 27 6d | hello world! I'm
258 * | 20 68 61 70 70 79 20 74 6f 20 62 65 20 68 65 72 | happy to be her
259 * | 65 | e
260 **/
261void tw_fprint_binary_array(FILE *output, char const * prefix, void const * array, size_t size) {
262 if (!size) {
263 return;
264 }
265
266 fprintf(output, "%s| hex output | bin output \n", prefix);
267
268 char output_line[70];
269 // "Emptying" output_Line
270 for (int j = 0; j < 69; j++) {
271 output_line[j] = ' ';
272 }
273 output_line[0] = '|';
274 output_line[50] = '|';
275 output_line[68] = '\n';
276 output_line[69] = '\0';
277
278 char hexline[] = "0123456789ABCDEF"; // Trick found in https://stackoverflow.com/a/12839870
279
280 // Printing 16 bytes at the time
281 size_t i = 0;
282 while (i < size) {
283 int const line_size = i + 16 <= size ? 16 : size - i;
284 int j = 0;
285 // Writing down array into output_line
286 for (; j < line_size; j++) {
287 char const val = ((char *) array)[i+j];
288 output_line[j*3+2] = hexline[(val >> 4) & 0xF];
289 output_line[j*3+3] = hexline[val & 0xF];
290 output_line[j+52] = isprint(val) ? val : '.';
291 }
292 // Cleaning
293 for (; j < 16; j++) {
294 output_line[j*3+2] = ' ';
295 output_line[j*3+3] = ' ';
296 output_line[j+52] = ' ';
297 }
298 fprintf(output, "%s%s", prefix, output_line);
299 i += 16;
300 }
301}
void tw_net_abort(void)
#define __attribute__(x)
Definition ross-base.h:17
tw_peid g_tw_mynode
Definition ross-global.c:92
tw_synch g_tw_synchronization_protocol
Definition ross-global.c:19
tw_out * tw_kp_grab_output_buffer(tw_kp *kp)
Definition tw-kp.c:210
#define TW_LOC
#define ROSS_MAX(a, b)
@ SEQUENTIAL
Definition ross-types.h:37
@ CONSERVATIVE
Definition ross-types.h:38
@ SEQUENTIAL_ROLLBACK_CHECK
Definition ross-types.h:42
struct mem_pool * next_pool
Definition tw-util.c:108
char * next_free
Definition tw-util.c:109
char * end_free
Definition tw-util.c:110
Event Stucture.
Definition ross-types.h:277
tw_out * out_msgs
Output messages.
Definition ross-types.h:321
tw_kpid id
ID number, otherwise its not available to the app.
Definition ross-types.h:378
LP State Structure.
Definition ross-types.h:336
tw_pe * pe
Definition ross-types.h:340
tw_kp * kp
kp – Kernel process that we belong to (must match pe).
Definition ross-types.h:345
Rollback-aware output mechanism.
Definition ross-types.h:246
struct tw_out * next
Definition ross-types.h:247
char message[256 - 2 *sizeof(void *)]
Definition ross-types.h:250
tw_event * cur_event
Current event being processed.
Definition ross-types.h:426
void * tw_calloc(const char *file, int line, const char *for_who, size_t e_sz, size_t n)
Definition tw-util.c:206
static unsigned malloc_calls
Definition tw-util.c:119
static void * my_malloc(size_t len)
Definition tw-util.c:243
static const size_t pool_align
Definition tw-util.c:117
void tw_calloc_stats(size_t *bytes_alloc, size_t *bytes_wasted)
Definition tw-util.c:123
static size_t total_allocated
Definition tw-util.c:118
void tw_fprint_binary_array(FILE *output, char const *prefix, void const *array, size_t size)
Prints content of memory into hexadecimal.
Definition tw-util.c:261
static struct mem_pool * main_pool
Definition tw-util.c:113
void tw_error(const char *file, int line, const char *fmt,...)
Definition tw-util.c:77
int tw_output(tw_lp *lp, const char *fmt,...)
Definition tw-util.c:10
static void * pool_alloc(size_t len)
Definition tw-util.c:163
void tw_printf(const char *file, int line, const char *fmt,...)
Definition tw-util.c:64
static const size_t pool_size
Definition tw-util.c:116
void tw_warning(const char *file, int line, const char *fmt,...)
Definition tw-util.c:93