blob: bc24ad5de66a74a43e54b575760c8b97ab2c31e7 [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>
Dileep Marchyae2a59082015-05-21 13:29:05 -070030#include <sys/time.h>
Dileep Marchyaf9ba4852014-10-24 19:56:57 -070031
Ramkumar Radhakrishnanef835262015-01-20 17:17:58 -080032#define SCOPE_LOCK(locker) Locker::ScopeLock lock(locker)
33#define SEQUENCE_ENTRY_SCOPE_LOCK(locker) Locker::SequenceEntryScopeLock lock(locker)
34#define SEQUENCE_EXIT_SCOPE_LOCK(locker) Locker::SequenceExitScopeLock lock(locker)
35#define SEQUENCE_WAIT_SCOPE_LOCK(locker) Locker::SequenceWaitScopeLock lock(locker)
36#define SEQUENCE_CANCEL_SCOPE_LOCK(locker) Locker::SequenceCancelScopeLock lock(locker)
Dileep Marchyaf9ba4852014-10-24 19:56:57 -070037
Dileep Marchya73d002e2015-05-08 18:58:33 -070038namespace sdm {
Dileep Marchyaf9ba4852014-10-24 19:56:57 -070039
40class Locker {
41 public:
42 class ScopeLock {
43 public:
44 explicit ScopeLock(Locker& locker) : locker_(locker) {
45 locker_.Lock();
46 }
47
48 ~ScopeLock() {
49 locker_.Unlock();
50 }
51
52 private:
53 Locker &locker_;
54 };
55
Ramkumar Radhakrishnanef835262015-01-20 17:17:58 -080056 class SequenceEntryScopeLock {
57 public:
58 explicit SequenceEntryScopeLock(Locker& locker) : locker_(locker) {
59 locker_.Lock();
60 locker_.sequence_wait_ = 1;
61 }
62
63 ~SequenceEntryScopeLock() {
64 locker_.Unlock();
65 }
66
67 private:
68 Locker &locker_;
69 };
70
71 class SequenceExitScopeLock {
72 public:
73 explicit SequenceExitScopeLock(Locker& locker) : locker_(locker) {
74 locker_.Lock();
75 locker_.sequence_wait_ = 0;
76 }
77
78 ~SequenceExitScopeLock() {
79 locker_.Broadcast();
80 locker_.Unlock();
81 }
82
83 private:
84 Locker &locker_;
85 };
86
87 class SequenceWaitScopeLock {
88 public:
89 explicit SequenceWaitScopeLock(Locker& locker) : locker_(locker), error_(false) {
90 locker_.Lock();
91
92 if (locker_.sequence_wait_ == 1) {
93 locker_.Wait();
94 error_ = (locker_.sequence_wait_ == -1);
95 }
96 }
97
98 ~SequenceWaitScopeLock() {
99 locker_.Unlock();
100 }
101
102 bool IsError() {
103 return error_;
104 }
105
106 private:
107 Locker &locker_;
108 bool error_;
109 };
110
111 class SequenceCancelScopeLock {
112 public:
113 explicit SequenceCancelScopeLock(Locker& locker) : locker_(locker) {
114 locker_.Lock();
115 locker_.sequence_wait_ = -1;
116 }
117
118 ~SequenceCancelScopeLock() {
119 locker_.Broadcast();
120 locker_.Unlock();
121 }
122
123 private:
124 Locker &locker_;
125 };
126
127 Locker() : sequence_wait_(0) {
Dileep Marchyaf9ba4852014-10-24 19:56:57 -0700128 pthread_mutex_init(&mutex_, 0);
129 pthread_cond_init(&condition_, 0);
130 }
131
132 ~Locker() {
133 pthread_mutex_destroy(&mutex_);
134 pthread_cond_destroy(&condition_);
135 }
136
137 void Lock() { pthread_mutex_lock(&mutex_); }
138 void Unlock() { pthread_mutex_unlock(&mutex_); }
139 void Signal() { pthread_cond_signal(&condition_); }
140 void Broadcast() { pthread_cond_broadcast(&condition_); }
141 void Wait() { pthread_cond_wait(&condition_, &mutex_); }
Ramkumar Radhakrishnanef835262015-01-20 17:17:58 -0800142 int WaitFinite(int ms) {
Dileep Marchyaf9ba4852014-10-24 19:56:57 -0700143 struct timespec ts;
144 struct timeval tv;
145 gettimeofday(&tv, NULL);
146 ts.tv_sec = tv.tv_sec + ms/1000;
147 ts.tv_nsec = tv.tv_usec*1000 + (ms%1000)*1000000;
148 ts.tv_sec += ts.tv_nsec/1000000000L;
149 ts.tv_nsec += ts.tv_nsec%1000000000L;
150 return pthread_cond_timedwait(&condition_, &mutex_, &ts);
151 }
152
153 private:
154 pthread_mutex_t mutex_;
155 pthread_cond_t condition_;
Ramkumar Radhakrishnanef835262015-01-20 17:17:58 -0800156 int sequence_wait_; // This flag is set to 1 on sequence entry, 0 on exit, and -1 on cancel.
157 // Some routines will wait for sequence of function calls to finish
158 // so that capturing a transitionary snapshot of context is prevented.
159 // If flag is set to -1, these routines will exit without doing any
160 // further processing.
Dileep Marchyaf9ba4852014-10-24 19:56:57 -0700161};
162
Dileep Marchya73d002e2015-05-08 18:58:33 -0700163} // namespace sdm
Dileep Marchyaf9ba4852014-10-24 19:56:57 -0700164
165#endif // __LOCKER_H__
166