📄 mutex.c
字号:
/* * mutex.c * * Copyright (C) 2006 Insigme Co., Ltd * * Authors: * - Lixing Chu * * 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. */ /* * mutex.c: mutex syscall functions * Reference to Kernel-win32 code */#include <linux/module.h>#include "mutex.h"#include "process.h"#include "thread.h"#include "objwait.h"#include <asm/uaccess.h>#ifdef CONFIG_UNIFIED_KERNELstatic int MutexConstructor(win32_object *, void *);static int MutexReconstructor(win32_object *, void *);static void MutexDestructor(win32_object *);static int MutexPoll(struct wait_table_entry *, struct ethread *);static void MutexDetach(win32_object *, struct eprocess *);struct win32_object_class mutex_objclass = { oc_type: "MUTEX", constructor: MutexConstructor, reconstructor: NULL, destructor: MutexDestructor, poll: MutexPoll, detach: MutexDetach};/* * initialise the mutex object class */void MutexClassInit(void){ InitObjectClass(&mutex_objclass);} /* end MutexClassInit() *//* * open a mutex object, creating if non-existent */NTSTATUSSTDCALLNtCreateMutant(OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN InitialOwner){ HANDLE hMutex; win32_object *obj; struct ethread *thread = thread_find(); struct mutex_args args; NTSTATUS Status = STATUS_SUCCESS; OBJECT_ATTRIBUTES obj_attr; UNICODE_STRING obj_name; ktrace("NtCreateMutant\n"); if(!thread) return -EINVAL; args.MutantHandle = MutantHandle; args.DesiredAccess = DesiredAccess; args.ObjectAttributes = ObjectAttributes; args.InitialOwner = InitialOwner; if (copy_from_user(&obj_attr, ObjectAttributes, sizeof(obj_attr))) return -EFAULT; if (copy_from_user(&obj_name, obj_attr.ObjectName, sizeof(obj_name))) return -EFAULT; obj_attr.ObjectName = &obj_name; args.ObjectAttributes = &obj_attr; obj = CreateObject(thread,&mutex_objclass, (char *) (obj_attr.ObjectName)->Buffer, &args, &hMutex); if (IS_ERR(obj)) return PTR_ERR(obj); /* now we may have to try and grab the mutex immediately */ if (InitialOwner) { DECLARE_SINGLE_WAIT(wt,obj); long timeout = MAX_SCHEDULE_TIMEOUT; add_wait_queue(&obj->o_wait,&wt.wt_entries[0].wte_wait); Status = do_wait_for_objects(thread,&wt,&timeout); remove_wait_queue(&obj->o_wait,&wt.wt_entries[0].wte_wait); if (Status != STATUS_WAIT_0) { /* couldn't grab the mutex - close handle and return */ NtClose(hMutex); objput(obj); return (Status<0 ? Status : -EIO); /* failed somehow */ } } objput(obj); if(copy_to_user(MutantHandle,&hMutex,sizeof(HANDLE))) Status = -EFAULT; return Status;} /* end NtCreateMutant() *//* * open a mutex object, failing if non-existent */NTSTATUSSTDCALLNtOpenMutant(OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes){ HANDLE hMutex; win32_object *obj; struct ethread *thread = thread_find(); ktrace("NtOpenMutant\n"); if(!thread) return -EINVAL; obj = OpenObject(thread,&mutex_objclass,(char *) ObjectAttributes->ObjectName->Buffer,&hMutex); if (IS_ERR(obj)) return PTR_ERR(obj); objput(obj); //*MutantHandle = hMutex; if((copy_to_user(MutantHandle,&hMutex,sizeof(HANDLE)))) return -EFAULT; return STATUS_SUCCESS;} /* end NtOpenMutant() *//* * release the state of a mutex */NTSTATUSSTDCALLNtReleaseMutant(IN HANDLE MutantHandle, IN PLONG PreviousCount OPTIONAL){ struct ethread *thread = thread_find(); struct eprocess *process = thread->threads_process; struct win32_mutex *mutex; win32_object *obj; ktrace("NtReleaseMutant\n"); if(!thread) return -EINVAL; obj = GetObject(thread,MutantHandle,&mutex_objclass); if (IS_ERR(obj)) return PTR_ERR(obj); mutex = obj->o_private; #ifdef __HAVE_ARCH_CMPXCHG /* release the object if we owned it */ if (cmpxchg(&mutex->wm_owner,process,NULL)==process) { /* we did own it */ signal_object(obj,1); }#else spin_lock(&mutex->wm_lock); if (mutex->wm_owner==process) { mutex->wm_owner = NULL; signal_object(obj,1); } spin_unlock(&mutex->wm_lock);#endif objput(obj); return STATUS_SUCCESS;} /* end NtReleaseMutant() *//* * poll the state of a mutex for WaitFor*() functions * - if signalled, sets to non-signalled before returning */static int MutexPoll(struct wait_table_entry *wte, struct ethread *thread){ struct eprocess *process = thread->threads_process; struct win32_mutex *mutex = wte->wte_obj->o_private; int ret; ktrace("MutexPoll\n"); ret = POLL_NOTSIG;#ifdef __HAVE_ARCH_CMPXCHG /* grab the mutex if available */ if (cmpxchg(&mutex->wm_owner,NULL,process)==NULL) ret = POLL_SIG; /* got it */#else spin_lock(&mutex->wm_lock); if (!mutex->wm_owner) { mutex->wm_owner = process; ret = POLL_SIG; } spin_unlock(&mutex->wm_lock);#endif return ret;} /* end MutexPoll() *//* * construct a mutex (allocate its private data) * - called by CreateObject if the mutex does not already exists * - called with the object class lock held */static int MutexConstructor(win32_object *obj, void *data){ struct win32_mutex *mutex; ktrace("MutexConstructor\n"); mutex = (struct win32_mutex *) kmalloc(sizeof(struct win32_mutex), GFP_KERNEL); if (!mutex) return -ENOMEM; obj->o_private = mutex; mutex->wm_owner = NULL;#ifndef __HAVE_ARCH_CMPXCHG spin_lock_init(&mutex->wm_lock);#endif return 0;} /* end MutexConstructor() *//* * reconstruct a mutex (allocate its private data) * - called by CreateObject if the mutex already exists * - called without the object class lock held */static int MutexReconstructor(win32_object *obj, void *data){ /* TODO */ ktrace("MutexReconstructor(%p)\n",obj); return 0;} /* end MutexReconstructor() *//* * destroy a mutex (discard its private data) */static void MutexDestructor(win32_object *obj){ ktrace("MutexDestructor\n"); kfree(obj->o_private);} /* end MutexDestructor() *//* * notification of abnormal mutex release * - called when attached process releases connection (probably terminates) */static void MutexDetach(win32_object *obj, struct eprocess *process){ struct win32_mutex *mutex = obj->o_private; ktrace("MutexDetach\n");#ifdef __HAVE_ARCH_CMPXCHG /* release the object if we owned it */ if (cmpxchg(&mutex->wm_owner,process,NULL)==process) signal_object(obj,1); /* we did own it */#else spin_lock(&mutex->wm_lock); if (mutex->wm_owner==process) { mutex->wm_owner = NULL; signal_object(obj,1); } spin_unlock(&mutex->wm_lock);#endif} /* end MutexDetach() */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -