📄 event.c
字号:
/* * event.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. *//* * event.c: event syscall functions * Reference to Kernel-win32 code */#include <linux/module.h>#include "event.h"#include "process.h"#include "thread.h"#include "objwait.h"#include <asm/uaccess.h>#ifdef CONFIG_UNIFIED_KERNELstatic int EventConstructor(win32_object *, void *);static int EventReconstructor(win32_object *, void *);static void EventDestructor(win32_object *);static int EventPoll(struct wait_table_entry *, struct ethread *);struct win32_object_class event_objclass = { oc_type: "EVENT", constructor: EventConstructor, reconstructor: NULL, destructor: EventDestructor, poll: EventPoll,};/* * notify all waiters of event signal * - returns 1 if no new waiter found (no change made) */extern inline int EventNotifyAllWaiters(win32_object *obj){ struct list_head *waiter; int i = 0; spin_lock(&obj->o_wait.lock); list_for_each(waiter,&obj->o_wait.task_list) { struct wait_table_entry *wte = list_entry(waiter, struct wait_table_entry, wte_wait.task_list); /* set i to 1 if we change a bit */ i |= test_and_set_bit(0, (unsigned long *)&wte->wte_data) ^ 1; } spin_unlock(&obj->o_wait.lock); return ~i & 1;} /* end EventNotifyAllWaiters() *//* * initialise the event win32_object class */void EventClassInit(void){ InitObjectClass(&event_objclass);} /* end EventClassInit() *//* * open a event object, creating if non-existent */NTSTATUSSTDCALLNtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN EVENT_TYPE EventType, IN BOOLEAN InitialState){ HANDLE Handle; win32_object *obj; struct event_args args; OBJECT_ATTRIBUTES _ObjectAttributes; struct ethread *thread; UNICODE_STRING _ObjectName; if(!(thread=thread_find())) { kdebug("***error find thread\n"); return -EINVAL; } args.DesiredAccess=DesiredAccess; args.EventType=EventType; args.InitialState=InitialState; if(copy_from_user(&_ObjectAttributes, ObjectAttributes,sizeof(OBJECT_ATTRIBUTES))) return -EFAULT; if(copy_from_user(&_ObjectName, _ObjectAttributes.ObjectName,sizeof(UNICODE_STRING))) return -EFAULT; obj = CreateObject(thread,&event_objclass, (char*)_ObjectName.Buffer,&args,&Handle); if (IS_ERR(obj)) return PTR_ERR(obj); ktrace("*** NtCreateEvent(%p)=%p\n",obj,Handle); objput(obj); if(copy_to_user(EventHandle,&Handle,sizeof(HANDLE))) return -EFAULT; return STATUS_SUCCESS; } /* end NtCreateEvent() *//* * open a event object, failing if non-existent */NTSTATUSSTDCALLNtOpenEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes){ HANDLE Handle; win32_object *obj; struct ethread *thread; OBJECT_ATTRIBUTES _ObjectAttributes; UNICODE_STRING _ObjectName; if(!(thread=thread_find())) { kdebug("***error find thread\n"); return -EINVAL; } if(copy_from_user(&_ObjectAttributes, ObjectAttributes,sizeof(OBJECT_ATTRIBUTES))) return -EFAULT; if(copy_from_user(&_ObjectName, _ObjectAttributes.ObjectName,sizeof(UNICODE_STRING))) return -EFAULT; obj = OpenObject(thread,&event_objclass, (char*)_ObjectName.Buffer,&Handle); if (IS_ERR(obj)) return PTR_ERR(obj); ktrace("*** NtOpenEvent(%p)=%p\n",obj,Handle); objput(obj); if(copy_to_user(EventHandle,&Handle,sizeof(HANDLE))) return -EFAULT; return STATUS_SUCCESS;}/* end NtOpenEvent() *//* * set an event */NTSTATUSSTDCALLNtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState){ struct win32_event *event; win32_object *obj; struct ethread *thread; if(!(thread=thread_find())) { kdebug("***error find thread\n"); return -EINVAL; } obj = GetObject(thread,EventHandle,&event_objclass); if (IS_ERR(obj)) return PTR_ERR(obj); event = obj->o_private; if(copy_to_user(PreviousState,&(event->we_state),sizeof(LONG))) return -EFAULT; write_lock(&event->we_lock); if (1==event->we_state) { /* if already set, do nothing */ kdebug("SetEvent: 0\n"); } else if (waitqueue_active(&obj->o_wait)) { /* waiters pending */ if (EventNotifyAllWaiters(obj)) { /* no unnotified waiters attached */ kdebug("SetEvent: 1\n"); event->we_state = 1; } else { /* at least one waiter was notified */ kdebug("SetEvent: 2\n"); event->we_state = event->we_manreset; } } else { /* no one was waiting */ kdebug("SetEvent: 3\n"); event->we_state = 1; } write_unlock(&event->we_lock); signal_object(obj,1); ktrace("*** [%d] SetEvent(%p) = 1\n",current->pid,obj); objput(obj); return STATUS_SUCCESS;}/* end NtSetEvent() *//* * reset an event */NTSTATUSSTDCALLNtResetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState){ struct win32_event *event; win32_object *obj; struct ethread *thread; if(!(thread=thread_find())) { kdebug("***error find thread\n"); return -EINVAL; } obj = GetObject(thread,EventHandle,&event_objclass); if (IS_ERR(obj)) return PTR_ERR(obj); event = obj->o_private; if(copy_to_user(PreviousState,&(event->we_state),sizeof(LONG))) return -EFAULT; write_lock(&event->we_lock); event->we_state = 0; write_unlock(&event->we_lock); ktrace("*** [%d] ResetEvent(%p) = 1\n",current->pid,obj); objput(obj); return STATUS_SUCCESS;}/* end NtResetEvent() *//* * pulse an event */NTSTATUSSTDCALLNtPulseEvent(IN HANDLE EventHandle, OUT PLONG PreviousState){ struct win32_event *event; win32_object *obj; struct ethread *thread; if(!(thread=thread_find())) { kdebug("***error find thread\n"); return -EINVAL; } obj = GetObject(thread,EventHandle,&event_objclass); if (IS_ERR(obj)) return PTR_ERR(obj); event=obj->o_private; if(copy_to_user(PreviousState,&(event->we_state),sizeof(LONG))) return -EFAULT; /* just kick all the waiters */ EventNotifyAllWaiters(obj); signal_object(obj,1); ktrace("*** [%d] PulseEvent(%p) = 1\n",current->pid,obj); objput(obj); return STATUS_SUCCESS;}/* end NtPulseEvent() *//* * poll the state of an event for WaitFor*() functions * - signal status for this wait entry is stored in wte->wte_data * - wte->wte_data is initialised to 0 by do_wait_for_objects() */static int EventPoll(struct wait_table_entry *wte, struct ethread *filp){ struct win32_event *event = wte->wte_obj->o_private; int ret; ktrace("*** [%d] EventPoll(%p[%x],%d)\n", current->pid,wte->wte_obj,wte->wte_data,event->we_state); if (test_bit(0, (unsigned long *)&wte->wte_data)) { /* already marked as received signal */ ret = POLL_SIG; } else { /* not marked as received signal * check event status (may be first iteration) */ write_lock(&event->we_lock); if (event->we_state) { event->we_state = event->we_manreset; ret = POLL_SIG; } else { ret = POLL_NOTSIG; } write_unlock(&event->we_lock); } return ret;} /* end EventPoll() *//* * construct a event (allocate its private data) * - called by CreateObject if the event does not already exists * - called with the object class lock held */static int EventConstructor(win32_object *obj, void *data){ struct event_args *args = data; struct win32_event *event; ktrace("EventConstructor(%p,%d,%d)\n", obj,!(args->EventType),args->InitialState); event = (struct win32_event *) kmalloc(sizeof(struct win32_event), GFP_KERNEL); if (!event) return -ENOMEM; obj->o_private = event; rwlock_init(&event->we_lock); event->we_manreset = !(args->EventType); event->we_state = args->InitialState; return 0;} /* end EventConstructor() *//* * reconstruct a event * - called by CreateObject if the event already exists * - called without the win32_object class lock held */static int EventReconstructor(win32_object *obj, void *data){ /* TODO */ ktrace("EventReconstructor(%p)\n",obj); return 0;} /* end EventReconstructor() *//* * destroy a event (discard its private data) */static void EventDestructor(win32_object *obj){ ktrace("EventDestructor(%p)\n",obj); kfree(obj->o_private);} /* end EventDestructor() */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -