1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=4:tabstop=4:
5 * Copyright (c) 2004 Cluster File Systems, Inc.
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or modify it under
10 * the terms of version 2 of the GNU General Public License as published by
11 * the Free Software Foundation. Lustre is distributed in the hope that it
12 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
13 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. You should have received a
15 * copy of the GNU General Public License along with Lustre; if not, write
16 * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
20 #define DEBUG_SUBSYSTEM S_LNET
22 #include <libcfs/libcfs.h>
23 #include <libcfs/kp30.h>
32 * Lustre thread procedure wrapper routine (It's an internal routine)
35 * context: a structure of cfs_thread_context_t, containing
36 * all the necessary parameters
50 cfs_thread_context_t * thread_context =
51 (cfs_thread_context_t *) context;
53 /* Execute the specified function ... */
55 if (thread_context->func) {
56 (thread_context->func)(thread_context->arg);
59 /* Free the context memory */
63 /* Terminate this system thread */
65 PsTerminateSystemThread(STATUS_SUCCESS);
70 * Create a system thread to execute the routine specified
73 * func: function to be executed in the thread
74 * arg: argument transferred to func function
75 * flag: thread creation flags.
78 * int: 0 on success or error codes
84 int cfs_kernel_thread(int (*func)(void *), void *arg, int flag)
86 cfs_handle_t thread = NULL;
88 cfs_thread_context_t * context = NULL;
90 /* Allocate the context to be transferred to system thread */
92 context = cfs_alloc(sizeof(cfs_thread_context_t), CFS_ALLOC_ZERO);
101 /* Create system thread with the cfs_thread_proc wrapper */
103 status = PsCreateSystemThread(
110 if (!NT_SUCCESS(status)) {
115 /* We need translate the nt status to linux error code */
117 return cfs_error_code(status);
121 // Query the thread id of the newly created thread
135 static CFS_DECL_RWSEM(cfs_symbol_lock);
136 CFS_LIST_HEAD(cfs_symbol_list);
138 int MPSystem = FALSE;
142 * To query the specified symbol form the symbol table
145 * name: the symbol name to be queried
148 * If the symbol is in the table, return the address of it.
149 * If not, return NULL.
156 cfs_symbol_get(const char *name)
158 struct list_head *walker;
159 struct cfs_symbol *sym = NULL;
161 down_read(&cfs_symbol_lock);
162 list_for_each(walker, &cfs_symbol_list) {
163 sym = list_entry (walker, struct cfs_symbol, sym_list);
164 if (!strcmp(sym->name, name)) {
169 up_read(&cfs_symbol_lock);
179 * To decrease the reference of the specified symbol
182 * name: the symbol name to be dereferred
192 cfs_symbol_put(const char *name)
194 struct list_head *walker;
195 struct cfs_symbol *sym = NULL;
197 down_read(&cfs_symbol_lock);
198 list_for_each(walker, &cfs_symbol_list) {
199 sym = list_entry (walker, struct cfs_symbol, sym_list);
200 if (!strcmp(sym->name, name)) {
201 LASSERT(sym->ref > 0);
206 up_read(&cfs_symbol_lock);
208 LASSERT(sym != NULL);
213 * cfs_symbol_register
214 * To register the specified symbol infromation
217 * name: the symbol name to be dereferred
218 * value: the value that the symbol stands for
224 * Zero: Succeed to register
225 * Non-Zero: Fail to register the symbol
229 cfs_symbol_register(const char *name, const void *value)
231 struct list_head *walker;
232 struct cfs_symbol *sym = NULL;
233 struct cfs_symbol *new = NULL;
235 new = cfs_alloc(sizeof(struct cfs_symbol), CFS_ALLOC_ZERO);
239 strncpy(new->name, name, CFS_SYMBOL_LEN);
240 new->value = (void *)value;
242 CFS_INIT_LIST_HEAD(&new->sym_list);
244 down_write(&cfs_symbol_lock);
245 list_for_each(walker, &cfs_symbol_list) {
246 sym = list_entry (walker, struct cfs_symbol, sym_list);
247 if (!strcmp(sym->name, name)) {
248 up_write(&cfs_symbol_lock);
250 return 0; // alreay registerred
253 list_add_tail(&new->sym_list, &cfs_symbol_list);
254 up_write(&cfs_symbol_lock);
260 * cfs_symbol_unregister
261 * To unregister/remove the specified symbol
264 * name: the symbol name to be dereferred
274 cfs_symbol_unregister(const char *name)
276 struct list_head *walker;
277 struct list_head *nxt;
278 struct cfs_symbol *sym = NULL;
280 down_write(&cfs_symbol_lock);
281 list_for_each_safe(walker, nxt, &cfs_symbol_list) {
282 sym = list_entry (walker, struct cfs_symbol, sym_list);
283 if (!strcmp(sym->name, name)) {
284 LASSERT(sym->ref == 0);
285 list_del (&sym->sym_list);
290 up_write(&cfs_symbol_lock);
295 * To clean all the symbols
310 struct list_head *walker;
311 struct cfs_symbol *sym = NULL;
313 down_write(&cfs_symbol_lock);
314 list_for_each(walker, &cfs_symbol_list) {
315 sym = list_entry (walker, struct cfs_symbol, sym_list);
316 LASSERT(sym->ref == 0);
317 list_del (&sym->sym_list);
320 up_write(&cfs_symbol_lock);
331 /* Timer dpc procedure */
336 IN PVOID DeferredContext,
337 IN PVOID SystemArgument1,
338 IN PVOID SystemArgument2)
343 timer = (cfs_timer_t *) DeferredContext;
346 KeAcquireSpinLock(&(timer->Lock), &Irql);
347 cfs_clear_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
348 KeReleaseSpinLock(&(timer->Lock), Irql);
350 /* call the user specified timer procedure */
351 timer->proc((unsigned long)(timer->arg));
356 * To initialize the cfs_timer_t
359 * timer: the cfs_timer to be initialized
360 * func: the timer callback procedure
361 * arg: argument for the callback proc
370 void cfs_timer_init(cfs_timer_t *timer, void (*func)(unsigned long), void *arg)
372 memset(timer, 0, sizeof(cfs_timer_t));
377 KeInitializeSpinLock(&(timer->Lock));
378 KeInitializeTimer(&timer->Timer);
379 KeInitializeDpc (&timer->Dpc, cfs_timer_dpc_proc, timer);
381 cfs_set_flag(timer->Flags, CFS_TIMER_FLAG_INITED);
386 * To finialize the cfs_timer_t (unused)
389 * timer: the cfs_timer to be cleaned up
398 void cfs_timer_done(cfs_timer_t *timer)
405 * To schedule the timer while touching @deadline
408 * timer: the cfs_timer to be freed
409 * dealine: timeout value to wake up the timer
418 void cfs_timer_arm(cfs_timer_t *timer, cfs_time_t deadline)
420 LARGE_INTEGER timeout;
423 KeAcquireSpinLock(&(timer->Lock), &Irql);
424 if (!cfs_is_flag_set(timer->Flags, CFS_TIMER_FLAG_TIMERED)){
426 timeout.QuadPart = (LONGLONG)-1*1000*1000*10/HZ*deadline;
428 if (KeSetTimer(&timer->Timer, timeout, &timer->Dpc )) {
429 cfs_set_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
432 timer->deadline = deadline;
435 KeReleaseSpinLock(&(timer->Lock), Irql);
440 * To discard the timer to be scheduled
443 * timer: the cfs_timer to be discarded
452 void cfs_timer_disarm(cfs_timer_t *timer)
456 KeAcquireSpinLock(&(timer->Lock), &Irql);
457 KeCancelTimer(&(timer->Timer));
458 cfs_clear_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
459 KeReleaseSpinLock(&(timer->Lock), Irql);
465 * To check the timer is scheduled or not
468 * timer: the cfs_timer to be checked
478 int cfs_timer_is_armed(cfs_timer_t *timer)
483 KeAcquireSpinLock(&(timer->Lock), &Irql);
484 if (cfs_is_flag_set(timer->Flags, CFS_TIMER_FLAG_TIMERED)) {
487 KeReleaseSpinLock(&(timer->Lock), Irql);
494 * To query the deadline of the timer
497 * timer: the cfs_timer to be queried
506 cfs_time_t cfs_timer_deadline(cfs_timer_t * timer)
508 return timer->deadline;
512 * daemonize routine stub
515 void cfs_daemonize(char *str)
521 * routine related with sigals
524 cfs_sigset_t cfs_get_blockedsigs()
529 cfs_sigset_t cfs_block_allsigs()
534 cfs_sigset_t cfs_block_sigs(sigset_t bit)
539 void cfs_restore_sigs(cfs_sigset_t old)
543 int cfs_signal_pending(void)
548 void cfs_clear_sigpending(void)
554 ** Initialize routines
558 libcfs_arch_init(void)
563 /* Workground to check the system is MP build or UP build */
564 spin_lock_init(&lock);
566 MPSystem = (int)lock.lock;
567 /* MP build system: it's a real spin, for UP build system, it
568 only raises the IRQL to DISPATCH_LEVEL */
571 /* create slab memory caches for page alloctors */
572 cfs_page_t_slab = cfs_mem_cache_create(
573 "CPGT", sizeof(cfs_page_t), 0, 0 );
575 cfs_page_p_slab = cfs_mem_cache_create(
576 "CPGP", CFS_PAGE_SIZE, 0, 0 );
578 if ( cfs_page_t_slab == NULL ||
579 cfs_page_p_slab == NULL ){
584 rc = init_task_manager();
587 cfs_enter_debugger();
588 KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing task manager ...\n"));
592 /* initialize the proc file system */
596 cfs_enter_debugger();
597 KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing proc fs ...\n"));
598 cleanup_task_manager();
602 /* initialize the tdi data */
603 rc = ks_init_tdi_data();
606 cfs_enter_debugger();
607 KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing tdi ...\n"));
609 cleanup_task_manager();
616 /* destroy the taskslot cache slab */
617 if (cfs_page_t_slab) {
618 cfs_mem_cache_destroy(cfs_page_t_slab);
620 if (cfs_page_p_slab) {
621 cfs_mem_cache_destroy(cfs_page_p_slab);
629 libcfs_arch_cleanup(void)
631 /* finialize the tdi data */
634 /* detroy the whole proc fs tree and nodes */
637 /* destroy the taskslot cache slab */
638 if (cfs_page_t_slab) {
639 cfs_mem_cache_destroy(cfs_page_t_slab);
642 if (cfs_page_p_slab) {
643 cfs_mem_cache_destroy(cfs_page_p_slab);
649 EXPORT_SYMBOL(libcfs_arch_init);
650 EXPORT_SYMBOL(libcfs_arch_cleanup);