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

📄 thread.c

📁 该项目主要是将wingdows程序直接运行在linux上
💻 C
字号:
/* * thread.c * * Copyright (C) 2006  Insigme Co., Ltd * * Authors: * - Limin Jin * * This software has been developed while working on the Linux Unified Kernel * project (http://linux.insigma.com.cn) in the Insigma Reaserch Institute, * which is a subdivision of Insigma Co., Ltd (http://www.insigma.com.cn). * * The project is sponsored by Insigma Co., Ltd. * * The authors can be reached at linux@insigma.com.cn. * * This program is free software; you can redistribute it and/or modify it * under the terms of  the GNU General  Public License as published by the * Free Software Foundation; either version 2 of the  License, or (at your * option) any later version. * * Revision History: *   Jan 2006 - Created. *//* * thread.c: thread implementation * Reference to ReactOS code */#include <linux/win32_process.h>#include <linux/mm.h>#include <asm/uaccess.h>#include <asm/ldt.h>#include <linux/file.h>#include <linux/nls.h>#include <linux/list.h>#include "../objwait.h"#include "../thread.h"#include "../apc.h"#include "../process.h"#include "thread.h"#include "../win32.h"#include "../mm/virtual.h"#include "../mm/attach.h"#include "../w32syscall.h"#ifdef CONFIG_UNIFIED_KERNEL//#define kdebug(fmt ...)//#define ktrace(fmt ...)extern long do_fork_from_task(task_t *ptsk,		unsigned long process_flags,		unsigned long clone_flags,		unsigned long stack_start,		struct pt_regs *regs,		unsigned long stack_size,		int __user *parent_tidptr,		int __user *child_tidptr);extern asmlinkage void KiThreadStartup(void);extern PTEB STDCALLMmCreateTeb(PEPROCESS Process,            PCLIENT_ID ClientId,	    PINITIAL_TEB InitialTeb);extern void STDCALLPspThreadSpecialApc(PKAPC Apc,		PKNORMAL_ROUTINE* NormalRoutine,		PVOID* NormalContext,		PVOID* SystemArgument1,		PVOID* SystemArgument2);extern unsigned long get_ntdll_entry(void);extern unsigned long get_interp_entry(void);/* * PspUserThreadStartup * prepare for jump to userspace to execute after new thread waken */VOIDSTDCALLPspUserThreadStartup(PKSTART_ROUTINE StartRoutine,		PVOID StartContext){	struct ethread  *thread;	PKAPC   thread_apc;	void * start_stack;	ktrace("PspUserThreadStartup\n");	if (!(thread = thread_find())) {		kdebug("***error find thread\n");		return;	}	if (!(thread_apc = kmalloc(sizeof(struct kapc),GFP_KERNEL))) {		kdebug("***error malloc, No memory\n");		return;	}	start_stack = (void *)thread->et_task->mm->start_stack; /* user stack base */	KeInitializeApc(thread_apc,			&thread->tcb,			OriginalApcEnvironment,			PspThreadSpecialApc,			NULL,			(PKNORMAL_ROUTINE)get_ntdll_entry(),			UserMode,			start_stack);	KeInsertQueueApc(thread_apc, (void *)get_interp_entry(), thread->threads_process->spare0[0], IO_NO_INCREMENT);	thread->tcb.apc_state.uapc_pending = 1;	set_tsk_thread_flag(current, TIF_APC);        try_module_get(THIS_MODULE);	asm("movl %0, %%fs\n" : : "r"(TEB_SELECTOR));	return;} /* end PspUserThreadStartup *//* * Ke386InitThreadWithContext * init context for thread */VOIDSTDCALLKe386InitThreadWithContext(PKTHREAD Thread,		PKSYSTEM_ROUTINE SystemRoutine,		PKSTART_ROUTINE StartRoutine, /* FIXME */		PVOID StartContext,           /* FIXME */		PCONTEXT Context){        struct thread_info *info;        struct task_struct *p;        unsigned long * trapframe;        struct pt_regs * regs;        PCONTEXT context;        if (!(context = kmalloc(sizeof(*context),GFP_KERNEL))) {                kdebug("***error malloc, No memory\n");                return;        }        if (copy_from_user(context, Context, sizeof(*context))) {                kdebug("copy from user error\n");                return;        }        info = (struct thread_info *)((unsigned long)Thread->stack_base - THREAD_SIZE);        p = info->task;	/* set for switch */        trapframe = (unsigned long *)((unsigned long)Thread->stack_base - 8 - sizeof(struct pt_regs) - 12);        regs = (struct pt_regs *)(trapframe + 3);        trapframe[0] = (unsigned long)SystemRoutine;        trapframe[1] = (unsigned long)StartRoutine;        trapframe[2] = (unsigned long)StartContext;             p->thread.eip = (unsigned long)KiThreadStartup;        p->thread.esp = (unsigned long)trapframe;        p->thread.esp0 = (unsigned long)(regs+1);         p->thread.fs = TEB_SELECTOR;	/* set for userspace */        regs->esp = context->Esp;        regs->eip = context->Eip;        kfree(context);	return;} /* end Ke386InitThreadWithContext *//* * KeInitializeThread * initialize kthread */VOIDSTDCALLKeInitializeThread(PKPROCESS Process,		PKTHREAD Thread,		PKSYSTEM_ROUTINE SystemRoutine,		PKSTART_ROUTINE StartRoutine,  /* FIXME */		PVOID StartContext,            /* FIXME */		PCONTEXT Context,		PVOID Teb,		PVOID KernelStack){	ktrace("KeInitializeThread kprocess %x, kthread %x, systemroutine %x, context %x, teb %x, kernelstack %x\n", Process, Thread, SystemRoutine, Context, Teb, KernelStack);        KThreadInit(Thread, (struct eprocess *)Process);        /*NOW FIXME Initialize the Suspend APC */        /* Initialize the Suspend Semaphore */        sema_init(&Thread->suspend_semaphore, 0);        /* Set the TEB */        Thread->teb = Teb;        /* Allocate Stack use linux task stack and init         * Set the Thread Stacks         */        Thread->initial_stack = (PCHAR)KernelStack + THREAD_SIZE;        Thread->stack_base = (PCHAR)KernelStack + THREAD_SIZE;        Thread->stack_limit = (ULONG_PTR)KernelStack + sizeof(struct thread_info);		/* FIXME	 * Establish the pde's for the new stack and the thread structure within the	 * address space of the new process. They are accessed while taskswitching or	 * while handling page faults. At this point it isn't possible to call the	 * page fault handler for the missing pde's.	 */        MmUpdatePageDir(((struct ethread *)Thread)->et_task->mm, (void *)Thread->stack_limit, THREAD_SIZE);        MmUpdatePageDir(((struct ethread *)Thread)->et_task->mm, Thread, sizeof(struct ethread));        Ke386InitThreadWithContext(Thread,                        SystemRoutine,                        StartRoutine,                        StartContext,                        Context);	return;} /* end KeInitializeThread *//* * PspCreateThread * create thread */NTSTATUSSTDCALLPspCreateThread(OUT PHANDLE ThreadHandle,		IN ACCESS_MASK DesiredAccess,		IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,		IN HANDLE ProcessHandle,		IN PEPROCESS TargetProcess,   			/* FIXME */		OUT PCLIENT_ID ClientId,		IN PCONTEXT ThreadContext,		IN PINITIAL_TEB InitialTeb,		IN BOOLEAN CreateSuspended,		IN PKSTART_ROUTINE StartRoutine OPTIONAL,   	/* FIXME */		IN PVOID StartContext OPTIONAL)            	/* FIXME */{	struct eprocess * process;	struct ethread * thread, * old_thread, *cur_thread;	struct task_struct * new_tsk;	struct win32_object * proc_obj = NULL, * thread_obj;	struct ethread_cons_data        etcd;	struct teb * teb_base;	long   cpid;	ktrace("PspCreateThread\n");	/* current still be regarded */	if (ProcessHandle&&ProcessHandle!=NtCurrentProcess()) {                if(!(cur_thread=thread_find())) {                        kdebug("***error find thread\n");                        return -EINVAL;                }                proc_obj = GetObject(cur_thread, ProcessHandle, &process_objclass);                if (IS_ERR(proc_obj)) {                        kdebug("can't find created eprocess\n");                        return -EINVAL;                }                process = proc_obj->o_private;                objput(proc_obj);        } else {                if (TargetProcess) {                        process = (struct eprocess * )TargetProcess;                        if (IS_ERR(proc_obj)) {                                kdebug("can't find created eprocess\n");                                return -EINVAL;                        }                } else {                        if(!(cur_thread=thread_find())) {                                kdebug("***error find thread\n");                                return -EINVAL;                        }                        process = cur_thread->threads_process;                }        }	if (!process->fork_in_progress) {		/* second and more */                   old_thread = list_entry(process->thread_list_head.next, struct ethread, thread_list_entry);                cpid = do_fork_from_task(old_thread->et_task, CREATE_THREAD,			       	SIGCHLD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 				old_thread->tcb.trap_frame->esp, (struct pt_regs *)old_thread->tcb.trap_frame, 0, NULL, NULL);                new_tsk = find_task_by_pid(cpid);                etcd.etcd_task = new_tsk;                etcd.etcd_process = process->ep_obj;                etcd.etcd_stack_top = (unsigned long)InitialTeb->StackBase; //stack_top                thread_obj = AllocObject(&thread_objclass, NULL, &etcd);                if (IS_ERR(thread_obj)) {                        kdebug("can't find created ethread\n");                        return -EINVAL;                }                /* the thread object can now be put, since a reference is held                 * by the Linux task structure. Similarly the process object                 * is now referenced by the thread object and can also be put                 */                objput(thread_obj);                thread = thread_obj->o_private;	} else {		/* for first thread */		thread = process->fork_in_progress;		new_tsk = thread->et_task;	}	module_put(THIS_MODULE);        /* FIXME Create Cid Handle */	memset(&thread->cid, 0, sizeof(struct client_id));        /* set user stack base */        thread->et_task->mm->start_stack = (unsigned long)InitialTeb->StackBase;	if (ThreadContext)	{                /* Create Teb */                teb_base = (struct teb * )MmCreateTeb(process, (PCLIENT_ID)&thread->cid, InitialTeb);                /* Set the Start Addresses */                thread->start_address = (PVOID)ThreadContext->Eip;                thread->win32_start_address = (PVOID)ThreadContext->Eax; /*FIXME */                /* intialize kthread */                KeInitializeThread(&process->pcb,                                &thread->tcb,                                PspUserThreadStartup,                                NULL,                                NULL,                                ThreadContext,                                teb_base,                                new_tsk->thread_info); 	} else {		/* FIXME PsCreateSystemThread */	}	/* move ethread to eprocess's thread_list	 * Insert the Thread into the Process's Thread List	 * Note, this is the ETHREAD Thread List. It is removed in	 * ps/kill.c!PspExitThread.	 */	        set_task_state(new_tsk, TASK_RUNNING);        clear_tsk_need_resched(new_tsk);        wake_up_new_task(new_tsk, CLONE_VM | CLONE_FS | CLONE_FILES| CLONE_SIGHAND);	/* FIXME Notify Thread Creation */	/* NOW FIXME Suspend the Thread if we have to */	/* FIXME: SECURITY */	/* FIXME Dispatch thread */	return STATUS_SUCCESS;} /* end PspCreateThread *//* * NtCreateThread */NTSTATUS STDCALLNtCreateThread(OUT PHANDLE              ThreadHandle,		IN  ACCESS_MASK          DesiredAccess,		IN  POBJECT_ATTRIBUTES   ObjectAttributes  OPTIONAL,		IN  HANDLE               ProcessHandle,		OUT PCLIENT_ID           ClientId,		IN  PCONTEXT             ThreadContext,		IN  PINITIAL_TEB         InitialTeb,		IN  BOOLEAN              CreateSuspended){	PINITIAL_TEB safe_initial_teb;	NTSTATUS	status;		ktrace("NtCreateThread\n");	/* copy data form userspace */	if (!(safe_initial_teb = kmalloc(sizeof(INITIAL_TEB), GFP_KERNEL))) {		kdebug("***error malloc, No memory\n");		return -EINVAL;	}	if (copy_from_user(safe_initial_teb, InitialTeb, sizeof(INITIAL_TEB)))		return -EFAULT;	/* Call the shared function */	status = PspCreateThread(ThreadHandle,			DesiredAccess,			ObjectAttributes,			ProcessHandle,			NULL,			ClientId,			ThreadContext,			safe_initial_teb,			CreateSuspended,			NULL,			NULL);	kfree(safe_initial_teb);		return status;} /* end NtCreateThread */#endif

⌨️ 快捷键说明

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