/*
* Copyright (c) 2001-2003 The Trustees of Indiana University.
* All rights reserved.
* Copyright (c) 1998-2001 University of Notre Dame.
* All rights reserved.
* Copyright (c) 1994-1998 The Ohio State University.
* All rights reserved.
*
* This file is part of the LAM/MPI software package. For license
* information, see the LICENSE file in the top level directory of the
* LAM/MPI source distribution.
*
* $HEADER$
*
* $Id: couter.c,v 1.5 2003/11/02 20:08:41 brbarret Exp $
*
* Function: - client protocols
* - OTB version
*/
#include <lam_config.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <kio.h>
#include <kreq.h>
#include <terror.h>
#include <typical.h>
#include <etc_misc.h>
/*
* local functions
*/
static void cipc_preempt(void);
/*
* global functions
*/
int _cipc_init(void);
int _cipc_ksend(struct kreq *pkq, struct kreply *pkr);
int _cipc_krecvfront(struct kreq *pkq);
int _cipc_ksrfront(struct kreq *pkq, struct kreply *pkr);
int _cipc_krecvback(struct kreq *pkq, struct kreply *pkr);
int _cipc_ksrback(struct kreq *pkq, struct kreply *pkr);
int _cipc_kreq(struct kreq *pkq, struct kreply *pkr);
void _cipc_cleanup(void);
/*
* external functions
*/
extern int _cio_init(void); /* initialize kernel I/O */
/* make a kernel request */
extern int _cio_kreq(struct kreq *pkq, struct kreply *pkr);
extern int _cio_kreqback(struct kreply *pkr); /* 1st half of kreq */
extern int _cio_kreqfront(struct kreq *pkq); /* 2nd half of kreq */
extern int _cio_send(struct kmsg *pkmsg); /* send data */
extern int _cio_recv(struct kmsg *pkmsg); /* recv data */
extern void _cio_cleanup(void); /* frees resources */
extern void _ksig_follow(); /* check signals */
extern void (*_lam_signal())(); /* portable signal() */
/*
* external variables
*/
extern struct kio_t _kio; /* Kernel I/O */
/*
* _cipc_init
*
* Function: - initializes OTB client interface
* Returns: - 0 or ERROR
*/
int
_cipc_init()
{
if (_cio_init()) return(LAMERROR);
/*
* Vector LAM_SIGUSR to preemption routine.
*/
if (_lam_signal(LAM_SIGUSR, cipc_preempt) == SIG_ERR) return(LAMERROR);
return(0);
}
/*
* _cipc_ksend
*
* Function: - OTB kernel message send
* - makes KQSEND request to kernel
* Accepts: - kernel request ptr
* - kernel reply ptr
* Returns: - 0 or ERROR
*/
int
_cipc_ksend(struct kreq *pkq, struct kreply *pkr)
{
int r;
sigset_t sigs_preempt;
if (_kio.ki_pid != lam_getpid()) {
errno = ENOTATTACHED;
return(LAMERROR);
}
memcpy((char *) pkq->kq_fyi, (char *) _kio.ki_fyi,
sizeof(_kio.ki_fyi));
sigemptyset(&sigs_preempt);
sigaddset(&sigs_preempt, LAM_SIGUSR);
sigprocmask(SIG_BLOCK, &sigs_preempt, (sigset_t *) 0);
if (_cio_kreq(pkq, pkr)) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(LAMERROR);
}
if (pkr->kr_reply) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(0);
}
pkq->kq_msg.k_length = pkr->kr_length;
r = _cio_send(&pkq->kq_msg);
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(r);
}
/*
* _cipc_krecvfront
*
* Function: - OTB kernel message receive
* - makes KQRECV request to kernel
* Accepts: - kernel request ptr
* Returns: - client/kernel comm. handle or ERROR
*/
int
_cipc_krecvfront(struct kreq *pkq)
{
sigset_t sigs_preempt;
int r;
if (_kio.ki_pid != lam_getpid()) {
errno = ENOTATTACHED;
return(LAMERROR);
}
memcpy((char *) pkq->kq_fyi, (char *) _kio.ki_fyi,
sizeof(_kio.ki_fyi));
sigemptyset(&sigs_preempt);
sigaddset(&sigs_preempt, LAM_SIGUSR);
sigprocmask(SIG_BLOCK, &sigs_preempt, (sigset_t *) 0);
if ((r = _cio_kreqfront(pkq)) < 0) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(LAMERROR);
}
return(r);
}
/*
* _cipc_krecvback
*
* Function: - OTB kernel message receive
* - receives reply for KQRECV from kernel
* - transfers message
* Accepts: - kernel request ptr
* - kernel reply ptr
* Returns: - 0 or ERROR
*/
int
_cipc_krecvback(struct kreq *pkq, struct kreply *pkr)
{
int r;
sigset_t sigs_preempt;
sigemptyset(&sigs_preempt);
sigaddset(&sigs_preempt, LAM_SIGUSR);
if (_cio_kreqback(pkr)) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(LAMERROR);
}
if (pkr->kr_reply) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(0);
}
pkq->kq_msg.k_length = pkr->kr_length;
r = _cio_recv(&pkq->kq_msg);
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(r);
}
/*
* _cipc_ksrfront
*
* Function: - OTB kernel message send/receive front end
* - makes KQSEND followed by KQRECV request to kernel
* Accepts: - kernel request ptr
* - kernel reply ptr
* Returns: - 0 or client/kernel socket
*/
int
_cipc_ksrfront(struct kreq *pkq, struct kreply *pkr)
{
sigset_t sigs_preempt;
int r;
if (_kio.ki_pid != lam_getpid()) {
errno = ENOTATTACHED;
return(LAMERROR);
}
memcpy((char *) pkq->kq_fyi, (char *) _kio.ki_fyi,
sizeof(_kio.ki_fyi));
sigemptyset(&sigs_preempt);
sigaddset(&sigs_preempt, LAM_SIGUSR);
sigprocmask(SIG_BLOCK, &sigs_preempt, (sigset_t *) 0);
if ((r = _cio_kreqfront(pkq)) < 0) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(LAMERROR);
}
if (_cio_kreqback(pkr) < 0) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(LAMERROR);
}
if (pkr->kr_reply) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(0);
}
pkq->kq_msg.k_length = pkr->kr_length;
if (_cio_send(&pkq->kq_msg)) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(LAMERROR);
}
return(r);
}
/*
* _cipc_ksrback
*
* Function: - OTB kernel message send/receive back end
*/
int
_cipc_ksrback(struct kreq *pkq, struct kreply *pkr)
{
int r;
sigset_t sigs_preempt;
sigemptyset(&sigs_preempt);
sigaddset(&sigs_preempt, LAM_SIGUSR);
if (_cio_kreqback(pkr)) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(LAMERROR);
}
if (pkr->kr_reply) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(0);
}
pkq->kq_msg2.k_length = pkr->kr_length;
r = _cio_recv(&pkq->kq_msg2);
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
return(r);
}
/*
* _cipc_kreq
*
* Function: - OTB kernel request
* - makes request to kernel
* Accepts: - kernel request ptr
* - kernel reply ptr
* Returns: - 0 or ERROR
*/
int
_cipc_kreq(struct kreq *pkq, struct kreply *pkr)
{
sigset_t sigs_preempt;
if (_kio.ki_pid != lam_getpid()) {
errno = ENOTATTACHED;
return(LAMERROR);
}
memcpy((char *) pkq->kq_fyi, (char *) _kio.ki_fyi,
sizeof(_kio.ki_fyi));
do {
sigemptyset(&sigs_preempt);
sigaddset(&sigs_preempt, LAM_SIGUSR);
sigprocmask(SIG_BLOCK, &sigs_preempt, (sigset_t *) 0);
if (_cio_kreq(pkq, pkr)) {
sigprocmask(SIG_UNBLOCK, &sigs_preempt,
(sigset_t *) 0);
return(LAMERROR);
}
sigprocmask(SIG_UNBLOCK, &sigs_preempt, (sigset_t *) 0);
/*
* Do we need to follow a signal?
*/
if (pkr->kr_signal) {
_kio.ki_signal |= pkr->kr_signal;
_ksig_follow();
}
} while (pkr->kr_reply == EINTR);
return(0);
}
/*
* _cipc_cleanup
*
* Function: - frees up client resources
*/
void
_cipc_cleanup()
{
_cio_cleanup();
}
/*
* cipc_preempt
*
* Function: - preempts myself
* - signal handler for LAM_SIGUSR
*/
static void
cipc_preempt()
{
struct kreq req; /* kernel request */
struct kreply reply; /* kernel reply */
if (_kio.ki_pid != lam_getpid()) return;
LAM_ZERO_ME(req);
req.kq_req = KQSURRENDER;
req.kq_index = _kio.ki_index;
if (_cio_kreq(&req, &reply)) return;
if (reply.kr_signal) {
_kio.ki_signal |= reply.kr_signal;
_ksig_follow();
}
/*
* Vector LAM_SIGUSR to preemption routine.
*/
if (_lam_signal(LAM_SIGUSR, cipc_preempt) == SIG_ERR) return;
}
syntax highlighted by Code2HTML, v. 0.9.1