blob: 549a282d643d5814fc2dc77a73e3d798c2d12d82 [file] [log] [blame]
Dileep Marchyaf9ba4852014-10-24 19:56:57 -07001/*
Ramkumar Radhakrishnanef835262015-01-20 17:17:58 -08002* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
Dileep Marchyaf9ba4852014-10-24 19:56:57 -07003*
4* Redistribution and use in source and binary forms, with or without modification, are permitted
5* provided that the following conditions are met:
6* * Redistributions of source code must retain the above copyright notice, this list of
7* conditions and the following disclaimer.
8* * Redistributions in binary form must reproduce the above copyright notice, this list of
9* conditions and the following disclaimer in the documentation and/or other materials provided
10* with the distribution.
11* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
12* endorse or promote products derived from this software without specific prior written
13* permission.
14*
15* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23*/
24
25#ifndef __LOCKER_H__
26#define __LOCKER_H__
27
28#include <stdint.h>
29#include <pthread.h>
30
Ramkumar Radhakrishnanef835262015-01-20 17:17:58 -080031#define SCOPE_LOCK(locker) Locker::ScopeLock lock(locker)
32#define SEQUENCE_ENTRY_SCOPE_LOCK(locker) Locker::SequenceEntryScopeLock lock(locker)
33#define SEQUENCE_EXIT_SCOPE_LOCK(locker) Locker::SequenceExitScopeLock lock(locker)
34#define SEQUENCE_WAIT_SCOPE_LOCK(locker) Locker::SequenceWaitScopeLock lock(locker)
35#define SEQUENCE_CANCEL_SCOPE_LOCK(locker) Locker::SequenceCancelScopeLock lock(locker)
Dileep Marchyaf9ba4852014-10-24 19:56:57 -070036
37namespace sde {
38
39class Locker {
40 public:
41 class ScopeLock {
42 public:
43 explicit ScopeLock(Locker& locker) : locker_(locker) {
44 locker_.Lock();
45 }
46
47 ~ScopeLock() {
48 locker_.Unlock();
49 }
50
51 private:
52 Locker &locker_;
53 };
54
Ramkumar Radhakrishnanef835262015-01-20 17:17:58 -080055 class SequenceEntryScopeLock {
56 public:
57 explicit SequenceEntryScopeLock(Locker& locker) : locker_(locker) {
58 locker_.Lock();
59 locker_.sequence_wait_ = 1;
60 }
61
62 ~SequenceEntryScopeLock() {
63 locker_.Unlock();
64 }
65
66 private:
67 Locker &locker_;
68 };
69
70 class SequenceExitScopeLock {
71 public:
72 explicit SequenceExitScopeLock(Locker& locker) : locker_(locker) {
73 locker_.Lock();
74 locker_.sequence_wait_ = 0;
75 }
76
77 ~SequenceExitScopeLock() {
78 locker_.Broadcast();
79 locker_.Unlock();
80 }
81
82 private:
83 Locker &locker_;
84 };
85
86 class SequenceWaitScopeLock {
87 public:
88 explicit SequenceWaitScopeLock(Locker& locker) : locker_(locker), error_(false) {
89 locker_.Lock();
90
91 if (locker_.sequence_wait_ == 1) {
92 locker_.Wait();
93 error_ = (locker_.sequence_wait_ == -1);
94 }
95 }
96
97 ~SequenceWaitScopeLock() {
98 locker_.Unlock();
99 }
100
101 bool IsError() {
102 return error_;
103 }
104
105 private:
106 Locker &locker_;
107 bool error_;
108 };
109
110 class SequenceCancelScopeLock {
111 public:
112 explicit SequenceCancelScopeLock(Locker& locker) : locker_(locker) {
113 locker_.Lock();
114 locker_.sequence_wait_ = -1;
115 }
116
117 ~SequenceCancelScopeLock() {
118 locker_.Broadcast();
119 locker_.Unlock();
120 }
121
122 private:
123 Locker &locker_;
124 };
125
126 Locker() : sequence_wait_(0) {
Dileep Marchyaf9ba4852014-10-24 19:56:57 -0700127 pthread_mutex_init(&mutex_, 0);
128 pthread_cond_init(&condition_, 0);
129 }
130
131 ~Locker() {
132 pthread_mutex_destroy(&mutex_);
133 pthread_cond_destroy(&condition_);
134 }
135
136 void Lock() { pthread_mutex_lock(&mutex_); }
137 void Unlock() { pthread_mutex_unlock(&mutex_); }
138 void Signal() { pthread_cond_signal(&condition_); }
139 void Broadcast() { pthread_cond_broadcast(&condition_); }
140 void Wait() { pthread_cond_wait(&condition_, &mutex_); }
Ramkumar Radhakrishnanef835262015-01-20 17:17:58 -0800141 int WaitFinite(int ms) {
Dileep Marchyaf9ba4852014-10-24 19:56:57 -0700142 struct timespec ts;
143 struct timeval tv;
144 gettimeofday(&tv, NULL);
145 ts.tv_sec = tv.tv_sec + ms/1000;
146 ts.tv_nsec = tv.tv_usec*1000 + (ms%1000)*1000000;
147 ts.tv_sec += ts.tv_nsec/1000000000L;
148 ts.tv_nsec += ts.tv_nsec%1000000000L;
149 return pthread_cond_timedwait(&condition_, &mutex_, &ts);
150 }
151
152 private:
153 pthread_mutex_t mutex_;
154 pthread_cond_t condition_;
Ramkumar Radhakrishnanef835262015-01-20 17:17:58 -0800155 int sequence_wait_; // This flag is set to 1 on sequence entry, 0 on exit, and -1 on cancel.
156 // Some routines will wait for sequence of function calls to finish
157 // so that capturing a transitionary snapshot of context is prevented.
158 // If flag is set to -1, these routines will exit without doing any
159 // further processing.
Dileep Marchyaf9ba4852014-10-24 19:56:57 -0700160};
161
162} // namespace sde
163
164#endif // __LOCKER_H__
165