mutex.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: mutex.c,v 11.14 2000/11/30 00:58:42 ubell Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #endif
  14. #include "db_int.h"
  15. /*
  16.  * __db_mutex_alloc --
  17.  * Allocate and initialize a mutex.
  18.  *
  19.  * PUBLIC: int __db_mutex_alloc __P((DB_ENV *, REGINFO *, MUTEX **));
  20.  */
  21. int
  22. __db_mutex_alloc(dbenv, infop, storep)
  23. DB_ENV *dbenv;
  24. REGINFO *infop;
  25. MUTEX **storep;
  26. {
  27. int ret;
  28. /*
  29.  * If the architecture supports mutexes in heap memory, use that
  30.  * memory.  If it doesn't, we have to allocate space in a region.
  31.  *
  32.  * XXX
  33.  * There's a nasty starvation issue here for applications running
  34.  * on systems that don't support mutexes in heap memory.  If the
  35.  * normal state of the entire region is dirty (e.g., mpool), then
  36.  * we can run out of memory to allocate for mutexes when new files
  37.  * are opened in the pool.  We're not trying to fix this for now,
  38.  * because the only known system where we can see this failure at
  39.  * the moment is HP-UX 10.XX.
  40.  */
  41. #ifdef MUTEX_NO_MALLOC_LOCKS
  42. R_LOCK(dbenv, infop);
  43. ret = __db_shalloc(infop->addr, sizeof(MUTEX), MUTEX_ALIGN, storep);
  44. R_UNLOCK(dbenv, infop);
  45. #else
  46. COMPQUIET(dbenv, NULL);
  47. COMPQUIET(infop, NULL);
  48. ret = __os_calloc(dbenv, 1, sizeof(MUTEX), storep);
  49. #endif
  50. if (ret != 0)
  51. __db_err(dbenv, "Unable to allocate memory for mutex");
  52. return (ret);
  53. }
  54. /*
  55.  * __db_mutex_free --
  56.  * Free a mutex.
  57.  *
  58.  * PUBLIC: void __db_mutex_free __P((DB_ENV *, REGINFO *, MUTEX *));
  59.  */
  60. void
  61. __db_mutex_free(dbenv, infop, mutexp)
  62. DB_ENV *dbenv;
  63. REGINFO *infop;
  64. MUTEX *mutexp;
  65. {
  66. if (F_ISSET(mutexp, MUTEX_INITED))
  67. __db_mutex_destroy(mutexp);
  68. #ifdef MUTEX_NO_MALLOC_LOCKS
  69. R_LOCK(dbenv, infop);
  70. __db_shalloc_free(infop->addr, mutexp);
  71. R_UNLOCK(dbenv, infop);
  72. #else
  73. COMPQUIET(dbenv, NULL);
  74. COMPQUIET(infop, NULL);
  75. __os_free(mutexp, sizeof(*mutexp));
  76. #endif
  77. }
  78. #ifdef MUTEX_SYSTEM_RESOURCES
  79. /*
  80.  * __db_shreg_locks_record --
  81.  * Record an entry in the shared locks area.
  82.  * Region lock must be held in caller.
  83.  *
  84.  * PUBLIC: int __db_shreg_locks_record __P((DB_ENV *, MUTEX *, REGINFO *,
  85.  * PUBLIC:    REGMAINT *));
  86.  */
  87. int
  88. __db_shreg_locks_record(dbenv, mutexp, infop, rp)
  89. DB_ENV *dbenv;
  90. MUTEX *mutexp;
  91. REGINFO *infop;
  92. REGMAINT *rp;
  93. {
  94. u_int i;
  95. if (!F_ISSET(mutexp, MUTEX_INITED))
  96. return (0);
  97. DB_ASSERT(mutexp->reg_off == INVALID_ROFF);
  98. rp->stat.st_records++;
  99. i = (roff_t *)R_ADDR(infop, rp->regmutex_hint) - &rp->regmutexes[0];
  100. if (rp->regmutexes[i] != INVALID_ROFF) {
  101. /*
  102.  * Our hint failed, search for a open slot.
  103.  */
  104. rp->stat.st_hint_miss++;
  105. for (i = 0; i < rp->reglocks; i++)
  106. if (rp->regmutexes[i] == INVALID_ROFF)
  107. break;
  108. if (i == rp->reglocks) {
  109. rp->stat.st_max_locks++;
  110. __db_err(dbenv,
  111.     "Region mutexes: Exceeded maximum lock slots %lu",
  112.     (u_long)rp->reglocks);
  113. return (ENOMEM);
  114. }
  115. } else
  116. rp->stat.st_hint_hit++;
  117. /*
  118.  * When we get here, i is an empty slot.  Record this
  119.  * mutex, set hint to point to the next slot and we are done.
  120.  */
  121. rp->regmutexes[i] = R_OFFSET(infop, mutexp);
  122. mutexp->reg_off = R_OFFSET(infop, &rp->regmutexes[i]);
  123. rp->regmutex_hint = (i < rp->reglocks - 1) ?
  124.     R_OFFSET(infop, &rp->regmutexes[i+1]) :
  125.     R_OFFSET(infop, &rp->regmutexes[0]);
  126. return (0);
  127. }
  128. /*
  129.  * __db_shreg_locks_clear --
  130.  * Erase an entry in the shared locks area.
  131.  * Region lock must be held in caller.
  132.  *
  133.  * PUBLIC: void __db_shreg_locks_clear __P((MUTEX *, REGINFO *, REGMAINT *));
  134.  */
  135. void
  136. __db_shreg_locks_clear(mutexp, infop, rp)
  137. MUTEX *mutexp;
  138. REGINFO *infop;
  139. REGMAINT *rp;
  140. {
  141. if (!F_ISSET(mutexp, MUTEX_INITED))
  142. return;
  143. /*
  144.  * This function is generally only called on a forcible
  145.  * remove of an environment.  We recorded our index in
  146.  * the mutex.  Find it and clear it.
  147.  */
  148. DB_ASSERT(mutexp->reg_off != INVALID_ROFF);
  149. DB_ASSERT(*(roff_t *)R_ADDR(infop, mutexp->reg_off) == 
  150.     R_OFFSET(infop, mutexp));
  151. *(roff_t *)R_ADDR(infop, mutexp->reg_off) = 0;
  152. rp->regmutex_hint = mutexp->reg_off;
  153. rp->stat.st_clears++;
  154. mutexp->reg_off = INVALID_ROFF;
  155. __db_mutex_destroy(mutexp);
  156. }
  157. /*
  158.  * __db_shreg_locks_destroy --
  159.  * Destroy all mutexes in a region's range.
  160.  *
  161.  * PUBLIC: void __db_shreg_locks_destroy __P((REGINFO *, REGMAINT *));
  162.  */
  163. void
  164. __db_shreg_locks_destroy(infop, rp)
  165. REGINFO *infop;
  166. REGMAINT *rp;
  167. {
  168. u_int32_t i;
  169. /*
  170.  * Go through the list of all mutexes and destroy them.
  171.  */
  172. for (i = 0; i < rp->reglocks; i++)
  173. if (rp->regmutexes[i] != 0) {
  174. rp->stat.st_destroys++;
  175. __db_mutex_destroy((MUTEX *)R_ADDR(infop,
  176.     rp->regmutexes[i]));
  177. }
  178. }
  179. /*
  180.  * __db_shreg_mutex_init --
  181.  * Initialize a shared memory mutex.
  182.  *
  183.  * PUBLIC: int __db_shreg_mutex_init __P((DB_ENV *, MUTEX *, u_int32_t,
  184.  * PUBLIC:    u_int32_t, REGINFO *, REGMAINT *));
  185.  */
  186. int
  187. __db_shreg_mutex_init(dbenv, mutexp, offset, flags, infop, rp)
  188. DB_ENV *dbenv;
  189. MUTEX *mutexp;
  190. u_int32_t offset;
  191. u_int32_t flags;
  192. REGINFO *infop;
  193. REGMAINT *rp;
  194. {
  195. int ret;
  196. if ((ret = __db_mutex_init(dbenv, mutexp, offset, flags)) != 0)
  197. return (ret);
  198. /*
  199.  * !!!
  200.  * Since __db_mutex_init is a macro, we may not be
  201.  * using the 'offset' as it is only used for one type
  202.  * of mutex.  We COMPQUIET it here, after the call above.
  203.  */
  204. COMPQUIET(offset, 0);
  205. if (!F_ISSET(mutexp, MUTEX_THREAD))
  206. ret = __db_shreg_locks_record(dbenv, mutexp, infop, rp);
  207. /*
  208.  * If we couldn't record it and we are returning an error,
  209.  * we need to destroy the mutex we just created.
  210.  */
  211. if (ret)
  212. __db_mutex_destroy(mutexp);
  213. return (ret);
  214. }
  215. /*
  216.  * __db_shreg_maintinit --
  217.  * Initialize a region's maintenance information.
  218.  *
  219.  * PUBLIC: void __db_shreg_maintinit __P((REGINFO *, void *addr, size_t));
  220.  */
  221. void
  222. __db_shreg_maintinit(infop, addr, size)
  223. REGINFO *infop;
  224. void *addr;
  225. size_t size;
  226. {
  227. REGMAINT *rp;
  228. rp = (REGMAINT *)addr;
  229. memset(addr, 0, sizeof(REGMAINT));
  230. rp->reglocks = size / sizeof(roff_t);
  231. rp->regmutex_hint = R_OFFSET(infop, &rp->regmutexes[0]);
  232. }
  233. #endif /* MUTEX_SYSTEM_RESOURCES */