Whamcloud - gitweb
b=19557 Add cond_resched calls to avoid hogging the cpu
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-prim.c
index 064b071..da12e24 100644 (file)
@@ -1,26 +1,42 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=4:tabstop=4:
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
  *
+ * GPL HEADER START
  *
- *  Copyright (c) 2004 Cluster File Systems, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *   This file is part of Lustre, http://www.lustre.org.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
  *
- *   Lustre is free software; you can redistribute it and/or modify it under
- *   the terms of version 2 of the GNU General Public License as published by
- *   the Free Software Foundation. Lustre is distributed in the hope that it
- *   will be useful, but WITHOUT ANY WARRANTY; without even the implied
- *   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details. You should have received a
- *   copy of the GNU General Public License along with Lustre; if not, write
- *   to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *   USA.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright  2008 Sun Microsystems, Inc. All rights reserved
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
  */
 
 #define DEBUG_SUBSYSTEM S_LNET
 
 #include <libcfs/libcfs.h>
-#include <libcfs/kp30.h>
 
 
 /*
@@ -38,7 +54,7 @@
  * Return Value:
  *   void: N/A
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
@@ -47,7 +63,7 @@ cfs_thread_proc(
     void * context
     )
 {
-    cfs_thread_context_t * thread_context = 
+    cfs_thread_context_t * thread_context =
         (cfs_thread_context_t *) context;
 
     /* Execute the specified function ... */
@@ -57,7 +73,7 @@ cfs_thread_proc(
     }
 
     /* Free the context memory */
-   
+
     cfs_free(context);
 
     /* Terminate this system thread */
