ARGOBOTS
valgrind.c
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #include "abti.h"
7 
8 #ifdef HAVE_VALGRIND_SUPPORT
9 
10 /*
11  * These routines register and unregister stacks of threads so that Valgrind can
12  * handle them. This implementation uses a very naive linear list to keep track
13  * of stacks and valgrind_id. Its performance is bad compared to, for example,
14  * hash tables, but performance is less important when Valgrind is used.
15  */
16 
17 typedef size_t ABTI_valgrind_id;
18 
19 typedef struct ABTI_valgrind_id_list_t {
20  const void *p_stack;
21  ABTI_valgrind_id valgrind_id;
22  struct ABTI_valgrind_id_list_t *p_next;
23 } ABTI_valgrind_id_list;
24 
25 /* The list is protected by a global lock. */
26 ABTI_spinlock g_valgrind_id_list_lock = ABTI_SPINLOCK_STATIC_INITIALIZER();
27 ABTI_valgrind_id_list *gp_valgrind_id_list_head = NULL;
28 ABTI_valgrind_id_list *gp_valgrind_id_list_tail = NULL;
29 
30 #include <valgrind/valgrind.h>
31 
32 void ABTI_valgrind_register_stack(const void *p_stack, size_t size)
33 {
34  if (p_stack == 0)
35  return;
36 
37  const void *p_start = (char *)(p_stack);
38  const void *p_end = (char *)(p_stack) + size;
39 
40  ABTI_spinlock_acquire(&g_valgrind_id_list_lock);
41  ABTI_valgrind_id valgrind_id = VALGRIND_STACK_REGISTER(p_start, p_end);
42  ABTI_valgrind_id_list *p_valgrind_id_list =
43  (ABTI_valgrind_id_list *)malloc(sizeof(ABTI_valgrind_id_list));
44  p_valgrind_id_list->p_stack = p_stack;
45  p_valgrind_id_list->valgrind_id = valgrind_id;
46  p_valgrind_id_list->p_next = 0;
47  if (!gp_valgrind_id_list_head) {
48  gp_valgrind_id_list_head = p_valgrind_id_list;
49  gp_valgrind_id_list_tail = p_valgrind_id_list;
50  } else {
51  gp_valgrind_id_list_tail->p_next = p_valgrind_id_list;
52  gp_valgrind_id_list_tail = p_valgrind_id_list;
53  }
54  LOG_DEBUG("valgrind : register stack %p (id = %d)\n", p_stack,
55  (int)valgrind_id);
56  ABTI_spinlock_release(&g_valgrind_id_list_lock);
57 }
58 
59 void ABTI_valgrind_unregister_stack(const void *p_stack)
60 {
61  if (p_stack == 0)
62  return;
63 
64  ABTI_spinlock_acquire(&g_valgrind_id_list_lock);
65  if (gp_valgrind_id_list_head->p_stack == p_stack) {
66  VALGRIND_STACK_DEREGISTER(gp_valgrind_id_list_head->valgrind_id);
67  ABTI_valgrind_id_list *p_next = gp_valgrind_id_list_head->p_next;
68  free(gp_valgrind_id_list_head);
69  gp_valgrind_id_list_head = p_next;
70  if (!p_next)
71  gp_valgrind_id_list_tail = NULL;
72  } else {
73  /* Do linear search to find the corresponding valgrind_id. */
74  ABTI_valgrind_id_list *p_prev = gp_valgrind_id_list_head;
75  ABTI_valgrind_id_list *p_current = gp_valgrind_id_list_head->p_next;
76  ABT_bool deregister_flag = ABT_FALSE;
77  while (p_current) {
78  if (p_current->p_stack == p_stack) {
79  LOG_DEBUG("valgrind : deregister stack %p (id = %d)\n", p_stack,
80  (int)p_current->valgrind_id);
81  VALGRIND_STACK_DEREGISTER(p_current->valgrind_id);
82  p_prev->p_next = p_current->p_next;
83  if (!p_prev->p_next)
84  gp_valgrind_id_list_tail = p_prev;
85  free(p_current);
86  deregister_flag = ABT_TRUE;
87  break;
88  }
89  p_prev = p_current;
90  p_current = p_current->p_next;
91  }
92  ABTI_ASSERT(deregister_flag);
93  }
94  ABTI_spinlock_release(&g_valgrind_id_list_lock);
95 }
96 
97 #endif
int ABT_bool
Definition: abt.h:309
#define ABT_FALSE
Definition: abt.h:224
#define ABT_TRUE
Definition: abt.h:223
#define LOG_DEBUG(fmt,...)
Definition: abti_log.h:61