AJA NTV2 SDK  17.5.0.1242
NTV2 SDK 17.5.0.1242
lockimpl.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
10 #include "ajabase/system/debug.h"
11 #include <errno.h>
12 
13 // For converting milliseconds to nanoseconds
14 static const int MIL_2_NSEC = 1000000;
15 
16 // Number of nanoseconds in a second
17 static const int MAX_NSEC = 1000000000;
18 
19 // class AJALockImpl
20 
21 AJALockImpl::AJALockImpl(const char* pName) :
22  mName(pName),
23  mOwner(0),
24  mRefCount(0)
25 {
26  bool okSoFar = true;
27  bool freeAttr = false;
28 #if 0
29  if (pName)
30  {
31  int key = ftok(NAMED_MEMORY, ID_TAG);
32  if (-1 == key)
33  {
34  printf("Unable to name shared memory\n");
35  exit(1);
36  }
37 
38  // Create the segment exclusively (if the segment already exists then a combination of IPC_CREAT | IPC_EXCL returns an error EEXIST)
39  int m_iShmid = shmget(key, TOTAL_SIZE, READ_WRITE_PERMISSIONS | IPC_CREAT | IPC_EXCL);
40  if (m_iShmid < 0)
41  {
42  if (EEXIST == errno)
43  {
44  // if the shared memory already exists we only fetch the id to that memory
45  m_iShmid = shmget(key, TOTAL_SIZE, READ_WRITE_PERMISSIONS);
46  }
47  if (m_iShmid < 0)
48  {
49  printf("Unable to create shared memory - %s\n",strerror(errno));
50  exit(1);
51  }
52  else
53  printf("Attached to the existing shared memory\n");
54  }
55  else
56  printf("Created new shared memory\n");
57 
58  // Now we attach the segment to our data space.
59  mutex = reinterpret_cast<pthread_mutex_t*>(shmat(m_iShmid, NULL, 0));
60  if (reinterpret_cast<pthread_mutex_t*>(-1) == mutex)
61  {
62  printf("Unable to attach shared memory to the process - %s\n",strerror(errno));
63  exit(1);
64  }
65 
66  // Now we can set this mutex to be shared between processes
67  pthread_mutex_t* mutex;
68  pthread_mutexattr_t mutexAttr;
69  ret = pthread_mutexattr_init(&mutexAttr);
70  if (ret != 0)
71  {
72  printf("pthread_mutexattr_init failed - err=%d\n",ret);
73  exit(1);
74  }
75  ret = pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
76  if (ret != 0)
77  {
78  printf("pthread_mutexattr_setpshared failed - err=%d\n",ret);
79  exit(1);
80  }
81  ret = pthread_mutexattr_setrobust_np(&mutexAttr, PTHREAD_MUTEX_ROBUST_NP);
82  if (ret != 0)
83  {
84  printf("pthread_mutexattr_setrobust_np failed - err=%d\n",ret);
85  exit(1);
86  }
87  ret = pthread_mutex_init(mutex, &mutexAttr);
88  if (ret != 0)
89  {
90  printf("pthread_mutex_init failed - err=%d\n",ret);
91  exit(1);
92  }
93  // ------ Use the mutex from here on between processes
94  }
95 #endif
96  // Set up the thread attributes
97  pthread_mutexattr_t attr;
98  int rc = pthread_mutexattr_init(&attr);
99  if (rc)
100  {
101  AJA_REPORT(0, AJA_DebugSeverity_Error, "AJALockImpl(%s) attr init reported error %d", mName, rc);
102  okSoFar = false;
103  }
104  freeAttr = true;
105 
106  if (okSoFar)
107  {
108  rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
109  if (rc)
110  {
111  AJA_REPORT(0, AJA_DebugSeverity_Error, "AJALockImpl(%s) attr settype reported error %d", mName, rc);
112  okSoFar = false;
113  }
114  }
115 
116  if (okSoFar)
117  {
118  rc = pthread_mutex_init(&mMutex, &attr);
119  if (rc)
120  {
121  AJA_REPORT(0, AJA_DebugSeverity_Error, "AJALockImpl(%s) mutex init reported error %d", mName, rc);
122  okSoFar = false;
123  }
124  }
125 
126  // Clean up the attribute memory
127  if (freeAttr)
128  {
129  rc = pthread_mutexattr_destroy(&attr);
130  if (rc)
131  {
132  AJA_REPORT(0, AJA_DebugSeverity_Error, "AJALockImpl(%s) attr destroy reported error %d", mName, rc);
133  }
134  }
135 }
136 
137 
139 {
140  int rc;
141 
142  rc = pthread_mutex_destroy(&mMutex);
143  if (rc)
144  {
145  AJA_REPORT(0, AJA_DebugSeverity_Error, "~AJALockImpl(%s) mutex destroy reported error %d", mName, rc);
146  }
147 }
148 
149 
150 AJAStatus
151 AJALockImpl::Lock(uint32_t timeout)
152 {
153  int rc;
154 
155  // Allow multiple locks by the same thread
156  if (mOwner && (mOwner == pthread_self()))
157  {
158  mRefCount++;
159  return AJA_STATUS_SUCCESS;
160  }
161 
162  // get the current time of day
163  struct timespec ts;
165 
166  // calculate how long to wait
167  if (timeout == 0xffffffff)
168  {
169  ts.tv_sec += 60 * 60 * 24 * 365; // A year is infinite enough
170  ts.tv_nsec = 0;
171  }
172  else
173  {
174  uint64_t bigtimeout = (uint64_t) timeout * MIL_2_NSEC;
175  ts.tv_sec += bigtimeout / MAX_NSEC;
176  ts.tv_nsec += bigtimeout % MAX_NSEC;
177  if (ts.tv_nsec >= MAX_NSEC)
178  {
179  ts.tv_sec++;
180  ts.tv_nsec -= MAX_NSEC;
181  }
182  }
183 
184  // Wait for the lock
185  rc = pthread_mutex_timedlock(&mMutex, &ts);
186  if (rc)
187  {
188  int err = errno;
189  if (err == ETIMEDOUT)
190  {
191  return AJA_STATUS_TIMEOUT; // We've worn out our welcome
192  }
193 
194  AJA_REPORT(0, AJA_DebugSeverity_Error, "AJALockImpl::Lock(%s) mutex lock reported error %d", mName, rc);
195  return AJA_STATUS_FAIL;
196  }
197 
198  mOwner = pthread_self();
199  mRefCount = 1;
200 
201  return AJA_STATUS_SUCCESS;
202 }
203 
204 
205 AJAStatus
207 {
208  if (mOwner != pthread_self())
209  {
210  return AJA_STATUS_FAIL;
211  }
212 
213  // Allow multiple unlocks by the same thread
214  mRefCount--;
215  if (mRefCount)
216  {
217  return AJA_STATUS_SUCCESS;
218  }
219 
220  mOwner = 0;
221  mRefCount = 0;
222  pthread_mutex_unlock(&mMutex);
223 
224  return AJA_STATUS_SUCCESS;
225 }
NULL
#define NULL
Definition: ntv2caption608types.h:19
AJALockImpl::~AJALockImpl
virtual ~AJALockImpl()
Definition: lockimpl.cpp:72
AJA_STATUS_SUCCESS
@ AJA_STATUS_SUCCESS
Definition: types.h:381
AJALockImpl::Unlock
AJAStatus Unlock()
Definition: lockimpl.cpp:143
AJA_DebugSeverity_Error
@ AJA_DebugSeverity_Error
Definition: debugshare.h:28
AJAStatus
AJAStatus
Definition: types.h:378
CLOCK_REALTIME
#define CLOCK_REALTIME
Definition: pthreadsextra.h:21
AJA_STATUS_FAIL
@ AJA_STATUS_FAIL
Definition: types.h:382
AJA_REPORT
#define AJA_REPORT(_index_, _severity_, _format_,...)
Definition: debug.h:117
lockimpl.h
Declares the AJALockImpl class.
AJALockImpl::Lock
AJAStatus Lock(uint32_t uTimeout=0xffffffff)
Definition: lockimpl.cpp:87
AJA_STATUS_TIMEOUT
@ AJA_STATUS_TIMEOUT
Definition: types.h:384
pthreadsextra.h
Declares extra symbols to make the Mac threads implementation look more like Unix.
AJALockImpl::AJALockImpl
AJALockImpl(const char *pName)
Definition: lockimpl.cpp:20
clock_gettime
int clock_gettime(clockid_t clk_id, struct timespec *tp)
Definition: pthreadsextra.cpp:12
MIL_2_NSEC
static const int MIL_2_NSEC
Definition: lockimpl.cpp:14
pthread_mutex_timedlock
int pthread_mutex_timedlock(pthread_mutex_t *__restrict mutex, const struct timespec *__restrict abs_timeout)
Definition: pthreadsextra.cpp:43
debug.h
Declares the AJADebug class.
MAX_NSEC
static const int MAX_NSEC
Definition: lockimpl.cpp:17