efl

Форк
0
/
eo_add_fallback.c 
218 строк · 4.8 Кб
1
#ifdef HAVE_CONFIG_H
2
# include <config.h>
3
#endif
4

5
#ifdef HAVE_VALGRIND
6
# include <valgrind.h>
7
# include <memcheck.h>
8
#endif
9

10
#if defined HAVE_DLADDR && ! defined _WIN32
11
# include <dlfcn.h>
12
#endif
13

14
#include <Eina.h>
15

16
#include "eo_ptr_indirection.h"
17
#include "eo_private.h"
18

19
#include "eo_add_fallback.h"
20

21
// 1024 entries == 16k or 32k (32 or 64bit) for eo call stack. that's 1023
22
// imbricated/recursive calls it can handle before barfing. i'd say that's ok
23
#define EFL_OBJECT_CALL_STACK_DEPTH_MIN 1024
24

25
typedef struct _Efl_Object_Call_Stack {
26
   Eo_Stack_Frame *frames;
27
   Eo_Stack_Frame *frame_ptr;
28
} Efl_Object_Call_Stack;
29

30
#define EFL_OBJECT_CALL_STACK_SIZE (EFL_OBJECT_CALL_STACK_DEPTH_MIN * sizeof(Eo_Stack_Frame))
31

32
static Eina_TLS _eo_call_stack_key = 0;
33

34
#define MEM_PAGE_SIZE 4096
35

36
static void *
37
_eo_call_stack_mem_alloc(size_t size)
38
{
39
#ifdef HAVE_MMAP
40
# ifdef HAVE_VALGRIND
41
   if (RUNNING_ON_VALGRIND) return calloc(1, size);
42
   else
43
# endif
44
     {
45
        if (_eo_no_anon == -1)
46
          {
47
             if (getenv("EFL_NO_MMAP_ANON")) _eo_no_anon = 1;
48
             else _eo_no_anon = 0;
49
          }
50
        if (_eo_no_anon == 1) return calloc(1, size);
51
        else
52
          {
53
             // allocate eo call stack via mmped anon segment if on linux - more
54
             // secure and safe. also gives page aligned memory allowing madvise
55
             void *ptr;
56
             size_t newsize;
57
             newsize = MEM_PAGE_SIZE * ((size + MEM_PAGE_SIZE - 1) /
58
                                        MEM_PAGE_SIZE);
59
             ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE,
60
                        MAP_PRIVATE | MAP_ANON, -1, 0);
61
             if (ptr == MAP_FAILED)
62
               {
63
                  ERR("eo call stack mmap failed.");
64
                  return NULL;
65
               }
66
             return ptr;
67
          }
68
     }
69
#else
70
   //in regular cases just use malloc
71
   return calloc(1, size);
72
#endif
73
}
74

75
static void
76
_eo_call_stack_mem_free(void *ptr, size_t size)
77
{
78
#ifdef HAVE_MMAP
79
# ifdef HAVE_VALGRIND
80
   if (RUNNING_ON_VALGRIND) free(ptr);
81
   else
82
# endif
83
     {
84
        if (_eo_no_anon == 1) free(ptr);
85
        else munmap(ptr, size);
86
     }
87
#else
88
   (void) size;
89
   free(ptr);
90
#endif
91
}
92

93
static Efl_Object_Call_Stack *
94
_eo_call_stack_create(void)
95
{
96
   Efl_Object_Call_Stack *stack;
97

98
   stack = calloc(1, sizeof(Efl_Object_Call_Stack));
99
   if (!stack)
100
     return NULL;
101

102
   stack->frames = _eo_call_stack_mem_alloc(EFL_OBJECT_CALL_STACK_SIZE);
103
   if (!stack->frames)
104
     {
105
        free(stack);
106
        return NULL;
107
     }
108

109
   // first frame is never used
110
   stack->frame_ptr = stack->frames;
111

112
   return stack;
113
}
114

115
static void
116
_eo_call_stack_free(void *ptr)
117
{
118
   Efl_Object_Call_Stack *stack = (Efl_Object_Call_Stack *) ptr;
119

120
   if (!stack) return;
121

122
   if (stack->frames)
123
     _eo_call_stack_mem_free(stack->frames, EFL_OBJECT_CALL_STACK_SIZE);
124

125
   free(stack);
126
}
127

128
static Efl_Object_Call_Stack *main_loop_stack = NULL;
129

130
#define _EFL_OBJECT_CALL_STACK_GET() ((EINA_LIKELY(eina_main_loop_is())) ? main_loop_stack : _eo_call_stack_get_thread())
131

132
static inline Efl_Object_Call_Stack *
133
_eo_call_stack_get_thread(void)
134
{
135
   Efl_Object_Call_Stack *stack = eina_tls_get(_eo_call_stack_key);
136

137
   if (stack) return stack;
138

139
   stack = _eo_call_stack_create();
140
   eina_tls_set(_eo_call_stack_key, stack);
141

142
   return stack;
143
}
144

145
EO_API Eo *
146
_efl_added_get(void)
147
{
148
   return _EFL_OBJECT_CALL_STACK_GET()->frame_ptr->obj;
149
}
150

151
Eo_Stack_Frame *
152
_efl_add_fallback_stack_push(Eo *obj)
153
{
154
   Efl_Object_Call_Stack *stack = _EFL_OBJECT_CALL_STACK_GET();
155
   if (stack->frame_ptr == (stack->frames + EFL_OBJECT_CALL_STACK_DEPTH_MIN))
156
     {
157
        CRI("efl_add fallback stack overflow.");
158
     }
159

160
   stack->frame_ptr++;
161
   stack->frame_ptr->obj = obj;
162

163
   return stack->frame_ptr;
164
}
165

166
Eo_Stack_Frame *
167
_efl_add_fallback_stack_pop(void)
168
{
169
   Efl_Object_Call_Stack *stack = _EFL_OBJECT_CALL_STACK_GET();
170
   if (stack->frame_ptr == stack->frames)
171
     {
172
        CRI("efl_add fallback stack underflow.");
173
     }
174

175
   stack->frame_ptr--;
176

177
   return stack->frame_ptr;
178
}
179

180
Eina_Bool
181
_efl_add_fallback_init(void)
182
{
183
   if (_eo_call_stack_key != 0)
184
     WRN("_eo_call_stack_key already set, this should not happen.");
185
   else
186
     {
187
        if (!eina_tls_cb_new(&_eo_call_stack_key, _eo_call_stack_free))
188
          {
189
             EINA_LOG_ERR("Could not create TLS key for call stack.");
190
             return EINA_FALSE;
191

192
          }
193
     }
194

195
   main_loop_stack = _eo_call_stack_create();
196
   if (!main_loop_stack)
197
     {
198
        EINA_LOG_ERR("Could not alloc eo call stack.");
199
        return EINA_FALSE;
200
     }
201

202
   return EINA_TRUE;
203
}
204

205
Eina_Bool
206
_efl_add_fallback_shutdown(void)
207
{
208
   if (_eo_call_stack_key != 0)
209
     {
210
        eina_tls_free(_eo_call_stack_key);
211
        _eo_call_stack_key = 0;
212
     }
213

214
   _eo_call_stack_free(main_loop_stack);
215
   main_loop_stack = NULL;
216

217
   return EINA_TRUE;
218
}
219

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.