• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "chpp/platform/platform_notifier.h"
18 
19 #include <pthread.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include "chpp/macros.h"
24 #include "chpp/mutex.h"
25 #include "chpp/platform/platform_time.h"
26 #include "chpp/transport.h"
27 #include "chpp/transport_signals.h"
28 #include "time.h"
29 
30 /************************************************
31  *  Public Functions
32  ***********************************************/
33 
chppPlatformNotifierInit(struct ChppNotifier * notifier)34 void chppPlatformNotifierInit(struct ChppNotifier *notifier) {
35   notifier->signal = 0;
36   chppMutexInit(&notifier->mutex);
37   pthread_cond_init(&notifier->cond, NULL);
38 }
39 
chppPlatformNotifierDeinit(struct ChppNotifier * notifier)40 void chppPlatformNotifierDeinit(struct ChppNotifier *notifier) {
41   pthread_cond_destroy(&notifier->cond);
42   chppMutexDeinit(&notifier->mutex);
43 }
44 
chppPlatformNotifierGetSignal(struct ChppNotifier * notifier)45 uint32_t chppPlatformNotifierGetSignal(struct ChppNotifier *notifier) {
46   chppMutexLock(&notifier->mutex);
47 
48   uint32_t signal = notifier->signal;
49   notifier->signal = 0;
50 
51   chppMutexUnlock(&notifier->mutex);
52   return signal;
53 }
54 
chppPlatformNotifierWait(struct ChppNotifier * notifier)55 uint32_t chppPlatformNotifierWait(struct ChppNotifier *notifier) {
56   chppMutexLock(&notifier->mutex);
57 
58   while (notifier->signal == 0) {
59     pthread_cond_wait(&notifier->cond, &notifier->mutex.lock);
60   }
61   uint32_t signal = notifier->signal;
62   notifier->signal = 0;
63 
64   chppMutexUnlock(&notifier->mutex);
65   return signal;
66 }
chppPlatformNotifierTimedWait(struct ChppNotifier * notifier,uint64_t timeoutNs)67 uint32_t chppPlatformNotifierTimedWait(struct ChppNotifier *notifier,
68                                        uint64_t timeoutNs) {
69   if (timeoutNs == CHPP_TRANSPORT_TIMEOUT_INFINITE) {
70     return chppPlatformNotifierWait(notifier);
71 
72   } else {
73     struct timespec timeout;
74     struct timespec absTime;
75     uint64_t timeoutS = timeoutNs / CHPP_NSEC_PER_SEC;
76     timeoutNs = timeoutNs % CHPP_NSEC_PER_SEC;
77 
78     chppMutexLock(&notifier->mutex);
79 
80     clock_gettime(CLOCK_REALTIME, &absTime);
81     timeout = absTime;
82     timeout.tv_sec += timeoutS;
83     timeout.tv_nsec += timeoutNs;
84 
85     while ((notifier->signal == 0) &&
86            (CHPP_TIMESPEC_TO_NS(absTime) < CHPP_TIMESPEC_TO_NS(timeout))) {
87       pthread_cond_timedwait(&notifier->cond, &notifier->mutex.lock, &absTime);
88       clock_gettime(CLOCK_REALTIME, &absTime);
89     }
90     uint32_t signal = notifier->signal;
91     notifier->signal = 0;
92 
93     chppMutexUnlock(&notifier->mutex);
94     return signal;
95   }
96 }
97 
chppPlatformNotifierSignal(struct ChppNotifier * notifier,uint32_t signal)98 void chppPlatformNotifierSignal(struct ChppNotifier *notifier,
99                                 uint32_t signal) {
100   chppMutexLock(&notifier->mutex);
101 
102   notifier->signal |= signal;
103   pthread_cond_signal(&notifier->cond);
104 
105   chppMutexUnlock(&notifier->mutex);
106 }
107