⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 entries.c

📁 linux进程间高级通信的一个模块 是一个很不错的东西.
💻 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. */#include <linux/config.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/sched.h>#include <linux/time.h>#include <linux/version.h>#include <linux/fusion.h>#include "fusiondev.h"#include "entries.h"voidfusion_entries_init( FusionEntries    *entries,                     FusionEntryClass *class,                     void             *ctx ){     FUSION_ASSERT( entries != NULL );     FUSION_ASSERT( class != NULL );     FUSION_ASSERT( class->object_size >= sizeof(FusionEntry) );     memset( entries, 0, sizeof(FusionEntries) );     entries->class = class;     entries->ctx   = ctx;     init_MUTEX( &entries->lock );}voidfusion_entries_deinit( FusionEntries *entries ){     FusionLink       *tmp;     FusionEntry      *entry;     FusionEntryClass *class;     FUSION_ASSERT( entries != NULL );     FUSION_ASSERT( entries->class != NULL );     class = entries->class;     down( &entries->lock );     fusion_list_foreach_safe (entry, tmp, entries->list) {          if (class->Destroy)               class->Destroy( entry, entries->ctx );          kfree( entry );     }     up( &entries->lock );}intfusion_entries_read_proc(char *buf, char **start, off_t offset,                         int len, int *eof, void *private){     FusionEntry      *entry;     FusionEntryClass *class;     FusionEntries    *entries = private;     int               written = 0;     struct timeval    now;     FUSION_ASSERT( entries != NULL );     FUSION_ASSERT( entries->class != NULL );     class = entries->class;     if (!class->Print)          return -ENOTSUPP;     if (down_interruptible (&entries->lock))          return -EINTR;     do_gettimeofday( &now );     fusion_list_foreach (entry, entries->list) {          if (entry->last_lock.tv_sec) {               int diff = ((now.tv_sec  - entry->last_lock.tv_sec) * 1000 +                           (now.tv_usec - entry->last_lock.tv_usec) / 1000);               if (diff < 1000) {                    written += sprintf( buf + written, "%3d  ms  ", diff );               }               else if (diff < 1000000) {                    written += sprintf( buf + written, "%3d.%d s  ",                                        diff / 1000, (diff % 1000) / 100 );               }               else {                    diff = ( now.tv_sec  - entry->last_lock.tv_sec +                            (now.tv_usec - entry->last_lock.tv_usec) / 1000000);                    written += sprintf( buf + written, "%3d.%d h  ",                                        diff / 3600, (diff % 3600) / 360 );               }          }          else               written += sprintf( buf + written, "  -.-    " );          written += sprintf( buf + written, "(%5d) 0x%08x  ", entry->pid, entry->id );          written += sprintf( buf + written, "%-24s  ", entry->name[0] ? entry->name : "" );          written += class->Print( entry, entries->ctx, buf + written );          if (written < offset) {               offset -= written;               written = 0;          }          if (written >= len)               break;     }     up (&entries->lock);     *start = buf + offset;     written -= offset;     if (written > len) {          *eof = 0;          return len;     }     *eof = 1;     return (written<0) ? 0 : written;}intfusion_entry_create( FusionEntries *entries,                     int           *ret_id ){     int               ret;     FusionEntry      *entry;     FusionEntryClass *class;     FUSION_ASSERT( entries != NULL );     FUSION_ASSERT( entries->class != NULL );     FUSION_ASSERT( ret_id != NULL );     class = entries->class;     entry = kmalloc( class->object_size, GFP_KERNEL );     if (!entry)          return -ENOMEM;     memset( entry, 0, class->object_size );     if (down_interruptible( &entries->lock )) {          kfree( entry );          return -EINTR;     }     entry->entries = entries;     entry->id      = entries->ids++;     entry->pid     = current->pid;     init_MUTEX( &entry->lock );     init_waitqueue_head( &entry->wait );     if (class->Init) {          ret = class->Init( entry, entries->ctx );          if (ret) {               kfree( entry );               return ret;          }     }     fusion_list_prepend( &entries->list, &entry->link );     up( &entries->lock );     *ret_id = entry->id;     return 0;}intfusion_entry_destroy( FusionEntries  *entries,                      int             id ){     FusionEntry      *entry;     FusionEntryClass *class;     FUSION_ASSERT( entries != NULL );     FUSION_ASSERT( entries->class != NULL );     class = entries->class;     /* Lock entries. */     if (down_interruptible( &entries->lock ))          return -EINTR;     /* Lookup the entry. */     fusion_list_foreach (entry, entries->list) {          if (entry->id == id)               break;     }     /* Check if no entry was found. */     if (!entry) {          up( &entries->lock );          return -EINVAL;     }     /* Lock the entry. */     if (down_interruptible( &entry->lock )) {          up( &entries->lock );          return -EINTR;     }     /* Remove the entry from the list. */     fusion_list_remove( &entries->list, &entry->link );     /* Wake up any waiting process. */     wake_up_interruptible_all( &entry->wait );     /* Unlock entries. */     up( &entries->lock );     /* Call the destroy function. */     if (class->Destroy)          class->Destroy( entry, entries->ctx );     /* Deallocate the entry. */     kfree( entry );     return 0;}intfusion_entry_set_info( FusionEntries         *entries,                       const FusionEntryInfo *info ){     int          ret;     FusionEntry *entry;     FUSION_ASSERT( entries != NULL );     FUSION_ASSERT( info != NULL );     ret = fusion_entry_lock( entries, info->id, &entry );     if (ret)          return ret;     snprintf( entry->name, FUSION_ENTRY_INFO_NAME_LENGTH, info->name );     fusion_entry_unlock( entry );     return 0;}intfusion_entry_get_info( FusionEntries   *entries,                       FusionEntryInfo *info ){     int          ret;     FusionEntry *entry;     FUSION_ASSERT( entries != NULL );     FUSION_ASSERT( info != NULL );     ret = fusion_entry_lock( entries, info->id, &entry );     if (ret)          return ret;     snprintf( info->name, FUSION_ENTRY_INFO_NAME_LENGTH, entry->name );     fusion_entry_unlock( entry );     return 0;}intfusion_entry_lock( FusionEntries  *entries,                   int             id,                   FusionEntry   **ret_entry ){     FusionEntry *entry;     FUSION_ASSERT( entries != NULL );     FUSION_ASSERT( ret_entry != NULL );     /* Lock entries. */     if (down_interruptible( &entries->lock ))          return -EINTR;     /* Lookup the entry. */     fusion_list_foreach (entry, entries->list) {          if (entry->id == id)               break;     }     /* Check if no entry was found. */     if (!entry) {          up( &entries->lock );          return -EINVAL;     }     FUSION_ASSUME( entry->lock_pid != current->pid );     /* Move the entry to the front of all entries. */     fusion_list_move_to_front( &entries->list, &entry->link );     /* Lock the entry. */     if (down_interruptible( &entry->lock )) {          up( &entries->lock );          return -EINTR;     }     /* Mark as locked. */     entry->lock_pid = current->pid;     /* Keep timestamp, but use the slightly        inexact version to avoid performance impacts. */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && defined _STRUCT_TIMESPEC     entry->last_lock.tv_sec = xtime.tv_sec;     entry->last_lock.tv_usec = xtime.tv_nsec / 1000;#else     entry->last_lock = xtime;#endif     /* Unlock entries. */     up( &entries->lock );     /* Return the locked entry. */     *ret_entry = entry;     return 0;}voidfusion_entry_unlock( FusionEntry *entry ){     FUSION_ASSERT( entry != NULL );     FUSION_ASSUME( entry->lock_pid == current->pid );     entry->lock_pid = 0;     /* Unlock the entry. */     up( &entry->lock );}intfusion_entry_wait( FusionEntry *entry, long *timeout ){     int            ret;     int            id;     FusionEntries *entries;     FusionEntry   *entry2;     FUSION_ASSERT( entry != NULL );     FUSION_ASSERT( entry->entries != NULL );     FUSION_ASSUME( entry->lock_pid == current->pid );     id      = entry->id;     entries = entry->entries;     entry->waiters++;     fusion_sleep_on( &entry->wait, &entry->lock, timeout );     entry->waiters--;     if (timeout && !*timeout)          return -ETIMEDOUT;     if (signal_pending(current))          return -EINTR;     ret = fusion_entry_lock( entries, id, &entry2 );     switch (ret) {          case -EINVAL:               return -EIDRM;          case 0:               if (entry != entry2)                    BUG();     }     return ret;}voidfusion_entry_notify( FusionEntry *entry, bool all ){     FUSION_ASSERT( entry != NULL );     FUSION_ASSUME( entry->lock_pid == current->pid );     if (!entry->waiters)          return;     if (all)          wake_up_interruptible_all( &entry->wait );     else          wake_up_interruptible( &entry->wait );}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -