ARGOBOTS  1.1
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 =
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  LOG_DEBUG("valgrind : register stack %p (id = %d)\n", p_stack,
58  (int)valgrind_id);
59  } else {
60  /* When malloc() fails, VALGRIND_STACK_REGISTER is not performed, so we
61  * cannot deregister this stack region. */
62  g_num_malloc_failures++;
63  }
64  ABTD_spinlock_release(&g_valgrind_id_list_lock);
65 }
66 
67 void ABTI_valgrind_unregister_stack(const void *p_stack)
68 {
69  if (p_stack == 0)
70  return;
71 
72  ABTD_spinlock_acquire(&g_valgrind_id_list_lock);
73  if (gp_valgrind_id_list_head->p_stack == p_stack) {
74  VALGRIND_STACK_DEREGISTER(gp_valgrind_id_list_head->valgrind_id);
75  ABTI_valgrind_id_list *p_next = gp_valgrind_id_list_head->p_next;
76  free(gp_valgrind_id_list_head);
77  gp_valgrind_id_list_head = p_next;
78  if (!p_next)
79  gp_valgrind_id_list_tail = NULL;
80  } else {
81  /* Do linear search to find the corresponding valgrind_id. */
82  ABTI_valgrind_id_list *p_prev = gp_valgrind_id_list_head;
83  ABTI_valgrind_id_list *p_current = gp_valgrind_id_list_head->p_next;
84  ABT_bool deregister_flag = ABT_FALSE;
85  while (p_current) {
86  if (p_current->p_stack == p_stack) {
87  LOG_DEBUG("valgrind : deregister stack %p (id = %d)\n", p_stack,
88  (int)p_current->valgrind_id);
89  VALGRIND_STACK_DEREGISTER(p_current->valgrind_id);
90  p_prev->p_next = p_current->p_next;
91  if (!p_prev->p_next)
92  gp_valgrind_id_list_tail = p_prev;
93  free(p_current);
94  deregister_flag = ABT_TRUE;
95  break;
96  }
97  p_prev = p_current;
98  p_current = p_current->p_next;
99  }
100  if (!deregister_flag) {
101  /* Although it is less likely, maybe we missed stack registration
102  * because of the failure of malloc. */
103  ABTI_ASSERT(g_num_malloc_failures > 0);
104  g_num_malloc_failures--;
105  }
106  }
107  ABTD_spinlock_release(&g_valgrind_id_list_lock);
108 }
109 
110 #endif
ABTD_SPINLOCK_STATIC_INITIALIZER
#define ABTD_SPINLOCK_STATIC_INITIALIZER()
Definition: abtd_spinlock.h:13
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1001
ABTD_spinlock
Definition: abtd_spinlock.h:9
abti.h
ABTD_spinlock_acquire
static void ABTD_spinlock_acquire(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:28
LOG_DEBUG
#define LOG_DEBUG(fmt,...)
Definition: abti_log.h:26
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:748
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:750
ABTD_spinlock_release
static void ABTD_spinlock_release(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:42