1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2010-10-26 Bernard the first version 9 */ 10 11 #include <rtthread.h> 12 #include "pthread.h" 13 14 #define MUTEXATTR_SHARED_MASK 0x0010 15 #define MUTEXATTR_TYPE_MASK 0x000f 16 17 const pthread_mutexattr_t pthread_default_mutexattr = PTHREAD_PROCESS_PRIVATE; 18 19 int pthread_mutexattr_init(pthread_mutexattr_t *attr) 20 { 21 if (attr) 22 { 23 *attr = pthread_default_mutexattr; 24 25 return 0; 26 } 27 28 return EINVAL; 29 } 30 RTM_EXPORT(pthread_mutexattr_init); 31 32 int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) 33 { 34 if (attr) 35 { 36 *attr = -1; 37 38 return 0; 39 } 40 41 return EINVAL; 42 } 43 RTM_EXPORT(pthread_mutexattr_destroy); 44 45 int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) 46 { 47 if (attr && type) 48 { 49 int atype = (*attr & MUTEXATTR_TYPE_MASK); 50 51 if (atype >= PTHREAD_MUTEX_NORMAL && atype <= PTHREAD_MUTEX_ERRORCHECK) 52 { 53 *type = atype; 54 55 return 0; 56 } 57 } 58 59 return EINVAL; 60 } 61 RTM_EXPORT(pthread_mutexattr_gettype); 62 63 int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) 64 { 65 if (attr && type >= PTHREAD_MUTEX_NORMAL && type <= PTHREAD_MUTEX_ERRORCHECK) 66 { 67 *attr = (*attr & ~MUTEXATTR_TYPE_MASK) | type; 68 69 return 0; 70 } 71 72 return EINVAL; 73 } 74 RTM_EXPORT(pthread_mutexattr_settype); 75 76 int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) 77 { 78 if (!attr) 79 return EINVAL; 80 81 switch (pshared) 82 { 83 case PTHREAD_PROCESS_PRIVATE: 84 *attr &= ~MUTEXATTR_SHARED_MASK; 85 return 0; 86 87 case PTHREAD_PROCESS_SHARED: 88 *attr |= MUTEXATTR_SHARED_MASK; 89 return 0; 90 } 91 92 return EINVAL; 93 } 94 RTM_EXPORT(pthread_mutexattr_setpshared); 95 96 int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared) 97 { 98 if (!attr || !pshared) 99 return EINVAL; 100 101 *pshared = (*attr & MUTEXATTR_SHARED_MASK) ? PTHREAD_PROCESS_SHARED 102 : PTHREAD_PROCESS_PRIVATE; 103 return 0; 104 } 105 RTM_EXPORT(pthread_mutexattr_getpshared); 106 107 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) 108 { 109 rt_err_t result; 110 char name[RT_NAME_MAX]; 111 static rt_uint16_t pthread_mutex_number = 0; 112 113 if (!mutex) 114 return EINVAL; 115 116 /* build mutex name */ 117 rt_snprintf(name, sizeof(name), "pmtx%02d", pthread_mutex_number ++); 118 if (attr == RT_NULL) 119 mutex->attr = pthread_default_mutexattr; 120 else 121 mutex->attr = *attr; 122 123 /* init mutex lock */ 124 result = rt_mutex_init(&(mutex->lock), name, RT_IPC_FLAG_FIFO); 125 if (result != RT_EOK) 126 return EINVAL; 127 128 /* detach the object from system object container */ 129 rt_object_detach(&(mutex->lock.parent.parent)); 130 mutex->lock.parent.parent.type = RT_Object_Class_Mutex; 131 132 return 0; 133 } 134 RTM_EXPORT(pthread_mutex_init); 135 136 int pthread_mutex_destroy(pthread_mutex_t *mutex) 137 { 138 if (!mutex || mutex->attr == -1) 139 return EINVAL; 140 141 /* it's busy */ 142 if (mutex->lock.owner != RT_NULL) 143 return EBUSY; 144 145 rt_memset(mutex, 0, sizeof(pthread_mutex_t)); 146 mutex->attr = -1; 147 148 return 0; 149 } 150 RTM_EXPORT(pthread_mutex_destroy); 151 152 int pthread_mutex_lock(pthread_mutex_t *mutex) 153 { 154 int mtype; 155 rt_err_t result; 156 157 if (!mutex) 158 return EINVAL; 159 160 if (mutex->attr == -1) 161 { 162 /* init mutex */ 163 pthread_mutex_init(mutex, RT_NULL); 164 } 165 166 mtype = mutex->attr & MUTEXATTR_TYPE_MASK; 167 rt_enter_critical(); 168 if (mutex->lock.owner == rt_thread_self() && 169 mtype != PTHREAD_MUTEX_RECURSIVE) 170 { 171 rt_exit_critical(); 172 173 return EDEADLK; 174 } 175 rt_exit_critical(); 176 177 result = rt_mutex_take(&(mutex->lock), RT_WAITING_FOREVER); 178 if (result == RT_EOK) 179 return 0; 180 181 return EINVAL; 182 } 183 RTM_EXPORT(pthread_mutex_lock); 184 185 int pthread_mutex_unlock(pthread_mutex_t *mutex) 186 { 187 rt_err_t result; 188 189 if (!mutex) 190 return EINVAL; 191 if (mutex->attr == -1) 192 { 193 /* init mutex */ 194 pthread_mutex_init(mutex, RT_NULL); 195 } 196 197 if (mutex->lock.owner != rt_thread_self()) 198 { 199 int mtype; 200 mtype = mutex->attr & MUTEXATTR_TYPE_MASK; 201 202 /* error check, return EPERM */ 203 if (mtype == PTHREAD_MUTEX_ERRORCHECK) 204 return EPERM; 205 206 /* no thread waiting on this mutex */ 207 if (mutex->lock.owner == RT_NULL) 208 return 0; 209 } 210 211 result = rt_mutex_release(&(mutex->lock)); 212 if (result == RT_EOK) 213 return 0; 214 215 return EINVAL; 216 } 217 RTM_EXPORT(pthread_mutex_unlock); 218 219 int pthread_mutex_trylock(pthread_mutex_t *mutex) 220 { 221 rt_err_t result; 222 int mtype; 223 224 if (!mutex) 225 return EINVAL; 226 if (mutex->attr == -1) 227 { 228 /* init mutex */ 229 pthread_mutex_init(mutex, RT_NULL); 230 } 231 232 mtype = mutex->attr & MUTEXATTR_TYPE_MASK; 233 rt_enter_critical(); 234 if (mutex->lock.owner == rt_thread_self() && 235 mtype != PTHREAD_MUTEX_RECURSIVE) 236 { 237 rt_exit_critical(); 238 239 return EDEADLK; 240 } 241 rt_exit_critical(); 242 243 result = rt_mutex_take(&(mutex->lock), 0); 244 if (result == RT_EOK) return 0; 245 246 return EBUSY; 247 } 248 RTM_EXPORT(pthread_mutex_trylock); 249