1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see [sun.com URL with a
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #define DEBUG_SUBSYSTEM S_LNET
39 #include <libcfs/libcfs.h>
48 * Lustre thread procedure wrapper routine (It's an internal routine)
51 * context: a structure of cfs_thread_context_t, containing
52 * all the necessary parameters
66 cfs_thread_context_t * thread_context =
67 (cfs_thread_context_t *) context;
69 /* Execute the specified function ... */
71 if (thread_context->func) {
72 (thread_context->func)(thread_context->arg);
75 /* Free the context memory */
79 /* Terminate this system thread */
81 PsTerminateSystemThread(STATUS_SUCCESS);
86 * Create a system thread to execute the routine specified
89 * func: function to be executed in the thread
90 * arg: argument transferred to func function
91 * flag: thread creation flags.
94 * int: 0 on success or error codes
100 int cfs_kernel_thread(int (*func)(void *), void *arg, int flag)
102 cfs_handle_t thread = NULL;
104 cfs_thread_context_t * context = NULL;
106 /* Allocate the context to be transferred to system thread */
108 context = cfs_alloc(sizeof(cfs_thread_context_t), CFS_ALLOC_ZERO);
114 context->func = func;
117 /* Create system thread with the cfs_thread_proc wrapper */
119 status = PsCreateSystemThread(
126 if (!NT_SUCCESS(status)) {
131 /* We need translate the nt status to linux error code */
133 return cfs_error_code(status);
137 // Query the thread id of the newly created thread
151 static CFS_DECL_RWSEM(cfs_symbol_lock);
152 CFS_LIST_HEAD(cfs_symbol_list);
154 int MPSystem = FALSE;
158 * To query the specified symbol form the symbol table
161 * name: the symbol name to be queried
164 * If the symbol is in the table, return the address of it.
165 * If not, return NULL.
172 cfs_symbol_get(const char *name)
174 struct list_head *walker;
175 struct cfs_symbol *sym = NULL;
177 down_read(&cfs_symbol_lock);
178 list_for_each(walker, &cfs_symbol_list) {
179 sym = list_entry (walker, struct cfs_symbol, sym_list);
180 if (!strcmp(sym->name, name)) {
185 up_read(&cfs_symbol_lock);
195 * To decrease the reference of the specified symbol
198 * name: the symbol name to be dereferred
208 cfs_symbol_put(const char *name)
210 struct list_head *walker;
211 struct cfs_symbol *sym = NULL;
213 down_read(&cfs_symbol_lock);
214 list_for_each(walker, &cfs_symbol_list) {
215 sym = list_entry (walker, struct cfs_symbol, sym_list);
216 if (!strcmp(sym->name, name)) {
217 LASSERT(sym->ref > 0);
222 up_read(&cfs_symbol_lock);
224 LASSERT(sym != NULL);
229 * cfs_symbol_register
230 * To register the specified symbol infromation
233 * name: the symbol name to be dereferred
234 * value: the value that the symbol stands for
240 * Zero: Succeed to register
241 * Non-Zero: Fail to register the symbol
245 cfs_symbol_register(const char *name, const void *value)
247 struct list_head *walker;
248 struct cfs_symbol *sym = NULL;
249 struct cfs_symbol *new = NULL;
251 new = cfs_alloc(sizeof(struct cfs_symbol), CFS_ALLOC_ZERO);
255 strncpy(new->name, name, CFS_SYMBOL_LEN);
256 new->value = (void *)value;
258 CFS_INIT_LIST_HEAD(&new->sym_list);
260 down_write(&cfs_symbol_lock);
261 list_for_each(walker, &cfs_symbol_list) {
262 sym = list_entry (walker, struct cfs_symbol, sym_list);
263 if (!strcmp(sym->name, name)) {
264 up_write(&cfs_symbol_lock);
266 return 0; // alreay registerred
269 list_add_tail(&new->sym_list, &cfs_symbol_list);
270 up_write(&cfs_symbol_lock);
276 * cfs_symbol_unregister
277 * To unregister/remove the specified symbol
280 * name: the symbol name to be dereferred
290 cfs_symbol_unregister(const char *name)
292 struct list_head *walker;
293 struct list_head *nxt;
294 struct cfs_symbol *sym = NULL;
296 down_write(&cfs_symbol_lock);
297 list_for_each_safe(walker, nxt, &cfs_symbol_list) {
298 sym = list_entry (walker, struct cfs_symbol, sym_list);
299 if (!strcmp(sym->name, name)) {
300 LASSERT(sym->ref == 0);
301 list_del (&sym->sym_list);
306 up_write(&cfs_symbol_lock);
311 * To clean all the symbols
326 struct list_head *walker;
327 struct cfs_symbol *sym = NULL;
329 down_write(&cfs_symbol_lock);
330 list_for_each(walker, &cfs_symbol_list) {
331 sym = list_entry (walker, struct cfs_symbol, sym_list);
332 LASSERT(sym->ref == 0);
333 list_del (&sym->sym_list);
336 up_write(&cfs_symbol_lock);
347 /* Timer dpc procedure */
352 IN PVOID DeferredContext,
353 IN PVOID SystemArgument1,
354 IN PVOID SystemArgument2)
359 timer = (cfs_timer_t *) DeferredContext;
362 KeAcquireSpinLock(&(timer->Lock), &Irql);
363 cfs_clear_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
364 KeReleaseSpinLock(&(timer->Lock), Irql);
366 /* call the user specified timer procedure */
367 timer->proc((unsigned long)(timer->arg));
372 * To initialize the cfs_timer_t
375 * timer: the cfs_timer to be initialized
376 * func: the timer callback procedure
377 * arg: argument for the callback proc
386 void cfs_timer_init(cfs_timer_t *timer, void (*func)(unsigned long), void *arg)
388 memset(timer, 0, sizeof(cfs_timer_t));
393 KeInitializeSpinLock(&(timer->Lock));
394 KeInitializeTimer(&timer->Timer);
395 KeInitializeDpc (&timer->Dpc, cfs_timer_dpc_proc, timer);
397 cfs_set_flag(timer->Flags, CFS_TIMER_FLAG_INITED);
402 * To finialize the cfs_timer_t (unused)
405 * timer: the cfs_timer to be cleaned up
414 void cfs_timer_done(cfs_timer_t *timer)
421 * To schedule the timer while touching @deadline
424 * timer: the cfs_timer to be freed
425 * dealine: timeout value to wake up the timer
434 void cfs_timer_arm(cfs_timer_t *timer, cfs_time_t deadline)
436 LARGE_INTEGER timeout;
439 KeAcquireSpinLock(&(timer->Lock), &Irql);
440 if (!cfs_is_flag_set(timer->Flags, CFS_TIMER_FLAG_TIMERED)){
442 timeout.QuadPart = (LONGLONG)-1*1000*1000*10/HZ*deadline;
444 if (KeSetTimer(&timer->Timer, timeout, &timer->Dpc )) {
445 cfs_set_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
448 timer->deadline = deadline;
451 KeReleaseSpinLock(&(timer->Lock), Irql);
456 * To discard the timer to be scheduled
459 * timer: the cfs_timer to be discarded
468 void cfs_timer_disarm(cfs_timer_t *timer)
472 KeAcquireSpinLock(&(timer->Lock), &Irql);
473 KeCancelTimer(&(timer->Timer));
474 cfs_clear_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
475 KeReleaseSpinLock(&(timer->Lock), Irql);
481 * To check the timer is scheduled or not
484 * timer: the cfs_timer to be checked
494 int cfs_timer_is_armed(cfs_timer_t *timer)
499 KeAcquireSpinLock(&(timer->Lock), &Irql);
500 if (cfs_is_flag_set(timer->Flags, CFS_TIMER_FLAG_TIMERED)) {
503 KeReleaseSpinLock(&(timer->Lock), Irql);
510 * To query the deadline of the timer
513 * timer: the cfs_timer to be queried
522 cfs_time_t cfs_timer_deadline(cfs_timer_t * timer)
524 return timer->deadline;
528 * daemonize routine stub
531 void cfs_daemonize(char *str)
537 * routine related with sigals
540 cfs_sigset_t cfs_get_blockedsigs()
545 cfs_sigset_t cfs_block_allsigs()
550 cfs_sigset_t cfs_block_sigs(sigset_t bit)
555 void cfs_restore_sigs(cfs_sigset_t old)
559 int cfs_signal_pending(void)
564 void cfs_clear_sigpending(void)
570 ** Initialize routines
574 libcfs_arch_init(void)
579 /* Workground to check the system is MP build or UP build */
580 spin_lock_init(&lock);
582 MPSystem = (int)lock.lock;
583 /* MP build system: it's a real spin, for UP build system, it
584 only raises the IRQL to DISPATCH_LEVEL */
587 /* create slab memory caches for page alloctors */
588 cfs_page_t_slab = cfs_mem_cache_create(
589 "CPGT", sizeof(cfs_page_t), 0, 0 );
591 cfs_page_p_slab = cfs_mem_cache_create(
592 "CPGP", CFS_PAGE_SIZE, 0, 0 );
594 if ( cfs_page_t_slab == NULL ||
595 cfs_page_p_slab == NULL ){
600 rc = init_task_manager();
603 cfs_enter_debugger();
604 KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing task manager ...\n"));
608 /* initialize the proc file system */
612 cfs_enter_debugger();
613 KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing proc fs ...\n"));
614 cleanup_task_manager();
618 /* initialize the tdi data */
619 rc = ks_init_tdi_data();
622 cfs_enter_debugger();
623 KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing tdi ...\n"));
625 cleanup_task_manager();
632 /* destroy the taskslot cache slab */
633 if (cfs_page_t_slab) {
634 cfs_mem_cache_destroy(cfs_page_t_slab);
636 if (cfs_page_p_slab) {
637 cfs_mem_cache_destroy(cfs_page_p_slab);
645 libcfs_arch_cleanup(void)
647 /* finialize the tdi data */
650 /* detroy the whole proc fs tree and nodes */
653 /* destroy the taskslot cache slab */
654 if (cfs_page_t_slab) {
655 cfs_mem_cache_destroy(cfs_page_t_slab);
658 if (cfs_page_p_slab) {
659 cfs_mem_cache_destroy(cfs_page_p_slab);
665 EXPORT_SYMBOL(libcfs_arch_init);
666 EXPORT_SYMBOL(libcfs_arch_cleanup);