blob: 872254b880beeadaf5b651a664a76026df2e1336 [file] [log] [blame]
/*
* Copyright (c) 2012 Linux Box Corporation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RPC_DPLX_INTERNAL_H
#define RPC_DPLX_INTERNAL_H
#include <rpc/rpc_dplx.h>
struct rpc_dplx_rec; /* in clnt_internal.h (avoids circular dependency) */
struct rpc_dplx_rec_set {
mutex_t clnt_fd_lock; /* XXX check dplx correctness */
struct rbtree_x xt;
};
/* XXX perhaps better off as a flag bit (until we can remove it) */
#define rpc_flag_clear 0
#define rpc_lock_value 1
enum rpc_duplex_callpath {
RPC_DPLX_CLNT = 1,
RPC_DPLX_SVC
};
#define RPC_DPLX_FLAG_NONE 0x0000
#define RPC_DPLX_FLAG_LOCKED 0x0001
#define RPC_DPLX_FLAG_LOCK 0x0002
#define RPC_DPLX_FLAG_LOCKREC 0x0004
#define RPC_DPLX_FLAG_RECLOCKED 0x0008
#define RPC_DPLX_FLAG_UNLOCK 0x0010
#ifndef HAVE_STRLCAT
extern size_t strlcat(char *, const char *, size_t);
#endif
#ifndef HAVE_STRLCPY
extern size_t strlcpy(char *, const char *src, size_t);
#endif
#define RPC_DPLX_LKP_FLAG_NONE 0x0000
#define RPC_DPLX_LKP_IFLAG_LOCKREC 0x0001
#define RPC_DPLX_LKP_OFLAG_ALLOC 0x0002
struct rpc_dplx_rec *rpc_dplx_lookup_rec(int, uint32_t, uint32_t *);
static inline void
rpc_dplx_lock_init(struct rpc_dplx_lock *lock)
{
lock->lock_flag_value = 0;
mutex_init(&lock->we.mtx, NULL);
cond_init(&lock->we.cv, 0, NULL);
}
static inline void
rpc_dplx_lock_destroy(struct rpc_dplx_lock *lock)
{
mutex_destroy(&lock->we.mtx);
cond_destroy(&lock->we.cv);
}
static inline int32_t
rpc_dplx_ref(struct rpc_dplx_rec *rec, u_int flags)
{
int32_t refcnt;
if (!(flags & RPC_DPLX_FLAG_LOCKED))
REC_LOCK(rec);
refcnt = ++(rec->refcnt);
/* release rec lock only if a) we took it and b) caller doesn't
* want it returned locked */
if ((!(flags & RPC_DPLX_FLAG_LOCKED))
&& (!(flags & RPC_DPLX_FLAG_LOCK)))
REC_UNLOCK(rec);
__warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: rec %p rec->refcnt %u", __func__,
rec, refcnt);
return (refcnt);
}
int32_t
rpc_dplx_unref(struct rpc_dplx_rec *rec, u_int flags);
/* swi: send wait impl */
static inline void
rpc_dplx_swi(struct rpc_dplx_rec *rec, uint32_t wait_for)
{
rpc_dplx_lock_t *lk = &rec->send.lock;
mutex_lock(&lk->we.mtx);
while (lk->lock_flag_value != rpc_flag_clear)
cond_wait(&lk->we.cv, &lk->we.mtx);
mutex_unlock(&lk->we.mtx);
}
/* swc: send wait clnt */
static inline void
rpc_dplx_swc(CLIENT *clnt, uint32_t wait_for)
{
struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2;
rpc_dplx_swi(rec, wait_for);
}
/* rwi: recv wait impl */
static inline void
rpc_dplx_rwi(struct rpc_dplx_rec *rec, uint32_t wait_for)
{
rpc_dplx_lock_t *lk = &rec->recv.lock;
mutex_lock(&lk->we.mtx);
while (lk->lock_flag_value != rpc_flag_clear)
cond_wait(&lk->we.cv, &lk->we.mtx);
mutex_unlock(&lk->we.mtx);
}
/* rwc: recv wait clnt */
static inline void
rpc_dplx_rwc(CLIENT *clnt, uint32_t wait_for)
{
struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2;
rpc_dplx_rwi(rec, wait_for);
}
/* ssi: send signal impl */
static inline void
rpc_dplx_ssi(struct rpc_dplx_rec *rec, uint32_t flags)
{
rpc_dplx_lock_t *lk = &rec->send.lock;
if (flags & RPC_DPLX_FLAG_LOCK)
mutex_lock(&lk->we.mtx);
cond_signal(&lk->we.cv);
if (flags & RPC_DPLX_FLAG_LOCK)
mutex_unlock(&lk->we.mtx);
}
/* ssc: send signal clnt */
static inline void
rpc_dplx_ssc(CLIENT *clnt, uint32_t flags)
{
struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2;
rpc_dplx_ssi(rec, flags);
}
/* swf: send wait fd */
#define rpc_dplx_swf(fd, wait_for) \
do { \
struct vc_fd_rec *rec = rpc_dplx_lookup_rec(fd); \
rpc_dplx_swi(rec, wait_for); \
} while (0)
/* rsi: recv signal impl */
static inline void
rpc_dplx_rsi(struct rpc_dplx_rec *rec, uint32_t flags)
{
rpc_dplx_lock_t *lk = &rec->recv.lock;
if (flags & RPC_DPLX_FLAG_LOCK)
mutex_lock(&lk->we.mtx);
cond_signal(&lk->we.cv);
if (flags & RPC_DPLX_FLAG_LOCK)
mutex_unlock(&lk->we.mtx);
}
/* rsc: recv signal clnt */
static inline void
rpc_dplx_rsc(CLIENT *clnt, uint32_t flags)
{
struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2;
rpc_dplx_rsi(rec, flags);
}
/* rwf: recv wait fd */
#define rpc_dplx_rwf(fd, wait_for) \
do { \
struct vc_fd_rec *rec = rpc_dplx_lookup_rec(fd); \
rpc_dplx_rwi(rec, wait_for); \
} while (0)
/* ssf: send signal fd */
#define rpc_dplx_ssf(fd, flags) \
do { \
struct vc_fd_rec *rec = rpc_dplx_lookup_rec(fd); \
rpc_dplx_ssi(rec, flags); \
} while (0)
/* rsf: send signal fd */
#define rpc_dplx_rsf(fd, flags) \
do { \
struct vc_fd_rec *rec = rpc_dplx_lookup_rec(fd); \
rpc_dplx_rsi(rec, flags); \
} while (0)
void rpc_dplx_shutdown(void);
#endif /* RPC_DPLX_INTERNAL_H */