tizen 2.3 release
[framework/system/swap-probe.git] / helper / dacollection.c
1 /*
2  *  DA probe
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim <jaewon81.lim@samsung.com>
9  * Woojin Jung <woojin2.jung@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  *
12  * This library is free software; you can redistribute it and/or modify it under
13  * the terms of the GNU Lesser General Public License as published by the
14  * Free Software Foundation; either version 2.1 of the License, or (at your option)
15  * any later version.
16  *
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
18  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
20  * License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * along with this library; if not, write to the Free Software Foundation, Inc., 51
24  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  *
29  */
30
31 #include <assert.h>             // for assert
32 #include <stdlib.h>             // for malloc, free
33 #include <string.h>             // for strlen, strcpy
34 #include <pthread.h>    // for pthread_mutex_t
35
36 #include "dahelper.h"
37 #include "daerror.h"
38 #include "dacollection.h"
39
40 // hash table variable
41 __hashInfo _hashinfo =
42 {
43         NULL,                                           // khash_t(symbol)*     symHash
44         PTHREAD_MUTEX_INITIALIZER,      // pthread_mutex_t symHashMutex
45         NULL,                                           // khash_t(allocmap)*   memHash
46         PTHREAD_MUTEX_INITIALIZER,      // pthread_mutex_t memHashMutex
47         NULL,                                           // khash_t(uiobject)*   uiobjHash
48         PTHREAD_MUTEX_INITIALIZER,      // pthread_mutex_t      uiobjHashMutex
49         NULL,                                           // khash_t(object)*     objHash
50         PTHREAD_MUTEX_INITIALIZER,      // pthread_mutex_t objHashMutex
51         NULL,                                           // khash_t(detector)*   dttHash
52         PTHREAD_MUTEX_INITIALIZER       // pthread_mutex_t dttHashMutex
53 };
54
55 // glist typedef and variable
56 struct _element
57 {
58         int             keylen;
59         char*   keystr;
60         void*   dataptr;
61         struct _element*        next;
62         struct _element*        prev;
63 };
64
65 typedef struct _element element_t;
66
67 element_t* gsymbol_list = NULL;
68 pthread_mutex_t glist_mutex = PTHREAD_MUTEX_INITIALIZER;
69
70 // *********************************************************************************************
71 // hash table related implemenation
72 // *********************************************************************************************
73
74 int initialize_hash_table()
75 {
76         SYMBOLHASH_LOCK;
77         SYMBOLHASH = kh_init(symbol);
78         SYMBOLHASH_UNLOCK;
79
80         MEMORYHASH_LOCK;
81         MEMORYHASH = kh_init(allocmap);
82         MEMORYHASH_UNLOCK;
83
84         UIOBJECTHASH_LOCK;
85         UIOBJECTHASH = kh_init(uiobject);
86         UIOBJECTHASH_UNLOCK;
87
88         OBJECTHASH_LOCK;
89         OBJECTHASH = kh_init(object);
90         OBJECTHASH_UNLOCK;
91
92         DETECTORHASH_LOCK;
93         DETECTORHASH = kh_init(detector);
94         DETECTORHASH_UNLOCK;
95
96         return 0;
97 }
98
99 int finalize_hash_table()
100 {
101         if (SYMBOLHASH)
102         {
103                 khiter_t k;
104                 char* val;
105
106                 SYMBOLHASH_LOCK;
107                 for(k = kh_begin(SYMBOLHASH); k != kh_end(SYMBOLHASH); k++)
108                 {
109                         if (kh_exist(SYMBOLHASH, k))
110                         {
111                                 val = kh_value(SYMBOLHASH, k);
112                                 free(val);
113                         }
114                 }
115                 kh_destroy(symbol, SYMBOLHASH);
116                 SYMBOLHASH = NULL;
117                 SYMBOLHASH_UNLOCK;
118         }
119
120         if (MEMORYHASH)
121         {
122                 MEMORYHASH_LOCK;
123                 kh_destroy(allocmap, MEMORYHASH);
124                 MEMORYHASH = NULL;
125                 MEMORYHASH_UNLOCK;
126         }
127
128         if (UIOBJECTHASH)
129         {
130                 khiter_t k;
131                 _uiobjectinfo* val;
132
133                 UIOBJECTHASH_LOCK;
134                 for(k = kh_begin(UIOBJECTHASH); k != kh_end(UIOBJECTHASH); k++)
135                 {
136                         if (kh_exist(UIOBJECTHASH, k))
137                         {
138                                 val = kh_value(UIOBJECTHASH, k);
139                                 if (likely(val->type != 0)) free(val->type);
140                                 if (likely(val->name != 0)) free(val->name);
141                                 free(val);
142                         }
143                 }
144                 kh_destroy(uiobject, UIOBJECTHASH);
145                 UIOBJECTHASH = NULL;
146                 UIOBJECTHASH_UNLOCK;
147         }
148
149         if (OBJECTHASH)
150         {
151                 OBJECTHASH_LOCK;
152                 kh_destroy(object, OBJECTHASH);
153                 OBJECTHASH = NULL;
154                 OBJECTHASH_UNLOCK;
155         }
156
157         if (DETECTORHASH)
158         {
159                 DETECTORHASH_LOCK;
160                 kh_destroy(detector, DETECTORHASH);
161                 DETECTORHASH = NULL;
162                 DETECTORHASH_UNLOCK;
163         }
164
165         return 0;
166 }
167
168 /***********************************************************
169  * symbol hash related functions
170  ***********************************************************/
171 // return 0 if there is no entry in hash
172 // return 1 if there is entry in hash
173 // return negative value if error occurred
174 int find_symbol_hash(void* ptr, char** psymbol)
175 {
176         khiter_t k;
177         int ret = 0;
178
179         if (unlikely(SYMBOLHASH == 0))
180                 return ERR_NOTINITIALIZED;
181
182         if (unlikely(ptr == NULL))
183                 return ERR_WRONGPARAMETER;
184
185         if (unlikely(psymbol == NULL))
186                 return ERR_WRONGPARAMETER;
187
188         probeBlockStart();
189
190         SYMBOLHASH_LOCK;
191         k = kh_get(symbol, SYMBOLHASH, (uint32_t)ptr);
192         if (k == kh_end(SYMBOLHASH))            // there is no entry for key
193         {
194                 ret = 0;
195         }
196         else
197         {
198                 *psymbol = kh_value(SYMBOLHASH, k);
199                 ret = 1;
200         }
201         SYMBOLHASH_UNLOCK;
202         probeBlockEnd();
203         return ret;
204 }
205
206 // return 0 if succeed
207 // return 1 if there is already exist in hash
208 // return negative value if other error occurred
209 int add_symbol_hash(void* ptr, const char* str, int strlen)
210 {
211         khiter_t k;
212         int rethash, ret = 0;
213
214         if (unlikely(SYMBOLHASH == 0))
215                 return ERR_NOTINITIALIZED;
216
217         if (unlikely(ptr == NULL))
218                 return ERR_WRONGPARAMETER;
219
220         if (unlikely(str == NULL))
221                 return ERR_WRONGPARAMETER;
222
223         probeBlockStart();
224
225         SYMBOLHASH_LOCK;
226         k = kh_put(symbol, SYMBOLHASH, (uint32_t)ptr, &rethash);
227         if (likely(rethash != 0))       // succeed to add in hash table
228         {
229                 char* tlast = (char*)real_malloc(strlen);
230                 if (likely(tlast != NULL))
231                 {
232                         memcpy(tlast, str, strlen);
233                         kh_value(SYMBOLHASH, k) = tlast;
234                 }
235                 else
236                 {
237                         kh_del(symbol, SYMBOLHASH, k);
238                         ret = ERR_OUTOFMEMORY;
239                 }
240         }
241         else
242         {
243                 // TODO : error handling
244                 ret = 1;
245         }
246         SYMBOLHASH_UNLOCK;
247         probeBlockEnd();
248         return ret;
249 }
250
251 /***********************************************************
252  * memory hash related functions
253  ***********************************************************/
254 // return 0 if succeed
255 // return 1 if key is already exist in hash table
256 // return negative value if other error occurred
257 int add_memory_hash(void* ptr, size_t size, unsigned short type, unsigned short caller)
258 {
259         khiter_t k;
260         int rethash, ret = 0;
261         size_t memsize;
262         uint64_t meminfo;
263
264         if (unlikely(MEMORYHASH == 0))
265                 return ERR_NOTINITIALIZED;
266
267         if (unlikely(ptr == NULL))
268                 return ERR_WRONGPARAMETER;
269
270         probeBlockStart();
271         MEMORYHASH_LOCK;
272         k = kh_put(allocmap, MEMORYHASH, (uint32_t)ptr, &rethash);
273         if (likely(rethash != 0))       // succeed to add in hash table
274         {
275                 kh_value(MEMORYHASH, k) = MAKE_MEMINFO(caller, type, size);
276                 update_heap_memory_size(true, size);
277         }
278         else
279         {
280                 // key is already exist in hash
281                 // update memory info
282                 meminfo = kh_value(MEMORYHASH, k);
283                 memsize = GET_MEMSIZE(meminfo);
284                 if (memsize == size)
285                 {
286                         kh_value(MEMORYHASH, k) = MAKE_MEMINFO(caller, type, size);
287                 }
288                 ret = 1;
289         }
290         MEMORYHASH_UNLOCK;
291         probeBlockEnd();
292         return ret;
293 }
294
295 // return 0 if succeed
296 // return 1 if key is not in hash table
297 // return negative if other error occurred
298 int del_memory_hash(void* ptr, unsigned short type, unsigned short* caller)
299 {
300         khiter_t k;
301         int ret = 0;
302         uint32_t size;
303         uint64_t meminfo;
304
305         if (unlikely(MEMORYHASH == 0))
306                 return ERR_NOTINITIALIZED;
307
308         if (unlikely(ptr == NULL))
309                 return ERR_WRONGPARAMETER;
310
311         probeBlockStart();
312         MEMORYHASH_LOCK;
313         k = kh_get(allocmap, MEMORYHASH, (uint32_t)ptr);
314         if (likely(k != kh_end(MEMORYHASH)))
315         {                               // there is entry in hash table
316                 meminfo = kh_value(MEMORYHASH, k);
317                 if (unlikely(type != GET_MEMTYPE(meminfo)))
318                 {
319                         ret = -1;
320                 }
321                 else
322                 {
323                         size = GET_MEMSIZE(meminfo);
324                         if (caller != NULL)
325                                 *caller = GET_MEMCALLER(meminfo);
326                         update_heap_memory_size(false, size);
327                         kh_del(allocmap, MEMORYHASH, k);
328                 }
329         }
330         else
331         {
332                 ret = 1;        // there is not entry in hash table
333         }
334         MEMORYHASH_UNLOCK;
335         probeBlockEnd();
336
337         return ret;
338 }
339
340 /***********************************************************
341  * uiobject hash related functions
342  ***********************************************************/
343 // return 0 if there is no entry in hash
344 // return 1 if there is entry in hash
345 // return negative value if error occurred
346 int find_uiobject_hash(void* ptr, char** type, char** classname)
347 {
348         khiter_t k;
349         int ret = 0;
350
351         if (unlikely(UIOBJECTHASH == 0))
352                 return ERR_NOTINITIALIZED;
353
354         if (unlikely(ptr == NULL))
355                 return ERR_WRONGPARAMETER;
356
357         if (unlikely(type == NULL))
358                 return ERR_WRONGPARAMETER;
359
360         if (unlikely(classname == NULL))
361                 return ERR_WRONGPARAMETER;
362
363         probeBlockStart();
364
365         UIOBJECTHASH_LOCK;
366         k = kh_get(uiobject, UIOBJECTHASH, (uint32_t)ptr);
367         if (unlikely(k == kh_end(UIOBJECTHASH)))                // there is no entry for key
368         {
369                 ret = 0;
370         }
371         else
372         {
373                 *classname = kh_value(UIOBJECTHASH, k)->name;
374                 *type = kh_value(UIOBJECTHASH, k)->type;
375                 ret = 1;
376         }
377         UIOBJECTHASH_UNLOCK;
378         probeBlockEnd();
379         return ret;
380 }
381
382 // return 0 if succeed
383 // return 1 if there is no entry in hash
384 // return negative value if other error occurred
385 int add_uiobject_hash_class(void* ptr, const char* classname)
386 {
387         int str_len;
388         khiter_t k;
389         int rethash, ret = 0;
390
391         if (unlikely(UIOBJECTHASH == 0))
392                 return ERR_NOTINITIALIZED;
393
394         if (unlikely(ptr == NULL))
395                 return ERR_WRONGPARAMETER;
396
397         if (unlikely(classname == NULL))
398                 return ERR_WRONGPARAMETER;
399
400         probeBlockStart();
401
402         str_len = strlen(classname) + 1;
403
404         UIOBJECTHASH_LOCK;
405         k = kh_put(uiobject, UIOBJECTHASH, (uint32_t)ptr, &rethash);
406         if (likely(rethash == 0))       // entry is already in hash table
407         {
408                 if (likely(kh_value(UIOBJECTHASH, k) != NULL))
409                 {
410                         if (kh_value(UIOBJECTHASH, k)->name == NULL)
411                         {
412                                 char* tlast = (char*)real_malloc(str_len);
413                                 if (likely(tlast != NULL))
414                                 {
415                                         memcpy(tlast, classname, str_len);
416                                         kh_value(UIOBJECTHASH, k)->name = tlast;
417                                 }
418                                 else
419                                 {
420                                         kh_value(UIOBJECTHASH, k)->name = NULL;
421                                         ret = ERR_OUTOFMEMORY;  // out of memory
422                                 }
423                         }
424                         else
425                                 ret = ERR_ALREADYEXIST;
426                 }
427                 else    // not possible
428                         ret = ERR_NOTEXIST;     // there is entry but there is no value
429         }
430         else    // error
431                 ret = 1;        // there is no entry
432
433         UIOBJECTHASH_UNLOCK;
434         probeBlockEnd();
435         return ret;
436 }
437
438 // return 0 if succeed
439 // return 1 if there is already exist in hash
440 // return negative value if other error occurred
441 int add_uiobject_hash_type(void* ptr, const char* type)
442 {
443         int str_len;
444         khiter_t k;
445         int rethash, ret = 0;
446
447         if (unlikely(UIOBJECTHASH == 0))
448                 return ERR_NOTINITIALIZED;
449
450         if (unlikely(ptr == NULL))
451                 return ERR_WRONGPARAMETER;
452
453         if (unlikely(type == NULL))
454                 return ERR_WRONGPARAMETER;
455
456         probeBlockStart();
457
458         str_len = strlen(type) + 1;
459
460         UIOBJECTHASH_LOCK;
461         k = kh_put(uiobject, UIOBJECTHASH, (uint32_t)ptr, &rethash);
462         if (likely(rethash != 0))       // succeed to add in hash table
463         {
464                 char* tlast;
465                 _uiobjectinfo* newentry;
466
467                 newentry = (_uiobjectinfo*)calloc(1, sizeof(_uiobjectinfo));
468                 if (likely(newentry != NULL))
469                 {
470                         kh_value(UIOBJECTHASH, k) = newentry;
471
472                         tlast = (char*)real_malloc(str_len);
473                         if (likely(tlast != NULL))
474                         {
475                                 memcpy(tlast, type, str_len);
476                                 kh_value(UIOBJECTHASH, k)->type = tlast;
477                         }
478                         else
479                         {
480                                 kh_value(UIOBJECTHASH, k)->type = NULL;
481                                 ret = ERR_OUTOFMEMORY;
482                         }
483                 }
484                 else
485                 {
486                         kh_del(uiobject, UIOBJECTHASH, k);
487                         ret = ERR_OUTOFMEMORY;
488                 }
489         }
490         else
491                 ret = 1;
492
493         UIOBJECTHASH_UNLOCK;
494         probeBlockEnd();
495         return ret;
496 }
497
498 // return 0 if succeed
499 // return 1 if key is not in hash table
500 // return negative value if other error occurred
501 int del_uiobject_hash(void* ptr)
502 {
503         khiter_t k;
504         _uiobjectinfo* val;
505         int ret = 0;
506
507         if (unlikely(UIOBJECTHASH == 0))
508                 return ERR_NOTINITIALIZED;
509
510         if (unlikely(ptr == NULL))
511                 return ERR_WRONGPARAMETER;
512
513         probeBlockStart();
514         UIOBJECTHASH_LOCK;
515         k = kh_get(uiobject, UIOBJECTHASH, (uint32_t)ptr);
516         if (likely(k != kh_end(UIOBJECTHASH)))          // there is entry in hash table
517         {
518                 val = kh_value(UIOBJECTHASH, k);
519                 kh_del(uiobject, UIOBJECTHASH, k);
520                 if (likely(val->type != NULL)) free(val->type);
521                 if (likely(val->name != NULL)) free(val->name);
522                 free(val);
523         }
524         else
525         {
526                 ret = 1;
527         }
528         UIOBJECTHASH_UNLOCK;
529         probeBlockEnd();
530
531         return ret;
532 }
533
534 /***********************************************************
535  * object hash related functions
536  ***********************************************************/
537 // return 0 if there is no entry in hash
538 // return 1 if there is entry in hash
539 // return negative value if error occurred
540 int find_object_hash(void* ptr, unsigned short *caller)
541 {
542         khiter_t k;
543         int ret = 0;
544
545         if (unlikely(OBJECTHASH == 0))
546                 return ERR_NOTINITIALIZED;
547
548         if (unlikely(ptr == NULL))
549                 return ERR_WRONGPARAMETER;
550
551         if (unlikely(caller == NULL))
552                 return ERR_WRONGPARAMETER;
553
554         probeBlockStart();
555
556         OBJECTHASH_LOCK;
557         k = kh_get(object, OBJECTHASH, (uint32_t)ptr);
558         if (unlikely(k == kh_end(OBJECTHASH)))          // there is no entry for key
559         {
560                 ret = 0;
561         }
562         else
563         {
564                 *caller = kh_value(OBJECTHASH, k);
565                 ret = 1;
566         }
567         OBJECTHASH_UNLOCK;
568         probeBlockEnd();
569         return ret;
570 }
571
572 // return 0 if succeed
573 // return 1 if there is no entry in hash
574 // return negative value if other error occurred
575 int add_object_hash(void* ptr, unsigned short caller)
576 {
577         khiter_t k;
578         int rethash, ret = 0;
579
580         if (unlikely(OBJECTHASH == 0))
581                 return ERR_NOTINITIALIZED;
582
583         if (unlikely(ptr == NULL))
584                 return ERR_WRONGPARAMETER;
585
586         probeBlockStart();
587
588         OBJECTHASH_LOCK;
589         k = kh_put(object, OBJECTHASH, (uint32_t)ptr, &rethash);
590         if (likely(rethash != 0))       // entry is already in hash table
591         {
592                 kh_value(OBJECTHASH, k) = caller;
593         }
594         else
595         {
596                 // TODO : error handling
597                 ret = 1;
598         }
599
600         OBJECTHASH_UNLOCK;
601         probeBlockEnd();
602         return ret;
603 }
604
605 // return 0 if succeed
606 // return 1 if key is not in hash table
607 // return negative value if other error occurred
608 int del_object_hash(void* ptr, unsigned short *caller)
609 {
610         khiter_t k;
611         int ret = 0;
612
613         if (unlikely(OBJECTHASH == 0))
614                 return ERR_NOTINITIALIZED;
615
616         if (unlikely(ptr == NULL))
617                 return ERR_WRONGPARAMETER;
618
619         if (unlikely(caller == NULL))
620                 return ERR_WRONGPARAMETER;
621
622         probeBlockStart();
623
624         OBJECTHASH_LOCK;
625         k = kh_get(object, OBJECTHASH, (uint32_t)ptr);
626         if (likely(k != kh_end(OBJECTHASH)))            // there is entry in hash table
627         {
628                 *caller = kh_value(OBJECTHASH, k);
629                 kh_del(object, OBJECTHASH, k);
630         }
631         else
632         {
633                 ret = 1;
634         }
635         OBJECTHASH_UNLOCK;
636         probeBlockEnd();
637
638         return ret;
639 }
640
641 /***********************************************************
642  * detector hash related functions
643  ***********************************************************/
644 // return 0 if succeed
645 // return 1 if there is already exist in hash
646 // return negative value if other error occurred
647 int add_detector_hash(void* ptr, void* listener)
648 {
649         khiter_t k;
650         int rethash, ret = 0;
651
652         if (unlikely(DETECTORHASH == 0))
653                 return ERR_NOTINITIALIZED;
654
655         if (unlikely(ptr == NULL))
656                 return ERR_WRONGPARAMETER;
657
658         if (unlikely(listener == NULL))
659                 return ERR_WRONGPARAMETER;
660
661         probeBlockStart();
662
663         DETECTORHASH_LOCK;
664         k = kh_put(detector, DETECTORHASH, (uint32_t)ptr, &rethash);
665         if (likely(rethash != 0))       // succeed to add in hash table
666         {
667                 kh_value(DETECTORHASH, k) = listener;
668         }
669         else
670         {
671                 // TODO : error handling
672                 ret = 1;
673         }
674         DETECTORHASH_UNLOCK;
675         probeBlockEnd();
676         return ret;
677 }
678
679 // return 0 if succeed
680 // return 1 if key is not in hash table
681 // return negative value if other error occurred
682 int del_detector_hash(void* ptr)
683 {
684         khiter_t k;
685         int ret = 0;
686
687         if (unlikely(DETECTORHASH == 0))
688                 return ERR_NOTINITIALIZED;
689
690         if (unlikely(ptr == NULL))
691                 return ERR_WRONGPARAMETER;
692
693         probeBlockStart();
694         DETECTORHASH_LOCK;
695         k = kh_get(detector, DETECTORHASH, (uint32_t)ptr);
696         if (likely(k != kh_end(DETECTORHASH)))          // there is entry in hash table
697         {
698                 kh_del(detector, DETECTORHASH, k);
699         }
700         else
701         {
702                 ret = 1;
703         }
704         DETECTORHASH_UNLOCK;
705         probeBlockEnd();
706
707         return ret;
708 }
709
710
711 // *********************************************************************************************
712 // glist implemenation
713 // *********************************************************************************************
714
715 // all function to call this function have to use mutex_lock
716 static element_t* find_element(char* key)
717 {
718         element_t* res;
719         int keylen;
720
721         if (unlikely(key == NULL))
722                 return NULL;
723
724         keylen = strlen(key);
725
726 //      pthread_mutex_lock(&glist_mutex);       // this is commented because of static function
727         res = gsymbol_list;
728         while(res != NULL)
729         {
730                 if (keylen == res->keylen && (strcmp(key, res->keystr) == 0))
731                         break;
732                 res = res->next;
733         }
734 //      pthread_mutex_unlock(&glist_mutex);     // this is commented because of static function
735
736         return res;
737 }
738
739 int add_to_glist(char* key, void* data)
740 {
741         element_t* elm;
742         int ret = 0;
743
744         if (unlikely(key == NULL || data == NULL))
745                 return 0;
746
747         pthread_mutex_lock(&glist_mutex);
748         elm = find_element(key);
749         if (elm == NULL)
750         {
751                 elm = (element_t*)real_malloc(sizeof(element_t));
752                 if (likely(elm != NULL))
753                 {
754                         elm->keylen = strlen(key);
755                         elm->keystr = (char*)real_malloc(elm->keylen + 1);
756                         if (likely(elm->keystr != NULL))
757                         {
758                                 memcpy(elm->keystr, key, elm->keylen + 1);
759                                 elm->dataptr = data;
760                                 elm->next = gsymbol_list;
761                                 elm->prev = NULL;
762                                 if (gsymbol_list)
763                                         gsymbol_list->prev = elm;
764                                 gsymbol_list = elm;
765                                 ret = 1;
766                         }
767                         else
768                         {
769                                 free(elm);
770                         }
771                 }
772         }
773         pthread_mutex_unlock(&glist_mutex);
774
775         return ret;
776 }
777
778 int remove_from_glist(char* key)
779 {
780         element_t* elm;
781         int ret = 0;
782
783         pthread_mutex_lock(&glist_mutex);
784         elm = find_element(key);
785         if (elm != NULL)
786         {
787                 if (elm->prev)
788                         elm->prev->next = elm->next;
789                 if (elm->next)
790                         elm->next->prev = elm->prev;
791                 if (gsymbol_list == elm)
792                         gsymbol_list = gsymbol_list->next;
793         }
794         pthread_mutex_unlock(&glist_mutex);
795
796         if (elm != NULL)
797         {
798                 free(elm->dataptr);
799                 free(elm->keystr);
800                 free(elm);
801                 ret = 1;
802         }
803
804         return ret;
805 }
806
807 int remove_all_glist()
808 {
809         element_t* elm;
810
811         pthread_mutex_lock(&glist_mutex);
812         while(gsymbol_list != NULL)
813         {
814                 elm = gsymbol_list;
815                 gsymbol_list = elm->next;
816                 free(elm->dataptr);
817                 free(elm->keystr);
818                 free(elm);
819         }
820         pthread_mutex_unlock(&glist_mutex);
821
822         return 1;
823 }
824
825 void* find_glist(char* key)
826 {
827         element_t* elm;
828
829         pthread_mutex_lock(&glist_mutex);
830         elm = find_element(key);
831         pthread_mutex_unlock(&glist_mutex);
832
833         if (elm)
834                 return elm->dataptr;
835         else
836                 return NULL;
837 }
838