RTE OSAdapter POSIX
0.1.0 build 41b3eb3
POSIX/Linux OAL OSAdapter for Platform_RTE
Toggle main menu visibility
Loading...
Searching...
No Matches
rte_posix_osadapter_lock.c
Go to the documentation of this file.
1
/* _POSIX_C_SOURCE: glibc declares pthread_mutex_timedlock(), clock_gettime() and nanosleep() only under a POSIX
2
* feature-test macro (this product builds strict C99), same as mutex.c's own. */
3
#define _POSIX_C_SOURCE 200809L
4
15
#include "
rte_posix_osadapter_lock.h
"
16
17
#include <errno.h>
18
#include <pthread.h>
19
#include <stdbool.h>
20
#include <stdint.h>
21
#include <time.h>
22
24
#define POSIX_LOCK_NS_PER_MS 1000000L
25
#define POSIX_LOCK_NS_PER_S 1000000000L
26
#if !defined(__linux__)
28
#define POSIX_LOCK_POLL_NS 1000000L
29
#endif
30
32
34
static
rte_status_t
try_lock_once
(pthread_mutex_t *mutex);
35
static
rte_status_t
lock_until_deadline
(pthread_mutex_t *mutex, rte_duration_ms_t timeout_ms);
36
static
void
deadline_add_ms
(
struct
timespec *ts, rte_duration_ms_t ms);
37
39
41
42
44
rte_status_t
posix_osa_lock_bounded
(pthread_mutex_t *mutex, rte_duration_ms_t timeout_ms)
45
{
46
rte_status_t status;
47
48
if
(mutex == NULL)
49
{
50
status = RTE_STATUS_INVALID_PARAM;
51
}
52
else
if
(timeout_ms == 0U)
53
{
54
/* REQ-OAL-MUTEX-014: timeout_ms == 0 is one non-blocking try. */
55
status =
try_lock_once
(mutex);
56
}
57
else
58
{
59
status =
lock_until_deadline
(mutex, timeout_ms);
60
}
61
return
status;
62
}
63
64
65
/****Local functions ****/
66
68
static
rte_status_t
try_lock_once
(pthread_mutex_t *mutex)
69
{
70
rte_status_t status;
71
int
rc = pthread_mutex_trylock(mutex);
72
73
if
(rc == 0)
74
{
75
status = RTE_STATUS_OK;
76
}
77
else
if
(rc == EBUSY)
78
{
79
status = RTE_STATUS_TIMEOUT;
80
}
81
else
82
{
83
status = RTE_STATUS_INTERNAL_ERROR;
84
}
85
return
status;
86
}
87
88
#if defined(__linux__)
90
static
rte_status_t
lock_until_deadline
(pthread_mutex_t *mutex, rte_duration_ms_t timeout_ms)
91
{
92
rte_status_t status;
93
struct
timespec deadline;
94
95
if
(clock_gettime(CLOCK_REALTIME, &deadline) != 0)
96
{
97
status = RTE_STATUS_INTERNAL_ERROR;
/* no deadline - never wait unbounded */
98
}
99
else
100
{
101
int
rc;
102
103
deadline_add_ms
(&deadline, timeout_ms);
104
rc = pthread_mutex_timedlock(mutex, &deadline);
105
if
(rc == 0)
106
{
107
status = RTE_STATUS_OK;
108
}
109
else
if
(rc == ETIMEDOUT)
110
{
111
status = RTE_STATUS_TIMEOUT;
112
}
113
else
114
{
115
status = RTE_STATUS_INTERNAL_ERROR;
116
}
117
}
118
return
status;
119
}
120
#else
123
static
rte_status_t
lock_until_deadline
(pthread_mutex_t *mutex, rte_duration_ms_t timeout_ms)
124
{
125
rte_status_t status;
126
struct
timespec deadline;
127
128
if
(clock_gettime(CLOCK_MONOTONIC, &deadline) != 0)
129
{
130
status = RTE_STATUS_INTERNAL_ERROR;
/* no deadline - never wait unbounded */
131
}
132
else
133
{
134
bool
waiting;
135
136
deadline_add_ms
(&deadline, timeout_ms);
137
status =
try_lock_once
(mutex);
138
waiting = (status == RTE_STATUS_TIMEOUT);
139
while
(waiting)
140
{
141
struct
timespec now;
142
143
if
(clock_gettime(CLOCK_MONOTONIC, &now) != 0)
144
{
145
status = RTE_STATUS_INTERNAL_ERROR;
146
waiting =
false
;
147
}
148
else
149
{
150
int64_t remaining_ns = (((int64_t)deadline.tv_sec - (int64_t)now.tv_sec) * POSIX_LOCK_NS_PER_S) +
151
((int64_t)deadline.tv_nsec - (int64_t)now.tv_nsec);
152
153
if
(remaining_ns <= 0)
154
{
155
waiting =
false
;
/* deadline reached: status stays RTE_STATUS_TIMEOUT */
156
}
157
else
158
{
159
struct
timespec nap;
160
161
nap.tv_sec = 0;
162
nap.tv_nsec = (long)((remaining_ns <
POSIX_LOCK_POLL_NS
) ? remaining_ns :
POSIX_LOCK_POLL_NS
);
163
/* An EINTR only ends the sleep early; the deadline still bounds the loop. */
164
(void)nanosleep(&nap, NULL);
165
status =
try_lock_once
(mutex);
166
waiting = (status == RTE_STATUS_TIMEOUT);
167
}
168
}
169
}
170
}
171
return
status;
172
}
173
#endif
174
176
static
void
deadline_add_ms
(
struct
timespec *ts, rte_duration_ms_t ms)
177
{
178
rte_duration_ms_t whole_s = ms / 1000U;
179
rte_duration_ms_t rest_ms = ms % 1000U;
180
181
ts->tv_sec += (time_t)whole_s;
182
ts->tv_nsec += (long)rest_ms *
POSIX_LOCK_NS_PER_MS
;
183
if
(ts->tv_nsec >= POSIX_LOCK_NS_PER_S)
184
{
185
ts->tv_sec += 1;
186
ts->tv_nsec -= POSIX_LOCK_NS_PER_S;
187
}
188
}
posix_osa_lock_bounded
rte_status_t posix_osa_lock_bounded(pthread_mutex_t *mutex, rte_duration_ms_t timeout_ms)
Waits at most timeout_ms for a pthread mutex.
Definition
rte_posix_osadapter_lock.c:44
deadline_add_ms
static void deadline_add_ms(struct timespec *ts, rte_duration_ms_t ms)
Definition
rte_posix_osadapter_lock.c:176
lock_until_deadline
static rte_status_t lock_until_deadline(pthread_mutex_t *mutex, rte_duration_ms_t timeout_ms)
Definition
rte_posix_osadapter_lock.c:123
try_lock_once
static rte_status_t try_lock_once(pthread_mutex_t *mutex)
Definition
rte_posix_osadapter_lock.c:68
POSIX_LOCK_POLL_NS
#define POSIX_LOCK_POLL_NS
Definition
rte_posix_osadapter_lock.c:28
POSIX_LOCK_NS_PER_MS
#define POSIX_LOCK_NS_PER_MS
Definition
rte_posix_osadapter_lock.c:24
rte_posix_osadapter_lock.h
Private helper: a bounded wait for a pthread mutex (OSA rule R2: every wait bounded).
src
rte_posix_osadapter_lock.c
Generated by
1.18.0