📄 pc_locks.c
字号:
/* 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 + -