PAPI 7.1.0.0
Loading...
Searching...
No Matches
sde_lib_datastructures.c File Reference

This is a collection of functions that manipulate datastructures that are used by libsde. More...

Include dependency graph for sde_lib_datastructures.c:

Go to the source code of this file.

Functions

uint32_t ht_hash_id (uint32_t uniq_id)
 
uint32_t ht_hash_name (const char *str)
 
void ht_insert (papisde_list_entry_t *hash_table, int ht_key, sde_counter_t *sde_counter)
 
int ht_to_array (papisde_list_entry_t *hash_table, sde_counter_t **rslt_array)
 
sde_counter_t * ht_delete (papisde_list_entry_t *hash_table, int ht_key, uint32_t uniq_id)
 
sde_counter_t * ht_lookup_by_name (papisde_list_entry_t *hash_table, const char *name)
 
sde_counter_t * ht_lookup_by_id (papisde_list_entry_t *hash_table, uint32_t uniq_id)
 
void exp_container_to_contiguous (recorder_data_t *exp_container, void *cont_buffer)
 
int exp_container_insert_element (recorder_data_t *exp_container, size_t typesize, const void *value)
 
int cset_insert_elem (cset_hash_table_t *hash_ptr, size_t element_size, size_t hashable_size, const void *element, uint32_t type_id)
 
int cset_remove_elem (cset_hash_table_t *hash_ptr, size_t hashable_size, const void *element, uint32_t type_id)
 
cset_list_object_t * cset_to_list (cset_hash_table_t *hash_ptr)
 
int cset_delete (cset_hash_table_t *hash_ptr)
 

Detailed Description

Function Documentation

◆ cset_delete()

int cset_delete ( cset_hash_table_t hash_ptr)

Definition at line 526 of file sde_lib_datastructures.c.

526 {
527 cset_hash_bucket_t *bucket_ptr;
528 int bucket_idx;
529 uint32_t i, occupied;
530
531 if( NULL == hash_ptr ){
532 return SDE_EINVAL;
533 }
534 bucket_ptr = hash_ptr->buckets;
535
536 for( bucket_idx = 0; bucket_idx < _SDE_HASH_BUCKET_COUNT_; bucket_idx++){
537 cset_hash_decorated_object_t *obj_ptr = bucket_ptr[bucket_idx].objects;
538 occupied = bucket_ptr[bucket_idx].occupied;
539 // Free all the elements that occupy entries in this bucket.
540 for(i=0; i<occupied; i++){
541 free(obj_ptr[i].ptr);
542 }
543 bucket_ptr[bucket_idx].occupied = 0;
544 }
545
546 cset_list_object_t *list_runner, *ptr_to_free=NULL;
547 // Since there are elements in the overflow list, we need to search for ours.
548 for( list_runner = hash_ptr->overflow_list; list_runner != NULL; list_runner = list_runner->next){
549 // Free the list element from the previous iteration.
550 free(ptr_to_free);
551 free(list_runner->ptr);
552 // Keep a reference to this element so we can free it _after_ this iteration, because we need the list_runner->next for now.
553 ptr_to_free = list_runner;
554 // If the current element is at the head of the overflow list, then we should mark the head as NULL.
555 if( list_runner == hash_ptr->overflow_list )
556 hash_ptr->overflow_list = NULL;
557
558 }
559 free(ptr_to_free);
560
561 return SDE_OK;
562}
int i
#define SDE_EINVAL
Definition: sde_lib.h:40
#define SDE_OK
Definition: sde_lib.h:39
#define _SDE_HASH_BUCKET_COUNT_
cset_hash_decorated_object_t objects[_SDE_HASH_BUCKET_WIDTH_]
cset_list_object_t * overflow_list
cset_hash_bucket_t buckets[_SDE_HASH_BUCKET_COUNT_]
Here is the caller graph for this function:

◆ cset_insert_elem()

int cset_insert_elem ( cset_hash_table_t hash_ptr,
size_t  element_size,
size_t  hashable_size,
const void *  element,
uint32_t  type_id 
)

Definition at line 285 of file sde_lib_datastructures.c.

285 {
286 cset_hash_bucket_t *bucket_ptr;
287 int element_found = 0;
288 uint32_t i, occupied;
289 int ret_val;
290
291 if( NULL == hash_ptr ){
292 ret_val = SDE_EINVAL;
293 goto fn_exit;
294 }
295 bucket_ptr = hash_ptr->buckets;
296
297 uint64_t seed = (uint64_t)79365; // decided to be a good seed by a committee.
298 uint64_t key = fasthash64(element, hashable_size, seed);
299 int bucket_idx = (int)(key % _SDE_HASH_BUCKET_COUNT_);
300 uint64_t *key_ptr = bucket_ptr[bucket_idx].keys;
301 cset_hash_decorated_object_t *obj_ptr = bucket_ptr[bucket_idx].objects;
302 occupied = bucket_ptr[bucket_idx].occupied;
303 if( occupied > _SDE_HASH_BUCKET_WIDTH_ ){
304 SDE_ERROR("cset_insert_elem(): Counting set is clobbered, bucket %d has exceeded capacity.",bucket_idx);
305 ret_val = SDE_ECMP;
306 goto fn_exit;
307 }
308
309 // First look in the bucket where the hash function told us to look.
310 for(i=0; i<occupied; i++){
311 // If the key and type_id match a stored element and the hashable_size is less or equal to
312 // the size of the stored element, then we are onto something.
313 if( (key == key_ptr[i]) && (type_id == obj_ptr[i].type_id) && (hashable_size <= obj_ptr[i].type_size) ){
314 // If the actual element matches too (or if we don't care about perfect matches),
315 // then we update the count for this entry and we are done.
316 if( SDE_HASH_IS_FUZZY || !memcmp(element, obj_ptr[i].ptr, hashable_size) ){
317 obj_ptr[i].count += 1;
318 element_found = 1;
319 break;
320 }
321 }
322 }
323
324 // If we didn't find the element in the appropriate bucket, then we need to add it (or look in the overflow list).
325 if( !element_found ){
326 // If the overflow list is empty, then we are certainly dealing with a new element.
327 if( NULL == hash_ptr->overflow_list ){
328 // Check if we still have room in the bucket, and if so, add the new element to the bucket.
330 key_ptr[i] = key;
331 obj_ptr[i].count = 1;
332 obj_ptr[i].type_id = type_id;
333 obj_ptr[i].type_size = element_size;
334 obj_ptr[i].ptr = malloc(element_size);
335 (void)memcpy(obj_ptr[i].ptr, element, element_size);
336 // Let the bucket know that it now has one more element.
337 bucket_ptr[bucket_idx].occupied += 1;
338 }else{
339 // If the overflow list is empty and the bucket does not have room,
340 // then we add the new element at the head of the overflow list.
341 cset_list_object_t *new_list_element = (cset_list_object_t *)malloc(sizeof(cset_list_object_t));
342 new_list_element->next = NULL;
343 new_list_element->count = 1;
344 new_list_element->type_id = type_id;
345 new_list_element->type_size = element_size;
346 new_list_element->ptr = malloc(element_size);
347 (void)memcpy(new_list_element->ptr, element, element_size);
348 // Make the head point to the new element.
349 hash_ptr->overflow_list = new_list_element;
350 }
351 }else{
352 // Since there are elements in the overflow list, we need to search there for the one we are looking for.
353 cset_list_object_t *list_runner;
354 for( list_runner = hash_ptr->overflow_list; list_runner != NULL; list_runner = list_runner->next){
355 // if we find the element in the overflow list, increment the counter and exit the loop.
356 // When we traverse the overflow list we can _not_ use the SDE_HASH_IS_FUZZY flag, because we
357 // don't have matching hashes to indicate that the two elements are close; we are traversing the whole list.
358 if( (hashable_size <= list_runner->type_size) && (type_id == list_runner->type_id) && !memcmp(element, list_runner->ptr, hashable_size) ){
359 list_runner->count += 1;
360 break;
361 }
362 }
363 // If we traversed the entire list and didn't find our element, insert it before the current head of the list.
364 if( NULL == list_runner ){
365 cset_list_object_t *new_list_element = (cset_list_object_t *)malloc(sizeof(cset_list_object_t));
366 // Make the new element's "next" pointer be the current head of the list.
367 new_list_element->next = hash_ptr->overflow_list;
368 new_list_element->count = 1;
369 new_list_element->type_id = type_id;
370 new_list_element->type_size = element_size;
371 new_list_element->ptr = malloc(element_size);
372 (void)memcpy(new_list_element->ptr, element, element_size);
373 // Update the head of the list to point to the new element.
374 hash_ptr->overflow_list = new_list_element;
375 }
376 }
377 }
378
379 ret_val = SDE_OK;
380fn_exit:
381 return ret_val;
382}
static pthread_key_t key
int
Definition: sde_internal.h:89
#define SDE_ECMP
Definition: sde_lib.h:42
static void SDE_ERROR(const char *format,...)
Definition: sde_lib.h:60
static uint64_t fasthash64(const void *buf, size_t len, uint64_t seed)
#define SDE_HASH_IS_FUZZY
#define _SDE_HASH_BUCKET_WIDTH_
uint64_t keys[_SDE_HASH_BUCKET_WIDTH_]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cset_remove_elem()

int cset_remove_elem ( cset_hash_table_t hash_ptr,
size_t  hashable_size,
const void *  element,
uint32_t  type_id 
)

Definition at line 385 of file sde_lib_datastructures.c.

385 {
386 cset_hash_bucket_t *bucket_ptr;
387 int element_found = 0;
388 uint32_t i, occupied;
389 int ret_val;
390
391 if( NULL == hash_ptr ){
392 ret_val = SDE_EINVAL;
393 goto fn_exit;
394 }
395 bucket_ptr = hash_ptr->buckets;
396
397 uint64_t seed = (uint64_t)79365; // decided to be a good seed by a committee.
398 uint64_t key = fasthash64(element, hashable_size, seed);
399 int bucket_idx = (int)(key % _SDE_HASH_BUCKET_COUNT_);
400 uint64_t *key_ptr = bucket_ptr[bucket_idx].keys;
401 cset_hash_decorated_object_t *obj_ptr = bucket_ptr[bucket_idx].objects;
402 occupied = bucket_ptr[bucket_idx].occupied;
403 if( occupied > _SDE_HASH_BUCKET_WIDTH_ ){
404 SDE_ERROR("cset_remove_elem(): Counting set is clobbered, bucket %d has exceeded capacity.",bucket_idx);
405 ret_val = SDE_EINVAL;
406 goto fn_exit;
407 }
408
409 // First look in the bucket where the hash function told us to look.
410 for(i=0; i<occupied; i++){
411 // If the key and type_id match a stored element and the hashable_size is less or equal to
412 // the size of the stored element, then we are onto something.
413 if( (key == key_ptr[i]) && (type_id == obj_ptr[i].type_id) && (hashable_size <= obj_ptr[i].type_size) ){
414 // If the actual element matches too (or if we don't care about perfect matches),
415 // then we update the count for this entry.
416 if( SDE_HASH_IS_FUZZY || !memcmp(element, obj_ptr[i].ptr, hashable_size) ){
417 obj_ptr[i].count -= 1;
418 // If the element reached a count of zero after we removed it, then shift all the other keys and entries in the bucket.
419 if( 0 == obj_ptr[i].count ){
420 uint32_t j;
421 // free the memory taken by the user object.
422 free(obj_ptr[i].ptr);
423 // now shift the remaining entries in this bucket.
424 for(j=i; j<occupied-1; j++){
425 key_ptr[j] = key_ptr[j+1];
426 obj_ptr[j] = obj_ptr[j+1];
427 }
428 bucket_ptr[bucket_idx].occupied -= 1;
429 }
430 // since we found the element, we don't need to look further.
431 element_found = 1;
432 break;
433 }
434 }
435 }
436
437 // If we didn't find the element in the appropriate bucket, then we need to look for it in the overflow list.
438 if( !element_found ){
439 // If the overflow list is empty, then something went wrong.
440 if( NULL == hash_ptr->overflow_list ){
441 SDE_ERROR("cset_remove_elem(): Attempted to remove element that is NOT in the counting set.");
442 }else{
443 // Since there are elements in the overflow list, we need to search there for the one we are looking for.
444 cset_list_object_t *list_runner, *prev;
445 prev = hash_ptr->overflow_list;
446 for( list_runner = hash_ptr->overflow_list; list_runner != NULL; list_runner = list_runner->next){
447 // if we find the element in the overflow list
448 if( (hashable_size <= list_runner->type_size) && (type_id == list_runner->type_id) && !memcmp(element, list_runner->ptr, hashable_size) ){
449 list_runner->count -= 1;
450 // If the element reached a count of zero, then remove it from the list, and connect the list around it.
451 if( 0 == list_runner->count ){
452 // free the memory taken by the user object.
453 free(list_runner->ptr);
454 if( list_runner == hash_ptr->overflow_list ){
455 hash_ptr->overflow_list = NULL;
456 }else{
457 prev->next = list_runner->next;
458 }
459 // free the memory taken by the link node. We can do this here safely
460 // because we will break out of the loop, so we will not need the "next" pointer.
461 free(list_runner);
462 }
463 // since we found the element, we don't need to look at the rest of the list.
464 break;
465 }
466 prev = list_runner;
467 }
468 }
469 }
470
471 ret_val = SDE_OK;
472fn_exit:
473 return ret_val;
474}
static long count
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cset_to_list()

