ARGOBOTS  dce6e727ffc4ca5b3ffc04cb9517c6689be51ec5
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 static ABTD_spinlock g_valgrind_id_list_lock =
27  ABTD_SPINLOCK_STATIC_INITIALIZER();
28 static int g_num_malloc_failures = 0;
29 static ABTI_valgrind_id_list *gp_valgrind_id_list_head = NULL;
30 static ABTI_valgrind_id_list *gp_valgrind_id_list_tail = NULL;
31 
32 #include <valgrind/valgrind.h>
33 
34 void ABTI_valgrind_register_stack(const void *p_stack, size_t size)
35 {
36  if (p_stack == 0)
37  return;
38 
39  const void *p_start = (char *)(p_stack);
40  const void *p_end = (char *)(p_stack) + size;
41 
42  ABTD_spinlock_acquire(&g_valgrind_id_list_lock);
43  ABTI_valgrind_id_list *p_valgrind_id_list =
44  (ABTI_valgrind_id_list *)malloc(sizeof(ABTI_valgrind_id_list));
45  if (p_valgrind_id_list) {
46  ABTI_valgrind_id valgrind_id = VALGRIND_STACK_REGISTER(p_start, p_end);
47  p_valgrind_id_list->p_stack = p_stack;
48  p_valgrind_id_list->valgrind_id = valgrind_id;
49  p_valgrind_id_list->p_next = 0;
50  if (!gp_valgrind_id_list_head) {
51  gp_valgrind_id_list_head = p_valgrind_id_list;
52  gp_valgrind_id_list_tail = p_valgrind_id_list;
53  } else {
54  gp_valgrind_id_list_tail->p_next = p_valgrind_id_list;
55  gp_valgrind_id_list_tail = p_valgrind_id_list;
56  }
57  } else {
58  /* When malloc() fails, VALGRIND_STACK_REGISTER is not performed, so we
59  * cannot deregister this stack region. */
60  g_num_malloc_failures++;
61  }
62  ABTD_spinlock_release(&g_valgrind_id_list_lock);
63 }
64 
65 void ABTI_valgrind_unregister_stack(const void *p_stack)
66 {
67  if (p_stack == 0)
68  return;
69 
70  ABTD_spinlock_acquire(&g_valgrind_id_list_lock);
71  if (gp_valgrind_id_list_head->p_stack == p_stack) {
72  VALGRIND_STACK_DEREGISTER(gp_valgrind_id_list_head->valgrind_id);
73  ABTI_valgrind_id_list *p_next = gp_valgrind_id_list_head->p_next;
74  free(gp_valgrind_id_list_head);
75  gp_valgrind_id_list_head = p_next;
76  if (!p_next)
77  gp_valgrind_id_list_tail = NULL;
78  } else {
79  /* Do linear search to find the corresponding valgrind_id. */
80  ABTI_valgrind_id_list *p_prev = gp_valgrind_id_list_head;
81  ABTI_valgrind_id_list *p_current = gp_valgrind_id_list_head->p_next;
82  ABT_bool deregister_flag = ABT_FALSE;
83  while (p_current) {
84  if (p_current->p_stack == p_stack) {
85  VALGRIND_STACK_DEREGISTER(p_current->valgrind_id);
86  p_prev->p_next = p_current->p_next;
87  if (!p_prev->p_next)
88  gp_valgrind_id_list_tail = p_prev;
89  free(p_current);
90  deregister_flag = ABT_TRUE;
91  break;
92  }
93  p_prev = p_current;
94  p_current = p_current->p_next;
95  }
96  if (!deregister_flag) {
97  /* Although it is less likely, maybe we missed stack registration
98  * because of the failure of malloc. */
99  ABTI_ASSERT(g_num_malloc_failures > 0);
100  g_num_malloc_failures--;
101  }
102  }
103  ABTD_spinlock_release(&g_valgrind_id_list_lock);
104 }
105 
106 #endif
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1043
abti.h
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:784
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:786