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

📄 pc_locks.c

📁 嵌入式操作系统Nucleus Plus中使用的文件系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Contains NUCLEUS Specific Code */
/*
* EBS - RTFS (Real Time File Manager)
*
* Copyright Peter Van Oudenaren , 1993
* All rights reserved.
* This code may not be redistributed in source or linkable object form
* without the consent of its author.
*/
/******************************************************************************
	PC_LOCKS -  System specific locking code (user supplied).

    NOTE: !!!!!!! - If you do not require the file system to be re-entrant 
                    you do not need to port this code.

 Description:
    This file contains system specific process control code. This includes
    messages used for locking access to critical data elements, and code
    to claim and release exclusive access to RTFS through a semaphore

    To simplify the porting process we have created 3 mutually exclusive
    "methods" for controlling the RTFS multitasking interface. Set the 
    constant LOCK_METHOD in pcdisk.h to the method you wish to use. Then
    port the relevent sections of code.

    We placed syntax errors in the code at appopriate places so you may
    use your compiler to help you.

    The lock methods are:

    LOCK_METHOD == 0
       NUM_USERS == 1, No multitasking. This code won't be included in the build

    LOCK_METHOD == 1
       Use the file system in a single threaded manner. A mutex semaphore
       is claimed by pc_fs_enter() and released by pc_fs_exit(). The owner
       of the semaphore has exclusive access to the file system. This method
       provides a re-entrant API, but the code runs to completion in a single 
       thread. This is the simplest way to use RTFS in a multitasking 
       environment. It has the advantage of being very easy to implement. Its
       big disadvantage is that it serializes all file system access so that 
       access to a very slow device such as a floppy disk will block threads 
       wishing to access a speedy disk such as a hard disk or ram disk. Also
       an operation that could otherwise get all of its data from internal
       buffers will have to wait for any operations ahead of it to finish 
       their IO operations.
       
       Nevertheless many or most designs may get away with this level of
       implementation.
    
    LOCK_METHOD == 2
       Use a semaphore to guard against other RTFS threads preempting the 
       current thread. RTFS grabs a semaphore in pc_fs_enter() and releases
       it in pc_fs_exit(), like  method 1. But it yields (by calling
       pc_wait_lock()) when it needs access to a locked resource. 
       pc_wait_lock() releases the semaphore before it yields
        (by calling fs_release()) and reclaims it when it returns
        (by calling fs_reclaim()). Note also that device drivers call
        fs_release() before they block in anticipation of a
       completion interrupt and call fs_reclaim() when they run again.

 Summary
	#include <pcdisk.h>

    UCOUNT pc_fs_enter()
    UCOUNT pc_fs_exit(UCOUNT previous_state)

    WAIT_HANDLE_TYPE pc_alloc_lock()
    VOID pc_wait_lock(WAIT_HANDLE_TYPE lock_handle)
    VOID pc_wake_lock(WAIT_HANDLE_TYPE lock_handle)

Example:
    pc_?????_enter() and pc_?????_exit().

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

#if (PLUS)
#include "nucleus.h"
#else
#include "nu_defs.h"
#include "nu_proto.h"
#endif


#include "pcdisk.h"

/* HAS NUCLEUS Specific changes */
#if (NUM_USERS > 1)

/******************************************************************************
    PC_FS_ENTER  - Claim exclusive access of all RTFS rewsources.

 Description:
    This routine is called by the file manager each time an API funtion is
    entered. Its complement function pc_fs_exit is called when the API is 
    exitted.

    In the reference port we grab a mutex semaphore providing exclusive
    access to RTFS. If LOCK_METHOD is one we will release the semaphore
    when we call pc_fs_exit().  If LOCK_METHOD is two we will release the
    semaphore  when we call pc_fs_exit() AND also every time
    we yield waiting for IO completion or for another thread to release a
    resource that we need.
 
Returns
    A UCOUNT which is later passed into pc_fs_exit() when the API call 
    completes. In the reference  port we do not use the return code.

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

UCOUNT pc_fs_enter()                                                /*__fn__*/
{
    /* Note in a single threaded OS kernel this is not needed */
#if (PLUS)
    NU_Obtain_Semaphore(&NUF_FILE_SYSTEM_MUTEX, NU_SUSPEND);
#else
    NU_Request_Resource(NUF_FILE_SYSTEM_MUTEX, NU_WAIT_FOREVER);
#endif  /*  PLUS  */
    return(1);
}

/******************************************************************************
    PC_FS_EXIT  - Release exclusive access of all RTFS resources.

  Description:
    This routine is called by the file manager each time an API funtion is
    left. It should provide a complemetary function to pc_fs_enter.

 Returns
    Nothing
****************************************************************************/
VOID pc_fs_exit(UCOUNT restore_state)                               /*__fn__*/
{
    /* Note in a single threaded OS kernel this is not needed */
    restore_state = restore_state;  /* Not used in reference port */
#if (PLUS)
    NU_Release_Semaphore(&NUF_FILE_SYSTEM_MUTEX);
#else
    NU_Release_Resource(NUF_FILE_SYSTEM_MUTEX);
#endif  /*  PLUS  */
}

#if (LOCK_METHOD == 2)
/******************************************************************************
    FS_SUSPEND_TASK  - Suspend a tas for one or more ticks.

 Description:
    pc_read_block() has a possible race condition when two or more tasks are 
    attempting IO on a block which is currently being read from the disk
    by another task. To compensate for this rare race condition the tasks
    NOT performing the IO suspend themselves and check the buffer when they
    resume. They loop this way until the task performing the IO set the buffer
    valid or in error.

    This call should suspend the current task for one or more ticks.
    
 Returns
    VOID
****************************************************************************/

VOID fs_suspend_task()
{
    /* We can't call NU_Reliquish() here because we need to allow tasks
       of even a lower priority to run. */
    NU_Sleep(1);
}


/******************************************************************************
    FS_LOCK_TASK  - Lock a task so it will not be preempted.

 Description:
    This is called by RTFS when a preemption would cause a race condition. The
    call should signal to the kernel that the current task should run until it
    is unlocked or it yields. 

    RTFS uses task locking sparingly. See pc_generic_enter and pc_generic exit.
    
 Returns
    A BOOLEAN that will be passed to FS_UNLOCK_TASK when RTFS releases. If the 
    kernel function supports pushing/pooping of the lock state this BOOL is 
    irrelevent. Otherwise use it to decide what action if any to take in
    FS_UNLOCK_TASK


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

BOOL fs_lock_task()
{
/* This sample code asks if the task is already locked. If not it 
   locks the task. It then returns YES if the task was already locked.
   This flag will be passed to fs_unlock_task() later. fs_unlock_task()
   will then restore the task state. 
    
   Note: If your kernel has a nested lock/unlock call you may just use it. In
         this case you may simply return a constant value an ignore it.
*/
#if (PLUS)
    OPTION      preempt_status;
    preempt_status = NU_Change_Preemption(NU_NO_PREEMPT);
    return((BOOL) preempt_status);
#else
    NU_Disable_Preemption();
    return(YES);
#endif  /*  PLUS  */
}
/******************************************************************************
    FS_UNLOCK_TASK  - Restore a tasks lock state to what it was before 
                      FS_LOCK_TASK was called.


 Description:
    This is called by RTFS preemption is safe again. The kernel should restore
    the  lock state to what it was before FS_LOCK_TASK was called.

 Returns
    Nothing

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

VOID fs_unlock_task(BOOL state_var)
{
/* This sample code complents the code in pc_lock_task()
    
   Note: If your kernel has a nested lock/unlock call you may just use it. In
         this case you may simply return a constant value an ignore it.
  */
    state_var = state_var;
#if (PLUS)
      NU_Change_Preemption((OPTION)state_var);
#else
    NU_Enable_Preemption();
#endif  /*  PLUS  */
}

/******************************************************************************
    FS_RELEASE  - Release all RTFS resources while we wait for a resource
                  to become free or we wait for IO completion.

 Description:
    This is called by RTFS before it blocks on a resource. The resource may
    be either an IO event in a device driver, or a locked data object 
    such as the fat or a directory that is open for write. It releases the
    RTFS semaphore.
    
 Returns
    Nothing

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

VOID fs_release()
{
    /* Note in a single threaded OS kernel this is not needed */
/* Note: If you can you should try not to cause a context switch here. The 
      routine calling fs_release() is going to yield momentarilly. If you
      do cause a switch here no harm is done, however. */

#if (PLUS)
    NU_Release_Semaphore(&NUF_FILE_SYSTEM_MUTEX);
#else
    NU_Release_Resource(NUF_FILE_SYSTEM_MUTEX);
#endif  /*  PLUS  */
}


/******************************************************************************
    FS_RECLAIM  -  Reclaim exclusive access to all RTFS resources after
                   returning from a resource wait or on an io completion
 Description:
    This is called by RTFS after it  returns from a resource block. It 
    reclaims RTFS resources that were released in ps_release

 Returns

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

VOID fs_reclaim()
{
    /* Note in a single threaded OS kernel this is not needed */
#if (PLUS)
    NU_Obtain_Semaphore(&NUF_FILE_SYSTEM_MUTEX, NU_SUSPEND);
#else
    NU_Request_Resource(NUF_FILE_SYSTEM_MUTEX, NU_WAIT_FOREVER);
#endif  /*  PLUS  */
}

/******************************************************************************
    PC_ALLOC_LOCK - Return an event handle which may be used as an argument to 
                    pc_wait_lock and pc_wake_lock.

 Description:
    This routine is called repeatedly by pc_memory_init() to allocate
    all of the event handles needed by RTFS.

    It returns an event handle. This handle will be used to block and wake as
    resources are needed/finished. 

    The handle type returned may be one of two types. 
        1. A mutex semaphore for which only one task awakes from pc_wait_lock()
           when signaled from pc_wake_lock(). If this method is used
           there will be a slight performance degradation in some cases since
           all resource accesses will be exclusive.
        2. An event handle for which all tasks awake from pc_wait_lock()
           when signaled from pc_wake_lock(). If this method is used RTFS
           will arbitrate for the resource after wait has returned. This is
           the preferred method because it allows RTFS to differentiate
           between exclusive and shared access to a resource.
 Returns
    A handle of type WAIT_HANDLE_TYPE. This is defined by you in pcdisk.h

⌨️ 快捷键说明

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