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

📄 pc_users.c

📁 nucleus 文件系统,内核和彩色图形系统,在小系统上非常好用
💻 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 + -