00001 /** @file 00002 00003 A brief file description 00004 00005 @section license License 00006 00007 Licensed to the Apache Software Foundation (ASF) under one 00008 or more contributor license agreements. See the NOTICE file 00009 distributed with this work for additional information 00010 regarding copyright ownership. The ASF licenses this file 00011 to you under the Apache License, Version 2.0 (the 00012 "License"); you may not use this file except in compliance 00013 with the License. You may obtain a copy of the License at 00014 00015 http://www.apache.org/licenses/LICENSE-2.0 00016 00017 Unless required by applicable law or agreed to in writing, software 00018 distributed under the License is distributed on an "AS IS" BASIS, 00019 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 See the License for the specific language governing permissions and 00021 limitations under the License. 00022 */ 00023 00024 #include "ink_config.h" 00025 #include "ink_rwlock.h" 00026 00027 //------------------------------------------------------------------------- 00028 // ink_rwlock_init 00029 //------------------------------------------------------------------------- 00030 00031 int 00032 ink_rwlock_init(ink_rwlock * rw) 00033 { 00034 00035 int result; 00036 00037 if ((result = ink_mutex_init(&rw->rw_mutex, NULL)) != 0) 00038 goto Lerror; 00039 ink_cond_init(&rw->rw_condreaders); 00040 ink_cond_init(&rw->rw_condwriters); 00041 rw->rw_nwaitreaders = 0; 00042 rw->rw_nwaitwriters = 0; 00043 rw->rw_refcount = 0; 00044 rw->rw_magic = RW_MAGIC; 00045 00046 return (0); 00047 00048 Lerror: 00049 return (result); /* an errno value */ 00050 00051 } 00052 00053 //------------------------------------------------------------------------- 00054 // ink_rwlock_destroy 00055 //------------------------------------------------------------------------- 00056 00057 int 00058 ink_rwlock_destroy(ink_rwlock * rw) 00059 { 00060 00061 if (rw->rw_magic != RW_MAGIC) 00062 return (EINVAL); 00063 if (rw->rw_refcount != 0 || rw->rw_nwaitreaders != 0 || rw->rw_nwaitwriters != 0) 00064 return (EBUSY); 00065 00066 ink_mutex_destroy(&rw->rw_mutex); 00067 ink_cond_destroy(&rw->rw_condreaders); 00068 ink_cond_destroy(&rw->rw_condwriters); 00069 rw->rw_magic = 0; 00070 00071 return (0); 00072 } 00073 00074 //------------------------------------------------------------------------- 00075 // ink_rwlock_rdlock 00076 //------------------------------------------------------------------------- 00077 00078 int 00079 ink_rwlock_rdlock(ink_rwlock * rw) 00080 { 00081 00082 int result; 00083 00084 if (rw->rw_magic != RW_MAGIC) 00085 return (EINVAL); 00086 00087 if ((result = ink_mutex_acquire(&rw->rw_mutex)) != 0) 00088 return (result); 00089 00090 /* give preference to waiting writers */ 00091 while (rw->rw_refcount < 0 || rw->rw_nwaitwriters > 0) { 00092 rw->rw_nwaitreaders++; 00093 ink_cond_wait(&rw->rw_condreaders, &rw->rw_mutex); 00094 rw->rw_nwaitreaders--; 00095 } 00096 rw->rw_refcount++; /* another reader has a read lock */ 00097 00098 ink_mutex_release(&rw->rw_mutex); 00099 00100 return (0); 00101 00102 } 00103 00104 //------------------------------------------------------------------------- 00105 // ink_rwlock_wrlock 00106 //------------------------------------------------------------------------- 00107 00108 int 00109 ink_rwlock_wrlock(ink_rwlock * rw) 00110 { 00111 00112 int result; 00113 00114 if (rw->rw_magic != RW_MAGIC) 00115 return (EINVAL); 00116 00117 if ((result = ink_mutex_acquire(&rw->rw_mutex)) != 0) 00118 return (result); 00119 00120 while (rw->rw_refcount != 0) { 00121 rw->rw_nwaitwriters++; 00122 ink_cond_wait(&rw->rw_condwriters, &rw->rw_mutex); 00123 rw->rw_nwaitwriters--; 00124 } 00125 rw->rw_refcount = -1; 00126 00127 ink_mutex_release(&rw->rw_mutex); 00128 00129 return (0); 00130 00131 } 00132 00133 //------------------------------------------------------------------------- 00134 // ink_rwlock_unlock 00135 //------------------------------------------------------------------------- 00136 00137 int 00138 ink_rwlock_unlock(ink_rwlock * rw) 00139 { 00140 00141 int result; 00142 00143 if (rw->rw_magic != RW_MAGIC) 00144 return (EINVAL); 00145 00146 if ((result = ink_mutex_acquire(&rw->rw_mutex)) != 0) 00147 return (result); 00148 00149 if (rw->rw_refcount > 0) 00150 rw->rw_refcount--; /* releasing a reader */ 00151 else if (rw->rw_refcount == -1) 00152 rw->rw_refcount = 0; /* releasing a reader */ 00153 else 00154 ink_release_assert("invalid rw_refcount!"); 00155 00156 /* give preference to waiting writers over waiting readers */ 00157 if (rw->rw_nwaitwriters > 0) { 00158 if (rw->rw_refcount == 0) 00159 ink_cond_signal(&rw->rw_condwriters); 00160 } else if (rw->rw_nwaitreaders > 0) 00161 ink_cond_broadcast(&rw->rw_condreaders); 00162 00163 ink_mutex_release(&rw->rw_mutex); 00164 00165 return (0); 00166 00167 }