2010-07-27 01:55:23 -07:00
|
|
|
/* EINA - EFL data type library
|
|
|
|
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2010
|
|
|
|
* Carsten Haitzler,
|
|
|
|
* Jorge Luis Zapata Muga,
|
|
|
|
* Cedric Bail,
|
|
|
|
* Gustavo Sverzut Barbieri
|
|
|
|
* Tom Hacohen
|
|
|
|
* Brett Nash
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library;
|
|
|
|
* if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following copyright and
|
|
|
|
* permission notice:
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008 Peter Wehrfritz
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies of the Software and its Copyright notices. In addition publicly
|
|
|
|
* documented acknowledgment must be given that this software has been used if no
|
|
|
|
* source code of this software is made available publicly. This includes
|
|
|
|
* acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
|
|
|
|
* documents or any documentation provided with any product containing this
|
|
|
|
* software. This License does not apply to any software that links to the
|
|
|
|
* libraries provided by this software (statically or dynamically), but only to
|
|
|
|
* the software provided.
|
|
|
|
*
|
|
|
|
* Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice
|
|
|
|
* and it's intent.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
#ifdef EFL_HAVE_POSIX_THREADS
|
|
|
|
# include <pthread.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "eina_config.h"
|
|
|
|
#include "eina_private.h"
|
|
|
|
#include "eina_hash.h"
|
|
|
|
#include "eina_rbtree.h"
|
|
|
|
#include "eina_error.h"
|
2011-04-24 09:49:48 -07:00
|
|
|
#include "eina_lock.h"
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
|
|
|
#include "eina_safety_checks.h"
|
|
|
|
#include "eina_share_common.h"
|
|
|
|
|
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* Local *
|
|
|
|
*============================================================================*/
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @cond LOCAL
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define EINA_SHARE_COMMON_BUCKETS 256
|
|
|
|
#define EINA_SHARE_COMMON_MASK 0xFF
|
|
|
|
|
|
|
|
static const char EINA_MAGIC_SHARE_STR[] = "Eina Share";
|
|
|
|
static const char EINA_MAGIC_SHARE_HEAD_STR[] = "Eina Share Head";
|
|
|
|
|
2011-05-18 00:56:11 -07:00
|
|
|
static int _eina_share_common_count = 0;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
#define EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(d, unlock, ...) \
|
|
|
|
do { \
|
|
|
|
if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_SHARE_HEAD)) \
|
|
|
|
{ \
|
|
|
|
EINA_MAGIC_FAIL((d), EINA_MAGIC_SHARE_HEAD); \
|
|
|
|
unlock; \
|
|
|
|
return __VA_ARGS__; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define EINA_MAGIC_CHECK_SHARE_COMMON_NODE(d, _node_magic, unlock) \
|
|
|
|
do { \
|
|
|
|
if (!EINA_MAGIC_CHECK((d), _node_magic)) \
|
|
|
|
{ \
|
|
|
|
EINA_MAGIC_FAIL((d), _node_magic); \
|
2011-01-18 00:34:14 -08:00
|
|
|
unlock; \
|
2010-07-27 19:37:05 -07:00
|
|
|
} \
|
|
|
|
} while (0)
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
#ifdef EINA_SHARE_USAGE
|
2010-07-27 19:37:05 -07:00
|
|
|
typedef struct _Eina_Share_Common_Population Eina_Share_Common_Population;
|
|
|
|
#endif
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
typedef struct _Eina_Share_Common Eina_Share_Common;
|
|
|
|
typedef struct _Eina_Share_Common_Node Eina_Share_Common_Node;
|
|
|
|
typedef struct _Eina_Share_Common_Head Eina_Share_Common_Head;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
struct _Eina_Share
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
Eina_Share_Common *share;
|
|
|
|
Eina_Magic node_magic;
|
|
|
|
#ifdef EINA_SHARE_COMMON_USAGE
|
|
|
|
Eina_Share_Common_Population population;
|
|
|
|
int max_node_population;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _Eina_Share_Common
|
|
|
|
{
|
|
|
|
Eina_Share_Common_Head *buckets[EINA_SHARE_COMMON_BUCKETS];
|
|
|
|
|
|
|
|
EINA_MAGIC
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _Eina_Share_Common_Node
|
|
|
|
{
|
|
|
|
Eina_Share_Common_Node *next;
|
|
|
|
|
|
|
|
EINA_MAGIC
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
unsigned int length;
|
|
|
|
unsigned int references;
|
|
|
|
char str[];
|
2010-07-27 01:55:23 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _Eina_Share_Common_Head
|
|
|
|
{
|
|
|
|
EINA_RBTREE;
|
|
|
|
EINA_MAGIC
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
int hash;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
#ifdef EINA_SHARE_COMMON_USAGE
|
2010-07-27 19:37:05 -07:00
|
|
|
int population;
|
2010-07-27 01:55:23 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
Eina_Share_Common_Node *head;
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_Share_Common_Node builtin_node;
|
2010-07-27 01:55:23 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
Eina_Bool _share_common_threads_activated = EINA_FALSE;
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
static Eina_Lock _mutex_big;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
#ifdef EINA_SHARE_COMMON_USAGE
|
|
|
|
struct _Eina_Share_Common_Population
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
int max;
|
|
|
|
};
|
|
|
|
|
|
|
|
static Eina_Share_Common_Population population = { 0, 0 };
|
|
|
|
|
|
|
|
static Eina_Share_Common_Population population_group[4] =
|
2010-07-27 19:37:05 -07:00
|
|
|
{
|
|
|
|
{ 0, 0 },
|
|
|
|
{ 0, 0 },
|
|
|
|
{ 0, 0 },
|
|
|
|
{ 0, 0 }
|
|
|
|
};
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
_eina_share_common_population_init(Eina_Share *share)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
for (i = 0;
|
|
|
|
i < sizeof (share->population_group) /
|
|
|
|
sizeof (share->population_group[0]);
|
|
|
|
++i)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
share->population_group[i].count = 0;
|
|
|
|
share->population_group[i].max = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eina_share_common_population_shutdown(Eina_Share *share)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
share->max_node_population = 0;
|
|
|
|
share->population.count = 0;
|
|
|
|
share->population.max = 0;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
for (i = 0;
|
|
|
|
i < sizeof (share->population_group) /
|
|
|
|
sizeof (share->population_group[0]);
|
|
|
|
++i)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
share->population_group[i].count = 0;
|
|
|
|
share->population_group[i].max = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eina_share_common_population_stats(Eina_Share *share)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
fprintf(stderr, "eina share_common statistic:\n");
|
|
|
|
fprintf(stderr,
|
|
|
|
" * maximum shared strings : %i\n",
|
2010-07-27 19:48:11 -07:00
|
|
|
share->population.max);
|
2010-07-27 19:37:05 -07:00
|
|
|
fprintf(stderr,
|
|
|
|
" * maximum shared strings per node : %i\n",
|
2010-07-27 19:48:11 -07:00
|
|
|
share->max_node_population);
|
2010-07-27 19:37:05 -07:00
|
|
|
|
|
|
|
for (i = 0;
|
|
|
|
i < sizeof (share->population_group) /
|
|
|
|
sizeof (share->population_group[0]);
|
|
|
|
++i)
|
|
|
|
fprintf(stderr,
|
2012-10-04 02:31:46 -07:00
|
|
|
"DDD: %i strings of length %u, max strings: %i\n",
|
2010-07-27 19:37:05 -07:00
|
|
|
share->population_group[i].count,
|
|
|
|
i,
|
|
|
|
share->population_group[i].max);
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
eina_share_common_population_add(Eina_Share *share, int slen)
|
|
|
|
{
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_take(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
share->population.count++;
|
|
|
|
if (share->population.count > share->population.max)
|
2010-07-27 19:37:05 -07:00
|
|
|
share->population.max = share->population.count;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
if (slen < 4)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
share->population_group[slen].count++;
|
|
|
|
if (share->population_group[slen].count >
|
|
|
|
share->population_group[slen].max)
|
|
|
|
share->population_group[slen].max =
|
|
|
|
share->population_group[slen].count;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
eina_share_common_population_del(Eina_Share *share, int slen)
|
|
|
|
{
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_take(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
share->population.count--;
|
|
|
|
if (slen < 4)
|
2010-07-27 19:37:05 -07:00
|
|
|
share->population_group[slen].count--;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_population_head_init(Eina_Share *share,
|
|
|
|
Eina_Share_Common_Head *head)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
head->population = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_population_head_add(Eina_Share *share,
|
|
|
|
Eina_Share_Common_Head *head)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
head->population++;
|
|
|
|
if (head->population > share->max_node_population)
|
2010-07-27 19:37:05 -07:00
|
|
|
share->max_node_population = head->population;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_population_head_del(Eina_Share *share,
|
|
|
|
Eina_Share_Common_Head *head)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
head->population--;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* EINA_SHARE_COMMON_USAGE undefined */
|
|
|
|
|
2012-10-05 13:09:47 -07:00
|
|
|
static void _eina_share_common_population_init(EINA_UNUSED Eina_Share *share) {
|
2010-07-27 19:37:05 -07:00
|
|
|
}
|
2012-10-05 13:09:47 -07:00
|
|
|
static void _eina_share_common_population_shutdown(EINA_UNUSED Eina_Share *share)
|
2010-07-27 19:37:05 -07:00
|
|
|
{
|
|
|
|
}
|
2012-10-05 13:09:47 -07:00
|
|
|
static void _eina_share_common_population_stats(EINA_UNUSED Eina_Share *share) {
|
2010-07-27 19:37:05 -07:00
|
|
|
}
|
2012-10-05 13:09:47 -07:00
|
|
|
void eina_share_common_population_add(EINA_UNUSED Eina_Share *share,
|
|
|
|
EINA_UNUSED int slen) {
|
2010-07-27 19:37:05 -07:00
|
|
|
}
|
2012-10-05 13:09:47 -07:00
|
|
|
void eina_share_common_population_del(EINA_UNUSED Eina_Share *share,
|
|
|
|
EINA_UNUSED int slen) {
|
2010-07-27 19:37:05 -07:00
|
|
|
}
|
|
|
|
static void _eina_share_common_population_head_init(
|
2012-10-05 13:09:47 -07:00
|
|
|
EINA_UNUSED Eina_Share *share,
|
|
|
|
EINA_UNUSED Eina_Share_Common_Head *head) {
|
2010-07-27 19:37:05 -07:00
|
|
|
}
|
|
|
|
static void _eina_share_common_population_head_add(
|
2012-10-05 13:09:47 -07:00
|
|
|
EINA_UNUSED Eina_Share *share,
|
|
|
|
EINA_UNUSED
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_Share_Common_Head *head) {
|
|
|
|
}
|
|
|
|
static void _eina_share_common_population_head_del(
|
2012-10-05 13:09:47 -07:00
|
|
|
EINA_UNUSED Eina_Share *share,
|
|
|
|
EINA_UNUSED
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_Share_Common_Head *head) {
|
|
|
|
}
|
2010-07-27 01:55:23 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static int
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_cmp(const Eina_Share_Common_Head *ed,
|
|
|
|
const int *hash,
|
2012-10-05 13:09:47 -07:00
|
|
|
EINA_UNUSED int length,
|
|
|
|
EINA_UNUSED void *data)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, , 0);
|
|
|
|
|
|
|
|
return ed->hash - *hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Rbtree_Direction
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_node(const Eina_Share_Common_Head *left,
|
|
|
|
const Eina_Share_Common_Head *right,
|
2012-10-05 13:09:47 -07:00
|
|
|
EINA_UNUSED void *data)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(left, , 0);
|
2010-07-27 01:55:23 -07:00
|
|
|
EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(right, , 0);
|
|
|
|
|
|
|
|
if (left->hash - right->hash < 0)
|
2010-07-27 19:37:05 -07:00
|
|
|
return EINA_RBTREE_LEFT;
|
|
|
|
|
2010-07-27 01:55:23 -07:00
|
|
|
return EINA_RBTREE_RIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-10-05 13:09:47 -07:00
|
|
|
_eina_share_common_head_free(Eina_Share_Common_Head *ed, EINA_UNUSED void *data)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, );
|
|
|
|
|
|
|
|
while (ed->head)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_Share_Common_Node *el = ed->head;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
ed->head = ed->head->next;
|
|
|
|
if (el != &ed->builtin_node)
|
|
|
|
MAGIC_FREE(el);
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
2010-07-27 19:37:05 -07:00
|
|
|
MAGIC_FREE(ed);
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_node_init(Eina_Share_Common_Node *node,
|
|
|
|
const char *str,
|
|
|
|
int slen,
|
|
|
|
unsigned int null_size,
|
|
|
|
Eina_Magic node_magic)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
EINA_MAGIC_SET(node, node_magic);
|
|
|
|
node->references = 1;
|
|
|
|
node->length = slen;
|
|
|
|
memcpy(node->str, str, slen);
|
|
|
|
memset(node->str + slen, 0, null_size); /* Nullify the null */
|
2010-07-29 06:59:31 -07:00
|
|
|
|
|
|
|
(void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Share_Common_Head *
|
|
|
|
_eina_share_common_head_alloc(int slen)
|
|
|
|
{
|
|
|
|
Eina_Share_Common_Head *head;
|
|
|
|
const size_t head_size = offsetof(Eina_Share_Common_Head, builtin_node.str);
|
|
|
|
|
|
|
|
head = malloc(head_size + slen);
|
|
|
|
if (!head)
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_add_head(Eina_Share *share,
|
|
|
|
Eina_Share_Common_Head **p_bucket,
|
|
|
|
int hash,
|
|
|
|
const char *str,
|
|
|
|
unsigned int slen,
|
|
|
|
unsigned int null_size)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket;
|
|
|
|
Eina_Share_Common_Head *head;
|
|
|
|
|
|
|
|
head = _eina_share_common_head_alloc(slen + null_size);
|
|
|
|
if (!head)
|
2010-07-27 19:37:05 -07:00
|
|
|
return NULL;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
EINA_MAGIC_SET(head, EINA_MAGIC_SHARE_HEAD);
|
|
|
|
head->hash = hash;
|
|
|
|
head->head = &head->builtin_node;
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_node_init(head->head,
|
|
|
|
str,
|
|
|
|
slen,
|
|
|
|
null_size,
|
|
|
|
share->node_magic);
|
2010-07-27 01:55:23 -07:00
|
|
|
head->head->next = NULL;
|
|
|
|
|
|
|
|
_eina_share_common_population_head_init(share, head);
|
|
|
|
|
|
|
|
*p_tree = eina_rbtree_inline_insert
|
2010-07-27 19:37:05 -07:00
|
|
|
(*p_tree, EINA_RBTREE_GET(head),
|
|
|
|
EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
return head->head->str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_del_head(Eina_Share_Common_Head **p_bucket,
|
|
|
|
Eina_Share_Common_Head *head)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket;
|
|
|
|
|
|
|
|
*p_tree = eina_rbtree_inline_remove
|
2010-07-27 19:37:05 -07:00
|
|
|
(*p_tree, EINA_RBTREE_GET(head),
|
|
|
|
EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
MAGIC_FREE(head);
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_node_eq(const Eina_Share_Common_Node *node,
|
|
|
|
const char *str,
|
|
|
|
unsigned int slen)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
return ((node->length == slen) &&
|
2010-07-27 19:37:05 -07:00
|
|
|
(memcmp(node->str, str, slen) == 0));
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Share_Common_Node *
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_head_find(Eina_Share_Common_Head *head,
|
|
|
|
const char *str,
|
|
|
|
unsigned int slen)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
Eina_Share_Common_Node *node, *prev;
|
|
|
|
|
|
|
|
node = head->head;
|
|
|
|
if (_eina_share_common_node_eq(node, str, slen))
|
2010-07-27 19:37:05 -07:00
|
|
|
return node;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
prev = node;
|
|
|
|
node = node->next;
|
2010-08-21 06:52:25 -07:00
|
|
|
for (; node; prev = node, node = node->next)
|
2010-07-27 19:37:05 -07:00
|
|
|
if (_eina_share_common_node_eq(node, str, slen))
|
|
|
|
{
|
|
|
|
/* promote node, make hot items be at the beginning */
|
|
|
|
prev->next = node->next;
|
|
|
|
node->next = head->head;
|
|
|
|
head->head = node;
|
|
|
|
return node;
|
|
|
|
}
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_head_remove_node(Eina_Share_Common_Head *head,
|
|
|
|
const Eina_Share_Common_Node *node)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
Eina_Share_Common_Node *cur, *prev;
|
|
|
|
|
|
|
|
if (head->head == node)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
head->head = node->next;
|
|
|
|
return 1;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
prev = head->head;
|
|
|
|
cur = head->head->next;
|
2010-08-21 06:52:25 -07:00
|
|
|
for (; cur; prev = cur, cur = cur->next)
|
2010-07-27 19:37:05 -07:00
|
|
|
if (cur == node)
|
|
|
|
{
|
|
|
|
prev->next = cur->next;
|
|
|
|
return 1;
|
|
|
|
}
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Share_Common_Head *
|
|
|
|
_eina_share_common_find_hash(Eina_Share_Common_Head *bucket, int hash)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
return (Eina_Share_Common_Head *)eina_rbtree_inline_lookup
|
|
|
|
(EINA_RBTREE_GET(bucket), &hash, 0,
|
|
|
|
EINA_RBTREE_CMP_KEY_CB(_eina_share_common_cmp), NULL);
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Share_Common_Node *
|
|
|
|
_eina_share_common_node_alloc(unsigned int slen, unsigned int null_size)
|
|
|
|
{
|
|
|
|
Eina_Share_Common_Node *node;
|
|
|
|
const size_t node_size = offsetof(Eina_Share_Common_Node, str);
|
|
|
|
|
|
|
|
node = malloc(node_size + slen + null_size);
|
|
|
|
if (!node)
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Share_Common_Node *
|
|
|
|
_eina_share_common_node_from_str(const char *str, Eina_Magic node_magic)
|
|
|
|
{
|
|
|
|
Eina_Share_Common_Node *node;
|
|
|
|
const size_t offset = offsetof(Eina_Share_Common_Node, str);
|
|
|
|
|
|
|
|
node = (Eina_Share_Common_Node *)(str - offset);
|
SVN revision: 3
Subject: [E-devel] [PATCH] eina share common check for node type
Hello, recentely I've been experiencing a lot of segfaults when running
an Elementary application which uses a genlist with some swallowed parts
in which I put some elm icons (png files).
When running it I often get crashes... Debugging it I found this:
=========
CRI<14207>: eina_share_common.c:561 _eina_share_common_node_from_str()
*** Eina Magic Check Failed !!!
Input handle is wrong type
Expected: 98761254 - Eina Stringshare Node
Supplied: 6e657070 - (unknown)
*** NAUGHTY PROGRAMMER!!!
*** SPANK SPANK SPANK!!!
*** Now go fix your code. Tut tut tut!
//DEBUG: Node referencies 622869060 (slen: 1145307236)
Program received signal SIGSEGV, Segmentation fault.
eina_share_common_del (share=0x65c810, str=0x7ffff1219150
"5hhu %5hu '%
s'\n")
at eina_share_common.c:858
858 node->references--;
=========
So it seems that edje tries to delete an invalid eina_share_common
string (is this a bug that should be fixed or is it
theme-dependent?),
and so the "node" pointer in eina share is not valid...
However eina never checks for its validity, so it seg-faults...
The attached patch fix this issue, setting the node to null when its
magic is not valid, and then always checking for its validity.
Is this fine?
Full stack trace:
#0 eina_share_common_del (share=0x65c810, str=0x7ffff1219150 "5hhu %5hu
'%s'\n")
at eina_share_common.c:858
#1 0x00007ffff120e047 in eina_stringshare_del (str=0x7ffff1219150
"5hhu
%5hu '%s'\n")
at eina_stringshare.c:632
#2 0x00007ffff1e1f7bc in _edje_text_recalc_apply (ed=0x95b900,
ep=0x70c3a0,
params=0x70c500, chosen_desc=<value optimized out>) at
edje_text.c:556
#3 0x00007ffff1de402d in _edje_part_recalc (ed=0x95b900,
ep=0x70c3a0,
flags=3)
at edje_calc.c:2007
#4 0x00007ffff1de4d86 in _edje_recalc_do (ed=0x95b900) at
edje_calc.c:268
#5 0x00007ffff1e25c7d in edje_object_part_swallow (obj=<value
optimized
out>,
part=0x7fffe001484c "elm.swallow.icon", obj_swallow=0x7fffe0017860)
at edje_util.c:2300
#6 0x00007ffff1b5d5fc in _item_realize (it=0x7fffe0016ed0,
in=10,
calc=1)
at elm_genlist.c:1489
#7 0x00007ffff1b5db89 in _item_block_recalc (itb=0x95b6a0,
in=<value
optimized out>,
qadd=<value optimized out>, norender=<value optimized out>) at
elm_genlist.c:1609
#8 0x00007ffff1b5e329 in _queue_proecess (wd=0x721b70,
norender=<value
optimized out>)
at elm_genlist.c:2425
#9 0x00007ffff1b5e567 in _item_queue (wd=0x721b70, it=<value
optimized
out>)
at elm_genlist.c:2476
#10 0x00007ffff1b5ead9 in elm_genlist_item_append (obj=<value
optimized
out>,
itc=0x7ffff2977040, data=0x8fed90, parent=0x0,
flags=ELM_GENLIST_ITEM_NONE,
func=<value optimized out>, func_data=0x0) at elm_genlist.c:2528
[eina-share-common-del-check-for-node.patch text/x-patch
(1.2KB)]
Index: src/lib/eina_share_common.c
===================================================================
--- src/lib/eina_share_common.c(revisione 55018)
+++ src/lib/eina_share_common.c(copia locale)
@@ -558,7 +558,7 @@
const size_t offset = offsetof(Eina_Share_Common_Node, str);
node = (Eina_Share_Common_Node *)(str - offset);
- EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, );
+ EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, node
= NULL);
return node;
(void) node_magic; /* When magic are disable, node_magic is
unused, this remove a warning. */
@@ -821,6 +821,7 @@
SHARE_COMMON_LOCK_BIG();
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node) return str;
node->references++;
DBG("str=%p refs=%u", str, node->references);
@@ -847,6 +848,9 @@
SHARE_COMMON_LOCK_BIG();
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node)
+ return;
+
slen = node->length;
eina_share_common_population_del(share, slen);
if (node->references > 1)
@@ -901,6 +905,7 @@
return -1;
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node) return 0;
return node->length;
}
SVN revision: 55265
2010-12-04 19:14:03 -08:00
|
|
|
EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, node = NULL);
|
2010-07-27 01:55:23 -07:00
|
|
|
return node;
|
2010-07-29 06:59:31 -07:00
|
|
|
|
|
|
|
(void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2012-10-05 13:09:47 -07:00
|
|
|
eina_iterator_array_check(const Eina_Rbtree *rbtree EINA_UNUSED,
|
2010-07-27 19:37:05 -07:00
|
|
|
Eina_Share_Common_Head *head,
|
|
|
|
struct dumpinfo *fdata)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
Eina_Share_Common_Node *node;
|
|
|
|
|
|
|
|
fdata->used += sizeof(Eina_Share_Common_Head);
|
|
|
|
for (node = head->head; node; node = node->next)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
printf("DDD: %5i %5i ", node->length, node->references);
|
2010-07-28 10:53:10 -07:00
|
|
|
printf("'%.*s'\n", node->length, ((char *)node) + sizeof(Eina_Share_Common_Node));
|
2010-07-27 19:37:05 -07:00
|
|
|
fdata->used += sizeof(Eina_Share_Common_Node);
|
|
|
|
fdata->used += node->length;
|
|
|
|
fdata->saved += (node->references - 1) * node->length;
|
|
|
|
fdata->dups += node->references - 1;
|
|
|
|
fdata->unique++;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @endcond
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* Global *
|
|
|
|
*============================================================================*/
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* @brief Initialize the share_common module.
|
|
|
|
*
|
|
|
|
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
|
|
|
|
*
|
|
|
|
* This function sets up the share_common module of Eina. It is called by
|
|
|
|
* eina_init().
|
|
|
|
*
|
|
|
|
* @see eina_init()
|
|
|
|
*/
|
|
|
|
Eina_Bool
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_share_common_init(Eina_Share **_share,
|
|
|
|
Eina_Magic node_magic,
|
|
|
|
const char *node_magic_STR)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
Eina_Share *share;
|
2011-05-18 00:56:11 -07:00
|
|
|
|
2010-07-27 01:55:23 -07:00
|
|
|
share = *_share = calloc(sizeof(Eina_Share), 1);
|
2011-05-18 00:56:11 -07:00
|
|
|
if (!share) goto on_error;
|
2010-07-27 19:37:05 -07:00
|
|
|
|
2010-07-27 01:55:23 -07:00
|
|
|
share->share = calloc(1, sizeof(Eina_Share_Common));
|
2012-01-20 23:21:23 -08:00
|
|
|
if (!share->share) goto on_error;
|
2010-07-27 19:37:05 -07:00
|
|
|
|
2010-07-27 01:55:23 -07:00
|
|
|
share->node_magic = node_magic;
|
2010-07-27 19:37:05 -07:00
|
|
|
#define EMS(n) eina_magic_string_static_set(n, n ## _STR)
|
2010-07-27 01:55:23 -07:00
|
|
|
EMS(EINA_MAGIC_SHARE);
|
|
|
|
EMS(EINA_MAGIC_SHARE_HEAD);
|
|
|
|
EMS(node_magic);
|
|
|
|
#undef EMS
|
|
|
|
EINA_MAGIC_SET(share->share, EINA_MAGIC_SHARE);
|
|
|
|
|
|
|
|
_eina_share_common_population_init(share);
|
2011-04-24 09:49:48 -07:00
|
|
|
|
2011-05-18 03:05:59 -07:00
|
|
|
/* below is the common part among other all eina_share_common user */
|
|
|
|
if (_eina_share_common_count++ != 0)
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_new(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
return EINA_TRUE;
|
2011-05-18 00:56:11 -07:00
|
|
|
|
|
|
|
on_error:
|
|
|
|
_eina_share_common_count--;
|
|
|
|
return EINA_FALSE;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* @brief Shut down the share_common module.
|
|
|
|
*
|
|
|
|
* @return #EINA_TRUE on success, #EINA_FALSE on failure.
|
|
|
|
*
|
|
|
|
* This function shuts down the share_common module set up by
|
|
|
|
* eina_share_common_init(). It is called by eina_shutdown().
|
|
|
|
*
|
|
|
|
* @see eina_shutdown()
|
|
|
|
*/
|
|
|
|
Eina_Bool
|
|
|
|
eina_share_common_shutdown(Eina_Share **_share)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
Eina_Share *share = *_share;
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_take(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
_eina_share_common_population_stats(share);
|
|
|
|
|
|
|
|
/* remove any string still in the table */
|
|
|
|
for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_rbtree_delete(EINA_RBTREE_GET(
|
|
|
|
share->share->buckets[i]),
|
|
|
|
EINA_RBTREE_FREE_CB(
|
|
|
|
_eina_share_common_head_free), NULL);
|
|
|
|
share->share->buckets[i] = NULL;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
MAGIC_FREE(share->share);
|
|
|
|
|
|
|
|
_eina_share_common_population_shutdown(share);
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
|
|
|
|
2010-07-27 01:55:23 -07:00
|
|
|
free(*_share);
|
|
|
|
*_share = NULL;
|
2011-05-18 03:05:59 -07:00
|
|
|
|
|
|
|
/* below is the common part among other all eina_share_common user */
|
|
|
|
if (--_eina_share_common_count != 0)
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
eina_lock_free(&_mutex_big);
|
|
|
|
|
2010-07-27 01:55:23 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef EFL_HAVE_THREADS
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
2010-09-10 05:01:52 -07:00
|
|
|
* @brief Activate the share_common mutexes.
|
2010-07-27 01:55:23 -07:00
|
|
|
*
|
2010-09-10 05:01:52 -07:00
|
|
|
* This function activate the mutexes in the eina share_common module. It is called by
|
|
|
|
* eina_threads_init().
|
2010-07-27 01:55:23 -07:00
|
|
|
*
|
2010-09-10 05:01:52 -07:00
|
|
|
* @see eina_threads_init()
|
2010-07-27 01:55:23 -07:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
eina_share_common_threads_init(void)
|
|
|
|
{
|
|
|
|
_share_common_threads_activated = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
2010-09-10 05:01:52 -07:00
|
|
|
* @brief Shut down the share_common mutexes.
|
2010-07-27 01:55:23 -07:00
|
|
|
*
|
2010-09-10 05:01:52 -07:00
|
|
|
* This function shuts down the mutexes in the share_common module.
|
|
|
|
* It is called by eina_threads_shutdown().
|
2010-07-27 01:55:23 -07:00
|
|
|
*
|
2010-09-10 05:01:52 -07:00
|
|
|
* @see eina_threads_shutdown()
|
2010-07-27 01:55:23 -07:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
eina_share_common_threads_shutdown(void)
|
|
|
|
{
|
|
|
|
_share_common_threads_activated = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*============================================================================*
|
2010-07-27 19:37:05 -07:00
|
|
|
* API *
|
|
|
|
*============================================================================*/
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @cond LOCAL
|
|
|
|
*/
|
|
|
|
|
|
|
|
const char *
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_share_common_add_length(Eina_Share *share,
|
|
|
|
const char *str,
|
|
|
|
unsigned int slen,
|
|
|
|
unsigned int null_size)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
Eina_Share_Common_Head **p_bucket, *ed;
|
|
|
|
Eina_Share_Common_Node *el;
|
|
|
|
int hash_num, hash;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!str)
|
|
|
|
return NULL;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
eina_share_common_population_add(share, slen);
|
|
|
|
|
|
|
|
if (slen <= 0)
|
2010-07-27 19:37:05 -07:00
|
|
|
return NULL;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
hash = eina_hash_superfast(str, slen);
|
|
|
|
hash_num = hash & 0xFF;
|
|
|
|
hash = (hash >> 8) & EINA_SHARE_COMMON_MASK;
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_take(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
p_bucket = share->share->buckets + hash_num;
|
|
|
|
|
|
|
|
ed = _eina_share_common_find_hash(*p_bucket, hash);
|
|
|
|
if (!ed)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
const char *s = _eina_share_common_add_head(share,
|
|
|
|
p_bucket,
|
|
|
|
hash,
|
|
|
|
str,
|
|
|
|
slen,
|
|
|
|
null_size);
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big), NULL);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
el = _eina_share_common_head_find(ed, str, slen);
|
|
|
|
if (el)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
EINA_MAGIC_CHECK_SHARE_COMMON_NODE(el,
|
|
|
|
share->node_magic,
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big));
|
2010-07-27 19:37:05 -07:00
|
|
|
el->references++;
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 19:37:05 -07:00
|
|
|
return el->str;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
el = _eina_share_common_node_alloc(slen, null_size);
|
|
|
|
if (!el)
|
|
|
|
{
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 19:37:05 -07:00
|
|
|
return NULL;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
_eina_share_common_node_init(el, str, slen, null_size, share->node_magic);
|
|
|
|
el->next = ed->head;
|
|
|
|
ed->head = el;
|
|
|
|
_eina_share_common_population_head_add(share, ed);
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
return el->str;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
eina_share_common_ref(Eina_Share *share, const char *str)
|
|
|
|
{
|
|
|
|
Eina_Share_Common_Node *node;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!str)
|
|
|
|
return NULL;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_take(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
node = _eina_share_common_node_from_str(str, share->node_magic);
|
2011-08-03 05:01:35 -07:00
|
|
|
if (!node)
|
|
|
|
{
|
|
|
|
eina_lock_release(&_mutex_big);
|
|
|
|
return str;
|
|
|
|
}
|
2010-07-27 01:55:23 -07:00
|
|
|
node->references++;
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
eina_share_common_population_add(share, node->length);
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-20 23:21:23 -08:00
|
|
|
Eina_Bool
|
2010-07-27 08:15:45 -07:00
|
|
|
eina_share_common_del(Eina_Share *share, const char *str)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
2010-07-27 08:15:45 -07:00
|
|
|
unsigned int slen;
|
2010-07-27 01:55:23 -07:00
|
|
|
Eina_Share_Common_Head *ed;
|
|
|
|
Eina_Share_Common_Head **p_bucket;
|
|
|
|
Eina_Share_Common_Node *node;
|
|
|
|
int hash_num, hash;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!str)
|
2012-01-20 23:21:23 -08:00
|
|
|
return EINA_TRUE;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_take(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
node = _eina_share_common_node_from_str(str, share->node_magic);
|
SVN revision: 3
Subject: [E-devel] [PATCH] eina share common check for node type
Hello, recentely I've been experiencing a lot of segfaults when running
an Elementary application which uses a genlist with some swallowed parts
in which I put some elm icons (png files).
When running it I often get crashes... Debugging it I found this:
=========
CRI<14207>: eina_share_common.c:561 _eina_share_common_node_from_str()
*** Eina Magic Check Failed !!!
Input handle is wrong type
Expected: 98761254 - Eina Stringshare Node
Supplied: 6e657070 - (unknown)
*** NAUGHTY PROGRAMMER!!!
*** SPANK SPANK SPANK!!!
*** Now go fix your code. Tut tut tut!
//DEBUG: Node referencies 622869060 (slen: 1145307236)
Program received signal SIGSEGV, Segmentation fault.
eina_share_common_del (share=0x65c810, str=0x7ffff1219150
"5hhu %5hu '%
s'\n")
at eina_share_common.c:858
858 node->references--;
=========
So it seems that edje tries to delete an invalid eina_share_common
string (is this a bug that should be fixed or is it
theme-dependent?),
and so the "node" pointer in eina share is not valid...
However eina never checks for its validity, so it seg-faults...
The attached patch fix this issue, setting the node to null when its
magic is not valid, and then always checking for its validity.
Is this fine?
Full stack trace:
#0 eina_share_common_del (share=0x65c810, str=0x7ffff1219150 "5hhu %5hu
'%s'\n")
at eina_share_common.c:858
#1 0x00007ffff120e047 in eina_stringshare_del (str=0x7ffff1219150
"5hhu
%5hu '%s'\n")
at eina_stringshare.c:632
#2 0x00007ffff1e1f7bc in _edje_text_recalc_apply (ed=0x95b900,
ep=0x70c3a0,
params=0x70c500, chosen_desc=<value optimized out>) at
edje_text.c:556
#3 0x00007ffff1de402d in _edje_part_recalc (ed=0x95b900,
ep=0x70c3a0,
flags=3)
at edje_calc.c:2007
#4 0x00007ffff1de4d86 in _edje_recalc_do (ed=0x95b900) at
edje_calc.c:268
#5 0x00007ffff1e25c7d in edje_object_part_swallow (obj=<value
optimized
out>,
part=0x7fffe001484c "elm.swallow.icon", obj_swallow=0x7fffe0017860)
at edje_util.c:2300
#6 0x00007ffff1b5d5fc in _item_realize (it=0x7fffe0016ed0,
in=10,
calc=1)
at elm_genlist.c:1489
#7 0x00007ffff1b5db89 in _item_block_recalc (itb=0x95b6a0,
in=<value
optimized out>,
qadd=<value optimized out>, norender=<value optimized out>) at
elm_genlist.c:1609
#8 0x00007ffff1b5e329 in _queue_proecess (wd=0x721b70,
norender=<value
optimized out>)
at elm_genlist.c:2425
#9 0x00007ffff1b5e567 in _item_queue (wd=0x721b70, it=<value
optimized
out>)
at elm_genlist.c:2476
#10 0x00007ffff1b5ead9 in elm_genlist_item_append (obj=<value
optimized
out>,
itc=0x7ffff2977040, data=0x8fed90, parent=0x0,
flags=ELM_GENLIST_ITEM_NONE,
func=<value optimized out>, func_data=0x0) at elm_genlist.c:2528
[eina-share-common-del-check-for-node.patch text/x-patch
(1.2KB)]
Index: src/lib/eina_share_common.c
===================================================================
--- src/lib/eina_share_common.c(revisione 55018)
+++ src/lib/eina_share_common.c(copia locale)
@@ -558,7 +558,7 @@
const size_t offset = offsetof(Eina_Share_Common_Node, str);
node = (Eina_Share_Common_Node *)(str - offset);
- EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, );
+ EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, node
= NULL);
return node;
(void) node_magic; /* When magic are disable, node_magic is
unused, this remove a warning. */
@@ -821,6 +821,7 @@
SHARE_COMMON_LOCK_BIG();
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node) return str;
node->references++;
DBG("str=%p refs=%u", str, node->references);
@@ -847,6 +848,9 @@
SHARE_COMMON_LOCK_BIG();
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node)
+ return;
+
slen = node->length;
eina_share_common_population_del(share, slen);
if (node->references > 1)
@@ -901,6 +905,7 @@
return -1;
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node) return 0;
return node->length;
}
SVN revision: 55265
2010-12-04 19:14:03 -08:00
|
|
|
if (!node)
|
2011-08-03 05:01:35 -07:00
|
|
|
goto on_error;
|
SVN revision: 3
Subject: [E-devel] [PATCH] eina share common check for node type
Hello, recentely I've been experiencing a lot of segfaults when running
an Elementary application which uses a genlist with some swallowed parts
in which I put some elm icons (png files).
When running it I often get crashes... Debugging it I found this:
=========
CRI<14207>: eina_share_common.c:561 _eina_share_common_node_from_str()
*** Eina Magic Check Failed !!!
Input handle is wrong type
Expected: 98761254 - Eina Stringshare Node
Supplied: 6e657070 - (unknown)
*** NAUGHTY PROGRAMMER!!!
*** SPANK SPANK SPANK!!!
*** Now go fix your code. Tut tut tut!
//DEBUG: Node referencies 622869060 (slen: 1145307236)
Program received signal SIGSEGV, Segmentation fault.
eina_share_common_del (share=0x65c810, str=0x7ffff1219150
"5hhu %5hu '%
s'\n")
at eina_share_common.c:858
858 node->references--;
=========
So it seems that edje tries to delete an invalid eina_share_common
string (is this a bug that should be fixed or is it
theme-dependent?),
and so the "node" pointer in eina share is not valid...
However eina never checks for its validity, so it seg-faults...
The attached patch fix this issue, setting the node to null when its
magic is not valid, and then always checking for its validity.
Is this fine?
Full stack trace:
#0 eina_share_common_del (share=0x65c810, str=0x7ffff1219150 "5hhu %5hu
'%s'\n")
at eina_share_common.c:858
#1 0x00007ffff120e047 in eina_stringshare_del (str=0x7ffff1219150
"5hhu
%5hu '%s'\n")
at eina_stringshare.c:632
#2 0x00007ffff1e1f7bc in _edje_text_recalc_apply (ed=0x95b900,
ep=0x70c3a0,
params=0x70c500, chosen_desc=<value optimized out>) at
edje_text.c:556
#3 0x00007ffff1de402d in _edje_part_recalc (ed=0x95b900,
ep=0x70c3a0,
flags=3)
at edje_calc.c:2007
#4 0x00007ffff1de4d86 in _edje_recalc_do (ed=0x95b900) at
edje_calc.c:268
#5 0x00007ffff1e25c7d in edje_object_part_swallow (obj=<value
optimized
out>,
part=0x7fffe001484c "elm.swallow.icon", obj_swallow=0x7fffe0017860)
at edje_util.c:2300
#6 0x00007ffff1b5d5fc in _item_realize (it=0x7fffe0016ed0,
in=10,
calc=1)
at elm_genlist.c:1489
#7 0x00007ffff1b5db89 in _item_block_recalc (itb=0x95b6a0,
in=<value
optimized out>,
qadd=<value optimized out>, norender=<value optimized out>) at
elm_genlist.c:1609
#8 0x00007ffff1b5e329 in _queue_proecess (wd=0x721b70,
norender=<value
optimized out>)
at elm_genlist.c:2425
#9 0x00007ffff1b5e567 in _item_queue (wd=0x721b70, it=<value
optimized
out>)
at elm_genlist.c:2476
#10 0x00007ffff1b5ead9 in elm_genlist_item_append (obj=<value
optimized
out>,
itc=0x7ffff2977040, data=0x8fed90, parent=0x0,
flags=ELM_GENLIST_ITEM_NONE,
func=<value optimized out>, func_data=0x0) at elm_genlist.c:2528
[eina-share-common-del-check-for-node.patch text/x-patch
(1.2KB)]
Index: src/lib/eina_share_common.c
===================================================================
--- src/lib/eina_share_common.c(revisione 55018)
+++ src/lib/eina_share_common.c(copia locale)
@@ -558,7 +558,7 @@
const size_t offset = offsetof(Eina_Share_Common_Node, str);
node = (Eina_Share_Common_Node *)(str - offset);
- EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, );
+ EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, node
= NULL);
return node;
(void) node_magic; /* When magic are disable, node_magic is
unused, this remove a warning. */
@@ -821,6 +821,7 @@
SHARE_COMMON_LOCK_BIG();
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node) return str;
node->references++;
DBG("str=%p refs=%u", str, node->references);
@@ -847,6 +848,9 @@
SHARE_COMMON_LOCK_BIG();
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node)
+ return;
+
slen = node->length;
eina_share_common_population_del(share, slen);
if (node->references > 1)
@@ -901,6 +905,7 @@
return -1;
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node) return 0;
return node->length;
}
SVN revision: 55265
2010-12-04 19:14:03 -08:00
|
|
|
|
2010-07-27 08:15:45 -07:00
|
|
|
slen = node->length;
|
|
|
|
eina_share_common_population_del(share, slen);
|
2010-07-27 01:55:23 -07:00
|
|
|
if (node->references > 1)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
node->references--;
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2012-01-20 23:21:23 -08:00
|
|
|
return EINA_TRUE;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
node->references = 0;
|
|
|
|
|
|
|
|
hash = eina_hash_superfast(str, slen);
|
|
|
|
hash_num = hash & 0xFF;
|
|
|
|
hash = (hash >> 8) & EINA_SHARE_COMMON_MASK;
|
|
|
|
|
|
|
|
p_bucket = share->share->buckets + hash_num;
|
|
|
|
ed = _eina_share_common_find_hash(*p_bucket, hash);
|
|
|
|
if (!ed)
|
2010-07-27 19:37:05 -07:00
|
|
|
goto on_error;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2012-01-20 23:21:23 -08:00
|
|
|
EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big), EINA_FALSE);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
if (!_eina_share_common_head_remove_node(ed, node))
|
2010-07-27 19:37:05 -07:00
|
|
|
goto on_error;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
if (node != &ed->builtin_node)
|
2010-07-27 19:37:05 -07:00
|
|
|
MAGIC_FREE(node);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
if (!ed->head)
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_del_head(p_bucket, ed);
|
2010-07-27 01:55:23 -07:00
|
|
|
else
|
2010-07-27 19:37:05 -07:00
|
|
|
_eina_share_common_population_head_del(share, ed);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2012-01-20 23:21:23 -08:00
|
|
|
return EINA_TRUE;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
on_error:
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
/* possible segfault happened before here, but... */
|
2012-01-20 23:21:23 -08:00
|
|
|
return EINA_FALSE;
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-10-05 13:09:47 -07:00
|
|
|
eina_share_common_length(EINA_UNUSED Eina_Share *share, const char *str)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
const Eina_Share_Common_Node *node;
|
|
|
|
|
|
|
|
if (!str)
|
2010-07-27 19:37:05 -07:00
|
|
|
return -1;
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
node = _eina_share_common_node_from_str(str, share->node_magic);
|
SVN revision: 3
Subject: [E-devel] [PATCH] eina share common check for node type
Hello, recentely I've been experiencing a lot of segfaults when running
an Elementary application which uses a genlist with some swallowed parts
in which I put some elm icons (png files).
When running it I often get crashes... Debugging it I found this:
=========
CRI<14207>: eina_share_common.c:561 _eina_share_common_node_from_str()
*** Eina Magic Check Failed !!!
Input handle is wrong type
Expected: 98761254 - Eina Stringshare Node
Supplied: 6e657070 - (unknown)
*** NAUGHTY PROGRAMMER!!!
*** SPANK SPANK SPANK!!!
*** Now go fix your code. Tut tut tut!
//DEBUG: Node referencies 622869060 (slen: 1145307236)
Program received signal SIGSEGV, Segmentation fault.
eina_share_common_del (share=0x65c810, str=0x7ffff1219150
"5hhu %5hu '%
s'\n")
at eina_share_common.c:858
858 node->references--;
=========
So it seems that edje tries to delete an invalid eina_share_common
string (is this a bug that should be fixed or is it
theme-dependent?),
and so the "node" pointer in eina share is not valid...
However eina never checks for its validity, so it seg-faults...
The attached patch fix this issue, setting the node to null when its
magic is not valid, and then always checking for its validity.
Is this fine?
Full stack trace:
#0 eina_share_common_del (share=0x65c810, str=0x7ffff1219150 "5hhu %5hu
'%s'\n")
at eina_share_common.c:858
#1 0x00007ffff120e047 in eina_stringshare_del (str=0x7ffff1219150
"5hhu
%5hu '%s'\n")
at eina_stringshare.c:632
#2 0x00007ffff1e1f7bc in _edje_text_recalc_apply (ed=0x95b900,
ep=0x70c3a0,
params=0x70c500, chosen_desc=<value optimized out>) at
edje_text.c:556
#3 0x00007ffff1de402d in _edje_part_recalc (ed=0x95b900,
ep=0x70c3a0,
flags=3)
at edje_calc.c:2007
#4 0x00007ffff1de4d86 in _edje_recalc_do (ed=0x95b900) at
edje_calc.c:268
#5 0x00007ffff1e25c7d in edje_object_part_swallow (obj=<value
optimized
out>,
part=0x7fffe001484c "elm.swallow.icon", obj_swallow=0x7fffe0017860)
at edje_util.c:2300
#6 0x00007ffff1b5d5fc in _item_realize (it=0x7fffe0016ed0,
in=10,
calc=1)
at elm_genlist.c:1489
#7 0x00007ffff1b5db89 in _item_block_recalc (itb=0x95b6a0,
in=<value
optimized out>,
qadd=<value optimized out>, norender=<value optimized out>) at
elm_genlist.c:1609
#8 0x00007ffff1b5e329 in _queue_proecess (wd=0x721b70,
norender=<value
optimized out>)
at elm_genlist.c:2425
#9 0x00007ffff1b5e567 in _item_queue (wd=0x721b70, it=<value
optimized
out>)
at elm_genlist.c:2476
#10 0x00007ffff1b5ead9 in elm_genlist_item_append (obj=<value
optimized
out>,
itc=0x7ffff2977040, data=0x8fed90, parent=0x0,
flags=ELM_GENLIST_ITEM_NONE,
func=<value optimized out>, func_data=0x0) at elm_genlist.c:2528
[eina-share-common-del-check-for-node.patch text/x-patch
(1.2KB)]
Index: src/lib/eina_share_common.c
===================================================================
--- src/lib/eina_share_common.c(revisione 55018)
+++ src/lib/eina_share_common.c(copia locale)
@@ -558,7 +558,7 @@
const size_t offset = offsetof(Eina_Share_Common_Node, str);
node = (Eina_Share_Common_Node *)(str - offset);
- EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, );
+ EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, node
= NULL);
return node;
(void) node_magic; /* When magic are disable, node_magic is
unused, this remove a warning. */
@@ -821,6 +821,7 @@
SHARE_COMMON_LOCK_BIG();
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node) return str;
node->references++;
DBG("str=%p refs=%u", str, node->references);
@@ -847,6 +848,9 @@
SHARE_COMMON_LOCK_BIG();
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node)
+ return;
+
slen = node->length;
eina_share_common_population_del(share, slen);
if (node->references > 1)
@@ -901,6 +905,7 @@
return -1;
node = _eina_share_common_node_from_str(str,
share->node_magic);
+ if (!node) return 0;
return node->length;
}
SVN revision: 55265
2010-12-04 19:14:03 -08:00
|
|
|
if (!node) return 0;
|
2010-07-27 01:55:23 -07:00
|
|
|
return node->length;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_share_common_dump(Eina_Share *share, void (*additional_dump)(
|
|
|
|
struct dumpinfo *), int used)
|
2010-07-27 01:55:23 -07:00
|
|
|
{
|
|
|
|
Eina_Iterator *it;
|
|
|
|
unsigned int i;
|
|
|
|
struct dumpinfo di;
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!share)
|
|
|
|
return;
|
|
|
|
|
2010-07-27 01:55:23 -07:00
|
|
|
di.used = used;
|
|
|
|
di.saved = 0;
|
|
|
|
di.dups = 0;
|
|
|
|
di.unique = 0;
|
|
|
|
printf("DDD: len ref string\n");
|
|
|
|
printf("DDD:-------------------\n");
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_take(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++)
|
|
|
|
{
|
2010-07-27 19:37:05 -07:00
|
|
|
if (!share->share->buckets[i])
|
2010-07-27 20:03:25 -07:00
|
|
|
{
|
|
|
|
continue; // printf("DDD: BUCKET # %i (HEAD=%i, NODE=%i)\n", i,
|
|
|
|
|
|
|
|
}
|
2010-07-27 19:37:05 -07:00
|
|
|
|
2010-07-27 01:55:23 -07:00
|
|
|
// sizeof(Eina_Share_Common_Head), sizeof(Eina_Share_Common_Node));
|
2010-07-27 19:37:05 -07:00
|
|
|
it = eina_rbtree_iterator_prefix(
|
|
|
|
(Eina_Rbtree *)share->share->buckets[i]);
|
2010-08-11 07:32:30 -07:00
|
|
|
eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_array_check), &di);
|
2010-07-27 19:37:05 -07:00
|
|
|
eina_iterator_free(it);
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
if (additional_dump)
|
|
|
|
additional_dump(&di);
|
2010-07-27 19:37:05 -07:00
|
|
|
|
2010-07-27 01:55:23 -07:00
|
|
|
#ifdef EINA_SHARE_COMMON_USAGE
|
|
|
|
/* One character strings are not counted in the hash. */
|
|
|
|
di.saved += share->population_group[0].count * sizeof(char);
|
|
|
|
di.saved += share->population_group[1].count * sizeof(char) * 2;
|
|
|
|
#endif
|
|
|
|
printf("DDD:-------------------\n");
|
|
|
|
printf("DDD: usage (bytes) = %i, saved = %i (%3.0f%%)\n",
|
2010-07-27 19:37:05 -07:00
|
|
|
di.used, di.saved, di.used ? (di.saved * 100.0 / di.used) : 0.0);
|
2010-07-27 01:55:23 -07:00
|
|
|
printf("DDD: unique: %d, duplicates: %d (%3.0f%%)\n",
|
2010-07-27 19:37:05 -07:00
|
|
|
di.unique, di.dups, di.unique ? (di.dups * 100.0 / di.unique) : 0.0);
|
2010-07-27 01:55:23 -07:00
|
|
|
|
|
|
|
#ifdef EINA_SHARE_COMMON_USAGE
|
2010-07-27 19:37:05 -07:00
|
|
|
printf("DDD: Allocated strings: %i\n", share->population.count);
|
2010-07-27 01:55:23 -07:00
|
|
|
printf("DDD: Max allocated strings: %i\n", share->population.max);
|
|
|
|
|
2010-07-27 19:37:05 -07:00
|
|
|
for (i = 0;
|
|
|
|
i < sizeof (share->population_group) /
|
|
|
|
sizeof (share->population_group[0]);
|
|
|
|
++i)
|
|
|
|
fprintf(stderr,
|
2012-10-04 02:31:46 -07:00
|
|
|
"DDD: %i strings of length %u, max strings: %i\n",
|
2010-07-27 19:37:05 -07:00
|
|
|
share->population_group[i].count,
|
|
|
|
i,
|
|
|
|
share->population_group[i].max);
|
2010-07-27 01:55:23 -07:00
|
|
|
#endif
|
|
|
|
|
2011-04-24 09:49:48 -07:00
|
|
|
eina_lock_release(&_mutex_big);
|
2010-07-27 01:55:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @endcond
|
|
|
|
*/
|