📄 fusionee.c
字号:
return 0;}intfusionee_get_messages (FusionDev *dev, Fusionee *fusionee, void *buf, int buf_size, bool block){ int written = 0; FusionFifo prev_msgs; if (down_interruptible (&fusionee->lock)) return -EINTR; prev_msgs = fusionee->prev_msgs; fusion_fifo_reset( &fusionee->prev_msgs ); while (!fusionee->messages.count) { if (!block) { unlock_fusionee (fusionee); flush_messages( dev, &prev_msgs ); return -EAGAIN; } fusion_sleep_on (&fusionee->wait, &fusionee->lock, 0); if (signal_pending(current)) { flush_messages( dev, &prev_msgs ); return -EINTR; } if (down_interruptible (&fusionee->lock)) { flush_messages( dev, &prev_msgs ); return -EINTR; } } while (fusionee->messages.count) { FusionReadMessage header; Message *message = (Message*) fusionee->messages.first; int bytes = ((message->size + 3) & ~3) + sizeof(header); if (bytes > buf_size) { if (!written) { unlock_fusionee (fusionee); flush_messages( dev, &prev_msgs ); return -EMSGSIZE; } break; } header.msg_type = message->type; header.msg_id = message->id; header.msg_channel = message->channel; header.msg_size = message->size; if (copy_to_user (buf, &header, sizeof(header)) || copy_to_user (buf + sizeof(header), message->data, message->size)) { unlock_fusionee (fusionee); flush_messages( dev, &prev_msgs ); return -EFAULT; } if (bytes > message->size + sizeof(header)) { int pad = bytes - message->size - sizeof(header); u8 *dst = buf + sizeof(header) + message->size; while (pad--) *dst++ = 0; } written += bytes; buf += bytes; buf_size -= bytes; fusion_fifo_get (&fusionee->messages); if (message->callback) fusion_fifo_put( &fusionee->prev_msgs, &message->link ); else kfree( message ); } unlock_fusionee (fusionee); flush_messages( dev, &prev_msgs ); return written;}unsigned intfusionee_poll (FusionDev *dev, Fusionee *fusionee, struct file *file, poll_table *wait){ int ret; FusionID id = fusionee->id; FusionFifo prev_msgs; ret = lock_fusionee (dev, id, &fusionee); if (ret) return POLLERR; prev_msgs = fusionee->prev_msgs; fusion_fifo_reset( &fusionee->prev_msgs ); unlock_fusionee (fusionee); flush_messages( dev, &prev_msgs ); poll_wait (file, &fusionee->wait, wait); ret = lock_fusionee (dev, id, &fusionee); if (ret) return POLLERR; if (fusionee->messages.count) { unlock_fusionee (fusionee); return POLLIN | POLLRDNORM; } unlock_fusionee (fusionee); return 0;}intfusionee_kill (FusionDev *dev, Fusionee *fusionee, FusionID target, int signal, int timeout_ms){ long timeout = -1; while (true) { FusionLink *l; int killed = 0; if (down_interruptible (&dev->fusionee.lock)) return -EINTR; fusion_list_foreach (l, dev->fusionee.list) { Fusionee *f = (Fusionee*) l; if (f != fusionee && (!target || target == f->id)) { struct task_struct *p;#ifdef rcu_read_lock rcu_read_lock();#else read_lock(&tasklist_lock);#endif#ifdef for_each_task // 2.4 for_each_task(p) {#else // for >= 2.6.0 & redhat WS EL3 w/ 2.4 kernel for_each_process(p) {#endif if (p->mm == f->mm) { send_sig_info( signal, (void*)1L /* 1 means from kernel */, p ); killed++; } }#ifdef rcu_read_unlock rcu_read_unlock();#else read_unlock(&tasklist_lock);#endif } } if (!killed || timeout_ms < 0) { up (&dev->fusionee.lock); break; } if (timeout_ms) { switch (timeout) { case 0: /* timed out */ up (&dev->fusionee.lock); return -ETIMEDOUT; case -1: /* setup timeout */ timeout = (timeout_ms * HZ + 500) / 1000; if (!timeout) timeout = 1; /* fall through */ default: fusion_sleep_on (&dev->fusionee.wait, &dev->fusionee.lock, &timeout); break; } } else fusion_sleep_on (&dev->fusionee.wait, &dev->fusionee.lock, NULL); if (signal_pending(current)) return -EINTR; } return 0;}voidfusionee_destroy (FusionDev *dev, Fusionee *fusionee){ FusionFifo prev_msgs; FusionFifo messages; /* Lock list. */ down (&dev->fusionee.lock); /* Lock fusionee. */ down (&fusionee->lock); prev_msgs = fusionee->prev_msgs; messages = fusionee->messages; /* Remove from list. */ fusion_list_remove (&dev->fusionee.list, &fusionee->link); /* Wake up waiting killer. */ wake_up_interruptible_all (&dev->fusionee.wait); /* Unlock list. */ up (&dev->fusionee.lock); /* Release locks, references, ... */ fusion_call_destroy_all (dev, fusionee->id); fusion_skirmish_dismiss_all (dev, fusionee->id); fusion_reactor_detach_all (dev, fusionee->id); fusion_property_cede_all (dev, fusionee->id); fusion_ref_clear_all_local (dev, fusionee->id); fusion_shmpool_detach_all (dev, fusionee->id); /* Unlock fusionee. */ up (&fusionee->lock); /* Free all pending messages. */ flush_messages( dev, &prev_msgs ); flush_messages( dev, &messages ); /* Free fusionee data. */ kfree (fusionee);}FusionIDfusionee_id( const Fusionee *fusionee ){ return fusionee->id;}/******************************************************************************/static intlookup_fusionee (FusionDev *dev, FusionID id, Fusionee **ret_fusionee){ FusionLink *l; if (down_interruptible (&dev->fusionee.lock)) return -EINTR; fusion_list_foreach (l, dev->fusionee.list) { Fusionee *fusionee = (Fusionee *) l; if (fusionee->id == id) { *ret_fusionee = fusionee; return 0; } } up (&dev->fusionee.lock); return -EINVAL;}static intlock_fusionee (FusionDev *dev, FusionID id, Fusionee **ret_fusionee){ int ret; Fusionee *fusionee; ret = lookup_fusionee (dev, id, &fusionee); if (ret) return ret; fusion_list_move_to_front (&dev->fusionee.list, &fusionee->link); if (down_interruptible (&fusionee->lock)) { up (&dev->fusionee.lock); return -EINTR; } up (&dev->fusionee.lock); *ret_fusionee = fusionee; return 0;}static voidunlock_fusionee (Fusionee *fusionee){ up (&fusionee->lock);}/******************************************************************************/static voidflush_messages( FusionDev *dev, FusionFifo *fifo ){ Message *message; while ((message = (Message*) fusion_fifo_get( fifo )) != NULL) { if (message->callback) message->callback( dev, message->id, message->callback_ctx, message->callback_param ); kfree( message ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -