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

MySQL数据库

开发平台:

Visual C++

  1. /* ==== cond.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 : Condition variable functions.
  33.  *
  34.  *  1.00 93/10/28 proven
  35.  *      -Started coding this file.
  36.  */
  37. #ifndef lint
  38. static const char rcsid[] = "$Id$";
  39. #endif
  40. #include <pthread.h>
  41. #include <sys/time.h>
  42. #include <stdlib.h>
  43. #include <timers.h>
  44. #include <errno.h>
  45. #ifndef ETIME
  46. #define ETIME ETIMEDOUT  
  47. #endif
  48. /* ==========================================================================
  49.  * pthread_cond_is_debug()
  50.  *
  51.  * Check that cond is a debug cond and if so returns entry number into
  52.  * array of debug condes.
  53.  */
  54. static int pthread_cond_debug_count = 0;
  55. static pthread_cond_t ** pthread_cond_debug_ptrs = NULL;
  56. static pthread_mutex_t pthread_cond_debug_mutex = PTHREAD_MUTEX_INITIALIZER;
  57. static inline int pthread_cond_is_debug(pthread_cond_t * cond) 
  58. {
  59. int i;
  60. for (i = 0; i < pthread_cond_debug_count; i++) {
  61. if (pthread_cond_debug_ptrs[i] == cond) {
  62. return(i);
  63. }
  64. }
  65. return(NOTOK);
  66. }
  67. /* ==========================================================================
  68.  * pthread_cond_init()
  69.  *
  70.  * In this implementation I don't need to allocate memory.
  71.  * ENOMEM, EAGAIN should never be returned. Arch that have
  72.  * weird constraints may need special coding.
  73.  */
  74. int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
  75. {
  76. enum pthread_condtype type;
  77. /* Only check if attr specifies some mutex type other than fast */
  78. if ((cond_attr) && (cond_attr->c_type != COND_TYPE_FAST)) {
  79. if (cond_attr->c_type >= COND_TYPE_MAX) {
  80. return(EINVAL);
  81. }
  82. type = cond_attr->c_type;
  83. } else {
  84. type = COND_TYPE_FAST;
  85. }
  86. switch (type) {
  87. case COND_TYPE_FAST:
  88. case COND_TYPE_COUNTING_FAST: 
  89. break;
  90. case COND_TYPE_DEBUG:
  91. pthread_mutex_lock(&pthread_cond_debug_mutex);
  92. if (pthread_cond_is_debug(cond) == NOTOK) {
  93. pthread_cond_t ** new;
  94. if ((new = (pthread_cond_t **)realloc(pthread_cond_debug_ptrs,
  95.   (pthread_cond_debug_count + 1) * (sizeof(void *)))) == NULL) {
  96. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  97. return(ENOMEM);
  98. }
  99. pthread_cond_debug_ptrs = new;
  100. pthread_cond_debug_ptrs[pthread_cond_debug_count++] = cond;
  101. } else {
  102. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  103. return(EBUSY);
  104. }
  105. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  106.         break;
  107.     case COND_TYPE_STATIC_FAST:
  108. defualt:
  109.         return(EINVAL);
  110.         break;
  111. }
  112. /* Set all other paramaters */
  113. pthread_queue_init(&cond->c_queue);
  114. cond->c_flags  |= COND_FLAGS_INITED;
  115. cond->c_type  = type;
  116. return(OK);
  117. }
  118. /* ==========================================================================
  119.  * pthread_cond_destroy()
  120.  */
  121. int pthread_cond_destroy(pthread_cond_t *cond)
  122. {
  123. int i;
  124. /* Only check if cond is of type other than fast */
  125. switch(cond->c_type) {
  126. case COND_TYPE_FAST:
  127. case COND_TYPE_COUNTING_FAST: 
  128. break;
  129.     case COND_TYPE_DEBUG:
  130.         if (pthread_queue_get(&(cond->c_queue))) {
  131.             return(EBUSY);
  132.         }
  133. pthread_mutex_lock(&pthread_cond_debug_mutex);
  134. if ((i = pthread_cond_is_debug(cond)) == NOTOK) {
  135. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  136.             return(EINVAL);
  137.         }
  138. /* Remove the cond from the list of debug condition variables */
  139. pthread_cond_debug_ptrs[i] = 
  140.   pthread_cond_debug_ptrs[--pthread_cond_debug_count];
  141. pthread_cond_debug_ptrs[pthread_cond_debug_count] = NULL;
  142. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  143.         break;
  144. case COND_TYPE_STATIC_FAST:
  145. default:
  146. return(EINVAL);
  147. break;
  148. }
  149. /* Cleanup cond, others might want to use it. */
  150. pthread_queue_init(&cond->c_queue);
  151. cond->c_flags = 0;
  152. return(OK);
  153. }
  154. /* ==========================================================================
  155.  * pthread_cond_wait()
  156.  */
  157. int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
  158. {
  159. int rval;
  160. pthread_sched_prevent();
  161. switch (cond->c_type) {
  162. case COND_TYPE_DEBUG: 
  163. pthread_mutex_lock(&pthread_cond_debug_mutex);
  164. if (pthread_cond_is_debug(cond) == NOTOK) {
  165. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  166. pthread_sched_resume();
  167. return(EINVAL);
  168. }
  169. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  170. /*
  171.  * Fast condition variables do not check for any error conditions.
  172.      */
  173. case COND_TYPE_FAST: 
  174. case COND_TYPE_STATIC_FAST:
  175. pthread_queue_enq(&cond->c_queue, pthread_run);
  176. pthread_mutex_unlock(mutex);
  177. pthread_run->data.mutex = mutex;
  178. SET_PF_WAIT_EVENT(pthread_run);
  179. SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
  180. /* Reschedule will unlock pthread_run */
  181. pthread_resched_resume(PS_COND_WAIT);
  182. CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
  183. CLEAR_PF_DONE_EVENT(pthread_run);
  184. pthread_run->data.mutex = NULL;
  185. rval = pthread_mutex_lock(mutex);
  186. return(rval);
  187. break;
  188. case COND_TYPE_COUNTING_FAST: 
  189. {
  190. int count = mutex->m_data.m_count;
  191. pthread_queue_enq(&cond->c_queue, pthread_run);
  192. pthread_mutex_unlock(mutex);
  193. mutex->m_data.m_count = 1;
  194. pthread_run->data.mutex = mutex;
  195. SET_PF_WAIT_EVENT(pthread_run);
  196. SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
  197. /* Reschedule will unlock pthread_run */
  198. pthread_resched_resume(PS_COND_WAIT);
  199. CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
  200. CLEAR_PF_DONE_EVENT(pthread_run);
  201. pthread_run->data.mutex = NULL;
  202. rval = pthread_mutex_lock(mutex);
  203. mutex->m_data.m_count = count;
  204. return(rval);
  205. break;
  206. }
  207. default:
  208. rval = EINVAL;
  209. break;
  210. }
  211. pthread_sched_resume();
  212. return(rval);
  213. }
  214. /* ==========================================================================
  215.  * pthread_cond_timedwait()
  216.  */
  217. int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
  218.   const struct timespec * abstime)
  219. {
  220. struct timespec current_time, new_time;
  221. int rval = OK;
  222. pthread_sched_prevent();
  223. machdep_gettimeofday(& current_time);
  224. switch (cond->c_type) {
  225. case COND_TYPE_DEBUG: 
  226. pthread_mutex_lock(&pthread_cond_debug_mutex);
  227. if (pthread_cond_is_debug(cond) == NOTOK) {
  228. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  229. pthread_sched_resume();
  230. return(EINVAL);
  231. }
  232. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  233. /*
  234.  * Fast condition variables do not check for any error conditions.
  235.      */
  236. case COND_TYPE_FAST: 
  237. case COND_TYPE_STATIC_FAST:
  238. /* Set pthread wakeup time*/
  239. pthread_run->wakeup_time = *abstime;
  240. /* Install us on the sleep queue */
  241. sleep_schedule (&current_time, &(pthread_run->wakeup_time));
  242. pthread_queue_enq(&cond->c_queue, pthread_run);
  243. SET_PF_WAIT_EVENT(pthread_run);
  244. pthread_mutex_unlock(mutex);
  245. pthread_run->data.mutex = mutex;
  246. SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
  247. /* Reschedule will unlock pthread_run */
  248. pthread_resched_resume(PS_COND_WAIT);
  249. CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
  250. pthread_run->data.mutex = NULL;
  251. /* Remove ourselves from sleep queue. If we fail then we timedout */
  252.         if (sleep_cancel(pthread_run) == NOTOK) {
  253. SET_ERRNO(ETIME);
  254. rval = ETIME;
  255. }
  256. CLEAR_PF_DONE_EVENT(pthread_run);
  257. pthread_mutex_lock(mutex);
  258. return(rval);
  259. break;
  260. case COND_TYPE_COUNTING_FAST: 
  261. {
  262. int count = mutex->m_data.m_count;
  263. /* Set pthread wakeup time*/
  264. pthread_run->wakeup_time = *abstime;
  265. /* Install us on the sleep queue */
  266. sleep_schedule (&current_time, &(pthread_run->wakeup_time));
  267. pthread_queue_enq(&cond->c_queue, pthread_run);
  268. SET_PF_WAIT_EVENT(pthread_run);
  269. pthread_mutex_unlock(mutex);
  270. pthread_run->data.mutex = mutex;
  271. SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
  272. /* Reschedule will unlock pthread_run */
  273. pthread_resched_resume(PS_COND_WAIT);
  274. CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
  275. pthread_run->data.mutex = NULL;
  276. /* Remove ourselves from sleep queue. If we fail then we timedout */
  277.         if (sleep_cancel(pthread_run) == NOTOK) {
  278. SET_ERRNO(ETIME);
  279. rval = ETIME;
  280. }
  281. CLEAR_PF_DONE_EVENT(pthread_run);
  282. pthread_mutex_lock(mutex);
  283. mutex->m_data.m_count = count;
  284. return(rval);
  285. break;
  286. }
  287. default:
  288. rval = EINVAL;
  289. break;
  290. }
  291. pthread_sched_resume();
  292. return(rval);
  293. }
  294. /* ==========================================================================
  295.  * pthread_cond_signal()
  296.  */
  297. int pthread_cond_signal(pthread_cond_t *cond)
  298. {
  299. struct pthread *pthread;
  300. int rval;
  301. pthread_sched_prevent();
  302. switch (cond->c_type) {
  303. case COND_TYPE_DEBUG: 
  304. pthread_mutex_lock(&pthread_cond_debug_mutex);
  305. if (pthread_cond_is_debug(cond) == NOTOK) {
  306. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  307. pthread_sched_resume();
  308. return(EINVAL);
  309. }
  310. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  311. case COND_TYPE_FAST: 
  312. case COND_TYPE_STATIC_FAST:
  313. if (pthread = pthread_queue_deq(&cond->c_queue)) {
  314.   if ((SET_PF_DONE_EVENT(pthread)) == OK) {
  315. pthread_sched_other_resume(pthread);
  316. } else {
  317. pthread_sched_resume();
  318. }
  319. return(OK);
  320. }
  321. rval = OK;
  322. break;
  323. default:
  324. rval = EINVAL;
  325. break;
  326. }
  327. pthread_sched_resume();
  328. return(rval);
  329. }
  330. /* ==========================================================================
  331.  * pthread_cond_broadcast() 
  332.  *
  333.  * Not much different then the above routine.
  334.  */
  335. int pthread_cond_broadcast(pthread_cond_t *cond)
  336. {
  337. struct pthread * pthread, * high_pthread, * low_pthread;
  338. int rval;
  339. pthread_sched_prevent();
  340. switch (cond->c_type) {
  341. case COND_TYPE_DEBUG: 
  342. pthread_mutex_lock(&pthread_cond_debug_mutex);
  343. if (pthread_cond_is_debug(cond) == NOTOK) {
  344. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  345. pthread_sched_resume();
  346. return(EINVAL);
  347. }
  348. pthread_mutex_unlock(&pthread_cond_debug_mutex);
  349. case COND_TYPE_FAST: 
  350. case COND_TYPE_STATIC_FAST:
  351. if (pthread = pthread_queue_deq(&cond->c_queue)) {
  352. pthread->state = PS_RUNNING;
  353. high_pthread = pthread;
  354. while (pthread = pthread_queue_deq(&cond->c_queue)) {
  355. if (pthread->pthread_priority > 
  356.   high_pthread->pthread_priority) {
  357. low_pthread = high_pthread;
  358. high_pthread = pthread;
  359. } else {
  360. low_pthread = pthread;
  361. }
  362.   if ((SET_PF_DONE_EVENT(low_pthread)) == OK) {
  363. pthread_prio_queue_enq(pthread_current_prio_queue, 
  364.   low_pthread);
  365. low_pthread->state = PS_RUNNING;
  366. }
  367. }
  368.   if ((SET_PF_DONE_EVENT(high_pthread)) == OK) {
  369. pthread_sched_other_resume(high_pthread);
  370. } else {
  371. pthread_sched_resume();
  372. }
  373. return(OK);
  374. }
  375. rval = OK;
  376. break;
  377. default:
  378. rval = EINVAL;
  379. break;
  380. }
  381. pthread_sched_resume();
  382. return(rval);
  383. }