[hsflinux] Actiontec MD560RD on Dell Inspiron 8200 - System Hangs on Disconnect

Chris Nitkin skatrek at yahoo.com
Wed Aug 28 12:25:46 EDT 2002


Andy, I was sent this email from Marc Bouche:

--snip---

Try replacing /usr/lib/hsf/modules/osspec/ostime.c with the enclosed
one, run hsfconfig -ka and hsfstop. Let me know if it helps..

/*osTime.c

This file includes os specific code for timing related functionalities.

*/

/*
 * Copyright (c) 2001 Conexant Systems, Inc.
 *
 * 1.   Permitted use. Redistribution and use in source and binary forms,
 * with or without modification, are permitted under the terms set forth
 * herein.
 *
 * 2.   Disclaimer of Warranties. CONEXANT AND OTHER CONTRIBUTORS MAKE NO
 * REPRESENTATION ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.
 * IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTIES OF ANY KIND.
 * CONEXANT AND OTHER CONTRIBUTORS DISCLAIMS ALL WARRANTIES WITH REGARD TO
 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, GOOD TITLE AND AGAINST INFRINGEMENT.
 *
 * This software has not been formally tested, and there is no guarantee that
 * it is free of errors including, but not limited to, bugs, defects,
 * interrupted operation, or unexpected results. Any use of this software is
 * at user's own risk.
 *
 * 3.   No Liability.
 *
 * (a) Conexant or contributors shall not be responsible for any loss or
 * damage to Company, its customers, or any third parties for any reason
 * whatsoever, and CONEXANT OR CONTRIBUTORS SHALL NOT BE LIABLE FOR ANY
 * ACTUAL, DIRECT, INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL, OR CONSEQUENTIAL
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED, WHETHER IN CONTRACT, STRICT OR OTHER LEGAL THEORY OF
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * (b) User agrees to hold Conexant and contributors harmless from any
 * liability, loss, cost, damage or expense, including attorney's fees,
 * as a result of any claims which may be made by any person, including
 * but not limited to User, its agents and employees, its customers, or
 * any third parties that arise out of or result from the manufacture,
 * delivery, actual or alleged ownership, performance, use, operation
 * or possession of the software furnished hereunder, whether such claims
 * are based on negligence, breach of contract, absolute liability or any
 * other legal theory.
 *
 * 4.   Notices. User hereby agrees not to remove, alter or destroy any
 * copyright, trademark, credits, other proprietary notices or confidential
 * legends placed upon, contained within or associated with the Software,
 * and shall include all such unaltered copyright, trademark, credits,
 * other proprietary notices or confidential legends on or in every copy of
 * the Software.
 *
 */
#include "oscompat.h"
#include <linux/timer.h>
#include <linux/time.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <asm/semaphore.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/system.h>
#include <linux/smp_lock.h>
#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) )
#include <linux/completion.h>
#endif

#include "oscompat.h"
#include "ossysenv.h"
#include "ostime_ex.h"
#include "osmemory_ex.h"
#include "osstring_ex.h"


#define TICKS_TO_MSECS(ticks) (ticks*(1000/HZ))

static inline long MSECS_TO_TICKS(UINT32 msecs)
{
long ticks = (msecs)/(1000/HZ);

// round up to next tick
if ((!ticks && msecs) || (msecs % (1000/HZ)) >= ((1000/HZ) / 2))
ticks++;

return ticks;
}

typedef struct TIME_OUT_INSTANCE_TYPE
{
struct tq_structTaskQueue;
struct wait_queue*WaitQueue;
struct timer_listTimer;
BOOL                active;
intSchedCount;

UINT32mSec;
BOOLbLocked;

PFREE_FUNCpFuncFree;
PVOIDpRefData;

PCBFUNCpTimeOutCallBack;

}TIME_OUT_INSTANCE_T, *PTIME_OUT_INSTANCE_T;

typedef struct TIMER_TAG
{
UINT32 msec;
struct timer_list timer;
} TIMER_T, *PTIMER_T;

/********************************************************************/

STATICVOID TimerThreadFunction(PVOID pData)
{
PTIME_OUT_INSTANCE_TpTimeOutInstance = (PTIME_OUT_INSTANCE_T)pData;

if (pTimeOutInstance->active == TRUE )
{
    /* beware: some callback functions use FPU instructions */
pTimeOutInstance->pTimeOutCallBack(pTimeOutInstance->pRefData);

// callback might have set active to FALSE
if (pTimeOutInstance->active == TRUE ) {
mod_timer(&pTimeOutInstance -> Timer, jiffies +
MSECS_TO_TICKS(pTimeOutInstance -> mSec));
}
}

pTimeOutInstance->SchedCount--;
}

