blob: 6286405eb76f2843db490fc4b17adb7c0677eb08 [file] [log] [blame]
/*******************************************************************************
* 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 <pthread.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <log/log.h>
/*******************************************************************************
* 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;
}