shm_regex.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2009 iptelorg GmbH
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. *
  27. * History
  28. * -------
  29. * 2009-04-03 Initial version (Miklos)
  30. * 2010-04-25 Use own struct with locking to work-around libc locking failure
  31. * on multi-core hw (skeller)
  32. */
  33. #include <malloc.h> /* hook prototypes */
  34. #include "../../mem/shm_mem.h"
  35. #include "shm_regex.h"
  36. typedef void *(malloc_hook_t) (size_t, const void *);
  37. typedef void *(realloc_hook_t) (void *, size_t, const void *);
  38. typedef void (free_hook_t) (void *, const void *);
  39. /* The memory hooks are overwritten before calling regcomp(), regfree(),
  40. * and regexec(), and shared memory function are called
  41. * from the hooks instead of libc malloc/realloc/free.
  42. */
  43. static void *shm_malloc_hook(size_t size, const void *caller)
  44. {
  45. return shm_malloc (size);
  46. }
  47. static void *shm_realloc_hook(void *p, size_t size, const void *caller)
  48. {
  49. return shm_realloc (p, size);
  50. }
  51. static void shm_free_hook(void *ptr, const void *caller)
  52. {
  53. if (ptr) shm_free (ptr);
  54. }
  55. #define replace_malloc_hooks() \
  56. do { \
  57. orig_malloc_hook = __malloc_hook; \
  58. orig_realloc_hook = __realloc_hook; \
  59. orig_free_hook = __free_hook; \
  60. __malloc_hook = shm_malloc_hook; \
  61. __realloc_hook = shm_realloc_hook; \
  62. __free_hook = shm_free_hook; \
  63. } while (0)
  64. #define restore_malloc_hooks() \
  65. do { \
  66. __malloc_hook = orig_malloc_hook; \
  67. __realloc_hook = orig_realloc_hook; \
  68. __free_hook = orig_free_hook; \
  69. } while (0)
  70. int shm_regcomp(shm_regex_t *preg, const char *regex, int cflags)
  71. {
  72. malloc_hook_t *orig_malloc_hook;
  73. realloc_hook_t *orig_realloc_hook;
  74. free_hook_t *orig_free_hook;
  75. int ret;
  76. if(!lock_init(&preg->lock)) {
  77. return REG_EEND;
  78. }
  79. replace_malloc_hooks();
  80. ret = regcomp(&preg->regexp, regex, cflags);
  81. restore_malloc_hooks();
  82. if(ret) lock_destroy(&preg->lock);
  83. return ret;
  84. }
  85. void shm_regfree(shm_regex_t *preg)
  86. {
  87. malloc_hook_t *orig_malloc_hook;
  88. realloc_hook_t *orig_realloc_hook;
  89. free_hook_t *orig_free_hook;
  90. lock_destroy(&preg->lock);
  91. replace_malloc_hooks();
  92. regfree(&preg->regexp);
  93. restore_malloc_hooks();
  94. }
  95. int shm_regexec(shm_regex_t *preg, const char *string, size_t nmatch,
  96. regmatch_t pmatch[], int eflags)
  97. {
  98. malloc_hook_t *orig_malloc_hook;
  99. realloc_hook_t *orig_realloc_hook;
  100. free_hook_t *orig_free_hook;
  101. int ret;
  102. /* regexec() allocates some memory for the pattern buffer
  103. * when it is successfully called for the first time, therefore
  104. * shared memory is required also here.
  105. * The drawback is that shared memory allocation is also used
  106. * needlessly for allocating the temporary space for
  107. * the elements of pmatch. -- Does not happen if pmatch and
  108. * nmatch are 0.
  109. * It is safe to call regexec() concurrently without locking,
  110. * because regexec() has its own locks.
  111. * (Miklos)
  112. *
  113. * Those locks, however, don't work with shm and multi-core hardware
  114. * causing a dead-lock. Tested with glibc 2.3.6. (skeller)
  115. */
  116. lock_get(&preg->lock);
  117. replace_malloc_hooks();
  118. ret = regexec(&preg->regexp, string, nmatch,
  119. pmatch, eflags);
  120. restore_malloc_hooks();
  121. lock_release(&preg->lock);
  122. return ret;
  123. }
  124. size_t shm_regerror(int errcode, const shm_regex_t *preg, char *errbuf,
  125. size_t errbuf_size)
  126. {
  127. return regerror(errcode, &preg->regexp, errbuf, errbuf_size);
  128. }