@@ -77,7 +93,7 @@ cfs_thread_proc(
  * Return Value:
  *   int:   0 on success or error codes
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
@@ -132,10 +148,10 @@ int cfs_kernel_thread(int (*func)(void *), void *arg, int flag)
  */
 
 
-static CFS_DECL_RWSEM(cfs_symbol_lock);
+static CFS_DECLARE_RWSEM(cfs_symbol_lock);
 CFS_LIST_HEAD(cfs_symbol_list);
 
-int MPSystem = FALSE;
+int libcfs_is_mp_system = FALSE;
 
 /*
  * cfs_symbol_get
@@ -148,27 +164,27 @@ int MPSystem = FALSE;
  *   If the symbol is in the table, return the address of it.
  *   If not, return NULL.
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
 void *
 cfs_symbol_get(const char *name)
 {
-    struct list_head    *walker;
-    struct cfs_symbol   *sym = NULL;
+    cfs_list_t              *walker;
+    struct cfs_symbol       *sym = NULL;
 
-    down_read(&cfs_symbol_lock);
-    list_for_each(walker, &cfs_symbol_list) {
-        sym = list_entry (walker, struct cfs_symbol, sym_list);
+    cfs_down_read(&cfs_symbol_lock);
+    cfs_list_for_each(walker, &cfs_symbol_list) {
+        sym = cfs_list_entry (walker, struct cfs_symbol, sym_list);
         if (!strcmp(sym->name, name)) {
             sym->ref ++;
             break;
-        } 
-    } 
-    up_read(&cfs_symbol_lock);
+        }
+    }
+    cfs_up_read(&cfs_symbol_lock);
 
-    if (sym != NULL) 
+    if (sym != NULL)
         return sym->value;
 
     return NULL;
@@ -184,26 +200,26 @@ cfs_symbol_get(const char *name)
  * Return Value:
  *   N/A
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
 void
 cfs_symbol_put(const char *name)
 {
-    struct list_head    *walker;
-    struct cfs_symbol   *sym = NULL;
+    cfs_list_t              *walker;
+    struct cfs_symbol       *sym = NULL;
 
-    down_read(&cfs_symbol_lock);
-    list_for_each(walker, &cfs_symbol_list) {
-        sym = list_entry (walker, struct cfs_symbol, sym_list);
+    cfs_down_read(&cfs_symbol_lock);
+    cfs_list_for_each(walker, &cfs_symbol_list) {
+        sym = cfs_list_entry (walker, struct cfs_symbol, sym_list);
         if (!strcmp(sym->name, name)) {
             LASSERT(sym->ref > 0);
             sym->ref--;
             break;
-        } 
-    } 
-    up_read(&cfs_symbol_lock);
+        }
+    }
+    cfs_up_read(&cfs_symbol_lock);
 
     LASSERT(sym != NULL);
 }
@@ -220,7 +236,7 @@ cfs_symbol_put(const char *name)
  * Return Value:
  *   N/A
  *
- * Notes: 
+ * Notes:
  *   Zero: Succeed to register
  *   Non-Zero: Fail to register the symbol
  */
@@ -228,9 +244,9 @@ cfs_symbol_put(const char *name)
 int
 cfs_symbol_register(const char *name, const void *value)
 {
-    struct list_head    *walker;
-    struct cfs_symbol   *sym = NULL;
-    struct cfs_symbol   *new = NULL;
+    cfs_list_t              *walker;
+    struct cfs_symbol       *sym = NULL;
+    struct cfs_symbol       *new = NULL;
 
     new = cfs_alloc(sizeof(struct cfs_symbol), CFS_ALLOC_ZERO);
     if (!new) {
@@ -241,17 +257,17 @@ cfs_symbol_register(const char *name, const void *value)
     new->ref = 0;
     CFS_INIT_LIST_HEAD(&new->sym_list);
 
-    down_write(&cfs_symbol_lock);
-    list_for_each(walker, &cfs_symbol_list) {
-        sym = list_entry (walker, struct cfs_symbol, sym_list);
+    cfs_down_write(&cfs_symbol_lock);
+    cfs_list_for_each(walker, &cfs_symbol_list) {
+        sym = cfs_list_entry (walker, struct cfs_symbol, sym_list);
         if (!strcmp(sym->name, name)) {
-            up_write(&cfs_symbol_lock);
+            cfs_up_write(&cfs_symbol_lock);
             cfs_free(new);
             return 0; // alreay registerred
         }
     }
-    list_add_tail(&new->sym_list, &cfs_symbol_list);
-    up_write(&cfs_symbol_lock);
+    cfs_list_add_tail(&new->sym_list, &cfs_symbol_list);
+    cfs_up_write(&cfs_symbol_lock);
 
     return 0;
 }
@@ -266,28 +282,28 @@ cfs_symbol_register(const char *name, const void *value)
  * Return Value:
  *   N/A
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
 void
 cfs_symbol_unregister(const char *name)
 {
-    struct list_head    *walker;
-    struct list_head    *nxt;
-    struct cfs_symbol   *sym = NULL;
+    cfs_list_t              *walker;
+    cfs_list_t              *nxt;
+    struct cfs_symbol       *sym = NULL;
 
-    down_write(&cfs_symbol_lock);
-    list_for_each_safe(walker, nxt, &cfs_symbol_list) {
-        sym = list_entry (walker, struct cfs_symbol, sym_list);
+    cfs_down_write(&cfs_symbol_lock);
+    cfs_list_for_each_safe(walker, nxt, &cfs_symbol_list) {
+        sym = cfs_list_entry (walker, struct cfs_symbol, sym_list);
         if (!strcmp(sym->name, name)) {
             LASSERT(sym->ref == 0);
-            list_del (&sym->sym_list);
+            cfs_list_del (&sym->sym_list);
             cfs_free(sym);
             break;
         }
     }
-    up_write(&cfs_symbol_lock);
+    cfs_up_write(&cfs_symbol_lock);
 }
 
 /*
@@ -300,24 +316,24 @@ cfs_symbol_unregister(const char *name)
  * Return Value:
  *   N/A
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
 void
 cfs_symbol_clean()
 {
-    struct list_head    *walker;
+    cfs_list_t          *walker;
     struct cfs_symbol   *sym = NULL;
 
-    down_write(&cfs_symbol_lock);
-    list_for_each(walker, &cfs_symbol_list) {
-        sym = list_entry (walker, struct cfs_symbol, sym_list);
+    cfs_down_write(&cfs_symbol_lock);
+    cfs_list_for_each(walker, &cfs_symbol_list) {
+        sym = cfs_list_entry (walker, struct cfs_symbol, sym_list);
         LASSERT(sym->ref == 0);
-        list_del (&sym->sym_list);
+        cfs_list_del (&sym->sym_list);
         cfs_free(sym);
     }
-    up_write(&cfs_symbol_lock);
+    cfs_up_write(&cfs_symbol_lock);
     return;
 }
 
@@ -329,7 +345,7 @@ cfs_symbol_clean()
 
 
 /* Timer dpc procedure */
+
 static void
 cfs_timer_dpc_proc (
     IN PKDPC Dpc,
@@ -348,7 +364,12 @@ cfs_timer_dpc_proc (
     KeReleaseSpinLock(&(timer->Lock), Irql);
 
     /* call the user specified timer procedure */
-    timer->proc((unsigned long)(timer->arg));
+    timer->proc((long_ptr_t)timer->arg);
+}
+
+void cfs_init_timer(cfs_timer_t *timer)
+{
+    memset(timer, 0, sizeof(cfs_timer_t));
 }
 
 /*
@@ -363,11 +384,11 @@ cfs_timer_dpc_proc (
  * Return Value:
  *   N/A
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
-void cfs_timer_init(cfs_timer_t *timer, void (*func)(unsigned long), void *arg)
+void cfs_timer_init(cfs_timer_t *timer, void (*func)(ulong_ptr_t), void *arg)
 {
     memset(timer, 0, sizeof(cfs_timer_t));
 
@@ -391,7 +412,7 @@ void cfs_timer_init(cfs_timer_t *timer, void (*func)(unsigned long), void *arg)
  * Return Value:
  *   N/A
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
@@ -411,7 +432,7 @@ void cfs_timer_done(cfs_timer_t *timer)
  * Return Value:
  *   N/A
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
@@ -423,9 +444,9 @@ void cfs_timer_arm(cfs_timer_t *timer, cfs_time_t deadline)
     KeAcquireSpinLock(&(timer->Lock), &Irql);
     if (!cfs_is_flag_set(timer->Flags, CFS_TIMER_FLAG_TIMERED)){
 
-        timeout.QuadPart = (LONGLONG)-1*1000*1000*10/HZ*deadline;
+        timeout.QuadPart = (LONGLONG)-1*1000*1000*10/CFS_HZ*deadline;
 
-        if (KeSetTimer(&timer->Timer, timeout, &timer->Dpc )) {
+        if (KeSetTimer(&timer->Timer, timeout, &timer->Dpc)) {
             cfs_set_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
         }
 
@@ -445,7 +466,7 @@ void cfs_timer_arm(cfs_timer_t *timer, cfs_time_t deadline)
  * Return Value:
  *   N/A
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
@@ -471,7 +492,7 @@ void cfs_timer_disarm(cfs_timer_t *timer)
  *   1:  if it's armed.
  *   0:  if it's not.
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
@@ -499,7 +520,7 @@ int cfs_timer_is_armed(cfs_timer_t *timer)
  * Return Value:
  *   the deadline value
  *
- * Notes: 
+ * Notes:
  *   N/A
  */
 
@@ -517,6 +538,11 @@ void cfs_daemonize(char *str)
     return;
 }
 
+int cfs_daemonize_ctxt(char *str) {
+    cfs_daemonize(str);
+    return 0;
+}
+
 /*
  *  routine related with sigals
  */
@@ -550,23 +576,203 @@ void cfs_clear_sigpending(void)
     return;
 }
 
+/*
+ *  thread cpu affinity routines
+ */
+
+typedef struct _THREAD_BASIC_INFORMATION {
+    NTSTATUS ExitStatus;
+    PVOID TebBaseAddress;
+    CLIENT_ID ClientId;
+    ULONG_PTR AffinityMask;
+    KPRIORITY Priority;
+    LONG BasePriority;
+} THREAD_BASIC_INFORMATION;
+
+typedef THREAD_BASIC_INFORMATION *PTHREAD_BASIC_INFORMATION;
+
+#define THREAD_QUERY_INFORMATION       (0x0040)
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+ZwOpenThread (
+    __out PHANDLE ThreadHandle,
+    __in ACCESS_MASK DesiredAccess,
+    __in POBJECT_ATTRIBUTES ObjectAttributes,
+    __in_opt PCLIENT_ID ClientId
+    );
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+ZwQueryInformationThread (
+    __in HANDLE ThreadHandle,
+    __in THREADINFOCLASS ThreadInformationClass,
+    __out_bcount(ThreadInformationLength) PVOID ThreadInformation,
+    __in ULONG ThreadInformationLength,
+    __out_opt PULONG ReturnLength
+    );
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+ZwSetInformationThread (
+    __in HANDLE ThreadHandle,
+    __in THREADINFOCLASS ThreadInformationClass,
+    __in_bcount(ThreadInformationLength) PVOID ThreadInformation,
+    __in ULONG ThreadInformationLength
+    );
+
+HANDLE
+cfs_open_current_thread()
+{
+    NTSTATUS         status;
+    HANDLE           handle = NULL;
+    OBJECT_ATTRIBUTES oa;
+    CLIENT_ID        cid;
+
+    /* initialize object attributes */
+    InitializeObjectAttributes( &oa, NULL, OBJ_KERNEL_HANDLE |
+                                OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+    /* initialize client id */
+    cid.UniqueProcess = PsGetCurrentProcessId();
+    cid.UniqueThread  = PsGetCurrentThreadId();
+
+    /* get thread handle */
+    status = ZwOpenThread( &handle, THREAD_QUERY_INFORMATION |
+                           THREAD_SET_INFORMATION, &oa, &cid);
+    if (!NT_SUCCESS(status)) {
+        handle = NULL;
+    }
+
+    return handle;
+}
+
+void
+cfs_close_thread_handle(HANDLE handle)
+{
+    if (handle)
+        ZwClose(handle);
+}
+
+KAFFINITY
+cfs_query_thread_affinity()
+{
+    NTSTATUS         status;
+    HANDLE           handle = NULL;
+    DWORD            size;
+    THREAD_BASIC_INFORMATION TBI = {0};
+
+    /* open current thread */
+    handle = cfs_open_current_thread();
+    if (!handle) {
+        goto errorout;
+    }
+
+    /* query thread cpu affinity */
+    status = ZwQueryInformationThread(handle, ThreadBasicInformation,
+                       &TBI, sizeof(THREAD_BASIC_INFORMATION), &size);
+    if (!NT_SUCCESS(status)) {
+        goto errorout;
+    }
+
+errorout:
+
+    cfs_close_thread_handle(handle);
+    return TBI.AffinityMask;
+}
+
+int
+cfs_set_thread_affinity(KAFFINITY affinity)
+{
+    NTSTATUS         status;
+    HANDLE           handle = NULL;
+
+    /* open current thread */
+    handle = cfs_open_current_thread();
+    if (!handle) {
+        goto errorout;
+    }
+
+    /* set thread cpu affinity */
+    status = ZwSetInformationThread(handle, ThreadAffinityMask,
+                                    &affinity, sizeof(KAFFINITY));
+    if (!NT_SUCCESS(status)) {
+        goto errorout;
+    }
+
+errorout:
+
+    cfs_close_thread_handle(handle);
+    return NT_SUCCESS(status);
+}
+
+int
+cfs_tie_thread_to_cpu(int cpu)
+{
+    return cfs_set_thread_affinity((KAFFINITY) (1 << cpu));
+}
+
+int
+cfs_set_thread_priority(KPRIORITY priority)
+{
+    NTSTATUS         status;
+    HANDLE           handle = NULL;
+
+    /* open current thread */
+    handle = cfs_open_current_thread();
+    if (!handle) {
+        goto errorout;
+    }
+
+    /* set thread cpu affinity */
+    status = ZwSetInformationThread(handle, ThreadPriority,
+                                    &priority, sizeof(KPRIORITY));
+    if (!NT_SUCCESS(status)) {
+        KdPrint(("set_thread_priority failed: %xh\n", status));
+        goto errorout;
+    }
+
+errorout:
+
+    cfs_close_thread_handle(handle);
+    return NT_SUCCESS(status);
+}
+
+int cfs_need_resched(void)
+{
+        return 0;
+}
+
+void cfs_cond_resched(void)
+{
+}
+
 /**
- **  Initialize routines 
+ **  Initialize routines
  **/
 
+void cfs_libc_init();
+
 int
 libcfs_arch_init(void)
-{ 
+{
     int         rc;
 
-    spinlock_t  lock;
+    cfs_spinlock_t  lock;
     /* Workground to check the system is MP build or UP build */
-    spin_lock_init(&lock);
-    spin_lock(&lock);
-    MPSystem = (int)lock.lock;
+    cfs_spin_lock_init(&lock);
+    cfs_spin_lock(&lock);
+    libcfs_is_mp_system = (int)lock.lock;
     /* MP build system: it's a real spin, for UP build system, it
        only raises the IRQL to DISPATCH_LEVEL */
-    spin_unlock(&lock);
+    cfs_spin_unlock(&lock);
+
+    /* initialize libc routines (confliction between libcnptr.lib
+       and kernel ntoskrnl.lib) */
+    cfs_libc_init();
 
     /* create slab memory caches for page alloctors */
     cfs_page_t_slab = cfs_mem_cache_create(
@@ -579,10 +785,9 @@ libcfs_arch_init(void)
          cfs_page_p_slab == NULL ){
         rc = -ENOMEM;
         goto errorout;
-    }    
+    }
 
     rc = init_task_manager();
-
     if (rc != 0) {
         cfs_enter_debugger();
         KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing task manager ...\n"));
@@ -591,7 +796,6 @@ libcfs_arch_init(void)
 
     /* initialize the proc file system */
     rc = proc_init_fs();
-
     if (rc != 0) {
         cfs_enter_debugger();
         KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing proc fs ...\n"));
@@ -601,15 +805,16 @@ libcfs_arch_init(void)
 
     /* initialize the tdi data */
     rc = ks_init_tdi_data();
-
     if (rc != 0) {
         cfs_enter_debugger();
-        KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing tdi ...\n"));
+        KdPrint(("winnt-prim.c:libcfs_arch_init: failed to initialize tdi.\n"));
         proc_destroy_fs();
         cleanup_task_manager();
         goto errorout;
     }
 
+    rc = start_shrinker_timer();
+
 errorout:
 
     if (rc != 0) {
@@ -628,12 +833,18 @@ errorout:
 void
 libcfs_arch_cleanup(void)
 {
+    /* stop shrinker timer */
+    stop_shrinker_timer();
+
     /* finialize the tdi data */
     ks_fini_tdi_data();
 
     /* detroy the whole proc fs tree and nodes */
     proc_destroy_fs();
 
+    /* cleanup context of task manager */
+    cleanup_task_manager();
+
     /* destroy the taskslot cache slab */
     if (cfs_page_t_slab) {
         cfs_mem_cache_destroy(cfs_page_t_slab);
@@ -643,7 +854,7 @@ libcfs_arch_cleanup(void)
         cfs_mem_cache_destroy(cfs_page_p_slab);
     }
 
-       return; 
+    return;
 }
 
 EXPORT_SYMBOL(libcfs_arch_init);