📄 fusionee.c
字号:
/* * Fusion Kernel Module * * (c) Copyright 2002-2003 Convergence GmbH * * Written by Denis Oliver Kropp <dok@directfb.org> * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#ifdef HAVE_LINUX_CONFIG_H#include <linux/config.h>#endif#include <linux/version.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/sched.h>#include <asm/uaccess.h>#include <linux/fusion.h>#include "call.h"#include "fifo.h"#include "list.h"#include "fusiondev.h"#include "fusionee.h"#include "property.h"#include "reactor.h"#include "ref.h"#include "skirmish.h"#include "shmpool.h"#if 0#define DEBUG(x...) printk (KERN_DEBUG "Fusion: " x)#else#define DEBUG(x...) do {} while (0)#endifstruct __Fusion_Fusionee { FusionLink link; struct semaphore lock; FusionID id; int pid; FusionFifo messages; FusionFifo prev_msgs; int rcv_total; /* Total number of messages received. */ int snd_total; /* Total number of messages sent. */ wait_queue_head_t wait; bool force_slave; struct mm_struct *mm;};typedef struct { FusionLink link; FusionMessageType type; int id; int channel; int size; void *data; MessageCallback callback; void *callback_ctx; int callback_param;} Message;/******************************************************************************/static int lookup_fusionee (FusionDev *dev, FusionID id, Fusionee **ret_fusionee);static int lock_fusionee (FusionDev *dev, FusionID id, Fusionee **ret_fusionee);static void unlock_fusionee (Fusionee *fusionee);static void flush_messages (FusionDev *dev, FusionFifo *fifo);/******************************************************************************/static intfusionees_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *private){ FusionLink *l; FusionDev *dev = private; int written = 0; if (down_interruptible (&dev->fusionee.lock)) return -EINTR; fusion_list_foreach (l, dev->fusionee.list) { Fusionee *fusionee = (Fusionee*) l; written += sprintf(buf+written, "(%5d) 0x%08lx (%4d messages waiting, %7d received, %7d sent)\n", fusionee->pid, fusionee->id, fusionee->messages.count, fusionee->rcv_total, fusionee->snd_total); if (written < offset) { offset -= written; written = 0; } if (written >= len) break; } up (&dev->fusionee.lock); *start = buf + offset; written -= offset; if (written > len) { *eof = 0; return len; } *eof = 1; return(written<0) ? 0 : written;}intfusionee_init (FusionDev *dev){ init_waitqueue_head (&dev->fusionee.wait); init_MUTEX (&dev->fusionee.lock); create_proc_read_entry("fusionees", 0, dev->proc_dir, fusionees_read_proc, dev); return 0;}voidfusionee_deinit (FusionDev *dev){ FusionLink *l; down (&dev->fusionee.lock); remove_proc_entry ("fusionees", dev->proc_dir); l = dev->fusionee.list; while (l) { FusionLink *next = l->next; Fusionee *fusionee = (Fusionee *) l; while (fusionee->messages.count) { Message *message = (Message*) fusion_fifo_get (&fusionee->messages); kfree (message); } kfree (fusionee); l = next; } up (&dev->fusionee.lock);}/******************************************************************************/intfusionee_new( FusionDev *dev, bool force_slave, Fusionee **ret_fusionee ){ Fusionee *fusionee; fusionee = kmalloc (sizeof(Fusionee), GFP_KERNEL); if (!fusionee) return -ENOMEM; memset (fusionee, 0, sizeof(Fusionee)); if (down_interruptible (&dev->fusionee.lock)) { kfree (fusionee); return -EINTR; } fusionee->pid = current->pid; fusionee->force_slave = force_slave; fusionee->mm = current->mm; init_MUTEX (&fusionee->lock); init_waitqueue_head (&fusionee->wait); fusion_list_prepend (&dev->fusionee.list, &fusionee->link); up (&dev->fusionee.lock); *ret_fusionee = fusionee; return 0;}intfusionee_enter( FusionDev *dev, FusionEnter *enter, Fusionee *fusionee ){ if (enter->api.major != FUSION_API_MAJOR || enter->api.minor > FUSION_API_MINOR) return -ENOPROTOOPT; if (down_interruptible( &dev->enter_lock )) return -EINTR; if (dev->fusionee.last_id || fusionee->force_slave) { while (!dev->enter_ok) { fusion_sleep_on( &dev->enter_wait, &dev->enter_lock, NULL ); if (signal_pending(current)) return -EINTR; if (down_interruptible( &dev->enter_lock )) return -EINTR; } FUSION_ASSERT( dev->fusionee.last_id != 0 ); } fusionee->id = ++dev->fusionee.last_id; up( &dev->enter_lock ); enter->fusion_id = fusionee->id; return 0;}intfusionee_fork( FusionDev *dev, FusionFork *fork, Fusionee *fusionee ){ int ret; ret = fusion_shmpool_fork_all( dev, fusionee->id, fork->fusion_id ); if (ret) return ret; ret = fusion_reactor_fork_all( dev, fusionee->id, fork->fusion_id ); if (ret) return ret; ret = fusion_ref_fork_all_local( dev, fusionee->id, fork->fusion_id ); if (ret) return ret; fork->fusion_id = fusionee->id; return 0;}intfusionee_send_message( FusionDev *dev, Fusionee *sender, FusionID recipient, FusionMessageType msg_type, int msg_id, int msg_channel, int msg_size, const void *msg_data, MessageCallback callback, void *callback_ctx, int callback_param ){ int ret; Message *message; Fusionee *fusionee; DEBUG( "fusionee_send_message (%d -> %d, type %d, id %d, size %d)\n", fusionee->id, recipient, msg_type, msg_id, msg_size ); ret = lookup_fusionee (dev, recipient, &fusionee); if (ret) return ret; if (down_interruptible (&fusionee->lock)) { up (&dev->fusionee.lock); return -EINTR; } if (sender && sender != fusionee) { if (down_interruptible (&sender->lock)) { unlock_fusionee (fusionee); up (&dev->fusionee.lock); return -EINTR; } } up (&dev->fusionee.lock); message = kmalloc (sizeof(Message) + msg_size, GFP_KERNEL); if (!message) { if (sender && sender != fusionee) unlock_fusionee (sender); unlock_fusionee (fusionee); return -ENOMEM; } message->data = message + 1; if (msg_type == FMT_CALL || msg_type == FMT_SHMPOOL) memcpy (message->data, msg_data, msg_size); else if (copy_from_user (message->data, msg_data, msg_size)) { kfree (message); if (sender && sender != fusionee) unlock_fusionee (sender); unlock_fusionee (fusionee); return -EFAULT; } message->type = msg_type; message->id = msg_id; message->channel = msg_channel; message->size = msg_size; message->callback = callback; message->callback_ctx = callback_ctx; message->callback_param = callback_param; fusion_fifo_put (&fusionee->messages, &message->link); fusionee->rcv_total++; if (sender) sender->snd_total++; wake_up_interruptible_all (&fusionee->wait); if (sender && sender != fusionee) unlock_fusionee (sender); unlock_fusionee (fusionee);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -