- {
- int ret=mh_mode;
-
- CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
- switch (mode)
- {
- /* for applications: */
- case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
- mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
- disabling_thread = 0;
- break;
- case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
- mh_mode = 0;
- disabling_thread = 0;
- break;
-
- /* switch off temporarily (for library-internal use): */
- case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
- if (mh_mode & CRYPTO_MEM_CHECK_ON)
- {
- mh_mode&= ~CRYPTO_MEM_CHECK_ENABLE;
- if (disabling_thread != CRYPTO_thread_id()) /* otherwise we already have the MALLOC2 lock */
- {
- /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
- * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
- * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release it
- * because we block entry to this function).
- * Give them a chance, first, and then claim the locks in
- * appropriate order (long-time lock first).
- */
- CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
- /* Note that after we have waited for CRYPTO_LOCK_MALLOC2
- * and CRYPTO_LOCK_MALLOC, we'll still be in the right
- * "case" and "if" branch because MemCheck_start and
- * MemCheck_stop may never be used while there are multiple
- * OpenSSL threads. */
- CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
- CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
- disabling_thread=CRYPTO_thread_id();
- }
- }
- break;
- case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
- if (mh_mode & CRYPTO_MEM_CHECK_ON)
- {
- mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
- if (disabling_thread != 0)
- {
- disabling_thread=0;
- CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
- }
- }
- break;
-
- default:
- break;
- }
- CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
- return(ret);
- }
-
-int CRYPTO_mem_check_on(void)
- {
- int ret = 0;
-
- if (mh_mode & CRYPTO_MEM_CHECK_ON)
- {
- CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
-
- ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
- && disabling_thread != CRYPTO_thread_id();
-
- CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
- }
- return(ret);
- }
-
-
-void CRYPTO_dbg_set_options(int bits)
- {
- options = bits;
- }
-
-int CRYPTO_dbg_get_options()
- {
- return options;
- }
-
-static int mem_cmp(MEM *a, MEM *b)
- {
- return(a->addr - b->addr);
- }
-
-static unsigned long mem_hash(MEM *a)
- {
- unsigned long ret;
-
- ret=(unsigned long)a->addr;
-
- ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
- return(ret);
- }
-
-static int app_info_cmp(APP_INFO *a, APP_INFO *b)
- {
- return(a->thread - b->thread);
- }
-
-static unsigned long app_info_hash(APP_INFO *a)
- {
- unsigned long ret;
-
- ret=(unsigned long)a->thread;
-
- ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
- return(ret);
- }
-
-static APP_INFO *remove_info()
- {
- APP_INFO tmp;
- APP_INFO *ret = NULL;
-
- if (amih != NULL)
- {
- tmp.thread=CRYPTO_thread_id();
- if ((ret=(APP_INFO *)lh_delete(amih,(char *)&tmp)) != NULL)
- {
- APP_INFO *next=ret->next;
-
- if (next != NULL)
- {
- next->references++;
- lh_insert(amih,(char *)next);
- }
-#ifdef LEVITTE_DEBUG
- if (ret->thread != tmp.thread)
- {
- fprintf(stderr, "remove_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
- ret->thread, tmp.thread);
- abort();
- }
+{
+#ifdef OPENSSL_NO_CRYPTO_MDEBUG
+ return mode - mode;
+#else
+ int ret = mh_mode;
+
+ if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
+ return -1;
+
+ CRYPTO_THREAD_write_lock(memdbg_lock);
+ switch (mode) {
+ default:
+ break;
+
+ case CRYPTO_MEM_CHECK_ON:
+ mh_mode = CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE;
+ num_disable = 0;
+ break;
+
+ case CRYPTO_MEM_CHECK_OFF:
+ mh_mode = 0;
+ num_disable = 0;
+ break;
+
+ /* switch off temporarily (for library-internal use): */
+ case CRYPTO_MEM_CHECK_DISABLE:
+ if (mh_mode & CRYPTO_MEM_CHECK_ON) {
+ CRYPTO_THREAD_ID cur = CRYPTO_THREAD_get_current_id();
+ /* see if we don't have long_memdbg_lock already */
+ if (!num_disable
+ || !CRYPTO_THREAD_compare_id(disabling_threadid, cur)) {
+ /*
+ * Long-time lock long_memdbg_lock must not be claimed
+ * while we're holding memdbg_lock, or we'll deadlock
+ * if somebody else holds long_memdbg_lock (and cannot
+ * release it because we block entry to this function). Give
+ * them a chance, first, and then claim the locks in
+ * appropriate order (long-time lock first).
+ */
+ CRYPTO_THREAD_unlock(memdbg_lock);
+ /*
+ * Note that after we have waited for long_memdbg_lock and
+ * memdbg_lock, we'll still be in the right "case" and
+ * "if" branch because MemCheck_start and MemCheck_stop may
+ * never be used while there are multiple OpenSSL threads.
+ */
+ CRYPTO_THREAD_write_lock(long_memdbg_lock);
+ CRYPTO_THREAD_write_lock(memdbg_lock);
+ mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
+ disabling_threadid = cur;
+ }
+ num_disable++;
+ }
+ break;
+
+ case CRYPTO_MEM_CHECK_ENABLE:
+ if (mh_mode & CRYPTO_MEM_CHECK_ON) {
+ if (num_disable) { /* always true, or something is going wrong */
+ num_disable--;
+ if (num_disable == 0) {
+ mh_mode |= CRYPTO_MEM_CHECK_ENABLE;
+ CRYPTO_THREAD_unlock(long_memdbg_lock);
+ }
+ }
+ }
+ break;
+ }
+ CRYPTO_THREAD_unlock(memdbg_lock);
+ return ret;