Whamcloud - gitweb
LU-459 tests: quiet spurious console/test messages
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-curproc.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
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.
11  *
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).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
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
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * libcfs/libcfs/winnt/winnt-curproc.c
37  *
38  * Impletion of winnt curproc routines.
39  */
40
41 #define DEBUG_SUBSYSTEM S_LNET
42
43 #include <libcfs/libcfs.h>
44
45 /*
46  * Implementation of cfs_curproc API (see portals/include/libcfs/curproc.h)
47  * for Linux kernel.
48  */
49
50 cfs_task_t this_task =
51     { /* umask */ 0,/* blocked*/0, /* pid */ 0, /* pgrp */ 0,
52       /* uid,euid,suid,fsuid */  0, 0, 0, 0, 
53       /* gid_t gid,egid,sgid,fsgid */ 0, 0, 0, 0,
54       /* ngroups*/ 1, /*cgroups*/ 0, /*groups*/ 0,
55       /* group_info */ NULL,
56       /* cap_effective, cap_inheritable, cap_permitted */  0, 0, 0,
57       /* comm */"sysetm\0",
58       /* journal_info */ NULL
59     };
60
61
62 uid_t  cfs_curproc_uid(void)
63 {
64     return this_task.uid;
65 }
66
67 gid_t  cfs_curproc_gid(void)
68 {
69     return this_task.gid;
70 }
71
72 uid_t  cfs_curproc_fsuid(void)
73 {
74     return this_task.fsuid;
75 }
76
77 gid_t cfs_curproc_fsgid(void)
78 {
79     return this_task.fsgid;
80 }
81
82 pid_t cfs_curproc_pid(void)
83 {
84     return cfs_current()->pid;
85 }
86
87 int cfs_curproc_groups_nr(void)
88 {
89     return this_task.ngroups;
90 }
91
92 void cfs_curproc_groups_dump(gid_t *array, int size)
93 {
94     LASSERT(size <= NGROUPS);
95     size = min_t(int, size, this_task.ngroups);
96     memcpy(array, this_task.groups, size * sizeof(__u32));
97 }
98
99 int cfs_curproc_is_in_groups(gid_t gid)
100 {
101     return in_group_p(gid);
102 }
103
104 mode_t cfs_curproc_umask(void)
105 {
106     return this_task.umask;
107 }
108
109 char  *cfs_curproc_comm(void)
110 {
111     return this_task.comm;
112 }
113
114 void cfs_cap_raise(cfs_cap_t cap)
115 {
116         this_task.cap_effective |= (1 << cap);
117 }
118
119 void cfs_cap_lower(cfs_cap_t cap)
120 {
121         this_task.cap_effective &= ~(1 << cap);
122 }
123
124 int cfs_cap_raised(cfs_cap_t cap)
125 {
126         return this_task.cap_effective & (1 << cap);
127 }
128
129 cfs_cap_t cfs_curproc_cap_pack(void) {
130         return this_task.cap_effective;
131 }
132
133 void cfs_curproc_cap_unpack(cfs_cap_t cap) {
134         this_task.cap_effective = cap;
135 }
136
137 int cfs_capable(cfs_cap_t cap)
138 {
139         return TRUE;
140 }
141
142 /*
143  * Implementation of linux task management routines
144  */
145
146
147 /* global of the task manager structure */
148
149 TASK_MAN cfs_win_task_manger;
150
151 /* global idr context */
152 struct idr_context * cfs_win_task_slot_idp = NULL;
153
154 /*
155  *  task slot routiens
156  */
157
158 PTASK_SLOT
159 alloc_task_slot()
160 {
161     PTASK_SLOT task = NULL;
162
163     if (cfs_win_task_manger.slab) {
164         task = cfs_mem_cache_alloc(cfs_win_task_manger.slab, 0);
165     } else {
166         task = cfs_alloc(sizeof(TASK_SLOT), 0);
167     }
168
169     return task;
170 }
171
172 void
173 init_task_slot(PTASK_SLOT task)
174 {
175     memset(task, 0, sizeof(TASK_SLOT));
176     task->Magic = TASKSLT_MAGIC;
177     task->task  = this_task;
178     cfs_init_event(&task->Event, TRUE, FALSE);
179 }
180
181 void
182 cleanup_task_slot(PTASK_SLOT task)
183 {
184     if (task->task.pid) {
185         cfs_idr_remove(cfs_win_task_slot_idp, task->task.pid);
186     }
187
188     if (cfs_win_task_manger.slab) {
189         cfs_mem_cache_free(cfs_win_task_manger.slab, task);
190     } else {
191         cfs_free(task);
192     }
193 }
194
195 /*
196  *  task manager related routines
197  */
198
199 VOID
200 task_manager_notify(
201     IN HANDLE   ProcessId,
202     IN HANDLE   ThreadId,
203     IN BOOLEAN  Create
204     )
205 {
206     PLIST_ENTRY ListEntry = NULL; 
207     PTASK_SLOT  TaskSlot  = NULL;
208
209     cfs_spin_lock(&(cfs_win_task_manger.Lock));
210
211     ListEntry = cfs_win_task_manger.TaskList.Flink;
212     while (ListEntry != (&(cfs_win_task_manger.TaskList))) {
213
214         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
215
216         if (TaskSlot->Pid == ProcessId && TaskSlot->Tid == ThreadId) {
217
218             if (!Create) {
219                 /* remove the taskslot */
220                 RemoveEntryList(&(TaskSlot->Link));
221                 cfs_win_task_manger.NumOfTasks--;
222
223                 /* now free the task slot */
224                 cleanup_task_slot(TaskSlot);
225             }
226         }
227
228         ListEntry = ListEntry->Flink;
229     }
230
231     cfs_spin_unlock(&(cfs_win_task_manger.Lock));
232 }
233
234 int
235 init_task_manager()
236 {
237     NTSTATUS    status;
238
239     /* initialize the content and magic */
240     memset(&cfs_win_task_manger, 0, sizeof(TASK_MAN));
241     cfs_win_task_manger.Magic = TASKMAN_MAGIC;
242
243     /* initialize the spinlock protection */
244     cfs_spin_lock_init(&cfs_win_task_manger.Lock);
245
246     /* create slab memory cache */
247     cfs_win_task_manger.slab = cfs_mem_cache_create(
248         "TSLT", sizeof(TASK_SLOT), 0, 0);
249
250     /* intialize the list header */
251     InitializeListHead(&(cfs_win_task_manger.TaskList));
252
253     cfs_win_task_slot_idp = cfs_idr_init();
254     if (!cfs_win_task_slot_idp) {
255         return -ENOMEM;
256     }
257
258     /* set the thread creation/destruction notify routine */
259     status = PsSetCreateThreadNotifyRoutine(task_manager_notify);
260
261     if (!NT_SUCCESS(status)) {
262         cfs_enter_debugger();
263         /* remove idr context */
264         if (cfs_win_task_slot_idp) {
265             cfs_idr_exit(cfs_win_task_slot_idp);
266             cfs_win_task_slot_idp = NULL;
267         }
268         return cfs_error_code(status);
269     }
270
271     return 0;
272 }
273
274 void
275 cleanup_task_manager()
276 {
277     PLIST_ENTRY ListEntry = NULL; 
278     PTASK_SLOT  TaskSlot  = NULL;
279
280     /* remove ThreadNotifyRoutine: task_manager_notify */
281     PsRemoveCreateThreadNotifyRoutine(task_manager_notify);
282
283     /* remove idr context */
284     if (cfs_win_task_slot_idp) {
285         cfs_idr_exit(cfs_win_task_slot_idp);
286         cfs_win_task_slot_idp = NULL;
287     }
288
289     /* cleanup all the taskslots attached to the list */
290     cfs_spin_lock(&(cfs_win_task_manger.Lock));
291
292     while (!IsListEmpty(&(cfs_win_task_manger.TaskList))) {
293
294         ListEntry = cfs_win_task_manger.TaskList.Flink;
295         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
296
297         RemoveEntryList(ListEntry);
298         cleanup_task_slot(TaskSlot);
299     }
300
301     cfs_spin_unlock(&cfs_win_task_manger.Lock);
302
303     /* destroy the taskslot cache slab */
304     cfs_mem_cache_destroy(cfs_win_task_manger.slab);
305     memset(&cfs_win_task_manger, 0, sizeof(TASK_MAN));
306 }
307
308
309 /*
310  * schedule routines (task slot list)
311  */
312
313
314 cfs_task_t *
315 cfs_current()
316 {
317     HANDLE      Pid = PsGetCurrentProcessId();
318     HANDLE      Tid = PsGetCurrentThreadId();
319     PETHREAD    Tet = PsGetCurrentThread();
320
321     PLIST_ENTRY ListEntry = NULL; 
322     PTASK_SLOT  TaskSlot  = NULL;
323
324     cfs_spin_lock(&(cfs_win_task_manger.Lock));
325
326     ListEntry = cfs_win_task_manger.TaskList.Flink;
327     while (ListEntry != (&(cfs_win_task_manger.TaskList))) {
328
329         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
330         if (TaskSlot->Pid == Pid && TaskSlot->Tid == Tid) {
331             if (TaskSlot->Tet != Tet) {
332
333                 //
334                 // The old thread was already exit. This must be a
335                 // new thread which get the same Tid to the previous.
336                 //
337
338                 TaskSlot->Tet = Tet;
339             }
340             break;
341
342         } else {
343
344             if (TaskSlot->Pid > Pid) {
345                 TaskSlot = NULL;
346                 break;
347             } else if (TaskSlot->Pid == Pid) {
348                 if (TaskSlot->Tid > Tid) {
349                     TaskSlot = NULL;
350                     break;
351                 }
352             }
353             TaskSlot =  NULL;
354         }
355
356         ListEntry = ListEntry->Flink;
357     }
358
359     if (!TaskSlot) {
360
361         /* allocate new task slot */
362         TaskSlot = alloc_task_slot();
363         if (!TaskSlot) {
364             cfs_enter_debugger();
365             goto errorout;
366         }
367
368         /* set task slot IDs */
369         init_task_slot(TaskSlot);
370         TaskSlot->Pid = Pid;
371         TaskSlot->Tid = Tid;
372         TaskSlot->Tet = Tet;
373         TaskSlot->task.pid = (pid_t)cfs_idr_get_new(cfs_win_task_slot_idp, Tet);
374
375         if (ListEntry == (&(cfs_win_task_manger.TaskList))) {
376             //
377             // Empty case or the biggest case, put it to the tail.
378             //
379             InsertTailList(&(cfs_win_task_manger.TaskList), &(TaskSlot->Link));
380         } else {
381             //
382             // Get a slot and smaller than it's tid, put it just before.
383             //
384             InsertHeadList(ListEntry->Blink, &(TaskSlot->Link));
385         }
386
387         cfs_win_task_manger.NumOfTasks++;
388     }
389
390     //
391     // To Check whether he task structures are arranged in the expected order ?
392     //
393
394     {
395         PTASK_SLOT  Prev = NULL, Curr = NULL;
396         
397         ListEntry = cfs_win_task_manger.TaskList.Flink;
398
399         while (ListEntry != (&(cfs_win_task_manger.TaskList))) {
400
401             Curr = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
402             ListEntry = ListEntry->Flink;
403
404             if (Prev) {
405                 if (Prev->Pid > Curr->Pid) {
406                     cfs_enter_debugger();
407                 } else if (Prev->Pid == Curr->Pid) {
408                     if (Prev->Tid > Curr->Tid) {
409                         cfs_enter_debugger();
410                     }
411                 }
412             }
413
414             Prev = Curr;
415         }
416     }
417
418 errorout:
419
420     cfs_spin_unlock(&(cfs_win_task_manger.Lock));
421
422     if (!TaskSlot) {
423         cfs_enter_debugger();
424         return NULL;
425     }
426
427     return (&(TaskSlot->task));
428 }
429
430 /* deschedule for a bit... */
431 void
432 cfs_pause(cfs_duration_t ticks)
433 {
434     cfs_schedule_timeout_and_set_state(CFS_TASK_UNINTERRUPTIBLE, ticks);
435 }
436
437 void
438 cfs_schedule_timeout_and_set_state(cfs_task_state_t state, int64_t time)
439 {
440     cfs_task_t * task = cfs_current();
441     PTASK_SLOT   slot = NULL;
442
443     if (!task) {
444         cfs_enter_debugger();
445         return;
446     }
447
448     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
449     cfs_assert(slot->Magic == TASKSLT_MAGIC);
450
451     if (time == CFS_MAX_SCHEDULE_TIMEOUT) {
452         time = 0;
453     }
454
455     cfs_wait_event_internal(&(slot->Event), time);
456 }
457
458 void
459 cfs_schedule()
460 {
461     cfs_schedule_timeout_and_set_state(CFS_TASK_UNINTERRUPTIBLE, 0);
462 }
463
464 int
465 wake_up_process(
466     cfs_task_t * task
467     )
468 {
469     PTASK_SLOT   slot = NULL;
470
471     if (!task) {
472         cfs_enter_debugger();
473         return 0;
474     }
475
476     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
477     cfs_assert(slot->Magic == TASKSLT_MAGIC);
478
479     cfs_wake_event(&(slot->Event));
480
481     return TRUE;
482 }
483
484 void
485 sleep_on(cfs_waitq_t *waitq)
486 {
487         cfs_waitlink_t link;
488         
489         cfs_waitlink_init(&link);
490         cfs_waitq_add(waitq, &link);
491         cfs_waitq_wait(&link, CFS_TASK_INTERRUPTIBLE);
492         cfs_waitq_del(waitq, &link);
493 }
494
495 EXPORT_SYMBOL(cfs_curproc_uid);
496 EXPORT_SYMBOL(cfs_curproc_pid);
497 EXPORT_SYMBOL(cfs_curproc_gid);
498 EXPORT_SYMBOL(cfs_curproc_fsuid);
499 EXPORT_SYMBOL(cfs_curproc_fsgid);
500 EXPORT_SYMBOL(cfs_curproc_umask);
501 EXPORT_SYMBOL(cfs_curproc_comm);
502 EXPORT_SYMBOL(cfs_curproc_groups_nr);
503 EXPORT_SYMBOL(cfs_curproc_groups_dump);
504 EXPORT_SYMBOL(cfs_curproc_is_in_groups);
505 EXPORT_SYMBOL(cfs_cap_raise);
506 EXPORT_SYMBOL(cfs_cap_lower);
507 EXPORT_SYMBOL(cfs_cap_raised);
508 EXPORT_SYMBOL(cfs_curproc_cap_pack);
509 EXPORT_SYMBOL(cfs_curproc_cap_unpack);
510 EXPORT_SYMBOL(cfs_capable);