!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/arch/ia64/sn/sn1/   drwxr-xr-x
Free 318.33 GB of 458.09 GB (69.49%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     sv.c (12.99 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2000 Silicon Graphics, Inc.  All rights reserved
 *
 * This implemenation of synchronization variables is heavily based on
 * one done by Steve Lord <lord@sgi.com>
 *
 * Paul Cassella <pwc@sgi.com>
 */

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>

#include <asm/semaphore.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
#include <asm/current.h>

#include <asm/sn/sv.h>

/* Define this to have sv_test() run some simple tests.
   kernel_thread() must behave as expected when this is called.  */
#undef RUN_SV_TEST

#define DEBUG

/* Set up some macros so sv_wait(), sv_signal(), and sv_broadcast()
   can sanity check interrupt state on architectures where we know
   how. */
#ifdef DEBUG
 #define SV_DEBUG_INTERRUPT_STATE
 #ifdef __mips64
  #define SV_TEST_INTERRUPTS_ENABLED(flags) ((flags & 0x1) != 0)
  #define SV_TEST_INTERRUPTS_DISABLED(flags) ((flags & 0x1) == 0)
  #define SV_INTERRUPT_TEST_WORKERS 31
 #elif defined(__ia64)
  #define SV_TEST_INTERRUPTS_ENABLED(flags) ((flags & 0x4000) != 0)
  #define SV_TEST_INTERRUPTS_DISABLED(flags) ((flags & 0x4000) == 0)
  #define SV_INTERRUPT_TEST_WORKERS 4 /* simulator's slow */
 #else
  #undef  SV_DEBUG_INTERRUPT_STATE
  #define SV_INTERRUPT_TEST_WORKERS 4 /* reasonable? default. */
 #endif /* __mips64 */
#endif /* DEBUG */


/* XXX FIXME hack hack hack.  Our mips64 tree is from before the
   switch to WQ_FLAG_EXCLUSIVE, and our ia64 tree is from after it. */
#ifdef TASK_EXCLUSIVE
  #undef EXCLUSIVE_IN_QUEUE
#else
  #define EXCLUSIVE_IN_QUEUE
  #define TASK_EXCLUSIVE 0 /* for the set_current_state() in sv_wait() */
#endif


static inline void sv_lock(sv_t *sv) {
    spin_lock(&sv->sv_lock);
}

static inline void sv_unlock(sv_t *sv) {
    spin_unlock(&sv->sv_lock);
}

/* up() is "extern inline", so we can't pass its address to sv_wait.
   Use this function's address instead. */
static void up_wrapper(struct semaphore *sem) {
    up(sem);
}

/* spin_unlock() is sometimes a macro. */
static void spin_unlock_wrapper(spinlock_t *s) {
    spin_unlock(s);
}

/* XXX Perhaps sv_wait() should do the switch() each time and avoid
   the extra indirection and the need for the _wrapper functions? */

static inline void sv_set_mon_type(sv_t *sv, int type) {
    switch (type) {
    case SV_MON_SPIN:
        sv->sv_mon_unlock_func =
          (sv_mon_unlock_func_t)spin_unlock_wrapper;
        break;
    case SV_MON_SEMA:
        sv->sv_mon_unlock_func =
          (sv_mon_unlock_func_t)up_wrapper;
        if(sv->sv_flags & SV_INTS) {
            printk(KERN_ERR "sv_set_mon_type: The monitor lock "
                   "cannot be shared with interrupts if it is a "
                   "semaphore!\n");
            BUG();
        }
        if(sv->sv_flags & SV_BHS) {
            printk(KERN_ERR "sv_set_mon_type: The monitor lock "
                   "cannot be shared with bottom-halves if it is "
                   "a semaphore!\n");
            BUG();
        }
        break;
#if 0 
    /*
     * If needed, and will need to think about interrupts.  This
     * may be needed, for example, if someone wants to use sv's
     * with something like dev_base; writers need to hold two
     * locks. 
     */
    case SV_MON_CUSTOM: 
        {
        struct sv_mon_custom *c = lock;
        sv->sv_mon_unlock_func = c->sv_mon_unlock_func;
        sv->sv_mon_lock        = c->sv_mon_lock;
        break;
        }
#endif
        
    default:
        printk(KERN_ERR "sv_set_mon_type: unknown type %d (0x%x)! "
               "(flags 0x%x)\n", type, type, sv->sv_flags);
        BUG();
        break;
    }
    sv->sv_flags |= type;
}

static inline void sv_set_ord(sv_t *sv, int ord) {
    if (!ord)
        ord = SV_ORDER_DEFAULT;

    if (ord != SV_ORDER_FIFO && ord != SV_ORDER_LIFO) {
        printk(KERN_EMERG "sv_set_ord: unknown order %d (0x%x)! ",
               ord, ord);
        BUG();
    }

    sv->sv_flags |= ord;
}

void sv_init(sv_t *sv, sv_mon_lock_t *lock, int flags) 
{
    int ord = flags & SV_ORDER_MASK;
    int type = flags & SV_MON_MASK;

    /* Copy all non-order, non-type flags */
    sv->sv_flags = (flags & ~(SV_ORDER_MASK | SV_MON_MASK));

    if((sv->sv_flags & (SV_INTS | SV_BHS)) == (SV_INTS | SV_BHS)) {
      printk(KERN_ERR "sv_init: do not set both SV_INTS and SV_BHS, only SV_INTS.\n");
      BUG();
    }

    sv_set_ord(sv, ord);
    sv_set_mon_type(sv, type);

    /* If lock is NULL, we'll get it from sv_wait_compat() (and
           ignore it in sv_signal() and sv_broadcast()). */
    sv->sv_mon_lock = lock;

    spin_lock_init(&sv->sv_lock);
    init_waitqueue_head(&sv->sv_waiters);
}

/*
 * The associated lock must be locked on entry.  It is unlocked on return.
 *
 * Return values:
 *
 * n < 0 : interrupted,  -n jiffies remaining on timeout, or -1 if timeout == 0
 * n = 0 : timeout expired
 * n > 0 : sv_signal()'d, n jiffies remaining on timeout, or 1 if timeout == 0
 */
signed long sv_wait(sv_t *sv, int sv_wait_flags, unsigned long timeout) 
{
    DECLARE_WAITQUEUE( wait, current );
    unsigned long flags;
    signed long ret = 0;

#ifdef SV_DEBUG_INTERRUPT_STATE
    {
    unsigned long flags;
    __save_flags(flags);

    if(sv->sv_flags & SV_INTS) {
        if(SV_TEST_INTERRUPTS_ENABLED(flags)) {
            printk(KERN_ERR "sv_wait: SV_INTS and interrupts "
                   "enabled (flags: 0x%lx)\n", flags);
            BUG();
        }
    } else {
        if (SV_TEST_INTERRUPTS_DISABLED(flags)) {
            printk(KERN_WARNING "sv_wait: !SV_INTS and interrupts "
                   "disabled! (flags: 0x%lx)\n", flags);
        }
    }
    }
#endif  /* SV_DEBUG_INTERRUPT_STATE */

    sv_lock(sv);

    sv->sv_mon_unlock_func(sv->sv_mon_lock);

    /* Add ourselves to the wait queue and set the state before
     * releasing the sv_lock so as to avoid racing with the
     * wake_up() in sv_signal() and sv_broadcast(). 
     */

    /* don't need the _irqsave part, but there is no wq_write_lock() */
    wq_write_lock_irqsave(&sv->sv_waiters.lock, flags);

#ifdef EXCLUSIVE_IN_QUEUE
    wait.flags |= WQ_FLAG_EXCLUSIVE;
#endif

    switch(sv->sv_flags & SV_ORDER_MASK) {
    case SV_ORDER_FIFO:
        __add_wait_queue_tail(&sv->sv_waiters, &wait);
        break;
    case SV_ORDER_FILO:
        __add_wait_queue(&sv->sv_waiters, &wait);
        break;
    default:
        printk(KERN_ERR "sv_wait: unknown order!  (sv: 0x%p, flags: 0x%x)\n",
                    sv, sv->sv_flags);
        BUG();
    }
    wq_write_unlock_irqrestore(&sv->sv_waiters.lock, flags);

    if(sv_wait_flags & SV_WAIT_SIG)
        set_current_state(TASK_EXCLUSIVE | TASK_INTERRUPTIBLE  );
    else
        set_current_state(TASK_EXCLUSIVE | TASK_UNINTERRUPTIBLE);

    spin_unlock(&sv->sv_lock);

    if(sv->sv_flags & SV_INTS)
        local_irq_enable();
    else if(sv->sv_flags & SV_BHS)
        local_bh_enable();

    if (timeout)
        ret = schedule_timeout(timeout);
    else
        schedule();

    if(current->state != TASK_RUNNING) /* XXX Is this possible? */ {
        printk(KERN_ERR "sv_wait: state not TASK_RUNNING after "
               "schedule().\n");
        set_current_state(TASK_RUNNING);
    }

    remove_wait_queue(&sv->sv_waiters, &wait);

    /* Return cases:
       - woken by a sv_signal/sv_broadcast
       - woken by a signal
       - woken by timeout expiring
    */

    /* XXX This isn't really accurate; we may have been woken
           before the signal anyway.... */
    if(signal_pending(current))
        return timeout ? -ret : -1;
    return timeout ? ret : 1;
}


void sv_signal(sv_t *sv) 
{
    /* If interrupts can acquire this lock, they can also acquire the
       sv_mon_lock, which we must already have to have called this, so
       interrupts must be disabled already.  If interrupts cannot
       contend for this lock, we don't have to worry about it. */

#ifdef SV_DEBUG_INTERRUPT_STATE
    if(sv->sv_flags & SV_INTS) {
        unsigned long flags;
        __save_flags(flags);
        if(SV_TEST_INTERRUPTS_ENABLED(flags))
            printk(KERN_ERR "sv_signal: SV_INTS and "
            "interrupts enabled! (flags: 0x%lx)\n", flags);
    }
#endif /* SV_DEBUG_INTERRUPT_STATE */

    sv_lock(sv);
    wake_up(&sv->sv_waiters);
    sv_unlock(sv);
}

void sv_broadcast(sv_t *sv) 
{
#ifdef SV_DEBUG_INTERRUPT_STATE
    if(sv->sv_flags & SV_INTS) {
        unsigned long flags;
        __save_flags(flags);
        if(SV_TEST_INTERRUPTS_ENABLED(flags))
            printk(KERN_ERR "sv_broadcast: SV_INTS and "
                   "interrupts enabled! (flags: 0x%lx)\n", flags);
    }
#endif /* SV_DEBUG_INTERRUPT_STATE */

    sv_lock(sv);
    wake_up_all(&sv->sv_waiters);
    sv_unlock(sv);
}

void sv_destroy(sv_t *sv) 
{
    if(!spin_trylock(&sv->sv_lock)) {
        printk(KERN_ERR "sv_destroy: someone else has sv 0x%p locked!\n", sv);
        BUG();
    }

    /* XXX Check that the waitqueue is empty? 
           Mark the sv destroyed?
    */
}


#ifdef RUN_SV_TEST

static DECLARE_MUTEX_LOCKED(talkback);
static DECLARE_MUTEX_LOCKED(sem);
sv_t sv;
sv_t sv_filo;

static int sv_test_1_w(void *arg) 
{
    printk("sv_test_1_w: acquiring spinlock 0x%p...\n", arg);

    spin_lock((spinlock_t*)arg);
    printk("sv_test_1_w: spinlock acquired, waking sv_test_1_s.\n");

    up(&sem);

    printk("sv_test_1_w: sv_spin_wait()'ing.\n");

    sv_spin_wait(&sv, arg);

    printk("sv_test_1_w: talkback.\n");
    up(&talkback);

    printk("sv_test_1_w: exiting.\n");
    return 0;
}

static int sv_test_1_s(void *arg) 
{
    printk("sv_test_1_s: waiting for semaphore.\n");
    down(&sem);
    printk("sv_test_1_s: semaphore acquired.  Acquiring spinlock.\n");
    spin_lock((spinlock_t*)arg);
    printk("sv_test_1_s: spinlock acquired.  sv_signaling.\n");
    sv_signal(&sv);
    printk("sv_test_1_s: talkback.\n");
    up(&talkback);
    printk("sv_test_1_s: exiting.\n");
    return 0;

}

static int count;
static DECLARE_MUTEX(monitor);

static int sv_test_2_w(void *arg) 
{
    int dummy = count++;
    sv_t *sv = (sv_t *)arg;

    down(&monitor);
    up(&talkback);
    printk("sv_test_2_w: thread %d started, sv_waiting.\n", dummy);
    sv_sema_wait(sv, &monitor);
    printk("sv_test_2_w: thread %d woken, exiting.\n", dummy);
    up(&sem);
    return 0;
}

static int sv_test_2_s_1(void *arg) 
{
    int i;
    sv_t *sv = (sv_t *)arg;

    down(&monitor);
    for(i = 0; i < 3; i++) {
        printk("sv_test_2_s_1: waking one thread.\n");
        sv_signal(sv);
        down(&sem);
    }

    printk("sv_test_2_s_1: signaling and broadcasting again.  Nothing should happen.\n");
    sv_signal(sv);
    sv_broadcast(sv);
    sv_signal(sv);
    sv_broadcast(sv);

    printk("sv_test_2_s_1: talkbacking.\n");
    up(&talkback);
    up(&monitor);
    return 0;
}

static int sv_test_2_s(void *arg) 
{
    int i;
    sv_t *sv = (sv_t *)arg;

    down(&monitor);
    for(i = 0; i < 3; i++) {
        printk("sv_test_2_s: waking one thread (should be %d.)\n", i);
        sv_signal(sv);
        down(&sem);
    }

    printk("sv_test_3_s: waking remaining threads with broadcast.\n");
    sv_broadcast(sv);
    for(; i < 10; i++)
        down(&sem);

    printk("sv_test_3_s: sending talkback.\n");
    up(&talkback);

    printk("sv_test_3_s: exiting.\n");
    up(&monitor);
    return 0;
}


static void big_test(sv_t *sv) 
{
    int i;

    count = 0;

    for(i = 0; i < 3; i++) {
        printk("big_test: spawning thread %d.\n", i);
        kernel_thread(sv_test_2_w, sv, 0);
        down(&talkback);
    }

    printk("big_test: spawning first wake-up thread.\n");
    kernel_thread(sv_test_2_s_1, sv, 0);

    down(&talkback);
    printk("big_test: talkback happened.\n");


    for(i = 3; i < 13; i++) {
        printk("big_test: spawning thread %d.\n", i);
        kernel_thread(sv_test_2_w, sv, 0);
        down(&talkback);
    }

    printk("big_test: spawning wake-up thread.\n");
    kernel_thread(sv_test_2_s, sv, 0);

    down(&talkback);
}

sv_t int_test_sv;
spinlock_t int_test_spin = SPIN_LOCK_UNLOCKED;
int int_test_ready;
static int irqtestcount;

static int interrupt_test_worker(void *unused) 
{
    int id = ++irqtestcount;
    int it = 0;
            unsigned long flags, flags2;

    printk("ITW: thread %d started.\n", id);

    while(1) {
        __save_flags(flags2);
        if(jiffies % 3) {
            printk("ITW %2d %5d: irqsaving          (%lx)\n", id, it, flags2);
            spin_lock_irqsave(&int_test_spin, flags);
        } else {
            printk("ITW %2d %5d: spin_lock_irqing   (%lx)\n", id, it, flags2);
            spin_lock_irq(&int_test_spin);
        }

        __save_flags(flags2);
        printk("ITW %2d %5d: locked, sv_waiting (%lx).\n", id, it, flags2);
        sv_wait(&int_test_sv, 0, 0);

        __save_flags(flags2);
        printk("ITW %2d %5d: wait finished      (%lx), pausing\n", id, it, flags2);
        set_current_state(TASK_INTERRUPTIBLE);
        schedule_timeout(jiffies & 0xf);
        if(current->state != TASK_RUNNING)
          printk("ITW:  current->state isn't RUNNING after schedule!\n");
        it++;
    }
}

static void interrupt_test(void) 
{
    int i;

    printk("interrupt_test: initing sv.\n");
    sv_init(&int_test_sv, &int_test_spin, SV_MON_SPIN | SV_INTS);

    for(i = 0; i < SV_INTERRUPT_TEST_WORKERS; i++) {
        printk("interrupt_test: starting test thread %d.\n", i);
        kernel_thread(interrupt_test_worker, 0, 0);
    }
    printk("interrupt_test: done with init part.\n");
    int_test_ready = 1;
}

int sv_test(void) 
{
    spinlock_t s = SPIN_LOCK_UNLOCKED;

    sv_init(&sv, &s, SV_MON_SPIN);
    printk("sv_test: starting sv_test_1_w.\n");
    kernel_thread(sv_test_1_w, &s, 0);
    printk("sv_test: starting sv_test_1_s.\n");
    kernel_thread(sv_test_1_s, &s, 0);

    printk("sv_test: waiting for talkback.\n");
    down(&talkback); down(&talkback);
    printk("sv_test: talkback happened, sv_destroying.\n");
    sv_destroy(&sv);

    count = 0;

    printk("sv_test: beginning big_test on sv.\n");

    sv_init(&sv, &monitor, SV_MON_SEMA);
    big_test(&sv);
    sv_destroy(&sv);

    printk("sv_test: beginning big_test on sv_filo.\n");
    sv_init(&sv_filo, &monitor, SV_MON_SEMA | SV_ORDER_FILO);
    big_test(&sv_filo);
    sv_destroy(&sv_filo);

    interrupt_test();

    printk("sv_test: done.\n");
    return 0;
}

__initcall(sv_test);

#endif /* RUN_SV_TEST */

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.014 ]--