STATIC VOID TimeOutHandler(unsigned long Data )
{
PTIME_OUT_INSTANCE_TpTimeOutInstance = (PTIME_OUT_INSTANCE_T)Data;

if (pTimeOutInstance->active == FALSE )
{
return;
}

pTimeOutInstance->SchedCount++;
if (OsModemThreadSchedule(&(pTimeOutInstance -> TaskQueue)) == 0)
{
//printk(KERN_ERR "%s: TimeOutHandler(%d) - schedule_task FAILED
(jiffies=%ld)\n", __FUNCTION__, pTimeOutInstance->SchedCount, jiffies);
pTimeOutInstance->SchedCount--;
}
}

static DECLARE_TASK_QUEUE(tq_mdmthrd);
static DECLARE_WAIT_QUEUE_HEAD(mdmthrd_wait);
#ifdef DECLARE_COMPLETION
static DECLARE_COMPLETION(mdmthrd_exited);
#endif
static int mdmthrd_pid;

int OsModemThreadSchedule(PVOID task)
{
int ret;

if(mdmthrd_pid <= 0) {
printk(KERN_ERR"%s: WARNING: modem thread not present\n", __FUNCTION__);
}
#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,19) )
ret = queue_task((struct tq_struct *)task, &tq_mdmthrd);
#else
{
struct tq_struct *bh_pointer = (struct tq_struct *)task;
task_queue *bh_list = &tq_mdmthrd;

ret = 0;
if (!test_and_set_bit(0,&bh_pointer->sync)) {
unsigned long flags;
spin_lock_irqsave(&tqueue_lock, flags);
bh_pointer->next = *bh_list;
*bh_list = bh_pointer;
spin_unlock_irqrestore(&tqueue_lock, flags);
ret = 1;
}
}
#endif
wake_up(&mdmthrd_wait);
return ret;
}

/* lock_kernel() must be called before this function */
static void thrd_daemonize(void)
{
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) )
exit_files(current);  /* daemonize doesn't do exit_files */
current->files = init_task.files;
atomic_inc(&current->files->count);
#endif
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) ) && !defined(daemonize)
{
struct fs_struct *fs;

exit_mm(current);

current->session = 1;
current->pgrp = 1;

exit_fs(current);/* current->fs->count--; */
fs = init_task.fs;
current->fs = fs;
atomic_inc(&fs->count);
}
#else
daemonize();
#endif

#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10) )
reparent_to_init();
#endif
}

#ifndef DECLARE_COMPLETION
static int mdmthrd_running;
#endif

static int mdmthrd(void *startup)
{
  register struct task_struct *curtask = current;

lock_kernel();

/*  this thread doesn't need any user-level access,
 *  so get rid of all our resources.
 */
thrd_daemonize();

strncpy(curtask->comm, __FUNCTION__, sizeof(curtask->comm));

unlock_kernel();

spin_lock_irq(&curtask->sigmask_lock);
sigemptyset(&curtask->blocked);
flush_signals(curtask);
{ // flush_signal_handlers
int i;
struct k_sigaction *ka = &curtask->sig->action[0];
for (i = _NSIG ; i != 0 ; i--) {
if (ka->sa.sa_handler != SIG_IGN)
ka->sa.sa_handler = SIG_DFL;
ka->sa.sa_flags = 0;
sigemptyset(&ka->sa.sa_mask);
ka++;
}
}
recalc_sigpending(curtask);
spin_unlock_irq(&curtask->sigmask_lock);

#ifdef DECLARE_COMPLETION
complete((struct completion *)startup);
#else
mdmthrd_running = 1;
#endif

/* beware: this thread executes floating-point instructions! */

while(1) {
    set_current_state(TASK_RUNNING);
run_task_queue(&tq_mdmthrd);
if(signal_pending(curtask))
    break;
interruptible_sleep_on(&mdmthrd_wait);
}

spin_lock_irq(&curtask->sigmask_lock);
flush_signals(curtask);
recalc_sigpending(curtask);
spin_unlock_irq(&curtask->sigmask_lock);

printk(KERN_ERR"%s: goodbye!\n", __FUNCTION__);

#ifdef DECLARE_COMPLETION
#if defined(complete_and_exit) || ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
)
complete_and_exit(&mdmthrd_exited, 0);
#else
complete(&mdmthrd_exited);
up_and_exit(NULL, 0);
#endif
#else
mdmthrd_running = 0;
return 0;
#endif
}

