/******************************************************************************* * Copyright (C) 2018 Cadence Design Systems, Inc. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to use this Software with Cadence processor cores only and * not with any other processors and platforms, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ #ifndef __XF_H #error "xf-osal.h mustn't be included directly" #endif /******************************************************************************* * Includes ******************************************************************************/ #include #include #include #include #include #include #include /******************************************************************************* * Tracing primitive ******************************************************************************/ #define __xf_puts(str) \ ALOG(LOG_INFO, "PROXY", "%s", (str)) /******************************************************************************* * Lock operation ******************************************************************************/ /* ...lock definition */ typedef pthread_mutex_t xf_lock_t; /* ...lock initialization */ static inline void __xf_lock_init(xf_lock_t *lock) { pthread_mutex_init(lock, NULL); } /* ...lock acquisition */ static inline void __xf_lock(xf_lock_t *lock) { pthread_mutex_lock(lock); } /* ...lock release */ static inline void __xf_unlock(xf_lock_t *lock) { pthread_mutex_unlock(lock); } /******************************************************************************* * Waiting object ******************************************************************************/ /* ...waiting object handle */ typedef struct __xf_wait { /* ...conditional variable */ pthread_cond_t wait; /* ...waiting mutex */ pthread_mutex_t mutex; } xf_wait_t; /* ...initialize waiting object */ static inline void __xf_wait_init(xf_wait_t *w) { pthread_cond_init(&w->wait, NULL); pthread_mutex_init(&w->mutex, NULL); } /* ...prepare to waiting */ static inline void __xf_wait_prepare(xf_wait_t *w) { pthread_mutex_lock(&w->mutex); } #define __xf_wait_prepare(w) \ ({ \ TRACE(1, _x("prepare-wait")); \ (__xf_wait_prepare)(w); \ }) /* ...wait until event is signalled */ static inline int __xf_wait(xf_wait_t *w, u32 timeout) { struct timespec ts; struct timeval tv; int r; /* ...wait with or without timeout (communication mutex is taken) */ if (!timeout) { r = -pthread_cond_wait(&w->wait, &w->mutex); } else { /* ...get current time */ gettimeofday(&tv, NULL); /* ...set absolute timeout */ ts.tv_sec = tv.tv_sec + timeout / 1000; ts.tv_nsec = tv.tv_usec * 1000 + (timeout % 1000) * 1000000; (ts.tv_nsec >= 1000000000 ? ts.tv_sec++, ts.tv_nsec -= 1000000000 : 0); /* ...wait conditionally with absolute timeout*/ r = -pthread_cond_timedwait(&w->wait, &w->mutex, &ts); } /* ...leave with communication mutex taken */ return r; } #define __xf_wait(w, timeout) \ ({ \ int __r; \ TRACE(1, _x("wait")); \ __r = (__xf_wait)(w, timeout); \ TRACE(1, _x("resume")); \ __r; \ }) /* ...wake up waiting handle */ static inline void __xf_wakeup(xf_wait_t *w) { /* ...take communication mutex before signaling */ pthread_mutex_lock(&w->mutex); /* ...signalling will resume waiting thread */ pthread_cond_signal(&w->wait); /* ...assure that waiting task will not resume until we say this - is that really needed? - tbd */ pthread_mutex_unlock(&w->mutex); } #define __xf_wakeup(w) \ ({ \ TRACE(1, _x("wakeup")); \ (__xf_wakeup)(w); \ }) /* ...complete waiting operation */ static inline void __xf_wait_complete(xf_wait_t *w) { pthread_mutex_unlock(&w->mutex); } #define __xf_wait_complete(w) \ ({ \ TRACE(1, _x("wait-complete")); \ (__xf_wait_complete)(w); \ }) /******************************************************************************* * Thread support ******************************************************************************/ /* ...thread handle definition */ typedef pthread_t xf_thread_t; /* ...thread creation */ static inline int __xf_thread_create(xf_thread_t *thread, void * (*f)(void *), void *arg) { pthread_attr_t attr; int r; /* ...initialize thread attributes - joinable with minimal stack */ pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN); /* ...create proxy asynchronous thread managing SHMEM */ r = -pthread_create(thread, &attr, f, arg); /* ...destroy thread attributes */ pthread_attr_destroy(&attr); return r; } /* ...terminate thread operation */ static inline int __xf_thread_destroy(xf_thread_t *thread) { void *r; /* ...tell the thread to terminate */ pthread_kill(*thread,SIGUSR1); /* ...wait until thread terminates */ pthread_join(*thread, &r); /* ...return final status */ return (int)(intptr_t)r; }