1 /** 2 * @file lock/lock.c Pthread mutex locking 3 * 4 * Copyright (C) 2010 Creytiv.com 5 */ 6 #define _DEFAULT_SOURCE 1 7 #define __USE_UNIX98 1 8 #include <pthread.h> 9 #include <re_types.h> 10 #include <re_mem.h> 11 #include <re_lock.h> 12 13 14 #define DEBUG_MODULE "lock" 15 #define DEBUG_LEVEL 5 16 #include <re_dbg.h> 17 18 19 #ifndef RELEASE 20 #define LOCK_DEBUG 0 21 #endif 22 23 24 /** Defines a lock */ 25 struct lock { 26 pthread_mutex_t m; 27 }; 28 29 30 static void lock_destructor(void *data) 31 { 32 struct lock *l = data; 33 34 int err = pthread_mutex_destroy(&l->m); 35 if (err) { 36 DEBUG_WARNING("pthread_mutex_destroy: %m\n", err); 37 } 38 } 39 40 41 /** 42 * Allocate a new lock 43 * 44 * @param lp Pointer to allocated lock object 45 * 46 * @return 0 if success, otherwise errorcode 47 */ 48 int lock_alloc(struct lock **lp) 49 { 50 pthread_mutexattr_t attr; 51 struct lock *l; 52 53 if (!lp) 54 return EINVAL; 55 56 l = mem_zalloc(sizeof(*l), lock_destructor); 57 if (!l) 58 return ENOMEM; 59 60 (void)pthread_mutex_init(&l->m, NULL); 61 62 pthread_mutexattr_init(&attr); 63 64 #if LOCK_DEBUG 65 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); 66 DEBUG_NOTICE("init debug lock\n"); 67 #else 68 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); 69 #endif 70 pthread_mutex_init(&l->m, &attr); 71 72 *lp = l; 73 return 0; 74 } 75 76 77 /** 78 * Get the lock for reading 79 * 80 * @param l Lock object 81 */ 82 void lock_read_get(struct lock *l) 83 { 84 const int err = pthread_mutex_lock(&l->m); 85 if (err) { 86 DEBUG_WARNING("lock_read_get: %m\n", err); 87 } 88 } 89 90 91 /** 92 * Get the lock for writing 93 * 94 * @param l Lock object 95 */ 96 void lock_write_get(struct lock *l) 97 { 98 const int err = pthread_mutex_lock(&l->m); 99 if (err) { 100 DEBUG_WARNING("lock_write_get: %m\n", err); 101 } 102 } 103 104 105 /** 106 * Attempt to get a lock for reading 107 * 108 * @param l Lock object 109 * 110 * @return 0 if success, otherwise errorcode 111 */ 112 int lock_read_try(struct lock *l) 113 { 114 return pthread_mutex_trylock(&l->m); 115 } 116 117 118 /** 119 * Attempt to get a lock for writing 120 * 121 * @param l Lock object 122 * 123 * @return 0 if success, otherwise errorcode 124 */ 125 int lock_write_try(struct lock *l) 126 { 127 return pthread_mutex_trylock(&l->m); 128 } 129 130 131 /** 132 * Release a lock 133 * 134 * @param l Lock object 135 */ 136 void lock_rel(struct lock *l) 137 { 138 const int err = pthread_mutex_unlock(&l->m); 139 if (err) { 140 DEBUG_WARNING("lock_rel: %m\n", err); 141 } 142 } 143