1 /*******************************************************************************
2 * Copyright (C) 2018 Cadence Design Systems, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to use this Software with Cadence processor cores only and
7 * not with any other processors and platforms, subject to
8 * the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included
11 * in all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 ******************************************************************************/
22
23 #ifndef __XF_H
24 #error "xf-osal.h mustn't be included directly"
25 #endif
26
27 /*******************************************************************************
28 * Includes
29 ******************************************************************************/
30
31 #include <pthread.h>
32 #include <fcntl.h>
33 #include <limits.h>
34 #include <sys/mman.h>
35 #include <sys/ioctl.h>
36 #include <sys/time.h>
37 #include <log/log.h>
38
39 /*******************************************************************************
40 * Tracing primitive
41 ******************************************************************************/
42
43 #define __xf_puts(str) \
44 ALOG(LOG_INFO, "PROXY", "%s", (str))
45
46 /*******************************************************************************
47 * Lock operation
48 ******************************************************************************/
49
50 /* ...lock definition */
51 typedef pthread_mutex_t xf_lock_t;
52
53 /* ...lock initialization */
__xf_lock_init(xf_lock_t * lock)54 static inline void __xf_lock_init(xf_lock_t *lock)
55 {
56 pthread_mutex_init(lock, NULL);
57 }
58
59 /* ...lock acquisition */
__xf_lock(xf_lock_t * lock)60 static inline void __xf_lock(xf_lock_t *lock)
61 {
62 pthread_mutex_lock(lock);
63 }
64
65 /* ...lock release */
__xf_unlock(xf_lock_t * lock)66 static inline void __xf_unlock(xf_lock_t *lock)
67 {
68 pthread_mutex_unlock(lock);
69 }
70
71 /*******************************************************************************
72 * Waiting object
73 ******************************************************************************/
74
75 /* ...waiting object handle */
76 typedef struct __xf_wait
77 {
78 /* ...conditional variable */
79 pthread_cond_t wait;
80
81 /* ...waiting mutex */
82 pthread_mutex_t mutex;
83
84 } xf_wait_t;
85
86 /* ...initialize waiting object */
__xf_wait_init(xf_wait_t * w)87 static inline void __xf_wait_init(xf_wait_t *w)
88 {
89 pthread_cond_init(&w->wait, NULL);
90 pthread_mutex_init(&w->mutex, NULL);
91 }
92
93 /* ...prepare to waiting */
__xf_wait_prepare(xf_wait_t * w)94 static inline void __xf_wait_prepare(xf_wait_t *w)
95 {
96 pthread_mutex_lock(&w->mutex);
97 }
98
99 #define __xf_wait_prepare(w) \
100 ({ \
101 TRACE(1, _x("prepare-wait")); \
102 (__xf_wait_prepare)(w); \
103 })
104
105 /* ...wait until event is signalled */
__xf_wait(xf_wait_t * w,u32 timeout)106 static inline int __xf_wait(xf_wait_t *w, u32 timeout)
107 {
108 struct timespec ts;
109 struct timeval tv;
110 int r;
111
112 /* ...wait with or without timeout (communication mutex is taken) */
113 if (!timeout)
114 {
115 r = -pthread_cond_wait(&w->wait, &w->mutex);
116 }
117 else
118 {
119 /* ...get current time */
120 gettimeofday(&tv, NULL);
121
122 /* ...set absolute timeout */
123 ts.tv_sec = tv.tv_sec + timeout / 1000;
124 ts.tv_nsec = tv.tv_usec * 1000 + (timeout % 1000) * 1000000;
125 (ts.tv_nsec >= 1000000000 ? ts.tv_sec++, ts.tv_nsec -= 1000000000 : 0);
126
127 /* ...wait conditionally with absolute timeout*/
128 r = -pthread_cond_timedwait(&w->wait, &w->mutex, &ts);
129 }
130
131 /* ...leave with communication mutex taken */
132 return r;
133 }
134
135 #define __xf_wait(w, timeout) \
136 ({ \
137 int __r; \
138 TRACE(1, _x("wait")); \
139 __r = (__xf_wait)(w, timeout); \
140 TRACE(1, _x("resume")); \
141 __r; \
142 })
143
144 /* ...wake up waiting handle */
__xf_wakeup(xf_wait_t * w)145 static inline void __xf_wakeup(xf_wait_t *w)
146 {
147 /* ...take communication mutex before signaling */
148 pthread_mutex_lock(&w->mutex);
149
150 /* ...signalling will resume waiting thread */
151 pthread_cond_signal(&w->wait);
152
153 /* ...assure that waiting task will not resume until we say this - is that really needed? - tbd */
154 pthread_mutex_unlock(&w->mutex);
155 }
156
157 #define __xf_wakeup(w) \
158 ({ \
159 TRACE(1, _x("wakeup")); \
160 (__xf_wakeup)(w); \
161 })
162
163 /* ...complete waiting operation */
__xf_wait_complete(xf_wait_t * w)164 static inline void __xf_wait_complete(xf_wait_t *w)
165 {
166 pthread_mutex_unlock(&w->mutex);
167 }
168
169 #define __xf_wait_complete(w) \
170 ({ \
171 TRACE(1, _x("wait-complete")); \
172 (__xf_wait_complete)(w); \
173 })
174
175 /*******************************************************************************
176 * Thread support
177 ******************************************************************************/
178
179 /* ...thread handle definition */
180 typedef pthread_t xf_thread_t;
181
182 /* ...thread creation */
__xf_thread_create(xf_thread_t * thread,void * (* f)(void *),void * arg)183 static inline int __xf_thread_create(xf_thread_t *thread, void * (*f)(void *), void *arg)
184 {
185 pthread_attr_t attr;
186 int r;
187
188 /* ...initialize thread attributes - joinable with minimal stack */
189 pthread_attr_init(&attr);
190 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
191 pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
192
193 /* ...create proxy asynchronous thread managing SHMEM */
194 r = -pthread_create(thread, &attr, f, arg);
195
196 /* ...destroy thread attributes */
197 pthread_attr_destroy(&attr);
198
199 return r;
200 }
201
202 /* ...terminate thread operation */
__xf_thread_destroy(xf_thread_t * thread)203 static inline int __xf_thread_destroy(xf_thread_t *thread)
204 {
205 void *r;
206
207 /* ...tell the thread to terminate */
208 pthread_kill(*thread,SIGUSR1);
209
210 /* ...wait until thread terminates */
211 pthread_join(*thread, &r);
212
213 /* ...return final status */
214 return (int)(intptr_t)r;
215 }
216