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