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

MySQL数据库

开发平台:

Visual C++

  1. /* ==== mutex.c ==============================================================
  2.  * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *  This product includes software developed by Chris Provenzano.
  16.  * 4. The name of Chris Provenzano may not be used to endorse or promote 
  17.  *   products derived from this software without specific prior written
  18.  *   permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND
  21.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED.  IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY 
  24.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  25.  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  26.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  27.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  28.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  30.  * SUCH DAMAGE.
  31.  *
  32.  * Description : Mutex functions.
  33.  *
  34.  *  1.00 93/07/19 proven
  35.  *      -Started coding this file.
  36.  */
  37. #ifndef lint
  38. static const char rcsid[] = "$Id$";
  39. #endif
  40. #include <pthread.h>
  41. #include <stdlib.h>
  42. #include <errno.h>
  43. /* ==========================================================================
  44.  * pthread_mutex_is_debug()
  45.  *
  46.  * Check that mutex is a debug mutex and if so returns entry number into
  47.  * array of debug mutexes.
  48.  */
  49. static int pthread_mutex_debug_count = 0;
  50. static pthread_mutex_t ** pthread_mutex_debug_ptrs = NULL;
  51. static inline int pthread_mutex_is_debug(pthread_mutex_t * mutex) 
  52. {
  53. int i;
  54. for (i = 0; i < pthread_mutex_debug_count; i++) {
  55. if (pthread_mutex_debug_ptrs[i] == mutex) {
  56. return(i);
  57. }
  58. }
  59. return(NOTOK);
  60. }
  61. /* ==========================================================================
  62.  * pthread_mutex_init()
  63.  *
  64.  * In this implementation I don't need to allocate memory.
  65.  * ENOMEM, EAGAIN should never be returned. Arch that have
  66.  * weird constraints may need special coding.
  67.  */
  68. int pthread_mutex_init(pthread_mutex_t *mutex, 
  69.   const pthread_mutexattr_t *mutex_attr)
  70. {
  71. enum pthread_mutextype type;
  72. /* Only check if attr specifies some mutex type other than fast */
  73. if ((mutex_attr) && (mutex_attr->m_type != MUTEX_TYPE_FAST)) {
  74. if (mutex_attr->m_type >= MUTEX_TYPE_MAX) {
  75. return(EINVAL);
  76. }
  77. type = mutex_attr->m_type;
  78. } else {
  79. type = MUTEX_TYPE_FAST;
  80. }
  81. mutex->m_flags = 0;
  82. pthread_sched_prevent();
  83. switch(type) {
  84.     case MUTEX_TYPE_FAST:
  85.         break;
  86.     case MUTEX_TYPE_STATIC_FAST:
  87. pthread_sched_resume();
  88.         return(EINVAL);
  89.         break;
  90. case MUTEX_TYPE_COUNTING_FAST:
  91. mutex->m_data.m_count = 0;
  92.         break;
  93.     case MUTEX_TYPE_DEBUG:
  94. if (pthread_mutex_is_debug(mutex) == NOTOK) {
  95. pthread_mutex_t ** new;
  96. if ((new = (pthread_mutex_t **)realloc(pthread_mutex_debug_ptrs,
  97.   (pthread_mutex_debug_count + 1) * (sizeof(void *)))) == NULL) {
  98. pthread_sched_resume();
  99. return(ENOMEM);
  100. }
  101. pthread_mutex_debug_ptrs = new;
  102. pthread_mutex_debug_ptrs[pthread_mutex_debug_count++] = mutex;
  103. } else {
  104. pthread_sched_resume();
  105.             return(EBUSY);
  106.         }
  107.         break;
  108.     default:
  109. pthread_sched_resume();
  110.         return(EINVAL);
  111. break;
  112. }
  113. /* Set all other paramaters */
  114. pthread_queue_init(&mutex->m_queue);
  115. mutex->m_flags  |= MUTEX_FLAGS_INITED;
  116. mutex->m_owner = NULL;
  117. mutex->m_type = type;
  118. pthread_sched_resume();
  119. return(OK);
  120. }
  121. /* ==========================================================================
  122.  * pthread_mutex_destroy()
  123.  */
  124. int pthread_mutex_destroy(pthread_mutex_t *mutex)
  125. {
  126. int i;
  127. pthread_sched_prevent();
  128. /* Only check if mutex is of type other than fast */
  129. switch(mutex->m_type) {
  130. case MUTEX_TYPE_FAST:
  131. break;
  132. case MUTEX_TYPE_STATIC_FAST:
  133. pthread_sched_resume();
  134. return(EINVAL);
  135. break;
  136. case MUTEX_TYPE_COUNTING_FAST:
  137. mutex->m_data.m_count = 0;
  138. break;
  139. case MUTEX_TYPE_DEBUG:
  140. if ((i = pthread_mutex_is_debug(mutex)) == NOTOK) {
  141. pthread_sched_resume();
  142.             return(EINVAL);
  143.         }
  144.         if (mutex->m_owner) {
  145. pthread_sched_resume();
  146.             return(EBUSY);
  147.         }
  148. /* Remove the mutex from the list of debug mutexes */
  149. pthread_mutex_debug_ptrs[i] = 
  150.   pthread_mutex_debug_ptrs[--pthread_mutex_debug_count];
  151. pthread_mutex_debug_ptrs[pthread_mutex_debug_count] = NULL;
  152.         break;
  153. default:
  154. pthread_sched_resume();
  155. return(EINVAL);
  156. break;
  157. }
  158. /* Cleanup mutex, others might want to use it. */
  159. pthread_queue_init(&mutex->m_queue);
  160. mutex->m_owner = NULL;
  161. mutex->m_flags = 0;
  162. pthread_sched_resume();
  163. return(OK);
  164. }
  165. /* ==========================================================================
  166.  * pthread_mutex_trylock()
  167.  */
  168. int pthread_mutex_trylock(pthread_mutex_t *mutex)
  169. {
  170. int rval;
  171. pthread_sched_prevent();
  172. switch (mutex->m_type) {
  173. /*
  174.  * Fast mutexes do not check for any error conditions.
  175.      */
  176. case MUTEX_TYPE_FAST: 
  177. case MUTEX_TYPE_STATIC_FAST:
  178. if (!mutex->m_owner) {
  179. mutex->m_owner = pthread_run;
  180. rval = OK;
  181. } else {
  182. rval = EBUSY;
  183. }
  184. break;
  185. case MUTEX_TYPE_COUNTING_FAST:
  186. if (mutex->m_owner) {
  187. if (mutex->m_owner == pthread_run) {
  188. mutex->m_data.m_count++;
  189. rval = OK;
  190. } else {
  191. rval = EBUSY;
  192. }
  193. } else {
  194. mutex->m_owner = pthread_run;
  195. rval = OK;
  196. }
  197. break;
  198. case MUTEX_TYPE_DEBUG:
  199.         if (pthread_mutex_is_debug(mutex) != NOTOK) {
  200.             if (!mutex->m_owner) {
  201.                 mutex->m_owner = pthread_run;
  202.                 rval = OK;
  203.             } else {
  204.                 rval = EBUSY;
  205.             }
  206.         } else {
  207.             rval = EINVAL;
  208.         }
  209.         break;
  210. default:
  211. rval = EINVAL;
  212. break;
  213. }
  214. pthread_sched_resume();
  215. return(rval);
  216. }
  217. /* ==========================================================================
  218.  * pthread_mutex_lock()
  219.  */
  220. int pthread_mutex_lock(pthread_mutex_t *mutex)
  221. {
  222. int rval;
  223. pthread_sched_prevent();
  224. switch (mutex->m_type) {
  225. /*
  226.  * Fast mutexes do not check for any error conditions.
  227.      */
  228. case MUTEX_TYPE_FAST: 
  229. case MUTEX_TYPE_STATIC_FAST:
  230. if (mutex->m_owner) {
  231. pthread_queue_enq(&mutex->m_queue, pthread_run);
  232. /* Reschedule will unlock scheduler */
  233. pthread_resched_resume(PS_MUTEX_WAIT);
  234. return(OK);
  235. }
  236. mutex->m_owner = pthread_run;
  237. rval = OK;
  238. break;
  239. case MUTEX_TYPE_COUNTING_FAST:
  240. if (mutex->m_owner) {
  241. if (mutex->m_owner != pthread_run) {
  242. pthread_queue_enq(&mutex->m_queue, pthread_run);
  243. /* Reschedule will unlock scheduler */
  244. pthread_resched_resume(PS_MUTEX_WAIT);
  245. return(OK);
  246. } else {
  247. mutex->m_data.m_count++;
  248. }
  249. } else {
  250. mutex->m_owner = pthread_run;
  251. }
  252. rval = OK;
  253. break;
  254.     case MUTEX_TYPE_DEBUG:
  255.         if (pthread_mutex_is_debug(mutex) != NOTOK) {
  256.             if (mutex->m_owner) {
  257.                 if (mutex->m_owner != pthread_run) {
  258.                     pthread_queue_enq(&mutex->m_queue, pthread_run);
  259.                     /* Reschedule will unlock pthread_run */
  260. pthread_resched_resume(PS_MUTEX_WAIT);
  261.                     if (mutex->m_owner != pthread_run) {
  262.                         PANIC();
  263.                     }
  264.                     return(OK);
  265.                 }
  266.                 rval = EDEADLK;
  267.                 break;
  268.             }
  269.             mutex->m_owner = pthread_run;
  270.             rval = OK;
  271.             break;
  272.         }
  273.         rval = EINVAL;
  274.         break;
  275. default:
  276. rval = EINVAL;
  277. break;
  278. }
  279. pthread_sched_resume();
  280. return(rval);
  281. }
  282. /* ==========================================================================
  283.  * pthread_mutex_unlock()
  284.  */
  285. int pthread_mutex_unlock(pthread_mutex_t *mutex)
  286. {
  287. struct pthread *pthread;
  288. int rval;
  289. pthread_sched_prevent();
  290. switch (mutex->m_type) {
  291.     /*
  292.      * Fast mutexes do not check for any error conditions.
  293.      */
  294.     case MUTEX_TYPE_FAST:
  295.     case MUTEX_TYPE_STATIC_FAST:
  296. if (mutex->m_owner = pthread_queue_deq(&mutex->m_queue)) {
  297. /* Reschedule will unlock scheduler */
  298. pthread_sched_other_resume(mutex->m_owner);
  299. return(OK);
  300. }
  301. rval = OK;
  302. break;
  303. case MUTEX_TYPE_COUNTING_FAST:
  304. if (mutex->m_data.m_count) {
  305. mutex->m_data.m_count--;
  306. rval = OK;
  307. break;
  308. }
  309. if (mutex->m_owner = pthread_queue_deq(&mutex->m_queue)) {
  310. /* Reschedule will unlock scheduler */
  311. pthread_sched_other_resume(mutex->m_owner);
  312. return(OK);
  313. }
  314. rval = OK;
  315. break;
  316.  case MUTEX_TYPE_DEBUG:
  317. if (pthread_mutex_is_debug(mutex) != NOTOK) {
  318.          if (mutex->m_owner == pthread_run) {
  319.              if (mutex->m_owner = pthread_queue_deq(&mutex->m_queue)) {
  320. /* Reschedule will unlock scheduler */
  321. pthread_sched_other_resume(mutex->m_owner);
  322. return(OK);
  323.              }
  324.              rval = OK;
  325.          } else {
  326.              rval = EPERM;
  327.          }
  328. } else {
  329. rval = EINVAL;
  330. }
  331.         break;
  332. default:
  333. rval = EINVAL;
  334. break;
  335. }
  336. pthread_sched_resume();
  337. return(rval);
  338. }