cset_list_object_t * cset_to_list ( cset_hash_table_t hash_ptr)

Definition at line 476 of file sde_lib_datastructures.c.

476 {
477 cset_hash_bucket_t *bucket_ptr;
478 int bucket_idx;
479 uint32_t i, occupied;
480 cset_list_object_t *head_ptr = NULL;
481
482 if( NULL == hash_ptr ){
483 return NULL;
484 }
485 bucket_ptr = hash_ptr->buckets;
486
487 for( bucket_idx = 0; bucket_idx < _SDE_HASH_BUCKET_COUNT_; bucket_idx++){
488 cset_hash_decorated_object_t *obj_ptr = bucket_ptr[bucket_idx].objects;
489 occupied = bucket_ptr[bucket_idx].occupied;
490
491 for(i=0; i<occupied; i++){
492 int type_size = obj_ptr[i].type_size;
493 cset_list_object_t *new_list_element = (cset_list_object_t *)malloc(sizeof(cset_list_object_t));
494 // make the current list head be the element after the new one we are creating.
495 new_list_element->next = head_ptr;
496 new_list_element->count = obj_ptr[i].count;
497 new_list_element->type_id = obj_ptr[i].type_id;
498 new_list_element->type_size = type_size;
499 new_list_element->ptr = malloc(type_size);
500 (void)memcpy(new_list_element->ptr, obj_ptr[i].ptr, type_size);
501 // Update the head of the list to point to the new element.
502 head_ptr = new_list_element;
503 }
504 }
505
506 cset_list_object_t *list_runner;
507 // Since there are elements in the overflow list, we need to search for ours.
508 for( list_runner = hash_ptr->overflow_list; list_runner != NULL; list_runner = list_runner->next){
509 int type_size = list_runner->type_size;
510 cset_list_object_t *new_list_element = (cset_list_object_t *)malloc(sizeof(cset_list_object_t));
511 // make the current list head be the element after the new one we are creating.
512 new_list_element->next = head_ptr;
513 new_list_element->count = list_runner->count;
514 new_list_element->type_id = list_runner->type_id;
515 new_list_element->type_size = type_size;
516 new_list_element->ptr = malloc(type_size);
517 (void)memcpy(new_list_element->ptr, list_runner->ptr, type_size);
518 // Update the head of the list to point to the new element.
519 head_ptr = new_list_element;
520 }
521
522 return head_ptr;
523}
Here is the caller graph for this function:

◆ exp_container_insert_element()

int exp_container_insert_element ( recorder_data_t *  exp_container,
size_t  typesize,
const void *  value 
)

Definition at line 229 of file sde_lib_datastructures.c.

229 {
230 long long used_entries, total_entries, prev_entries, offset;
231 int i, chunk;
232 long long tmp_size;
233
234 if( NULL == exp_container || NULL == exp_container->ptr_array[0]){
235 SDE_ERROR("exp_container_insert_element(): Exponential container is clobbered. Unable to insert element.");
236 return SDE_EINVAL;
237 }
238
239 used_entries = exp_container->used_entries;
240 total_entries = exp_container->total_entries;
241 assert(used_entries <= total_entries);
242
243 // Find how many chunks we have already allocated
244 tmp_size = 0;
245 for(i=0; i<EXP_CONTAINER_ENTRIES; i++){
246 long long factor = (long long)1<<i; // 2^i;
247 prev_entries = tmp_size;
248 tmp_size += factor * EXP_CONTAINER_MIN_SIZE;
249 // At least the first chunk "exp_container->ptr_array[0]"
250 // must have been already allocated when creating the recorder, so we can
251 // compare the total size after we add the "i-th" size.
252 if (total_entries == tmp_size)
253 break;
254 }
255 chunk = i;
256
257 // Find how many entries down the last chunk we are.
258 offset = used_entries - prev_entries;
259
260 if( used_entries == total_entries ){
261 long long new_segment_size;
262
263 // If we had used all the available entries (and thus we are allocating more), we start from the beginning of the new chunk.
264 offset = 0;
265
266 chunk += 1; // we need to allocate the next chunk from the last one we found.
267 new_segment_size = ((long long)1<<chunk) * EXP_CONTAINER_MIN_SIZE;
268 exp_container->ptr_array[chunk] = malloc(new_segment_size*typesize);
269 exp_container->total_entries += new_segment_size;
270 }
271
272 void *dest = (char *)(exp_container->ptr_array[chunk]) + offset*typesize;
273
274 (void)memcpy( dest, value, typesize );
275 exp_container->used_entries++;
276
277 return SDE_OK;
278}
long long int long long
Definition: sde_internal.h:85
#define EXP_CONTAINER_MIN_SIZE
#define EXP_CONTAINER_ENTRIES
Here is the call graph for this function:
Here is the caller graph for this function:

◆ exp_container_to_contiguous()

void exp_container_to_contiguous ( recorder_data_t *  exp_container,
void *  cont_buffer 
)

Definition at line 204 of file sde_lib_datastructures.c.

204 {
205 long long current_size, typesize, used_entries, tmp_size = 0;
206 void *src, *dst;
207 int i;
208
209 typesize = exp_container->typesize;
210 used_entries = exp_container->used_entries;
211
212 for(i=0; i<EXP_CONTAINER_ENTRIES; i++){
213 current_size = ((long long)1<<i) * EXP_CONTAINER_MIN_SIZE;
214 src = exp_container->ptr_array[i];
215 dst = (char *)cont_buffer + tmp_size*typesize;
216 if ( (tmp_size+current_size) <= used_entries){
217 memcpy(dst, src, current_size*typesize);
218 if ( (tmp_size+current_size) == used_entries){
219 return;
220 }
221 }else{
222 memcpy(dst, src, (used_entries-tmp_size)*typesize);
223 return;
224 }
225 tmp_size += current_size;
226 }
227}
Here is the caller graph for this function:

◆ ht_delete()

sde_counter_t * ht_delete ( papisde_list_entry_t *  hash_table,
int  ht_key,
uint32_t  uniq_id 
)

Definition at line 114 of file sde_lib_datastructures.c.

115{
116 papisde_list_entry_t *list_head, *curr, *prev;
117 sde_counter_t *item;
118
119 list_head = &hash_table[ht_key];
120 if( NULL == list_head->item ){
121 SDE_ERROR("ht_delete(): the entry does not exist.");
122 return NULL;
123 }
124
125 // If the head contains the element to be deleted, free the space of the counter and pull the list up.
126 if( list_head->item->glb_uniq_id == uniq_id ){
127 item = list_head->item;
128 if( NULL != list_head->next){
129 *list_head = *(list_head->next);
130 }else{
131 memset(list_head, 0, sizeof(papisde_list_entry_t));
132 }
133 return item;
134 }
135
136 prev = list_head;
137 // Traverse the linked list to find the element.
138 for(curr=list_head->next; NULL != curr; curr=curr->next){
139 if(NULL == curr->item){ // This is only permitted for the head of the list.
140 SDE_ERROR("ht_delete(): the hash table is clobbered.");
141 return NULL;
142 }
143 if(curr->item->glb_uniq_id == uniq_id){
144 prev->next = curr->next;
145 item = curr->item;
146 free(curr); // free the hash table entry
147 return item;
148 }
149 prev = curr;
150 }
151
152 SDE_ERROR("ht_delete(): the item is not in the list.");
153 return NULL;
154}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ht_hash_id()

uint32_t ht_hash_id ( uint32_t  uniq_id)

Definition at line 18 of file sde_lib_datastructures.c.

18 {
19 return uniq_id%PAPISDE_HT_SIZE;
20}
#define PAPISDE_HT_SIZE
Here is the caller graph for this function:

◆ ht_hash_name()

uint32_t ht_hash_name ( const char *  str)

Definition at line 23 of file sde_lib_datastructures.c.

24{
25 uint32_t hash = 5381;
26 int c;
27
28 while ((c = *str++))
29 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
30
31 return hash % PAPISDE_HT_SIZE;
32}
static double c[MATRIX_SIZE][MATRIX_SIZE]
Definition: libmsr_basic.c:40
Here is the caller graph for this function:

◆ ht_insert()

void ht_insert ( papisde_list_entry_t *  hash_table,
int  ht_key,
sde_counter_t *  sde_counter 
)

Definition at line 34 of file sde_lib_datastructures.c.

35{
36 papisde_list_entry_t *list_head, *new_entry;
37
38 list_head = &hash_table[ht_key];
39 // If we have no counter is associated with this key we will put the new
40 // counter on the head of the list which has already been allocated.
41 if( NULL == list_head->item ){
42 list_head->item = sde_counter;
43 list_head->next = NULL; // Just for aesthetic reasons.
44 return;
45 }
46
47 // If we made it here it means that the head was occupied, so we
48 // will allocate a new element and put it just after the head.
49 new_entry = (papisde_list_entry_t *)calloc(1, sizeof(papisde_list_entry_t));
50 new_entry->item = sde_counter;
51 new_entry->next = list_head->next;
52 list_head->next = new_entry;
53
54 return;
55}
Here is the caller graph for this function:

◆ ht_lookup_by_id()

sde_counter_t * ht_lookup_by_id ( papisde_list_entry_t *  hash_table,
uint32_t  uniq_id 
)

Definition at line 178 of file sde_lib_datastructures.c.

179{
180 papisde_list_entry_t *list_head, *curr;
181
182 list_head = &hash_table[ht_hash_id(uniq_id)];
183 if( NULL == list_head->item ){
184 return NULL;
185 }
186
187 for(curr=list_head; NULL != curr; curr=curr->next){
188 if(NULL == curr->item){ // This can only legally happen for the head of the list.
189 SDE_ERROR("ht_lookup_by_id() the hash table is clobbered.");
190 return NULL;
191 }
192 if(curr->item->glb_uniq_id == uniq_id){
193 return curr->item;
194 }
195 }
196
197 return NULL;
198}
uint32_t ht_hash_id(uint32_t uniq_id)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ht_lookup_by_name()

sde_counter_t * ht_lookup_by_name ( papisde_list_entry_t *  hash_table,
const char *  name 
)

Definition at line 156 of file sde_lib_datastructures.c.

157{
158 papisde_list_entry_t *list_head, *curr;
159
160 list_head = &hash_table[ht_hash_name(name)];
161 if( NULL == list_head->item ){
162 return NULL;
163 }
164
165 for(curr=list_head; NULL != curr; curr=curr->next){
166 if(NULL == curr->item){ // This can only legally happen for the head of the list.
167 SDE_ERROR("ht_lookup_by_name() the hash table is clobbered.");
168 return NULL;
169 }
170 if( !strcmp(curr->item->name, name) ){
171 return curr->item;
172 }
173 }
174
175 return NULL;
176}
const char * name
Definition: rocs.c:225
uint32_t ht_hash_name(const char *str)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ht_to_array()

int ht_to_array ( papisde_list_entry_t *  hash_table,
sde_counter_t **  rslt_array 
)

Definition at line 65 of file sde_lib_datastructures.c.

66{
67 int i, item_cnt = 0, index=0;
68 papisde_list_entry_t *list_head, *curr;
69
70 // First pass counts how many items have been inserted in the hash table.
71
72 // Traverse all the elements of the hash-table.
73 for(i=0; i<PAPISDE_HT_SIZE; i++){
74 // For each element traverse the linked-list starting there (if any).
75 list_head = &(hash_table[i]);
76
77 if(NULL != list_head->item){
78 item_cnt++;
79 }
80 for(curr = list_head->next; NULL != curr; curr=curr->next){
81 if(NULL == curr->item){ // This can only legally happen for the head of the list.
82 SDE_ERROR("ht_to_array(): the hash table is clobbered.");
83 }else{
84 item_cnt++;
85 }
86 }
87 }
88
89 // Allocate a contiguous array to store the items.
90 sde_counter_t *array = (sde_counter_t *)malloc( item_cnt * sizeof(sde_counter_t));
91
92 // Traverse the hash-table again and copy all the items to the array we just allocated.
93 for(i=0; i<PAPISDE_HT_SIZE; i++){
94 list_head = &(hash_table[i]);
95
96 if(NULL != list_head->item){
97 memcpy( &array[index], list_head->item, sizeof(sde_counter_t) );
98 index++;
99 }
100 for(curr = list_head->next; NULL != curr; curr=curr->next){
101 if(NULL == curr->item){ // This can only legally happen for the head of the list.
102 SDE_ERROR("ht_to_array(): the hash table is clobbered.");
103 }else{
104 memcpy( &array[index], curr->item, sizeof(sde_counter_t) );
105 index++;
106 }
107 }
108 }
109 *rslt_array = array;
110
111 return item_cnt;
112}
static double array[ARRAYSIZE]
Definition: papi_l1_dca.c:23
Here is the call graph for this function:
Here is the caller graph for this function: