RDK Documentation (Open Sourced RDK Components)
rmh_monitor_util.c
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 #include <signal.h>
21 #include <pthread.h>
22 #include <sys/time.h>
23 #include <errno.h>
24 #include "rmh_monitor.h"
25 
26 RMHMonitor_hSemaphore RMHMonitor_Semaphore_Create() {
27  RMHMonitor_hSemaphore eventHandle;
28 
29  eventHandle=malloc(sizeof(*eventHandle));
30  if (!eventHandle) return NULL;
31  memset(eventHandle, 0, sizeof(*eventHandle));
32 
33  if (pthread_mutex_init(&eventHandle->lock, NULL) != 0) {
34  free(eventHandle);
35  return NULL;
36  }
37  if (pthread_cond_init(&eventHandle->cond, NULL) != 0) {
38  pthread_mutex_destroy (&eventHandle->lock);
39  free(eventHandle);
40  return NULL;
41  }
42  eventHandle->signal = false;
43  return eventHandle;
44 }
45 
46 void RMHMonitor_Semaphore_Destroy(RMHMonitor_hSemaphore eventHandle) {
47  if (eventHandle) {
48  pthread_mutex_destroy (&eventHandle->lock);
49  pthread_cond_destroy (&eventHandle->cond);
50  free(eventHandle);
51  }
52 }
53 
54 RMH_Result RMHMonitor_Semaphore_Reset(RMHMonitor_hSemaphore eventHandle) {
55  pthread_mutex_lock(&eventHandle->lock);
56  eventHandle->signal = false ;
57  pthread_mutex_unlock(&eventHandle->lock);
58  return RMH_SUCCESS;
59 }
60 
61 RMH_Result RMHMonitor_Semaphore_Signal(RMHMonitor_hSemaphore eventHandle) {
62  pthread_mutex_lock(&eventHandle->lock);
63  eventHandle->signal = true;
64  pthread_cond_signal(&eventHandle->cond);
65  pthread_mutex_unlock(&eventHandle->lock);
66  return RMH_SUCCESS;
67 }
68 
69 RMH_Result RMHMonitor_Semaphore_WaitTimeout(RMHMonitor_hSemaphore eventHandle, const int timeoutMsec) {
70  struct timeval now;
71  struct timespec timeout;
72  RMH_Result result=RMH_FAILURE;
73 
74  pthread_mutex_lock(&eventHandle->lock);
75  if (eventHandle->signal) {
76  result=RMH_SUCCESS;
77  eventHandle->signal = false;
78  goto exit;
79  }
80  do {
81  gettimeofday(&now, NULL);
82  timeout.tv_nsec = now.tv_usec * 1000 + (timeoutMsec%1000)*1000000;
83  timeout.tv_sec = now.tv_sec + (timeoutMsec/1000);
84  if (timeout.tv_nsec >= 1000000000) {
85  timeout.tv_nsec -= 1000000000;
86  timeout.tv_sec ++;
87  }
88 
89  int rc = pthread_cond_timedwait(&eventHandle->cond, &eventHandle->lock, &timeout);
90  if (eventHandle->signal) {
91  /* even if we timed out, if the signal was set, we succeed. this allows magnum to
92  be resilient to large OS scheduler delays */
93  result = RMH_SUCCESS;
94  break;
95  }
96  if (rc==ETIMEDOUT) {
97  result = RMH_TIMEOUT;
98  goto exit;
99  }
100  else if(rc==EINTR) {
101  continue;
102  }
103  if (rc!=0) {
104  result = RMH_FAILURE;
105  goto exit;
106  }
107  } while(!eventHandle->signal); /* we might have been wokenup and then event has been cleared */
108 
109  eventHandle->signal = false;
110 exit:
111  pthread_mutex_unlock(&eventHandle->lock);
112  return result;
113 }
114 
115 
116 /**
117  * This function will post to the event queue which will then be read by the event thread
118 */
119 void RMHMonitor_Queue_Enqueue(RMHMonitor *app, const enum RMH_Event event, const struct RMH_EventData *eventData) {
120  RMHMonitor_CallbackEvent *cbE = malloc(sizeof(RMHMonitor_CallbackEvent));
121  char printBuff[128];
122 
123  if (cbE) {
124  /* Enqueue the event and the time it occurred */
125  gettimeofday(&cbE->eventTime, NULL);
126  cbE->event = event;
127  cbE->eventData = *eventData;
128 
129  /* Lock the queue before we modify it */
130  pthread_mutex_lock(&app->eventQueueProtect);
131  TAILQ_INSERT_HEAD(&app->eventQueue, cbE, entries);
132  RMH_PrintDbg("%s[%u] ENQUEUED event '%s' in %p\n", __FUNCTION__, __LINE__, RMH_EventToString(cbE->event, printBuff, sizeof(printBuff)/sizeof(printBuff[0])), cbE);
133  pthread_mutex_unlock(&app->eventQueueProtect);
134  RMHMonitor_Semaphore_Signal(app->eventNotify);
135  }
136 }
137 
138 
139 /**
140  * This function will remove the oldest event from the event queue.
141 */
142 void RMHMonitor_Queue_Dequeue(RMHMonitor *app) {
144  char printBuff[128];
145 
146  /* Remove the tail of the queue. Lock the queue before we modify it */
147  pthread_mutex_lock(&app->eventQueueProtect);
148  cbE=app->eventQueue.tqh_first;
149  if (cbE) {
150  TAILQ_REMOVE(&app->eventQueue, app->eventQueue.tqh_first, entries);
151  RMH_PrintDbg("%s[%u] DEQUEUED event '%s' in %p\n", __FUNCTION__, __LINE__, RMH_EventToString(cbE->event, printBuff, sizeof(printBuff)/sizeof(printBuff[0])), cbE);
152  free(cbE);
153  }
154  pthread_mutex_unlock(&app->eventQueueProtect);
155 }
RMHMonitor
Definition: rmh_monitor.h:77
RMH_EventData
Definition: rmh_type.h:157
RMHMonitor_CallbackEvent
Definition: rmh_monitor.h:41
RMHMonitor_Semaphore
Definition: rmh_monitor.h:31
RMH_EventToString
const char *const RMH_EventToString(const uint32_t value, char *responseBuf, const size_t responseBufSize)
Return the bitmask value as a string.
Definition: librmh_api_no_wrap.c:170