5
#include "eo_ptr_indirection.h"
7
extern Eina_Thread _efl_object_main_thread;
9
//////////////////////////////////////////////////////////////////////////
11
Eina_TLS _eo_table_data;
12
Eo_Id_Data *_eo_table_data_shared = NULL;
13
Eo_Id_Table_Data *_eo_table_data_shared_data = NULL;
15
//////////////////////////////////////////////////////////////////////////
18
_eo_pointer_error(const Eo *obj_id, const char *func_name, const char *file, int line, const char *fmt, ...)
20
/* NOTE: this function exists to allow easy breakpoint on pointer errors */
23
eina_log_vprint(_eo_log_dom, EINA_LOG_LEVEL_ERR, file, func_name, line, fmt, args);
25
_eo_log_obj_report((Eo_Id)obj_id, EINA_LOG_LEVEL_ERR, func_name, file, line);
29
_eo_obj_pointer_invalid(const Eo_Id obj_id,
32
const char *func_name,
36
Eina_Thread thread = eina_thread_self();
37
const char *tself = "main";
38
const char *type = "object";
39
const char *reason = "This ID has probably been deleted";
41
if (obj_id & MASK_CLASS_TAG) type = "class";
42
if (thread != _efl_object_main_thread)
44
snprintf(tbuf, sizeof(tbuf), "%p", (void *)thread);
48
if (!data->tables[(int)data->local_domain])
49
reason = "This ID does not seem to belong to this thread";
50
else if ((Efl_Id_Domain)domain == EFL_ID_DOMAIN_SHARED)
51
reason = "This shared ID has probably been deleted";
53
eina_log_print(_eo_log_dom, EINA_LOG_LEVEL_ERR,
54
file, func_name, line,
55
"Eo ID %p is not a valid %s. "
56
"Current thread: %s. "
57
"%s or this was never a valid %s ID. "
58
"(domain=%i, current_domain=%i, local_domain=%i, "
59
"available_domains=[%s %s %s %s], "
60
"generation=%lx, id=%lx, ref=%i)",
67
(int)data->domain_stack[data->stack_top],
68
(int)data->local_domain,
69
(data->tables[0]) ? "0" : " ",
70
(data->tables[1]) ? "1" : " ",
71
(data->tables[2]) ? "2" : " ",
72
(data->tables[3]) ? "3" : " ",
73
(unsigned long)(obj_id & MASK_GENERATIONS),
74
(unsigned long)(obj_id >> SHIFT_ENTRY_ID) & (MAX_ENTRY_ID | MAX_TABLE_ID | MAX_MID_TABLE_ID),
75
(int)(obj_id >> REF_TAG_SHIFT) & 0x1);
76
_eo_log_obj_report(obj_id, EINA_LOG_LEVEL_ERR, func_name, file, line);
80
_eo_obj_pointer_get(const Eo_Id obj_id, const char *func_name, const char *file, int line)
83
Generation_Counter generation;
84
Table_Index mid_table_id, table_id, entry_id;
87
Eo_Id_Table_Data *tdata;
90
// NULL objects will just be sensibly ignored. not worth complaining
93
data = _eo_table_data_get();
94
EINA_PREFETCH(&(data->tables[0]));
95
domain = (obj_id >> SHIFT_DOMAIN) & MASK_DOMAIN;
96
tdata = _eo_table_data_table_get(data, domain);
97
if (EINA_UNLIKELY(!tdata)) goto err;
98
_eo_cache_prefetch(tdata);
100
if (EINA_LIKELY(domain != EFL_ID_DOMAIN_SHARED))
104
obj = _eo_cache_find(tdata, obj_id);
107
mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID;
108
EINA_PREFETCH(&(tdata->eo_ids_tables[mid_table_id])); //prefetch for line 119
109
table_id = (obj_id >> SHIFT_TABLE_ID) & MASK_TABLE_ID;
110
EINA_PREFETCH((tdata->eo_ids_tables[mid_table_id] + table_id)); //prefetch for line 121
111
entry_id = (obj_id >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID;
112
generation = obj_id & MASK_GENERATIONS;
114
// get tag bit to check later down below - pipelining
115
tag_bit = (obj_id) & MASK_OBJ_TAG;
116
if (!obj_id) goto err_null;
117
else if (!tag_bit) goto err;
119
// Check the validity of the entry
120
if (tdata->eo_ids_tables[mid_table_id])
122
_Eo_Ids_Table *tab = TABLE_FROM_IDS;
123
EINA_PREFETCH_NOCACHE(tab); //prefetch for line 125
126
entry = &(tab->entries[entry_id]);
127
if (entry->active && (entry->generation == generation))
129
// Cache the result of that lookup
130
_eo_cache_store(tdata, obj_id, entry->ptr);
141
eina_lock_take(&(_eo_table_data_shared_data->obj_lock));
142
// yes we return keeping the lock locked. that's why
143
// you must call _eo_obj_pointer_done() wrapped
144
// by EO_OBJ_DONE() to release
145
obj = _eo_cache_find(tdata, obj_id);
148
mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID;
149
EINA_PREFETCH(&(tdata->eo_ids_tables[mid_table_id]));
150
table_id = (obj_id >> SHIFT_TABLE_ID) & MASK_TABLE_ID;
151
EINA_PREFETCH((tdata->eo_ids_tables[mid_table_id] + table_id));
152
entry_id = (obj_id >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID;
153
generation = obj_id & MASK_GENERATIONS;
155
// get tag bit to check later down below - pipelining
156
tag_bit = (obj_id) & MASK_OBJ_TAG;
157
if (!obj_id) goto err_shared_null;
158
else if (!tag_bit) goto err_shared;
160
// Check the validity of the entry
161
if (tdata->eo_ids_tables[mid_table_id])
163
_Eo_Ids_Table *tab = TABLE_FROM_IDS;
164
EINA_PREFETCH_NOCACHE(tab);
168
entry = &(tab->entries[entry_id]);
169
if (entry->active && (entry->generation == generation))
171
// Cache the result of that lookup
172
_eo_cache_store(tdata, obj_id, entry->ptr);
173
// yes we return keeping the lock locked. that's why
174
// you must call _eo_obj_pointer_done() wrapped
175
// by EO_OBJ_DONE() to release
183
eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
185
eina_log_print(_eo_log_dom,
187
file, func_name, line,
188
"obj_id is NULL. Possibly unintended access?");
191
eina_lock_release(&(_eo_table_data_shared_data->obj_lock));
193
_eo_obj_pointer_invalid(obj_id, data, domain, func_name, file, line);