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

📄 skirmish.c

📁 linux下的fusion程序,可以和directfb配合使用
💻 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/types.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/sched.h>#include <linux/fusion.h>#include "fusiondev.h"#include "fusionee.h"#include "list.h"#include "skirmish.h"#define MAX_PRE_ACQUISITIONS  256typedef struct __FUSION_FusionSkirmish FusionSkirmish;struct __FUSION_FusionSkirmish {     FusionEntry  entry;     int          lock_fid;  /* non-zero if locked */     int          lock_pid;     int          lock_count;     int          lock_total;     unsigned int notify_count;     unsigned long  lock_time;#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK     int          pre_acquis[MAX_PRE_ACQUISITIONS];     bool         outer;#endif};/******************************************************************************/#ifndef PID_MAX_DEFAULT#define PID_MAX_DEFAULT PID_MAX#endifstatic unsigned int m_pidlocks[PID_MAX_DEFAULT+1];  /* FIXME: find cleaner, but still fast method */static sigset_t     m_sigmask;#ifdef FUSION_BLOCK_SIGNALSstatic intskirmish_signal_handler( void *ctx ){     if (current->pid <= PID_MAX_DEFAULT && !m_pidlocks[current->pid]) {          unblock_all_signals();          return 1;     }     printk( KERN_DEBUG "FusionSkirmish: Blocking signal for process %d!\n", current->pid );          return 0;}#endif/******************************************************************************/static intfusion_skirmish_print( FusionEntry *entry,                       void        *ctx,                       char        *buf ){     int             written  = 0;     FusionSkirmish *skirmish = (FusionSkirmish*) entry;#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK     int             i, n;     for (i=0, n=0; i<MAX_PRE_ACQUISITIONS; i++) {          if (skirmish->pre_acquis[i]) {               n++;          }     }     written += sprintf( buf + written, "[%2d]%s", n, skirmish->outer ? "." : " " );     for (i=0, n=0; i<MAX_PRE_ACQUISITIONS; i++) {          if (skirmish->pre_acquis[i]) {               written += sprintf( buf + written, "%s%02x", n ? "," : "", skirmish->pre_acquis[i] - 1 );               n++;          }     }#endif     if (skirmish->lock_fid) {          if (skirmish->entry.waiters)               return sprintf( buf + written, " - %dx [0x%08x] (%d)  %d WAITING\n",                               skirmish->lock_count, skirmish->lock_fid,                               skirmish->lock_pid, skirmish->entry.waiters ) + written;          else               return sprintf( buf + written, " - %dx [0x%08x] (%d)\n",                               skirmish->lock_count, skirmish->lock_fid,                               skirmish->lock_pid ) + written;     }     return sprintf( buf + written, "\n" ) + written;}FUSION_ENTRY_CLASS( FusionSkirmish, skirmish, NULL, NULL, fusion_skirmish_print )/******************************************************************************/intfusion_skirmish_init (FusionDev *dev){     fusion_entries_init( &dev->skirmish, &skirmish_class, dev );     create_proc_read_entry( "skirmishs", 0, dev->proc_dir,                             fusion_entries_read_proc, &dev->skirmish );     sigemptyset( &m_sigmask );     sigaddset( &m_sigmask, SIGSTOP );     sigaddset( &m_sigmask, SIGTTIN );     sigaddset( &m_sigmask, SIGTERM );     sigaddset( &m_sigmask, SIGINT );     return 0;}voidfusion_skirmish_deinit (FusionDev *dev){     remove_proc_entry ("skirmishs", dev->proc_dir);     fusion_entries_deinit( &dev->skirmish );}/******************************************************************************/intfusion_skirmish_new (FusionDev *dev, int *ret_id){     return fusion_entry_create( &dev->skirmish, ret_id, NULL );}intfusion_skirmish_prevail (FusionDev *dev, int id, int fusion_id){     int             ret;     FusionSkirmish *skirmish;#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK     FusionSkirmish *s;     int             i;     bool            outer = true;#endif     dev->stat.skirmish_prevail_swoop++;     ret = fusion_skirmish_lock( &dev->skirmish, id, true, &skirmish );     if (ret)          return ret;     if (skirmish->lock_pid == current->pid) {          skirmish->lock_count++;          skirmish->lock_total++;          fusion_skirmish_unlock( skirmish );          up( &dev->skirmish.lock );          return 0;     }#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK     /* look in currently acquired skirmishs for this one being        a pre-acquisition, indicating a potential deadlock */     fusion_list_foreach (s, dev->skirmish.list) {          if (s->lock_pid != current->pid)               continue;          outer = false;          for (i=0; i<MAX_PRE_ACQUISITIONS; i++) {               if (s->pre_acquis[i] == id + 1) {                    printk( KERN_DEBUG "FusionSkirmish: Potential deadlock "                            "between locked 0x%x and to be locked 0x%x in world %d!\n",                            s->entry.id, skirmish->entry.id, dev->index );               }          }     }     if (outer)          skirmish->outer = true;     /* remember all previously acquired skirmishs being pre-acquisitions for        this one, to detect potential deadlocks due to a lock order twist */     fusion_list_foreach (s, dev->skirmish.list) {          int free = -1;          if (s->lock_pid != current->pid)               continue;          for (i=0; i<MAX_PRE_ACQUISITIONS; i++) {               if (skirmish->pre_acquis[i]) {                    if (skirmish->pre_acquis[i] == s->entry.id + 1) {                         break;                    }               }               else                    free = i;          }          /* not found? */          if (i == MAX_PRE_ACQUISITIONS) {               if (free != -1) {                    skirmish->pre_acquis[free] = s->entry.id + 1;               }               else {                    printk( KERN_DEBUG "FusionSkirmish: Too many pre-acquisitions to remember.\n" );                    printk( KERN_DEBUG " [ '%s' ] <- ", skirmish->entry.name );                    for (i=0; i<MAX_PRE_ACQUISITIONS; i++)                         printk( "0x%03x ", skirmish->pre_acquis[i] - 1 );                    printk( "\n" );               }          }     }#endif     up( &dev->skirmish.lock );     while (skirmish->lock_pid) {          ret = fusion_skirmish_wait( skirmish, NULL );          if (ret)               return ret;     }#ifdef FUSION_BLOCK_SIGNALS     if (current->pid <= PID_MAX_DEFAULT && !m_pidlocks[current->pid]++)          block_all_signals( skirmish_signal_handler, dev, &m_sigmask );#endif     skirmish->lock_fid   = fusion_id;     skirmish->lock_pid   = current->pid;     skirmish->lock_count = 1;     skirmish->lock_time  = jiffies;     skirmish->lock_total++;     fusion_skirmish_unlock( skirmish );     return 0;}intfusion_skirmish_swoop (FusionDev *dev, int id, int fusion_id){     int             ret;     FusionSkirmish *skirmish;     ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );     if (ret)          return ret;     dev->stat.skirmish_prevail_swoop++;     if (skirmish->lock_fid) {          if (skirmish->lock_pid == current->pid) {               skirmish->lock_count++;               skirmish->lock_total++;               fusion_skirmish_unlock( skirmish );               return 0;          }          fusion_skirmish_unlock( skirmish );          return -EAGAIN;     }#ifdef FUSION_BLOCK_SIGNALS     if (current->pid <= PID_MAX_DEFAULT && !m_pidlocks[current->pid]++)          block_all_signals( skirmish_signal_handler, dev, &m_sigmask );#endif     skirmish->lock_fid   = fusion_id;     skirmish->lock_pid   = current->pid;     skirmish->lock_count = 1;     skirmish->lock_total++;     fusion_skirmish_unlock( skirmish );     return 0;}intfusion_skirmish_lock_count (FusionDev *dev, int id, int fusion_id, int *ret_lock_count){     int             ret;     FusionSkirmish *skirmish;     ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );     if (ret)          return ret;     if (skirmish->lock_fid == fusion_id &&         skirmish->lock_pid == current->pid)     {          *ret_lock_count = skirmish->lock_count;     }     else     {          *ret_lock_count = 0;      }     fusion_skirmish_unlock( skirmish );     return 0;}intfusion_skirmish_dismiss (FusionDev *dev, int id, int fusion_id){     int             ret;     FusionSkirmish *skirmish;     unsigned long   lock_jiffies = 0;     ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );     if (ret)          return ret;     dev->stat.skirmish_dismiss++;     if (skirmish->lock_pid != current->pid) {          fusion_skirmish_unlock( skirmish );          return -EIO;     }     if (--skirmish->lock_count == 0) {          skirmish->lock_fid = 0;          skirmish->lock_pid = 0;          lock_jiffies = jiffies - skirmish->lock_time;          fusion_skirmish_notify( skirmish, true );#ifdef FUSION_BLOCK_SIGNALS          if (current->pid <= PID_MAX_DEFAULT && ! --m_pidlocks[current->pid])               unblock_all_signals();#endif     }     fusion_skirmish_unlock( skirmish );     /* Locked > 20 ms ? */     if (lock_jiffies > HZ/50)// && current->policy == SCHED_NORMAL)          yield();     return 0;}intfusion_skirmish_destroy (FusionDev *dev, int id){     int             ret;     FusionSkirmish *skirmish;#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK     int             i;     FusionSkirmish *s;#endif     ret = fusion_skirmish_lock( &dev->skirmish, id, true, &skirmish );     if (ret)          return ret;#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK     /* remove from all pre-acquisition lists */     fusion_list_foreach (s, dev->skirmish.list) {          for (i=0; i<MAX_PRE_ACQUISITIONS; i++) {               if (s->pre_acquis[i] == id + 1)                    s->pre_acquis[i] = 0;          }     }#endif     up( &dev->skirmish.lock );#ifdef FUSION_BLOCK_SIGNALS     if (skirmish->lock_pid == current->pid &&         current->pid <= PID_MAX_DEFAULT && ! --m_pidlocks[current->pid])          unblock_all_signals();#endif     fusion_skirmish_unlock( skirmish );     /* FIXME: gap? */     return fusion_entry_destroy( &dev->skirmish, id );}intfusion_skirmish_wait_ (FusionDev *dev, int id, int fusion_id, unsigned int timeout){     int             ret;     int             lock_count;     unsigned int    notify_count;     FusionSkirmish *skirmish;     ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );     if (ret)          return ret;     dev->stat.skirmish_wait++;     if (skirmish->lock_pid != current->pid) {          fusion_skirmish_unlock( skirmish );          return -EIO;     }     lock_count   = skirmish->lock_count;     notify_count = skirmish->notify_count;     skirmish->lock_fid = 0;     skirmish->lock_pid = 0;#ifdef FUSION_BLOCK_SIGNALS     if (current->pid <= PID_MAX_DEFAULT && ! --m_pidlocks[current->pid])          unblock_all_signals();#endif     fusion_skirmish_notify( skirmish, true );     if (timeout) {          long timeout_jiffies = timeout * HZ / 1000;          while (notify_count == skirmish->notify_count) {               ret = fusion_skirmish_wait( skirmish, &timeout_jiffies );               if (ret)                    return ret;          }     }     else {          while (notify_count == skirmish->notify_count) {               ret = fusion_skirmish_wait( skirmish, NULL );               if (ret)                    return ret;          }     }     while (skirmish->lock_pid) {          ret = fusion_skirmish_wait( skirmish, NULL );          if (ret)               return ret;     }#ifdef FUSION_BLOCK_SIGNALS     if (current->pid <= PID_MAX_DEFAULT && !m_pidlocks[current->pid]++)          block_all_signals( skirmish_signal_handler, dev, &m_sigmask );#endif     skirmish->lock_fid   = fusion_id;     skirmish->lock_pid   = current->pid;     skirmish->lock_count = lock_count;     fusion_skirmish_unlock( skirmish );     return 0;}intfusion_skirmish_notify_ (FusionDev *dev, int id, int fusion_id){     int             ret;     FusionSkirmish *skirmish;     ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );     if (ret)          return ret;     dev->stat.skirmish_notify++;     if (skirmish->lock_pid != current->pid) {          fusion_skirmish_unlock( skirmish );          return -EIO;     }     skirmish->notify_count++;     fusion_skirmish_notify( skirmish, true );     fusion_skirmish_unlock( skirmish );     return 0;}voidfusion_skirmish_dismiss_all (FusionDev *dev, int fusion_id){     FusionLink *l;     down (&dev->skirmish.lock);     fusion_list_foreach (l, dev->skirmish.list) {          FusionSkirmish *skirmish = (FusionSkirmish *) l;          down (&skirmish->entry.lock);          if (skirmish->lock_fid == fusion_id) {               m_pidlocks[skirmish->lock_pid] = 0;               skirmish->lock_fid   = 0;               skirmish->lock_pid   = 0;               skirmish->lock_count = 0;               wake_up_interruptible_all (&skirmish->entry.wait);          }          up (&skirmish->entry.lock);     }     up (&dev->skirmish.lock);}voidfusion_skirmish_dismiss_all_from_pid (FusionDev *dev, int pid){     FusionLink *l;     down (&dev->skirmish.lock);     m_pidlocks[pid] = 0;     fusion_list_foreach (l, dev->skirmish.list) {          FusionSkirmish *skirmish = (FusionSkirmish *) l;          down (&skirmish->entry.lock);          if (skirmish->lock_pid == pid) {               skirmish->lock_fid   = 0;               skirmish->lock_pid   = 0;               skirmish->lock_count = 0;               wake_up_interruptible_all (&skirmish->entry.wait);          }          up (&skirmish->entry.lock);     }     up (&dev->skirmish.lock);}

⌨️ 快捷键说明

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