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