diff -uNrb linux-fusion-8.1.1_or/linux/drivers/char/fusion/call.c linux-fusion-8.1.1/linux/drivers/char/fusion/call.c --- linux-fusion-8.1.1_or/linux/drivers/char/fusion/call.c 2009-03-31 15:04:32.000000000 +0200 +++ linux-fusion-8.1.1/linux/drivers/char/fusion/call.c 2010-05-07 20:15:33.000000000 +0200 @@ -42,6 +42,7 @@ int call_id; unsigned int serial; + int caller_pid; } FusionCallExecution; typedef struct { @@ -102,6 +103,31 @@ free_all_executions(call); } + +static void print_call( FusionCall* call ) +{ + FusionEntry *entry; + FusionLink *e; + + entry = &call->entry; + + printk( KERN_CRIT "%-2d %s, fid:%d, %d calls)", + entry->id, + entry->name[0] ? entry->name : "???", + call->fusion_id, + call->count); + + fusion_list_foreach(e, call->executions) { + FusionCallExecution *exec = (FusionCallExecution *) e; + + printk( "/%lx:%s", + exec->caller ? fusionee_id(exec->caller) : -1, + exec->executed ? "idle" : "busy" ); + } + + printk("\n"); +} + static void fusion_call_print(FusionEntry * entry, void *ctx, struct seq_file *p) { @@ -221,14 +247,21 @@ /* Transfer held skirmishs (locks). */ fusion_skirmish_transfer_all(dev, call->fusion_id, fusionee_id(fusionee), - current->pid); + current->pid, + serial); /* Unlock call and wait for execution result. TODO: add timeout? */ + fusion_sleep_on(&execution->wait, &call->entry.lock, 0); if (signal_pending(current)) { /* Indicate that a signal was received and execution won't be freed by caller. */ execution->caller = NULL; + printk( KERN_EMERG "NDC signal_pending(current) -> exit from fusion_call_execute() without reclaiming our skirmishes. current->pid=%d, fid=0x%08x, call->fusion_id=%d\n", + current->pid, + (int)(fusionee_id(fusionee)), + call->fusion_id ); + return -EINTR; } @@ -300,6 +333,9 @@ /* FIXME: Caller might still have received a signal since check above. */ FUSION_ASSERT(execution->caller != NULL); + /* Return skirmishs. */ + fusion_skirmish_return_all(dev, fusion_id, execution->caller_pid, execution->serial); + /* Wake up caller. */ wake_up_interruptible(&execution->wait); @@ -349,8 +385,11 @@ fusion_sleep_on(&execution->wait, &call->entry.lock, 0); if (signal_pending(current)) + { + printk( KERN_EMERG "NDC signal_pending(current) -> exit from fusion_call_destroy()\n"); return -EINTR; } + } } while (execution); fusion_entry_destroy_locked(call->entry.entries, &call->entry); @@ -402,6 +441,7 @@ memset(execution, 0, sizeof(FusionCallExecution)); execution->caller = caller; + execution->caller_pid = current->pid; execution->call_id = call->entry.id; execution->serial = serial; diff -uNrb linux-fusion-8.1.1_or/linux/drivers/char/fusion/skirmish.c linux-fusion-8.1.1/linux/drivers/char/fusion/skirmish.c --- linux-fusion-8.1.1_or/linux/drivers/char/fusion/skirmish.c 2009-03-31 15:04:32.000000000 +0200 +++ linux-fusion-8.1.1/linux/drivers/char/fusion/skirmish.c 2010-05-07 20:15:32.000000000 +0200 @@ -52,6 +52,13 @@ FusionID transfer_from; int transfer_from_pid; int transfer_count; + unsigned int transfer_serial; + + FusionID transfer2_to; + FusionID transfer2_from; + int transfer2_from_pid; + int transfer2_count; + unsigned int transfer2_serial; #ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK int pre_acquis[MAX_PRE_ACQUISITIONS]; @@ -69,6 +76,87 @@ static unsigned int m_pidlocks[PID_MAX_DEFAULT + 1]; /* FIXME: find cleaner, but still fast method */ static sigset_t m_sigmask; + +static void +print_skirmish_internal( FusionSkirmish* skirmish, const char* pHeader ) +{ + FusionEntry *entry; + char p[16]; + struct timeval now; + static kaboemcount = 100; + + // kaboemcount--; + + do_gettimeofday(&now); + + entry = &skirmish->entry; + + 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) { + sprintf(p, "%3d ms ", diff); + } else if (diff < 1000000) { + sprintf(p, "%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); + + sprintf(p, "%3d.%d h ", diff / 3600, + (diff % 3600) / 360); + } + } else + sprintf(p, " -.- "); + + + printk( "%s %s %-3d.%03d %d %-18s [1] t:%d f:%d fpid:%-4d c:%d s:%d [2] t:%d f:%d fpid:%-4d c:%d s:%d - c:%d f:%d p:%-4d w:%d\n", + pHeader ? pHeader : " ", + p, + entry->last_lock.tv_sec, + (entry->last_lock.tv_usec)/1000000 , + entry->id, + entry->name[0] ? entry->name : "???", + + skirmish->transfer_to, + skirmish->transfer_from, + skirmish->transfer_from_pid, + skirmish->transfer_count, + skirmish->transfer_serial, + + skirmish->transfer2_to, + skirmish->transfer2_from, + skirmish->transfer2_from_pid, + skirmish->transfer2_count, + skirmish->transfer2_serial, + + skirmish->lock_count, + skirmish->lock_fid, + skirmish->lock_pid, + skirmish->entry.waiters + ); + + if( kaboemcount <= 0 ) + { + printk( KERN_EMERG "boem !\n" ); + kill_pgrp(task_pgrp(current), SIGSEGV, 1); + while(1) + { + yield(); + } + } + +} + +static void +print_skirmish( FusionSkirmish* skirmish ) +{ + print_skirmish_internal( skirmish, KERN_EMERG " skirmish" ); +} + + #ifdef FUSION_BLOCK_SIGNALS static int skirmish_signal_handler(void *ctx) { @@ -77,7 +165,7 @@ return 1; } - printk(KERN_DEBUG "FusionSkirmish: Blocking signal for process %d!\n", + printk(KERN_EMERG "FusionSkirmish: Blocking signal for process %d!\n", current->pid); return 0; @@ -111,20 +199,23 @@ } } #endif - - if (skirmish->lock_fid) { - if (skirmish->entry.waiters) - seq_printf(p, " - %dx [0x%08x] (%d) %d WAITING\n", - skirmish->lock_count, skirmish->lock_fid, - skirmish->lock_pid, skirmish->entry.waiters); - else - seq_printf(p, " - %dx [0x%08x] (%d)\n", - skirmish->lock_count, skirmish->lock_fid, - skirmish->lock_pid); - return; - } - - seq_printf(p, "\n"); + seq_printf(p, "[1] t:%d, f:%d, fpid:%d, c:%d s:%d, [2] t:%d, f:%d, fpid:%d, c:%d, s:%d", + skirmish->transfer_to, + skirmish->transfer_from, + skirmish->transfer_from_pid, + skirmish->transfer_count, + skirmish->transfer_serial, + skirmish->transfer2_to, + skirmish->transfer2_from, + skirmish->transfer2_from_pid, + skirmish->transfer2_count, + skirmish->transfer2_serial ); + seq_printf(p, ", c:%d, f:0x%08x, p:%d, waiters:%d\n", + skirmish->lock_count, + skirmish->lock_fid, + skirmish->lock_pid, + skirmish->entry.waiters + ); } FUSION_ENTRY_CLASS(FusionSkirmish, skirmish, NULL, NULL, fusion_skirmish_print) @@ -245,11 +336,14 @@ up(&dev->skirmish.lock); - while (skirmish->lock_pid || (skirmish->transfer_to != 0 && - fusionee_dispatcher_pid(dev, - skirmish-> - transfer_to) != - current->pid)) { + + while ( skirmish->lock_pid + || ( (skirmish->transfer2_to == 0) + && skirmish->transfer_to + && (fusionee_dispatcher_pid(dev, skirmish-> transfer_to) != current->pid)) + || ( skirmish->transfer2_to + && (fusionee_dispatcher_pid(dev, skirmish-> transfer2_to) != current->pid)) ) + { ret = fusion_skirmish_wait(skirmish, NULL); if (ret) return ret; @@ -283,11 +377,13 @@ dev->stat.skirmish_prevail_swoop++; - if (skirmish->lock_fid || (skirmish->transfer_to != 0 && - fusionee_dispatcher_pid(dev, - skirmish-> - transfer_to) != - current->pid)) { + if ( skirmish->lock_fid + || ( (skirmish->transfer2_to == 0) + && skirmish->transfer_to + && (fusionee_dispatcher_pid(dev, skirmish->transfer_to) != current->pid)) + || ( skirmish->transfer2_to + && (fusionee_dispatcher_pid(dev, skirmish-> transfer2_to) != current->pid)) ) + { if (skirmish->lock_pid == current->pid) { skirmish->lock_count++; skirmish->lock_total++; @@ -515,6 +611,8 @@ break; case -EINTR: + printk( KERN_EMERG "NDC fusion_skirmish_wait EINTR()\n"); + /* Return immediately upon signal. */ FUSION_SKIRMISH_LOG ("FusionSkirmish: Interrupted while waiting for notification!\n"); @@ -538,6 +636,7 @@ break; case -EINTR: + printk( KERN_EMERG "NDC fusion_skirmish_wait 2 EINTR()\n"); /* Return immediately upon signal. */ FUSION_SKIRMISH_LOG ("FusionSkirmish: Interrupted while waiting for relock!\n"); @@ -614,11 +713,26 @@ wake_up_interruptible_all(&skirmish->entry.wait); } + if (skirmish->transfer2_from == fusion_id) { + skirmish->transfer2_to = 0; + skirmish->transfer2_from = 0; + skirmish->transfer2_from_pid = 0; + skirmish->transfer2_count = 0; + + wake_up_interruptible_all(&skirmish->entry.wait); + } + if (skirmish->transfer_from == fusion_id) { - skirmish->transfer_to = 0; - skirmish->transfer_from = 0; - skirmish->transfer_from_pid = 0; - skirmish->transfer_count = 0; + skirmish->transfer_to = skirmish->transfer2_to; + skirmish->transfer_from = skirmish->transfer2_from; + skirmish->transfer_from_pid = skirmish->transfer2_from_pid; + skirmish->transfer_count = skirmish->transfer2_count; + if (skirmish->transfer2_to) { + skirmish->transfer2_to = 0; + skirmish->transfer2_from = 0; + skirmish->transfer2_from_pid = 0; + skirmish->transfer2_count = 0; + } wake_up_interruptible_all(&skirmish->entry.wait); } @@ -650,11 +764,26 @@ wake_up_interruptible_all(&skirmish->entry.wait); } + if (skirmish->transfer2_from_pid == pid) { + skirmish->transfer2_to = 0; + skirmish->transfer2_from = 0; + skirmish->transfer2_from_pid = 0; + skirmish->transfer2_count = 0; + + wake_up_interruptible_all(&skirmish->entry.wait); + } + if (skirmish->transfer_from_pid == pid) { - skirmish->transfer_to = 0; - skirmish->transfer_from = 0; - skirmish->transfer_from_pid = 0; - skirmish->transfer_count = 0; + skirmish->transfer_to = skirmish->transfer2_to; + skirmish->transfer_from = skirmish->transfer2_from; + skirmish->transfer_from_pid = skirmish->transfer2_from_pid; + skirmish->transfer_count = skirmish->transfer2_count; + if (skirmish->transfer2_to) { + skirmish->transfer2_to = 0; + skirmish->transfer2_from = 0; + skirmish->transfer2_from_pid = 0; + skirmish->transfer2_count = 0; + } wake_up_interruptible_all(&skirmish->entry.wait); } @@ -667,7 +796,7 @@ void fusion_skirmish_transfer_all(FusionDev * dev, - FusionID to, FusionID from, int from_pid) + FusionID to, FusionID from, int from_pid, unsigned int serial) { FusionLink *l; @@ -679,6 +808,7 @@ down(&skirmish->entry.lock); if ( (skirmish->lock_pid == from_pid) && (skirmish->transfer_to == 0) ) { + if (skirmish->transfer_to == 0) { FUSION_ASSERT(skirmish->transfer_from == 0); FUSION_ASSERT(skirmish->transfer_from_pid == 0); FUSION_ASSERT(skirmish->transfer_count == 0); @@ -689,6 +818,24 @@ skirmish->transfer_from_pid = from_pid; skirmish->transfer_count = skirmish->lock_count; + skirmish->transfer_serial = serial; + + skirmish->lock_fid = 0; + skirmish->lock_pid = 0; + skirmish->lock_count = 0; + + wake_up_interruptible_all(&skirmish->entry.wait); + } else if (skirmish->transfer2_to == 0) { + FUSION_ASSERT(skirmish->transfer2_from == 0); + FUSION_ASSERT(skirmish->transfer2_from_pid == 0); + FUSION_ASSERT(skirmish->transfer2_count == 0); + FUSION_ASSERT(skirmish->lock_count > 0); + + skirmish->transfer2_to = to; + skirmish->transfer2_from = from; + skirmish->transfer2_from_pid = from_pid; + skirmish->transfer2_count = skirmish->lock_count; + skirmish->transfer2_serial = serial; skirmish->lock_fid = 0; skirmish->lock_pid = 0; skirmish->lock_count = 0; @@ -695,6 +843,7 @@ wake_up_interruptible_all(&skirmish->entry.wait); } + } up(&skirmish->entry.lock); } @@ -713,11 +862,18 @@ down(&skirmish->entry.lock); - if (skirmish->transfer_from_pid == from_pid) { + if ( (skirmish->transfer2_to == 0) + && skirmish->transfer_to + && (skirmish->transfer_from_pid == from_pid) ) + { FUSION_ASSERT(skirmish->transfer_to != 0); FUSION_ASSERT(skirmish->transfer_from != 0); FUSION_ASSERT(skirmish->transfer_count > 0); - FUSION_ASSUME(skirmish->lock_pid == 0); + if( skirmish->lock_pid != -1 ) + { + print_skirmish( skirmish ); + } + FUSION_ASSERT(skirmish->lock_pid == -1); skirmish->lock_fid = skirmish->transfer_from; skirmish->lock_pid = skirmish->transfer_from_pid; @@ -727,6 +883,68 @@ skirmish->transfer_from = 0; skirmish->transfer_from_pid = 0; skirmish->transfer_count = 0; + } else if ( skirmish->transfer2_to + && (skirmish->transfer2_from_pid == from_pid) ) { + FUSION_ASSERT(skirmish->transfer2_to != 0); + FUSION_ASSERT(skirmish->transfer2_from != 0); + FUSION_ASSERT(skirmish->transfer2_count > 0); + FUSION_ASSERT(skirmish->lock_pid == -1); + + skirmish->lock_fid = skirmish->transfer2_from; + skirmish->lock_pid = skirmish->transfer2_from_pid; + skirmish->lock_count = skirmish->transfer2_count; + + skirmish->transfer2_to = 0; + skirmish->transfer2_from = 0; + skirmish->transfer2_from_pid = 0; + skirmish->transfer2_count = 0; + } + up(&skirmish->entry.lock); + } + + up(&dev->skirmish.lock); +} + +void fusion_skirmish_return_all(FusionDev * dev, int from_fusion_id, int to_pid, unsigned int serial) +{ + FusionLink *l; + + down(&dev->skirmish.lock); + + fusion_list_foreach(l, dev->skirmish.list) { + FusionSkirmish *skirmish = (FusionSkirmish *) l; + + down(&skirmish->entry.lock); + + if (skirmish->transfer2_to == 0) { + if ( skirmish->transfer_to == from_fusion_id && + skirmish->transfer_from_pid == to_pid && + skirmish->transfer_serial == serial ) + { + FUSION_ASSERT(skirmish->transfer_from != 0); + FUSION_ASSERT(skirmish->transfer_count > 0); + if( skirmish->lock_count != 0 ) + { + print_skirmish( skirmish ); + } + FUSION_ASSERT(skirmish->lock_count == 0); + FUSION_ASSERT(skirmish->lock_fid == 0); + FUSION_ASSERT(skirmish->lock_pid == 0); + + skirmish->lock_pid = -1; + } + } + else if (skirmish->transfer2_from_pid == to_pid && + skirmish->transfer2_to == from_fusion_id && + skirmish->transfer2_serial == serial ) + { + FUSION_ASSERT(skirmish->transfer2_from != 0); + FUSION_ASSERT(skirmish->transfer2_count > 0); + FUSION_ASSERT(skirmish->lock_count == 0); + FUSION_ASSERT(skirmish->lock_fid == 0); + FUSION_ASSERT(skirmish->lock_pid == 0); + + skirmish->lock_pid = -1; } up(&skirmish->entry.lock); @@ -734,3 +952,4 @@ up(&dev->skirmish.lock); } + diff -uNrb linux-fusion-8.1.1_or/linux/drivers/char/fusion/skirmish.h linux-fusion-8.1.1/linux/drivers/char/fusion/skirmish.h --- linux-fusion-8.1.1_or/linux/drivers/char/fusion/skirmish.h 2009-03-31 15:04:32.000000000 +0200 +++ linux-fusion-8.1.1/linux/drivers/char/fusion/skirmish.h 2010-05-07 20:15:31.000000000 +0200 @@ -50,8 +50,10 @@ void fusion_skirmish_dismiss_all_from_pid(FusionDev * dev, int pid); void fusion_skirmish_transfer_all(FusionDev * dev, - FusionID to, FusionID from, int from_pid); + FusionID to, FusionID from, int from_pid, unsigned int serial); void fusion_skirmish_reclaim_all(FusionDev * dev, int from_pid); +void fusion_skirmish_return_all(FusionDev * dev, int from_fusion_id, int to_fusion_id, unsigned int serial); + #endif diff -uNrb linux-fusion-8.1.1_or/Makefile linux-fusion-8.1.1/Makefile --- linux-fusion-8.1.1_or/Makefile 2009-03-31 15:04:32.000000000 +0200 +++ linux-fusion-8.1.1/Makefile 2010-06-04 23:41:54.140625000 +0200 @@ -49,7 +49,7 @@ modules: rm -f $(SUB)/Makefile - ln -s Makefile-2.$(K_PATCHLEVEL) $(SUB)/Makefile + cp $(SUB)/Makefile-2.$(K_PATCHLEVEL) $(SUB)/Makefile echo kernel is in $(KERNEL_SOURCE) and version is $(K_SUBLEVEL) ifeq ($(call check-version,2,6,24),1) $(MAKE) -C $(KERNEL_BUILD) \