📄 pc_users.c
字号:
/* Contains NUCLEUS Specific Code */
/* PC_USERS.C - Manage the fs_user structure code.
Since each task may have its own errno and current working directory, it
must also have its own file system context. Through this file and some
allocation code in pc_memry.c we attempt to provide a kernel independent
way to do this.
The following functions are provided:
pc_free_all_users() - Free all cwds for a drive
NU_Become_File_User() - Register a task as an RTFS user
NU_Release_File_User() - Register task as no longer an RTFS user
NU_Check_File_User() - check if task is a registered RTFS user
pc_rtfs_switch_in() - Called after a context switch
*/
#if (PLUS)
#include "nucleus.h"
#else
#include "nu_defs.h"
#include "nu_proto.h"
#endif
#include "pcdisk.h"
/* pc_free_all_users(COUNT driveno) - Free all cwd objects for a drive
*
* Runs down the list of user structures, frees the cwd structure for the
* specified drive for each (if it exists)
*
* Called by pc_dskfree() in lowl.c
*
*
*/
extern PFILE_SYSTEM_USER user_heap;
VOID pc_free_all_users(COUNT driveno) /*__fn__*/
{
PFILE_SYSTEM_USER p;
COUNT i;
p = user_heap;
for (i = 0; i < NUM_USERS; i++, p++)
{
if (p->lcwd[driveno])
{
pc_freeobj(p->lcwd[driveno]);
p->lcwd[driveno] = NULL;
}
}
}
#if (NUM_USERS != 1)
/* Implement these macros for your kernel*/
/* Return CONTEXT_HANDLE_TYPE that uniquely represents the current task
May not be zero. */
/* NUCLEUS - We set GET_CONTEXT_HANDLE() to (NU_Current_Task_ID()+1) so
we are sure not to get a zero. If we are using Nucleus PLUS, the task
ID must be converted to a task pointer. NUFP_Current_Task_ID performs
this conversion. */
#if (PLUS)
IMPORT void NUFP_Remove_User(signed int task_id);
#define GET_CONTEXT_HANDLE() (NUFP_Current_Task_ID()+1)
#else
#define GET_CONTEXT_HANDLE() (NU_Current_Task_ID()+1)
#endif
/* Put the (UCOUNT) X into the task control block of the current task */
/* NUCLEUS - We use an array of ints to map nucleus tasks to rtfs user
structures. This is done because RTFS user structures use a lot of
core (200 or so bytes). And it it not necessary to have one RTFS user
structure per nucleus task. We only need one structure per file
system user. When a nucleus task calls NU_Become_File_User() it will
get a map index in this table. GET_RTFS_TASKNO() and SET_RTFS_TASKNO()
are macros described below */
/* This array is allocated in pc_memory_init(). It has a slot for every
Nucleus task */
IMPORT COUNT *nu_to_rtfs_task_map;
#if (PLUS)
/* Nucleus PLUS uses task pointers not IDs. The call to NUFP_Current_Task_ID
makes the appropriate conversion. */
#define SET_RTFS_TASKNO(X) nu_to_rtfs_task_map[NUFP_Current_Task_ID()] = X
/* Return the UCOUNT assigned to this task by SET_RTFS_TASK_NO() If
SET_RTFS_TASK_NO() was never called, this routine may return a random value*/
#define GET_RTFS_TASKNO() nu_to_rtfs_task_map[NUFP_Current_Task_ID()]
#else
#define SET_RTFS_TASKNO(X) nu_to_rtfs_task_map[NU_Current_Task_ID()] = X
/* Return the UCOUNT assigned to this task by SET_RTFS_TASK_NO() If
SET_RTFS_TASK_NO() was never called, this routine may return a random value*/
#define GET_RTFS_TASKNO() nu_to_rtfs_task_map[NU_Current_Task_ID()]
#endif /* PLUS */
extern PFILE_SYSTEM_USER user_heap;
/* NUCLEUS - This function is called every time the user or the file system
kernel invokes the fs_user macro. It returns the task's private FILE_SYSTEM_USER
structure that was allocated by calling NU_Become_File_User(). If the
program has a bug in it and calls fs_user without having first called
NU_Become_File_User(), a default structure is returned so the system
doesn't crash, and pc_report_error() is called. */
FILE_SYSTEM_USER default_user;
PFILE_SYSTEM_USER fs_current_user_structure()
{
COUNT i;
i = GET_RTFS_TASKNO();
if ( (i < NUM_USERS) && (user_heap[i].context_handle == GET_CONTEXT_HANDLE()) )
{
return(user_heap + i);
}
else
{
pc_report_error(PCERR_BAD_USER);
return(&default_user);
}
}
/* BOOL NU_Become_File_User() - Register a task as an RTFS user.
Description:
In a multitasking environment this function must be called by a task
before it may use the API. This reserves a user structure from the
pool of user structures for the task.
Returns:
YES if the task may use the file system
NO if too many users already.
If this routine fails it calls
pc_report_error(PCERR_USERS);
As a diagnostic.
*/
BOOL NU_Become_File_User() /*__fn__*/
{
UCOUNT i;
PFILE_SYSTEM_USER p;
#if (PLUS)
OPTION preempt_status;
preempt_status = NU_Change_Preemption(NU_NO_PREEMPT);
#else
NU_Disable_Preemption();
#endif /* PLUS */
p = user_heap;
if (p)
{
for (i = 0; i < NUM_USERS; i++, p++)
{
if (!p->context_handle)
{
pc_memfill(p, sizeof(FILE_SYSTEM_USER), (UTINY) 0);
p->context_handle = GET_CONTEXT_HANDLE();
SET_RTFS_TASKNO(i);
/* NUCLEUS - fs_user is a macro under nucleus. Not a static */
/* fs_user = p; */
#if (PLUS)
NU_Change_Preemption(preempt_status);
#else
NU_Enable_Preemption();
#endif /* PLUS */
return(YES);
}
}
}
#if (PLUS)
NU_Change_Preemption(preempt_status);
#else
NU_Enable_Preemption();
#endif /* PLUS */
return(NO);
}
/* VOID NU_Release_File_User() - Register a task as no longer an RTFS user.
Description:
When a task is through with RTFS it should call here. This frees up a user
structure so it may be used by other tasks callers to (NU_Become_File_User)
Subsequent API calls will fail if this routine has been called
Returns:
NOTHING
*/
VOID NU_Release_File_User() /*__fn__*/
{
COUNT driveno;
if (NU_Check_File_User())
{
for(driveno = 0; driveno < NDRIVES; driveno++)
{
if (fs_user->lcwd[driveno])
{
pc_freeobj(fs_user->lcwd[driveno]);
fs_user->lcwd[driveno] = NULL;
}
}
pc_memfill(fs_user, sizeof(FILE_SYSTEM_USER), (UTINY) 0);
#if (PLUS)
/* Release the Task Pointer to Task ID conversion. */
NUFP_Remove_User(GET_RTFS_TASKNO());
#endif
}
}
/* BOOL NU_Check_File_User() - Check if a task is registered as an RTFS user.
Description:
The API prolog code calls this if ENABLE_MULTI_TASKING is turned on
If the the current task is registered as an RTFS user it returns YES
otherwise it returns NO and the PROLOG code causes the API call to fail.
Returns:
YES if the task may use the file system
NO if not registered
If this routine fails it calls pc_report_error(PCERR_BAD_USER); As a
diagnostic.
*/
BOOL NU_Check_File_User() /*__fn__*/
{
UCOUNT i;
i = GET_RTFS_TASKNO();
if ( (i < NUM_USERS) &&
(user_heap[i].context_handle == GET_CONTEXT_HANDLE()) )
{
return(YES);
}
pc_report_error(PCERR_BAD_USER);
return(NO);
}
/* VOID pc_rtfs_switch_in() - Call this after a task switch
Description:
This function should be called by the kernel when a task goes into the
run state. It switches the the fs_user structure to the current task.
If the current task is NOT registered as a file system user no harm is
done and fs_user is not changed.
Since this code occurs on every task switch its performance is
crucial. It may be moved to the kernel if desired. Or preferably
you should have a flag in the control block that the kernel
inspects on each task switch. If the flag is set call this function
otherwise dont. Modify NU_Become_File_User() to set the flag flag
and pc_rtfs_relase_user() to clear the flag.
Returns:
Nothing
fs_user points to the user structure reserved for this TASK if
the task was registered though NU_Become_File_User().
*/
/* NUCLEUS - We don't switch fs_user during a task switch. Instead fs_user
is implemented as a macro that calls
fs_current_user_structure() (see above) */
#if 0
VOID pc_rtfs_switch_in() /*__fn__*/
{
UCOUNT i;
i = GET_RTFS_TASKNO();
if ( (i < NUM_USERS) && (user_heap[i].context_handle == GET_CONTEXT_HANDLE()) )
fs_user = user_heap + i;
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -