/src/sleuthkit/tsk/base/tsk_lock.c
Line | Count | Source |
1 | | /* |
2 | | * The Sleuth Kit |
3 | | * |
4 | | * Brian Carrier [carrier <at> sleuthkit [dot] org] |
5 | | * Copyright (c) 2011 Brian Carrier. All Rights reserved |
6 | | * |
7 | | * This software is distributed under the Common Public License 1.0 |
8 | | */ |
9 | | |
10 | | #include "tsk_base_i.h" |
11 | | |
12 | | #ifdef TSK_MULTITHREAD_LIB |
13 | | |
14 | | #ifdef TSK_WIN32 |
15 | | |
16 | | void |
17 | | tsk_init_lock(tsk_lock_t * lock) |
18 | | { |
19 | | InitializeCriticalSection(&lock->critical_section); |
20 | | } |
21 | | |
22 | | void |
23 | | tsk_deinit_lock(tsk_lock_t * lock) |
24 | | { |
25 | | DeleteCriticalSection(&lock->critical_section); |
26 | | } |
27 | | |
28 | | void |
29 | | tsk_take_lock(tsk_lock_t * lock) |
30 | | { |
31 | | EnterCriticalSection(&lock->critical_section); |
32 | | } |
33 | | |
34 | | void |
35 | | tsk_release_lock(tsk_lock_t * lock) |
36 | | { |
37 | | LeaveCriticalSection(&lock->critical_section); |
38 | | } |
39 | | |
40 | | #else |
41 | | |
42 | | #include <assert.h> |
43 | | |
44 | | void |
45 | | tsk_init_lock(tsk_lock_t * lock) |
46 | 108k | { |
47 | 108k | pthread_mutexattr_t attr; |
48 | 108k | pthread_mutexattr_init(&attr); |
49 | | |
50 | | // Locks on Linux are not recursive (unlike on Windows), so things |
51 | | // will hang if the current thread tries to take the lock again. |
52 | | // While debugging, it's sometimes useful to call |
53 | | // |
54 | | // pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); |
55 | | // |
56 | | // which will provoke an immediate error rather than a hang. |
57 | | // |
58 | | // PTHREAD_MUTEX_ERRORCHECK is not defined by default on Linux, |
59 | | // but it is portable if you have the right_XOPEN_SOURCE settings. |
60 | | // However, that macro affects the availability of other features |
61 | | // like BSD-style u_int types used in afflib. |
62 | | // PTHREAD_MUTEX_ERRORCHECK -is- available by default on Mac. |
63 | | // |
64 | | // PTHREAD_MUTEX_ERRORCHECK_NP is the Linux/gcc non-portable |
65 | | // equivalent which does not require _XOPEN_SOURCE. |
66 | | // |
67 | | // Other interesting attributes are PTHREAD_MUTEX_RECURSIVE (and |
68 | | // PTHREAD_MUTEX_RECURSIVE_NP). We avoided those out of portability |
69 | | // concerns with the _XOPEN_SOURCE settings. |
70 | | |
71 | 108k | int e = pthread_mutex_init(&lock->mutex, &attr); |
72 | 108k | pthread_mutexattr_destroy(&attr); |
73 | 108k | if (e != 0) { |
74 | 0 | fprintf(stderr, "tsk_init_lock: thread_mutex_init failed %d\n", e); |
75 | 0 | assert(0); |
76 | 0 | } |
77 | 108k | } |
78 | | |
79 | | void |
80 | | tsk_deinit_lock(tsk_lock_t * lock) |
81 | 108k | { |
82 | 108k | pthread_mutex_destroy(&lock->mutex); |
83 | 108k | } |
84 | | |
85 | | void |
86 | | tsk_take_lock(tsk_lock_t * lock) |
87 | 29.0M | { |
88 | 29.0M | int e = pthread_mutex_lock(&lock->mutex); |
89 | 29.0M | if (e != 0) { |
90 | 0 | fprintf(stderr, "tsk_take_lock: thread_mutex_lock failed %d\n", e); |
91 | 0 | assert(0); |
92 | 0 | } |
93 | 29.0M | } |
94 | | |
95 | | void |
96 | | tsk_release_lock(tsk_lock_t * lock) |
97 | 29.0M | { |
98 | 29.0M | int e = pthread_mutex_unlock(&lock->mutex); |
99 | 29.0M | if (e != 0) { |
100 | 0 | fprintf(stderr, |
101 | 0 | "tsk_release_lock: thread_mutex_unlock failed %d\n", e); |
102 | | assert(0); |
103 | 0 | } |
104 | 29.0M | } |
105 | | |
106 | | #endif |
107 | | |
108 | | // single-threaded |
109 | | #else |
110 | | |
111 | | void |
112 | | tsk_init_lock(tsk_lock_t * lock) |
113 | | { |
114 | | } |
115 | | |
116 | | void |
117 | | tsk_deinit_lock(tsk_lock_t * lock) |
118 | | { |
119 | | } |
120 | | |
121 | | void |
122 | | tsk_take_lock(tsk_lock_t * lock) |
123 | | { |
124 | | } |
125 | | |
126 | | void |
127 | | tsk_release_lock(tsk_lock_t * lock) |
128 | | { |
129 | | } |
130 | | |
131 | | #endif |