HelenOS sources

root/kernel/generic/include/ipc/ipc.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


/*
 * Copyright (c) 2006 Ondrej Palkovsky
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - 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.
 * - The name of the author may not be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * 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.
 */

/** @addtogroup kernel_generic_ipc
 * @{
 */
/** @file
 */

#ifndef KERN_IPC_H_
#define KERN_IPC_H_

#include <synch/spinlock.h>
#include <synch/mutex.h>
#include <synch/waitq.h>
#include <abi/ipc/ipc.h>
#include <abi/proc/task.h>
#include <typedefs.h>
#include <mm/slab.h>
#include <cap/cap.h>

struct answerbox;
struct task;
struct call;

typedef enum {
        /** Phone is free and can be allocated */
        IPC_PHONE_FREE = 0,
        /** Phone is connecting somewhere */
        IPC_PHONE_CONNECTING,
        /** Phone is connected */
        IPC_PHONE_CONNECTED,
        /** Phone is hung up, waiting for answers to come */
        IPC_PHONE_HUNGUP,
        /** Phone was hungup from server */
        IPC_PHONE_SLAMMED
} ipc_phone_state_t;

/** Structure identifying phone (in TASK structure) */
typedef struct phone {
        mutex_t lock;
        link_t link;
        struct task *caller;
        struct answerbox *callee;
        /* A call prepared for hangup ahead of time, so that it cannot fail. */
        struct call *hangup_call;
        ipc_phone_state_t state;
        atomic_size_t active_calls;
        /** User-defined label */
        sysarg_t label;
        kobject_t *kobject;
} phone_t;

typedef struct answerbox {
        IRQ_SPINLOCK_DECLARE(lock);

        /** Answerbox is active until it enters cleanup. */
        bool active;

        struct task *task;

        waitq_t wq;

        /**
         * Number of answers the answerbox is expecting to eventually arrive.
         */
        atomic_size_t active_calls;

        /** Phones connected to this answerbox. */
        list_t connected_phones;
        /** Received calls. */
        list_t calls;
        list_t dispatched_calls;  /* Should be hash table in the future */

        /** Answered calls. */
        list_t answers;

        IRQ_SPINLOCK_DECLARE(irq_lock);

        /** Notifications from IRQ handlers. */
        list_t irq_notifs;
} answerbox_t;

typedef struct call {
        kobject_t *kobject;

        /**
         * Task link.
         * Valid only when the call is not forgotten.
         * Protected by the task's active_calls_lock.
         */
        link_t ta_link;

        /** Answerbox link. */
        link_t ab_link;

        unsigned int flags;

        /** Protects the forget member. */
        SPINLOCK_DECLARE(forget_lock);

        /**
         * True if the caller 'forgot' this call and donated it to the callee.
         * Forgotten calls are discarded upon answering (the answer is not
         * delivered) and answered calls cannot be forgotten. Forgotten calls
         * also do not figure on the task's active call list.
         *
         * We keep this separate from the flags so that it is not necessary
         * to take a lock when accessing them.
         */
        bool forget;

        /** True if the call is in the active list. */
        bool active;

        /**
         * Identification of the caller.
         * Valid only when the call is not forgotten.
         */
        struct task *sender;

        /*
         * Answerbox that will receive the answer.
         * This will most of the times be the sender's answerbox,
         * but we allow for useful exceptions.
         */
        answerbox_t *callerbox;

        /** Phone which was used to send the call. */
        phone_t *caller_phone;

        /** Private data to internal IPC. */
        sysarg_t priv;

        /** Data passed from/to userspace. */
        ipc_data_t data;

        /** Method as it was sent in the request. */
        sysarg_t request_method;

        /** Buffer for IPC_M_DATA_WRITE and IPC_M_DATA_READ. */
        uint8_t *buffer;
} call_t;

extern slab_cache_t *phone_cache;

extern answerbox_t *ipc_box_0;

extern kobject_ops_t call_kobject_ops;

extern void ipc_init(void);

extern call_t *ipc_call_alloc(void);

extern errno_t ipc_call_sync(phone_t *, call_t *);
extern errno_t ipc_call(phone_t *, call_t *);
extern errno_t ipc_wait_for_call(answerbox_t *, uint32_t, unsigned int, call_t **);
extern errno_t ipc_forward(call_t *, phone_t *, answerbox_t *, unsigned int);
extern void ipc_answer(answerbox_t *, call_t *);
extern void _ipc_answer_free_call(call_t *, bool);

extern void ipc_phone_init(phone_t *, struct task *);
extern bool ipc_phone_connect(phone_t *, answerbox_t *);
extern errno_t ipc_phone_hangup(phone_t *);

extern void ipc_answerbox_init(answerbox_t *, struct task *);

extern void ipc_cleanup(void);
extern void ipc_backsend_err(phone_t *, call_t *, errno_t);
extern void ipc_answerbox_slam_phones(answerbox_t *, bool);
extern void ipc_cleanup_call_list(answerbox_t *, list_t *);

extern void ipc_print_task(task_id_t);

#endif

/** @}
 */

/* [<][>][^][v][top][bottom][index][help] */
HelenOS homepage, sources at GitHub