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>
31 * Lustre thread procedure wrapper routine (It's an internal routine)
34 * context: a structure of cfs_thread_context_t, containing
35 * all the necessary parameters
49 cfs_thread_context_t * thread_context =
50 (cfs_thread_context_t *) context;
52 /* Execute the specified function ... */
54 if (thread_context->func) {
55 (thread_context->func)(thread_context->arg);
58 /* Free the context memory */
62 /* Terminate this system thread */
64 PsTerminateSystemThread(STATUS_SUCCESS);
69 * Create a system thread to execute the routine specified
72 * func: function to be executed in the thread
73 * arg: argument transferred to func function
74 * flag: thread creation flags.
77 * int: 0 on success or error codes
83 int cfs_kernel_thread(int (*func)(void *), void *arg, int flag)
85 cfs_handle_t thread = NULL;
87 cfs_thread_context_t * context = NULL;
89 /* Allocate the context to be transferred to system thread */
91 context = cfs_alloc(sizeof(cfs_thread_context_t), CFS_ALLOC_ZERO);
100 /* Create system thread with the cfs_thread_proc wrapper */
102 status = PsCreateSystemThread(
109 if (!NT_SUCCESS(status)) {
114 /* We need translate the nt status to linux error code */
116 return cfs_error_code(status);
120 // Query the thread id of the newly created thread
134 static CFS_DECL_RWSEM(cfs_symbol_lock);
135 CFS_LIST_HEAD(cfs_symbol_list);
137 int MPSystem = FALSE;
141 * To query the specified symbol form the symbol table
144 * name: the symbol name to be queried
147 * If the symbol is in the table, return the address of it.
148 * If not, return NULL.
155 cfs_symbol_get(const char *name)
157 struct list_head *walker;
158 struct cfs_symbol *sym = NULL;
160 down_read(&cfs_symbol_lock);
161 list_for_each(walker, &cfs_symbol_list) {
162 sym = list_entry (walker, struct cfs_symbol, sym_list);
163 if (!strcmp(sym->name, name)) {
168 up_read(&cfs_symbol_lock);
178 * To decrease the reference of the specified symbol
181 * name: the symbol name to be dereferred
191 cfs_symbol_put(const char *name)
193 struct list_head *walker;
194 struct cfs_symbol *sym = NULL;
196 down_read(&cfs_symbol_lock);
197 list_for_each(walker, &cfs_symbol_list) {
198 sym = list_entry (walker, struct cfs_symbol, sym_list);
199 if (!strcmp(sym->name, name)) {
200 LASSERT(sym->ref > 0);
205 up_read(&cfs_symbol_lock);
207 LASSERT(sym != NULL);
212 * cfs_symbol_register
213 * To register the specified symbol infromation
216 * name: the symbol name to be dereferred
217 * value: the value that the symbol stands for
223 * Zero: Succeed to register
224 * Non-Zero: Fail to register the symbol
228 cfs_symbol_register(const char *name, const void *value)
230 struct list_head *walker;
231 struct cfs_symbol *sym = NULL;
232 struct cfs_symbol *new = NULL;
234 new = cfs_alloc(sizeof(struct cfs_symbol), CFS_ALLOC_ZERO);
238 strncpy(new->name, name, CFS_SYMBOL_LEN);
239 new->value = (void *)value;
241 CFS_INIT_LIST_HEAD(&new->sym_list);
243 down_write(&cfs_symbol_lock);
244 list_for_each(walker, &cfs_symbol_list) {
245 sym = list_entry (walker, struct cfs_symbol, sym_list);
246 if (!strcmp(sym->name, name)) {
247 up_write(&cfs_symbol_lock);
249 return 0; // alreay registerred
252 list_add_tail(&new->sym_list, &cfs_symbol_list);
253 up_write(&cfs_symbol_lock);
259 * cfs_symbol_unregister
260 * To unregister/remove the specified symbol
263 * name: the symbol name to be dereferred
273 cfs_symbol_unregister(const char *name)
275 struct list_head *walker;
276 struct list_head *nxt;
277 struct cfs_symbol *sym = NULL;
279 down_write(&cfs_symbol_lock);
280 list_for_each_safe(walker, nxt, &cfs_symbol_list) {
281 sym = list_entry (walker, struct cfs_symbol, sym_list);
282 if (!strcmp(sym->name, name)) {
283 LASSERT(sym->ref == 0);
284 list_del (&sym->sym_list);
289 up_write(&cfs_symbol_lock);
294 * To clean all the symbols
309 struct list_head *walker;
310 struct cfs_symbol *sym = NULL;
312 down_write(&cfs_symbol_lock);
313 list_for_each(walker, &cfs_symbol_list) {
314 sym = list_entry (walker, struct cfs_symbol, sym_list);
315 LASSERT(sym->ref == 0);
316 list_del (&sym->sym_list);
319 up_write(&cfs_symbol_lock);
330 /* Timer dpc procedure */
335 IN PVOID DeferredContext,
336 IN PVOID SystemArgument1,
337 IN PVOID SystemArgument2)
342 timer = (cfs_timer_t *) DeferredContext;
345 KeAcquireSpinLock(&(timer->Lock), &Irql);
346 cfs_clear_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
347 KeReleaseSpinLock(&(timer->Lock), Irql);
349 /* call the user specified timer procedure */
350 timer->proc((unsigned long)(timer->arg));
355 * To initialize the cfs_timer_t
358 * timer: the cfs_timer to be initialized
359 * func: the timer callback procedure
360 * arg: argument for the callback proc
369 void cfs_timer_init(cfs_timer_t *timer, void (*func)(unsigned long), void *arg)
371 memset(timer, 0, sizeof(cfs_timer_t));
376 KeInitializeSpinLock(&(timer->Lock));
377 KeInitializeTimer(&timer->Timer);
378 KeInitializeDpc (&timer->Dpc, cfs_timer_dpc_proc, timer);
380 cfs_set_flag(timer->Flags, CFS_TIMER_FLAG_INITED);
385 * To finialize the cfs_timer_t (unused)
388 * timer: the cfs_timer to be cleaned up
397 void cfs_timer_done(cfs_timer_t *timer)
404 * To schedule the timer while touching @deadline
407 * timer: the cfs_timer to be freed
408 * dealine: timeout value to wake up the timer
417 void cfs_timer_arm(cfs_timer_t *timer, cfs_time_t deadline)
419 LARGE_INTEGER timeout;
422 KeAcquireSpinLock(&(timer->Lock), &Irql);
423 if (!cfs_is_flag_set(timer->Flags, CFS_TIMER_FLAG_TIMERED)){
425 timeout.QuadPart = (LONGLONG)-1*1000*1000*10/HZ*deadline;
427 if (KeSetTimer(&timer->Timer, timeout, &timer->Dpc )) {
428 cfs_set_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
431 timer->deadline = deadline;
434 KeReleaseSpinLock(&(timer->Lock), Irql);
439 * To discard the timer to be scheduled
442 * timer: the cfs_timer to be discarded
451 void cfs_timer_disarm(cfs_timer_t *timer)
455 KeAcquireSpinLock(&(timer->Lock), &Irql);
456 KeCancelTimer(&(timer->Timer));
457 cfs_clear_flag(timer->Flags, CFS_TIMER_FLAG_TIMERED);
458 KeReleaseSpinLock(&(timer->Lock), Irql);
464 * To check the timer is scheduled or not
467 * timer: the cfs_timer to be checked
477 int cfs_timer_is_armed(cfs_timer_t *timer)
482 KeAcquireSpinLock(&(timer->Lock), &Irql);
483 if (cfs_is_flag_set(timer->Flags, CFS_TIMER_FLAG_TIMERED)) {
486 KeReleaseSpinLock(&(timer->Lock), Irql);
493 * To query the deadline of the timer
496 * timer: the cfs_timer to be queried
505 cfs_time_t cfs_timer_deadline(cfs_timer_t * timer)
507 return timer->deadline;
511 * daemonize routine stub
514 void cfs_daemonize(char *str)
520 * routine related with sigals
523 cfs_sigset_t cfs_get_blockedsigs()
528 cfs_sigset_t cfs_block_allsigs()
533 cfs_sigset_t cfs_block_sigs(sigset_t bit)
538 void cfs_restore_sigs(cfs_sigset_t old)
542 int cfs_signal_pending(void)
547 void cfs_clear_sigpending(void)
553 ** Initialize routines
557 libcfs_arch_init(void)
562 /* Workground to check the system is MP build or UP build */
563 spin_lock_init(&lock);
565 MPSystem = (int)lock.lock;
566 /* MP build system: it's a real spin, for UP build system, it
567 only raises the IRQL to DISPATCH_LEVEL */
570 /* create slab memory caches for page alloctors */
571 cfs_page_t_slab = cfs_mem_cache_create(
572 "CPGT", sizeof(cfs_page_t), 0, 0 );
574 cfs_page_p_slab = cfs_mem_cache_create(
575 "CPGP", CFS_PAGE_SIZE, 0, 0 );
577 if ( cfs_page_t_slab == NULL ||
578 cfs_page_p_slab == NULL ){
583 rc = init_task_manager();
586 cfs_enter_debugger();
587 KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing task manager ...\n"));
591 /* initialize the proc file system */
595 cfs_enter_debugger();
596 KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing proc fs ...\n"));
597 cleanup_task_manager();
601 /* initialize the tdi data */
602 rc = ks_init_tdi_data();
605 cfs_enter_debugger();
606 KdPrint(("winnt-prim.c:libcfs_arch_init: error initializing tdi ...\n"));
608 cleanup_task_manager();
615 /* destroy the taskslot cache slab */
616 if (cfs_page_t_slab) {
617 cfs_mem_cache_destroy(cfs_page_t_slab);
619 if (cfs_page_p_slab) {
620 cfs_mem_cache_destroy(cfs_page_p_slab);
628 libcfs_arch_cleanup(void)
630 /* finialize the tdi data */
633 /* detroy the whole proc fs tree and nodes */
636 /* destroy the taskslot cache slab */
637 if (cfs_page_t_slab) {
638 cfs_mem_cache_destroy(cfs_page_t_slab);
641 if (cfs_page_p_slab) {
642 cfs_mem_cache_destroy(cfs_page_p_slab);
648 EXPORT_SYMBOL(libcfs_arch_init);
649 EXPORT_SYMBOL(libcfs_arch_cleanup);