1 /**
2  * @file rwlock.c  Pthread read/write locking
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #define _GNU_SOURCE 1
7 #include <pthread.h>
8 #include <re_types.h>
9 #include <re_mem.h>
10 #include <re_lock.h>
11 
12 
13 #define DEBUG_MODULE "rwlock"
14 #define DEBUG_LEVEL 5
15 #include <re_dbg.h>
16 
17 
18 struct lock {
19 	pthread_rwlock_t lock;
20 };
21 
22 
23 static void lock_destructor(void *data)
24 {
25 	struct lock *l = data;
26 
27 	int err = pthread_rwlock_destroy(&l->lock);
28 	if (err) {
29 		DEBUG_WARNING("pthread_rwlock_destroy: %m\n", err);
30 	}
31 }
32 
33 
34 int lock_alloc(struct lock **lp)
35 {
36 	struct lock *l;
37 	int err;
38 
39 	if (!lp)
40 		return EINVAL;
41 
42 	l = mem_zalloc(sizeof(*l), lock_destructor);
43 	if (!l)
44 		return ENOMEM;
45 
46 	err = pthread_rwlock_init(&l->lock, NULL);
47 	if (err)
48 		goto out;
49 
50 	*lp = l;
51 
52  out:
53 	if (err)
54 		mem_deref(l);
55 	return err;
56 }
57 
58 
59 void lock_read_get(struct lock *l)
60 {
61 	int err;
62 
63 	if (!l)
64 		return;
65 
66 	err = pthread_rwlock_rdlock(&l->lock);
67 	if (err) {
68 		DEBUG_WARNING("lock_read_get: %m\n", err);
69 	}
70 }
71 
72 
73 void lock_write_get(struct lock *l)
74 {
75 	int err;
76 
77 	if (!l)
78 		return;
79 
80 	err = pthread_rwlock_wrlock(&l->lock);
81 	if (err) {
82 		DEBUG_WARNING("lock_write_get: %m\n", err);
83 	}
84 }
85 
86 
87 int lock_read_try(struct lock *l)
88 {
89 	if (!l)
90 		return EINVAL;
91 	return pthread_rwlock_tryrdlock(&l->lock);
92 }
93 
94 
95 int lock_write_try(struct lock *l)
96 {
97 	if (!l)
98 		return EINVAL;
99 	return pthread_rwlock_trywrlock(&l->lock);
100 }
101 
102 
103 void lock_rel(struct lock *l)
104 {
105 	int err;
106 
107 	if (!l)
108 		return;
109 
110 	err = pthread_rwlock_unlock(&l->lock);
111 	if (err) {
112 		DEBUG_WARNING("lock_rel: %m\n", err);
113 	}
114 }
115