Skip to content

Commit 4a66982

Browse files
authored
Merge pull request #715 from abouteiller/feature/thread-safe-zonemalloc
Make zone-malloc/free thread safe
2 parents 0faa783 + d2dfcbd commit 4a66982

File tree

2 files changed

+25
-16
lines changed

2 files changed

+25
-16
lines changed

parsec/utils/zone_malloc.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012-2019 The University of Tennessee and The University
2+
* Copyright (c) 2012-2024 The University of Tennessee and The University
33
* of Tennessee Research Foundation. All rights
44
* reserved.
55
*/
@@ -35,12 +35,12 @@ zone_malloc_t* zone_malloc_init(void* base_ptr, int _max_segment, size_t _unit_s
3535
}
3636

3737
gdata = (zone_malloc_t*)malloc( sizeof(zone_malloc_t) );
38-
gdata->base = base_ptr;
39-
gdata->unit_size = _unit_size;
40-
gdata->max_segment = _max_segment;
41-
42-
gdata->next_tid = 0;
43-
gdata->segments = (segment_t *)malloc(sizeof(segment_t) * _max_segment);
38+
gdata->base = base_ptr;
39+
gdata->unit_size = _unit_size;
40+
gdata->max_segment = _max_segment;
41+
gdata->next_tid = 0;
42+
gdata->segments = (segment_t *)malloc(sizeof(segment_t) * _max_segment);
43+
parsec_atomic_lock_init(&gdata->lock);
4444
#if defined(PARSEC_DEBUG)
4545
for(int i = 0; i < _max_segment; i++) {
4646
SEGMENT_AT_TID(gdata, i)->status = SEGMENT_UNDEFINED;
@@ -74,6 +74,7 @@ void *zone_malloc(zone_malloc_t *gdata, size_t size)
7474
int next_tid, current_tid, new_tid;
7575
int cycled_through = 0, nb_units;
7676

77+
parsec_atomic_lock(&gdata->lock);
7778
/* Let's start with the last remembered free slot */
7879
current_tid = gdata->next_tid;
7980
nb_units = (size + gdata->unit_size - 1) / gdata->unit_size;
@@ -82,13 +83,10 @@ void *zone_malloc(zone_malloc_t *gdata, size_t size)
8283
current_segment = SEGMENT_AT_TID(gdata, current_tid);
8384
if( NULL == current_segment ) {
8485
/* Maybe there is a free slot in the beginning. Let's cycle at least once before we bail out */
85-
if( cycled_through == 0 ) {
86-
current_tid = 0;
87-
cycled_through = 1;
88-
current_segment = SEGMENT_AT_TID(gdata, current_tid);
89-
} else {
90-
return NULL;
91-
}
86+
if( 0 != cycled_through ) break;
87+
current_tid = 0;
88+
cycled_through = 1;
89+
current_segment = SEGMENT_AT_TID(gdata, current_tid);
9290
}
9391

9492
if( current_segment->status == SEGMENT_EMPTY && current_segment->nb_units >= nb_units ) {
@@ -111,12 +109,14 @@ void *zone_malloc(zone_malloc_t *gdata, size_t size)
111109

112110
current_segment->nb_units = nb_units;
113111
}
112+
parsec_atomic_unlock(&gdata->lock);
114113
return (void*)(gdata->base + (current_tid * gdata->unit_size));
115114
}
116115

117116
current_tid += current_segment->nb_units;
118117
} while( current_tid != gdata->next_tid );
119118

119+
parsec_atomic_unlock(&gdata->lock);
120120
return NULL;
121121
}
122122

@@ -126,18 +126,21 @@ void zone_free(zone_malloc_t *gdata, void *add)
126126
int current_tid, next_tid, prev_tid;
127127
off_t offset;
128128

129+
parsec_atomic_lock(&gdata->lock);
129130
offset = (char*)add -gdata->base;
130131
assert( (offset % gdata->unit_size) == 0);
131132
current_tid = offset / gdata->unit_size;
132133
current_segment = SEGMENT_AT_TID(gdata, current_tid);
133134

134135
if( NULL == current_segment ) {
135136
zone_malloc_error("address to free not allocated\n");
137+
parsec_atomic_unlock(&gdata->lock);
136138
return;
137139
}
138140

139141
if( SEGMENT_EMPTY == current_segment->status ) {
140142
zone_malloc_error("double free (or other buffer overflow) error in ZONE allocation");
143+
parsec_atomic_unlock(&gdata->lock);
141144
return;
142145
}
143146

@@ -173,20 +176,23 @@ void zone_free(zone_malloc_t *gdata, void *add)
173176
next_segment->nb_prev = current_segment->nb_units;
174177
}
175178
}
179+
parsec_atomic_unlock(&gdata->lock);
176180
}
177181

178182
size_t zone_in_use(zone_malloc_t *gdata)
179183
{
180184
size_t ret = 0;
181185
segment_t *current_segment;
182186
int current_tid;
187+
parsec_atomic_lock(&gdata->lock);
183188
for(current_tid = 0;
184189
(current_segment = SEGMENT_AT_TID(gdata, current_tid)) != NULL;
185190
current_tid += current_segment->nb_units) {
186191
if( current_segment->status == SEGMENT_FULL ) {
187192
ret += gdata->unit_size * current_segment->nb_units;
188193
}
189194
}
195+
parsec_atomic_unlock(&gdata->lock);
190196
return ret;
191197
}
192198

@@ -197,6 +203,7 @@ size_t zone_debug(zone_malloc_t *gdata, int level, int output_id, const char *pr
197203
int current_tid;
198204
size_t ret = 0;
199205

206+
parsec_atomic_lock(&gdata->lock);
200207
for(current_tid = 0;
201208
(current_segment = SEGMENT_AT_TID(gdata, current_tid)) != NULL;
202209
current_tid += current_segment->nb_units) {
@@ -217,6 +224,6 @@ size_t zone_debug(zone_malloc_t *gdata, int level, int output_id, const char *pr
217224
gdata->base + (current_tid+current_segment->nb_units) * gdata->unit_size - 1);
218225
}
219226
}
220-
227+
parsec_atomic_unlock(&gdata->lock);
221228
return ret;
222229
}

parsec/utils/zone_malloc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012-2019 The University of Tennessee and The University
2+
* Copyright (c) 2012-2024 The University of Tennessee and The University
33
* of Tennessee Research Foundation. All rights
44
* reserved.
55
*/
@@ -8,6 +8,7 @@
88
#define _ZONE_MALLOC_H_
99

1010
#include "parsec/parsec_config.h"
11+
#include "parsec/sys/atomic.h"
1112

1213
#include <stdlib.h>
1314
#include <assert.h>
@@ -30,6 +31,7 @@ typedef struct zone_malloc_s {
3031
size_t unit_size; /* Basic Unit */
3132
int max_segment; /* Maximum number of segment */
3233
int next_tid; /* Next TID to look at for a malloc */
34+
parsec_atomic_lock_t lock;
3335
} zone_malloc_t;
3436

3537

0 commit comments

Comments
 (0)