Threading primitives separated.
[strongswan.git] / src / libstrongswan / threading / rwlock.c
1 /*
2 * Copyright (C) 2008-2009 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #define _GNU_SOURCE
18 #include <pthread.h>
19
20 #include <threading.h>
21 #include <library.h>
22 #include <debug.h>
23
24 #include "rwlock.h"
25 #include "lock_profiler.h"
26
27 /**
28 * Implementation of rwlock_t.read_lock
29 */
30 static void read_lock(private_rwlock_t *this)
31 {
32 int err;
33
34 profiler_start(&this->profile);
35 err = pthread_rwlock_rdlock(&this->rwlock);
36 if (err != 0)
37 {
38 DBG1("!!! RWLOCK READ LOCK ERROR: %s !!!", strerror(err));
39 }
40 profiler_end(&this->profile);
41 }
42
43 /**
44 * Implementation of rwlock_t.write_lock
45 */
46 static void write_lock(private_rwlock_t *this)
47 {
48 int err;
49
50 profiler_start(&this->profile);
51 err = pthread_rwlock_wrlock(&this->rwlock);
52 if (err != 0)
53 {
54 DBG1("!!! RWLOCK WRITE LOCK ERROR: %s !!!", strerror(err));
55 }
56 profiler_end(&this->profile);
57 }
58
59 /**
60 * Implementation of rwlock_t.try_write_lock
61 */
62 static bool try_write_lock(private_rwlock_t *this)
63 {
64 return pthread_rwlock_trywrlock(&this->rwlock) == 0;
65 }
66
67 /**
68 * Implementation of rwlock_t.unlock
69 */
70 static void rw_unlock(private_rwlock_t *this)
71 {
72 int err;
73
74 err = pthread_rwlock_unlock(&this->rwlock);
75 if (err != 0)
76 {
77 DBG1("!!! RWLOCK UNLOCK ERROR: %s !!!", strerror(err));
78 }
79 }
80
81 /**
82 * Implementation of rwlock_t.destroy
83 */
84 static void rw_destroy(private_rwlock_t *this)
85 {
86 pthread_rwlock_destroy(&this->rwlock);
87 profiler_cleanup(&this->profile);
88 free(this);
89 }
90
91 /*
92 * see header file
93 */
94 rwlock_t *rwlock_create(rwlock_type_t type)
95 {
96 switch (type)
97 {
98 case RWLOCK_TYPE_DEFAULT:
99 default:
100 {
101 private_rwlock_t *this = malloc_thing(private_rwlock_t);
102
103 this->public.read_lock = (void(*)(rwlock_t*))read_lock;
104 this->public.write_lock = (void(*)(rwlock_t*))write_lock;
105 this->public.try_write_lock = (bool(*)(rwlock_t*))try_write_lock;
106 this->public.unlock = (void(*)(rwlock_t*))rw_unlock;
107 this->public.destroy = (void(*)(rwlock_t*))rw_destroy;
108
109 pthread_rwlock_init(&this->rwlock, NULL);
110 profiler_init(&this->profile);
111
112 return &this->public;
113 }
114 }
115 }
116