named_locks.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2016, Fairview 5 Engineering, LLC
  5. *
  6. * George Joseph <george.joseph@fairview5.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*! \file
  19. *
  20. * \brief Named Locks
  21. *
  22. * \author George Joseph <george.joseph@fairview5.com>
  23. */
  24. #include "asterisk.h"
  25. ASTERISK_REGISTER_FILE()
  26. #include "asterisk/_private.h"
  27. #include "asterisk/astobj2.h"
  28. #include "asterisk/named_locks.h"
  29. #include "asterisk/utils.h"
  30. struct ao2_container *named_locks;
  31. #define NAMED_LOCKS_BUCKETS 101
  32. struct ast_named_lock {
  33. char key[0];
  34. };
  35. AO2_STRING_FIELD_HASH_FN(ast_named_lock, key)
  36. AO2_STRING_FIELD_CMP_FN(ast_named_lock, key)
  37. static void named_locks_shutdown(void)
  38. {
  39. ao2_cleanup(named_locks);
  40. }
  41. int ast_named_locks_init(void)
  42. {
  43. named_locks = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0,
  44. NAMED_LOCKS_BUCKETS, ast_named_lock_hash_fn, NULL, ast_named_lock_cmp_fn);
  45. if (!named_locks) {
  46. return -1;
  47. }
  48. ast_register_cleanup(named_locks_shutdown);
  49. return 0;
  50. }
  51. struct ast_named_lock *__ast_named_lock_get(const char *filename, int lineno, const char *func,
  52. enum ast_named_lock_type lock_type, const char *keyspace, const char *key)
  53. {
  54. struct ast_named_lock *lock = NULL;
  55. int concat_key_buff_len = strlen(keyspace) + strlen(key) + 2;
  56. char *concat_key = ast_alloca(concat_key_buff_len);
  57. sprintf(concat_key, "%s-%s", keyspace, key); /* Safe */
  58. ao2_lock(named_locks);
  59. lock = ao2_find(named_locks, concat_key, OBJ_SEARCH_KEY | OBJ_NOLOCK);
  60. if (lock) {
  61. ao2_unlock(named_locks);
  62. ast_assert((ao2_options_get(lock) & AO2_ALLOC_OPT_LOCK_MASK) == lock_type);
  63. return lock;
  64. }
  65. lock = ao2_alloc_options(sizeof(*lock) + concat_key_buff_len, NULL, lock_type);
  66. if (lock) {
  67. strcpy(lock->key, concat_key); /* Safe */
  68. ao2_link_flags(named_locks, lock, OBJ_NOLOCK);
  69. }
  70. ao2_unlock(named_locks);
  71. return lock;
  72. }
  73. int __ast_named_lock_put(const char *filename, int lineno, const char *func,
  74. struct ast_named_lock *lock)
  75. {
  76. if (!lock) {
  77. return -1;
  78. }
  79. ao2_lock(named_locks);
  80. if (ao2_ref(lock, -1) == 2) {
  81. ao2_unlink_flags(named_locks, lock, OBJ_NOLOCK);
  82. }
  83. ao2_unlock(named_locks);
  84. return 0;
  85. }