-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbufcounts.c
More file actions
159 lines (139 loc) · 4.42 KB
/
bufcounts.c
File metadata and controls
159 lines (139 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <malloc.h>
#include "donottouch.h"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE 32
#endif
#ifndef THREAD_MAX
#define THREAD_MAX 1
#endif
#ifndef ITERATIONS
#define ITERATIONS 100000
#endif
#ifdef USE_MUTEX
typedef pthread_mutex_t lock_t;
#define lock_acquire pthread_mutex_lock
#define lock_release pthread_mutex_unlock
#define lock_init pthread_mutex_init
#else
typedef pthread_spinlock_t lock_t;
#define lock_acquire pthread_spin_lock
#define lock_release pthread_spin_unlock
#define lock_init pthread_spin_init
#endif
typedef struct {
lock_t lock;
long total_count;
buf buffer;
} item;
item items[ARRAY_SIZE];
void update_buffer_elements(unsigned thread_id) {
for (int i = 0; i < ARRAY_SIZE; i++) {
#if THREAD_MAX > 1
lock_acquire(&items[i].lock);
#endif
update_buffer(&items[i].buffer,0);
#if THREAD_MAX > 1
lock_release(&items[i].lock);
#endif
}
}
void update_item_counts(unsigned thread_id) {
for (int i = 0; i < ARRAY_SIZE; i++) {
#if THREAD_MAX > 1
lock_acquire(&items[i].lock);
#endif
items[i].total_count++;
#if THREAD_MAX > 1
lock_release(&items[i].lock);
#endif
}
}
void* thread_function(void* arg) {
int identifier = (int)(long)arg; // Cast back to int
for (int i = 0; i < ITERATIONS; i++) {
update_buffer_elements(identifier);
}
return NULL;
}
void* thread_function2(void* arg) {
int identifier = (int)(long)arg; // Cast back to int
for (int i = 0; i < ITERATIONS; i++) {
update_item_counts(identifier);
}
return NULL;
}
int main() {
struct timespec start_buffer, end_buffer, start_item, end_item;
int correct = 1;
for (int i = 0; i < ARRAY_SIZE; i++) {
memset(items[i].buffer.counter,0,BUF_SIZE*8);
lock_init(&items[i].lock, 0);
}
malloc_trim(0);
struct mallinfo2 info = mallinfo2();
if(info.arena > 0)
fprintf(stderr,"Heap size is %lu after allocating buffers. Buffers are %u total.\n",info.arena,ARRAY_SIZE*BUF_SIZE*8);
pthread_t threads[THREAD_MAX];
clock_gettime(CLOCK_MONOTONIC, &start_buffer);
for (int i = 0; i < THREAD_MAX; i++) {
if (pthread_create(&threads[i], NULL, thread_function, (void*)(long)i) != 0) {
perror("Failed to create thread");
return 1;
}
}
for (int i = 0; i < THREAD_MAX; i++) {
if (pthread_join(threads[i], NULL) != 0) {
perror("Failed to join thread");
return 1;
}
}
clock_gettime(CLOCK_MONOTONIC, &end_buffer);
clock_gettime(CLOCK_MONOTONIC, &start_item);
for (int i = 0; i < THREAD_MAX; i++) {
if (pthread_create(&threads[i], NULL, thread_function2, (void*)(long)i) != 0) {
perror("Failed to create thread");
return 1;
}
}
for (int i = 0; i < THREAD_MAX; i++) {
if (pthread_join(threads[i], NULL) != 0) {
perror("Failed to join thread");
return 1;
}
}
clock_gettime(CLOCK_MONOTONIC, &end_item);
// Check that things match up
for (int i = 0; i < ARRAY_SIZE; i++) {
long sum = 0;
for (int j = 0; j < BUF_SIZE; j++) {
sum+=items[i].buffer.counter[j];
}
if (sum != items[i].total_count) {
fprintf(stderr,"Error: Item %d has sum %ld != %ld. Expected %d.\n",
i,sum,items[i].total_count,THREAD_MAX*ITERATIONS);
correct = 0;
break;
}
if(check_buffer_alignment(&items[i].buffer)!=0) {
printf("Error: Buffer is incorrectly aligned %p, should be aligned %lu.\n",
&items[i].buffer, alignof(buf));
}
}
// Calculate elapsed time in nanoseconds
long elapsed_ns_buf = (end_buffer.tv_sec - start_buffer.tv_sec) * 1000000000LL + (end_buffer.tv_nsec - start_buffer.tv_nsec);
long elapsed_ns_item = (end_item.tv_sec - start_item.tv_sec) * 1000000000LL + (end_item.tv_nsec - start_item.tv_nsec);
// Output the result
if (correct) {
printf("%d threads, %d items, %d iterations. count: %.2lf buf: %.2lf ns\n",THREAD_MAX, ARRAY_SIZE, ITERATIONS,
elapsed_ns_item / (double)(ARRAY_SIZE * ITERATIONS),
elapsed_ns_buf / (double)(ARRAY_SIZE * ITERATIONS));
} else {
printf("Error: Buffer values are incorrect.\n");
}
return 0;
}