static INT32 ntimers;

/********************************************************************/
/* Construct a periodic time out instance.RunTime manager does not*/
/* simply use global timers , since these are called with the*/
/* same thread handle as the ring3 application. This prevent*/
/* synchronization between passive and async calls with semaphores*/
/* or mutexes.                                                      */
/* Parameters :                                                     */
/* Irql - run time IQRL in which the timeout call back              */ 
/*        should be called. In Wi95 this parameter in ignored,      */
/*        and all timeout are called at dispatch level.             */
/* InitialTimeout - Initial timeout interval in ms pRefData         */
/*                  should be passed as a parameter to this function*/
/* PTimeOutCallBack - CallBack to be call every timeout duration.   */
/* pFuncAlloc - alloc function,pRefData should be passed as         */
/*              parameter for thids function. function should       */
/*              allocate memory in non-paged pool                   */
/* pFuncFree - free function,pRefData should be passed as           */
/*             parameter for thids function                         */
/* pRefData -  reference data to be passed to pTimeOutCallBack      */
/*             pFuncAllc and pFuncFree                              */
/********************************************************************/
// @@@@ Irql unreferenced

GLOBALHANDLEOSCreatePeriodicTimeOut(INTIMER_IRQL_TYPEIrql,
INUINT32InitialTimeOut,
INPCBFUNCpTimeOutCallBack,
INPALLOC_FUNCpFuncAlloc,
INPFREE_FUNCpFuncFree,
INPVOIDpRefData)
{
PTIME_OUT_INSTANCE_TpTimeOutInstance;
if(pFuncAlloc) {
pTimeOutInstance= pFuncAlloc(sizeof(TIME_OUT_INSTANCE_T), pRefData);
} else {
ASSERT(OSContextAllowsSleeping());
pTimeOutInstance= kmalloc(sizeof(TIME_OUT_INSTANCE_T), GFP_KERNEL);
}
if (NULL == pTimeOutInstance )
return(NULL);
pTimeOutInstance->pFuncFree= pFuncFree;
pTimeOutInstance->pRefData= pRefData;
pTimeOutInstance->pTimeOutCallBack= pTimeOutCallBack;
pTimeOutInstance->bLocked= FALSE;
pTimeOutInstance->mSec= InitialTimeOut;

INIT_TQUEUE(&pTimeOutInstance -> TaskQueue, TimerThreadFunction,
pTimeOutInstance);

init_timer(&pTimeOutInstance -> Timer);
pTimeOutInstance -> Timer.function = TimeOutHandler;
pTimeOutInstance -> Timer.data = (unsigned long)pTimeOutInstance;
pTimeOutInstance -> Timer.expires = jiffies + MSECS_TO_TICKS(100);
pTimeOutInstance -> SchedCount = 0;

if(OsAtomicIncrement(&ntimers) == 1) {
#ifdef COMPLETION_INITIALIZER
static struct completion startup = COMPLETION_INITIALIZER(startup);
#endif

MOD_INC_USE_COUNT;
#ifdef COMPLETION_INITIALIZER
mdmthrd_pid = kernel_thread(mdmthrd, &startup, 0);
wait_for_completion(&startup);
#else
mdmthrd_running = 0;
mdmthrd_pid = kernel_thread(mdmthrd, NULL, 0);
{
int i;

/* wait 5 seconds maximum for modem thread to start */
for (i=5000; !mdmthrd_running && (i > 0); i -= 50) {
OsSleep(50);
}
if(i <= 0) {
printk(KERN_ERR"%s: giving up on modem thread\n", __FUNCTION__);
}
}
#endif

if(mdmthrd_pid <= 0) {
MOD_DEC_USE_COUNT;
OsAtomicDecrement(&ntimers);
if(pTimeOutInstance->pFuncFree) {
pTimeOutInstance->pFuncFree(pTimeOutInstance,pTimeOutInstance->pRefData);
} else {
kfree(pTimeOutInstance);
}
return NULL;
}
}

if(InitialTimeOut != 0) {
pTimeOutInstance -> active = TRUE;
add_timer(&(pTimeOutInstance -> Timer));
} else
pTimeOutInstance -> active = FALSE;

return( (HANDLE)pTimeOutInstance);
}

/********************************************************************/
GLOBALVOIDOSDestroyPeriodicTimeOut(INHANDLEhTimeOut)
{
PTIME_OUT_INSTANCE_TpTimeOutInstance = (PTIME_OUT_INSTANCE_T)hTimeOut;

ASSERT(OSContextAllowsSleeping());

pTimeOutInstance -> bLocked= TRUE;
pTimeOutInstance -> active = FALSE;

#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) )
del_timer_sync(&pTimeOutInstance -> Timer);
#else
del_timer(&pTimeOutInstance -> Timer);
#endif

while(pTimeOutInstance->SchedCount > 0) {
    schedule();
}

if(OsAtomicDecrement(&ntimers) == 0) {
if(mdmthrd_pid > 0) {
int r = kill_proc(mdmthrd_pid, SIGKILL, 1);
if(r) {
printk(KERN_ERR"%s: kill_proc mdmthrd_pid=%d r=%d\n", __FUNCTION__,
mdmthrd_pid, r);
}
#ifdef DECLARE_COMPLETION
wait_for_completion(&mdmthrd_exited);
#else
{
int i;

/* wait 5 seconds maximum for modem thread to terminate */
for (i=5000; mdmthrd_running && (i > 0); i -= 50) {
OsSleep(50);
}
if(i <= 0) {
printk(KERN_ERR"%s: giving up on modem thread\n", __FUNCTION__);
}
}
#endif
MOD_DEC_USE_COUNT;
}
}

if(pTimeOutInstance->pFuncFree) {
pTimeOutInstance->pFuncFree(pTimeOutInstance,pTimeOutInstance->pRefData);
} else {
kfree(pTimeOutInstance);
}

}
/********************************************************************/
GLOBALBOOLOSSetPeriodicTimeOut(INHANDLEhTimeOut,
INUINT32NewTimeOut)
{
PTIME_OUT_INSTANCE_TpTimeOutInstance = (PTIME_OUT_INSTANCE_T)hTimeOut;

pTimeOutInstance->mSec = NewTimeOut;
if(NewTimeOut != 0) {
pTimeOutInstance -> active = TRUE;
mod_timer(&pTimeOutInstance -> Timer, jiffies +
MSECS_TO_TICKS(pTimeOutInstance -> mSec));
} else {
pTimeOutInstance -> active = FALSE;
del_timer(&pTimeOutInstance -> Timer);
}
return TRUE;
}

static time_t epoch = 0;

/********************************************************************/
GLOBALUINT32OSGetSystemTime(VOID)
{
struct timeval timestamp;
do_gettimeofday(&timestamp);
// result returned in milliseconds
return ((UINT32)(((timestamp.tv_sec-epoch)*1000) + (timestamp.tv_usec/1000)));
}

GLOBALVOIDOSInitTime(VOID)
{
struct timeval timestamp;
do_gettimeofday(&timestamp);

epoch = timestamp.tv_sec;
}

/********************************************************************/

HANDLE OSCreateTimer(UINT32 msec, PVOID pCBFunc, PVOID pRefData)
{
PTIMER_T pTimer;

if ( pCBFunc == NULL )
{
ASSERT(pCBFunc);
return (NULL);
}

ASSERT(OSContextAllowsSleeping());
pTimer = kmalloc(sizeof(TIMER_T),GFP_KERNEL);
if ( NULL == pTimer )
{
ASSERT(pTimer);
return (NULL);
}

memset(pTimer,0,sizeof(TIMER_T));

init_timer(&(pTimer->timer));
pTimer->timer.function = pCBFunc ;
pTimer->timer.data = (unsigned long)pRefData;
pTimer->timer.expires = jiffies + MSECS_TO_TICKS(msec);
pTimer->msec = msec;
return ((HANDLE)pTimer);
}

void OSSetTimer(PVOID pTimer)
{
struct timer_list*pTimerH;
PTIMER_T pTimerS = (PTIMER_T)pTimer;
if ( pTimer == NULL )
{
ASSERT(pTimer);
return;
}
pTimerH = &(pTimerS->timer);
mod_timer(pTimerH, jiffies + MSECS_TO_TICKS(pTimerS->msec));
}

void OSCancelTimer(PVOID pTimer)
{
struct timer_list*pTimerH;
if ( pTimer == NULL )
{
ASSERT(pTimer);
return;
}
pTimerH = &((PTIMER_T)pTimer)->timer;

del_timer(pTimerH);
}

void OSChangeTimerTimeOut(PVOID pTimer, UINT32 msec)
{
PTIMER_T pTimerS = (PTIMER_T)pTimer;
if ( pTimer == NULL )
{
ASSERT(pTimer);
return;
}
pTimerS->msec = msec;
}

void OSDestroyTimer(PVOID pTimer)
{
if ( pTimer == NULL )
{
ASSERT(pTimer);
return;
}

#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) )
del_timer_sync(&((PTIMER_T)pTimer)->timer);
#else
del_timer(&((PTIMER_T)pTimer)->timer);
#endif
kfree(pTimer);
}

/********************************************************************/
/* Utilities                                                        */
/********************************************************************/

static spinlock_t atomic_lock __attribute__((unused)) = SPIN_LOCK_UNLOCKED;

/****************************************************************************************
    The OsAtomicCompareAndSwap function compares the value at the specified
address with
oldVal. The value of newValue is written to the address only if oldValue and
the
value at the address are equal. OSCompareAndSwap returns true if newValue is
written
to the address; otherwise, it returns false.
   
    Params:
        oldValue The value to compare at address.
        newValue The value to write to address if oldValue compares true.
        address The 4-byte aligned address of the data to update atomically.
    Result: true if newValue was written to the address.
****************************************************************************************/
BOOL OsAtomicCompareAndSwap (PVOID oldValue, PVOID newValue, PVOID* address)
{
#ifdef __HAVE_ARCH_CMPXCHG
return (cmpxchg(address, oldValue, newValue) == oldValue);
#else
unsigned long flags;

spin_lock_irqsave(&atomic_lock, flags);
  if (*(PUINT32)address ==  (UINT32)oldValue)
  {
*(PUINT32)address = (UINT32)newValue;
spin_unlock_irqrestore(&atomic_lock, flags);
  return TRUE;
  }
spin_unlock_irqrestore(&atomic_lock, flags);

return FALSE;
#endif
}
/****************************************************************************************
    OsAtomicAdd
  
    OsAtomicAdd function adds the specified amount to the value at the
specified
    address and returns the result.
    Params:
        amount  The amount to add.
        address The 4-byte aligned address of the value to update atomically.
    Result: The result of the addition.
****************************************************************************************/
INT32OsAtomicAdd   (INT32 amount, PINT32 address)
{
unsigned long flags;
atomic_t *v = (atomic_t *)address;

spin_lock_irqsave(&atomic_lock, flags);
atomic_add(amount, v);
amount = atomic_read(v);
spin_unlock_irqrestore(&atomic_lock, flags);

return amount;
}

INT32OsAtomicIncrement (PINT32 address)
{
unsigned long flags;
atomic_t *v = (atomic_t *)address;
INT32 amount;

spin_lock_irqsave(&atomic_lock, flags);
atomic_inc(v);
amount = atomic_read(v);
spin_unlock_irqrestore(&atomic_lock, flags);

return amount;
}

INT32OsAtomicDecrement (PINT32 address)
{
unsigned long flags;
atomic_t *v = (atomic_t *)address;
INT32 amount;

spin_lock_irqsave(&atomic_lock, flags);
atomic_dec(v);
amount = atomic_read(v);
spin_unlock_irqrestore(&atomic_lock, flags);

return amount;
}

void OsSleep(UINT32 ms)
{
if(!OSContextAllowsSleeping()) {
printk(KERN_ERR"%s(%lu): cannot sleep in this context!\n", __FUNCTION__, ms);
ASSERT(OSContextAllowsSleeping());
return;
}

if(ms > TICKS_TO_MSECS(1)) {
UINT32 start, end;
long timeout = MSECS_TO_TICKS(ms);
//long ort = timeout;

start = OSGetSystemTime();
do {
set_current_state(TASK_UNINTERRUPTIBLE);
} while ((timeout = schedule_timeout(timeout)));
end = OSGetSystemTime() - start;
if(end < ms) {
//printk(KERN_ERR"OsSleep: short timeout; wanted %ld got %ldms ort=%ld\n",
ms, end, ort);
OsSleep(end);
}
//else if(end > ms) {
//printk(KERN_ERR"OsSleep: timeout %ldms (%ldms too much) ort=%ld\n", ms,
end - ms, ort);
//}
} else {
// short delay
mdelay(ms);
}
}


static atomic_t locksHeld;

void OsObtainedLock(void)
{
atomic_inc(&locksHeld);
}

void OsReleasedLock(void)
{
atomic_dec(&locksHeld);
}

int OsLocksHeld(void)
{
return atomic_read(&locksHeld);
}

/* Semaphores */
/********************************************************************/
GLOBAL HANDLEOSSemaphoreCreate(INint InitCount)
{
struct semaphore *pSemaphore;

ASSERT(OSContextAllowsSleeping());
pSemaphore = kmalloc(sizeof(struct semaphore), GFP_KERNEL);
if (NULL == pSemaphore)
{
ASSERT(pSemaphore);
return (NULL);
}
sema_init(pSemaphore, InitCount);
return ((HANDLE)pSemaphore);
}

/********************************************************************/
GLOBAL VOIDOSSemaphoreDestroy(INHANDLE hSemaphore)
{
if (NULL != hSemaphore)
kfree((void *)hSemaphore);
}

/********************************************************************/
GLOBAL VOIDOSSemaphoreWait(INHANDLE hSemaphore)
{
struct semaphore *pSemaphore = (struct semaphore *)hSemaphore;
if (NULL == hSemaphore) {
ASSERT(hSemaphore);
return;
}
ASSERT(OSContextAllowsSleeping());
down(pSemaphore);
}

/********************************************************************/
GLOBAL VOIDOSSemaphoreSignal(INHANDLE hSemaphore)
{
struct semaphore *pSemaphore = (struct semaphore *)hSemaphore;
if (NULL == hSemaphore) {
ASSERT(hSemaphore);
return;
}
up(pSemaphore);
}

/* Critical Section (Mutex) */
/********************************************************************/
typedef struct {
spinlock_t spinlock;
unsigned long flags;
#ifdef DEBUG
void *pmutex, *pfrom;
#endif
} CRIT_T;

GLOBAL HANDLE __OSCriticalSectionCreate( char *file, int line )
{
    CRIT_T *mutex;

ASSERT(OSContextAllowsSleeping());
    mutex  = kmalloc(sizeof(CRIT_T), GFP_KERNEL);
if(!mutex) {
ASSERT(mutex);
return NULL;
}

spin_lock_init(&mutex->spinlock);
#ifdef DEBUG
mutex->pmutex = NULL;
mutex->pfrom = NULL;
#endif

    return ((HANDLE)mutex);
}

/********************************************************************/
GLOBAL VOIDOSCriticalSectionDestroy(INHANDLE hMutex)
{
if ( NULL == hMutex )
{
ASSERT(hMutex);
return;
}
kfree((CRIT_T *)hMutex);
}

#ifdef DEBUG
static CRIT_T *pmutex;
static void *pfrom;
#endif

/********************************************************************/
GLOBAL VOIDOSCriticalSectionAcquire(INHANDLE hMutex)
{
CRIT_T *mutex = (CRIT_T *) hMutex;
unsigned long flags;

spin_lock_irqsave(&mutex->spinlock, flags);
mutex->flags = flags;
#ifdef DEBUG
mutex->pmutex = pmutex;
mutex->pfrom = pfrom;
pmutex = mutex;
pfrom = __builtin_return_address(0);
#endif
OsObtainedLock();
}

/********************************************************************/
GLOBAL VOIDOSCriticalSectionRelease(INHANDLE hMutex)
{
CRIT_T *mutex = (CRIT_T *) hMutex;

#ifdef DEBUG
ASSERT(pmutex == mutex);
pmutex = mutex->pmutex;
pfrom  = mutex->pfrom;
#endif
spin_unlock_irqrestore(&mutex->spinlock, mutex->flags);
OsReleasedLock();
}

/********************************************************************/
GLOBALVOIDOSSetTimeSensitivity(INUINT32Interval)
{
}
/********************************************************************/
GLOBALVOIDOSRestoreTimeSensitivity(INUINT32Interval)
{
}

---snip---

__________________________________________________
Do You Yahoo!?
Yahoo! Finance - Get real-time stock quotes
http://finance.yahoo.com



More information about the hsflinux mailing list