📄 thread.c
字号:
/* * thread.c * * Copyright (C) 2006 Insigme Co., Ltd * * Authors: * - Chenzhan Hu, Lixing Chu, Limin Jin, Liwei Zhou, Zhiqiang Jiao * * 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: win32 thread handling * Reference to Kernel-win32 code */#include <linux/module.h>#include <linux/win32_process.h>#include <linux/mm.h>#include <asm/uaccess.h>#include <asm/ldt.h>#include "objwait.h"#include "thread.h"#include "apc.h"#ifdef CONFIG_UNIFIED_KERNELstatic int ThreadConstructor(win32_object *, void *);static int ThreadReconstructor(win32_object *, void *);static void ThreadDestructor(win32_object *);static int ThreadPoll(struct wait_table_entry *, struct ethread *);asmlinkage int set_win_fs(struct user_desc *info);struct win32_object_class thread_objclass = { oc_type: "THRD ", constructor: ThreadConstructor, reconstructor: NULL, destructor: ThreadDestructor, poll: ThreadPoll,};static void ThreadClose(struct ethread *);static int ThreadSignal(struct ethread *, int);static void ThreadExit(struct ethread *, int);static void ThreadExecve(struct ethread *);static void ThreadFork(struct ethread *, struct task_struct *, struct task_struct *, unsigned long);static const struct ethread_operations ethread_ops = { name: "ethread", owner: THIS_MODULE, close: ThreadClose, exit: ThreadExit, signal: ThreadSignal, execve: ThreadExecve, fork: ThreadFork};#define arch_init_thread i386_init_thread#define i386_init_thread(th, ctx) do { } while (0)void __attribute__((regparm(3)))set_trap_frame(unsigned long esp, task_t *tsk){ if (tsk->ethread) tsk->ethread->tcb.trap_frame = (struct ktrap_frame *)esp;} /* * initialise the thread object class */void ThreadClassInit(void){ InitObjectClass(&thread_objclass);} /* end ThreadClassInit() *//* * poll the state of a thread for WaitFor*() functions * - if signalled, sets to non-signalled before returning */static int ThreadPoll(struct wait_table_entry *wte, struct ethread *_thread){ struct ethread *thread = wte->wte_obj->o_private; int ret; ret = (thread->tcb.state==Running) ? POLL_NOTSIG : POLL_SIG; return ret;} /* end ThreadPoll() *//* * construct a thread (allocate its private data) * - called by CreateObject if the thread does not already exist * - called with the object class lock held */static int ThreadConstructor(win32_object *obj, void *data){ struct ethread_cons_data *etcd = data; struct eprocess *process; struct ethread *thread; ktrace("ThreadConstructor\n"); if (!etcd->etcd_process || etcd->etcd_process->o_class!=&process_objclass ) { return -EINVAL; } process = (struct eprocess *) etcd->etcd_process->o_private; thread = (struct ethread *) kmalloc(sizeof(struct ethread), GFP_KERNEL); if (!thread) return -ENOMEM; obj->o_private = thread; thread->et_obj = obj; thread->et_task = etcd->etcd_task; thread->et_ops = (struct ethread_operations *)ðread_ops; atomic_set(&thread->et_count,0); /* attach to the containing process */ write_lock(&process->ep_lock); objget(etcd->etcd_process); thread->threads_process = process; write_unlock(&process->ep_lock); EThreadInit(thread, process); /* create a thread object and hook in to the Linux task */ try_module_get(THIS_MODULE); add_ethread(thread->et_task, thread); objget(obj); return 0;} /* end ThreadConstructor() *//* initialize ethread */void EThreadInit(struct ethread *thread, struct eprocess *process){ ktrace("EThreadInit\n"); /* FIXME: PsCreateCidHandle(Thread, PsThreadType, &Thread->Cid.UniqueThread) */ INIT_LIST_HEAD(&thread->lpc_reply_chain); INIT_LIST_HEAD(&thread->irp_list); INIT_LIST_HEAD(&thread->active_timer_list_head); thread->active_timer_list_lock = SPIN_LOCK_UNLOCKED; sema_init(&thread->lpc_reply_semaphore, 0); thread->cid.unique_process = process->unique_processid; thread->threads_process = process; thread->win32_start_address = 0; /* context->Eax, default is 0 */ list_add_tail(&thread->thread_list_entry, &process->thread_list_head);} /* end EThreadInit *//* initialize kthread */void KThreadInit(struct kthread *thread, struct eprocess *process){ ktrace("KThreadInit\n"); INIT_DISP_HEADER(&thread->header, thread_object, sizeof(struct ethread), false); /* initialize the mutant list */ INIT_LIST_HEAD(&thread->mutant_list_head); /* setup apc fields */ INIT_LIST_HEAD(&thread->apc_state.apc_list_head[0]); INIT_LIST_HEAD(&thread->apc_state.apc_list_head[1]); INIT_LIST_HEAD(&thread->saved_apc_state.apc_list_head[0]); INIT_LIST_HEAD(&thread->saved_apc_state.apc_list_head[1]); thread->apc_state.process = (struct kprocess * )process; thread->apc_state_pointer[OriginalApcEnvironment] = &thread->apc_state; thread->apc_state_pointer[AttachedApcEnvironment] = &thread->saved_apc_state; thread->apc_state_index = OriginalApcEnvironment; thread->apc_queue_lock = SPIN_LOCK_UNLOCKED; thread->apc_queueable = true; /* initialize the suspend semaphore */ /* FIXME: sema_init(&thread->suspend_semaphore, 0); */ /* FIXME: keinitializetimer(&thread->timer); */ /* * 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. */ arch_init_thread(thread, context); thread->base_priority = process->pcb.base_priority; thread->quantum = process->pcb.quantum_reset; thread->quantum_reset = process->pcb.quantum_reset; thread->affinity = process->pcb.affinity; thread->priority = process->pcb.base_priority; thread->user_affinity = process->pcb.affinity; thread->disable_boost = process->pcb.disable_boost; thread->auto_alignment = process->pcb.auto_alignment;#if defined(_M_IX86) thread->iopl = process->pcb.iopl;#endif /* set the thread to initalized */ thread->state = Initialized; list_add_tail(&thread->thread_list_entry, &process->pcb.thread_list_head);} /* end KThreadInit *//* * reconstruct a thread (allocate its private data) * - called by CreateObject if the thread already exists * - called without the object class lock held */static int ThreadReconstructor(win32_object *obj, void *data){ /* TODO */ return -ENOANO;} /* end ThreadReconstructor() *//* * destroy a thread (discard its private data) */static void ThreadDestructor(win32_object *obj){ struct ethread *thread; struct eprocess *process; BOOLEAN last; ktrace("ThreadDestructor, obj %p\n", obj); thread = obj->o_private; process = thread->threads_process; /* detach from the containing process */ list_del(&thread->thread_list_entry); list_del(&thread->tcb.thread_list_entry); last = list_empty(&process->thread_list_head); if (thread->tcb.state != Terminated) remove_ethread(thread->et_task, thread); /* if it's the last thread, terminate the process */ if (last) objput(process->ep_obj); kfree(obj->o_private);} /* end ThreadDestructor() *//* * thread object destructor */static void ThreadClose(struct ethread *thread){ /* detach the thread record from the Linux task */ ktrace("ThreadClose, obj %p\n", thread->et_obj); thread->et_task = NULL; thread->tcb.state = Terminated; objput(thread->et_obj);} /* end ThreadClose() *//* * notification of exit * - the exit_status is as sys_wait() would return * - notification includes fatal signals */static void ThreadExit(struct ethread *thread, int exit_status){ ktrace("ThreadExit\n"); thread->exit_status = exit_status;} /* end ThreadExit() *//* * notification of signal */static int ThreadSignal(struct ethread *thread, int signal){ return WIN32_THREAD_SIGNAL_OKAY;} /* end ThreadSignal() *//* * notification of execve * - if this is NULL, a thread object will be destroyed on execve */static void ThreadExecve(struct ethread *thread){ /* TODO */} /* end ThreadExecve() *//* * notification that fork/clone has set up the new process and * is just about to dispatch it * - no threads will have been copied by default */static void ThreadFork(struct ethread *thread, struct task_struct *parent, struct task_struct *child, unsigned long clone_flags){ /* TODO */} /* end ThreadFork() *//* find the current thread */struct ethread *thread_find(void){ struct ethread *thread; ktrace("thread_find\n"); read_lock(¤t->alloc_lock); thread = current->ethread; read_unlock(¤t->alloc_lock); return thread;} /* end thread_find() *//* * set teb on fs */int set_teb_selector(long teb){ struct user_desc info; unsigned int fs = TEB_SELECTOR; info.entry_number = fs >> 3; info.base_addr = teb; info.limit = 1; info.contents = 0; info.read_exec_only = 0; info.seg_not_present = 0; info.seg_32bit = 1; info.limit_in_pages = 1; info.useable = 0; return set_win_fs(&info);} /* end set_teb_selector *//* create teb */PTEB create_teb(struct eprocess *process, PCLIENT_ID client_id, unsigned long stack_top){ PTEB teb, kteb; unsigned long addr = TEB_BASE + PAGE_SIZE; unsigned long brk_res; struct mm_struct *mm = current->mm; struct vm_area_struct *vma; ktrace("create_teb\n"); /* Allocate the TEB */ kteb = kmalloc(sizeof(TEB), GFP_KERNEL); if (!kteb) return ERR_PTR(-ENOMEM); do { addr -= PAGE_SIZE; vma = find_vma(mm, addr); } while (vma && vma->vm_start < addr + PAGE_SIZE); down_write(&mm->mmap_sem); brk_res = do_brk(addr, PAGE_SIZE); up_write(&mm->mmap_sem); if (brk_res == addr) teb = (PTEB)addr; else { kfree(kteb); return ERR_PTR(-EINVAL); } /* Initialize the PEB */ memset(kteb, 0, sizeof(TEB)); /* Set TIB Data */ kteb->Tib.ExceptionList = (PVOID)0xFFFFFFFF; kteb->Tib.DUMMYUNIONNAME.Version = 1; kteb->Tib.Self = (PNT_TIB)teb; /* Set TEB Data */ if (client_id) { kteb->Cid = *client_id; kteb->RealClientId = *client_id; } else { memset(&kteb->Cid, 0, sizeof(CLIENT_ID)); memset(&kteb->RealClientId, 0, sizeof(CLIENT_ID)); } kteb->Peb = process->peb; kteb->CurrentLocale = 0; /* FIXME: PsDefaultThreadLocaleId; */ kteb->Tib.StackBase = (PVOID)stack_top; kteb->Tib.StackLimit = (PVOID)(stack_top - 0x400000); kteb->DeallocationStack = 0; if (copy_to_user(teb, kteb, sizeof(TEB))) { kfree(kteb); return ERR_PTR(-EFAULT); } /* Return TEB Address */ kfree(kteb); return teb;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -