Whamcloud - gitweb
Branch HEAD
[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  2008 Sun Microsystems, Inc. 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 /*
47  * Implementation of cfs_curproc API (see portals/include/libcfs/curproc.h)
48  * for Linux kernel.
49  */
50
51 cfs_task_t this_task = 
52     { 0, 0, 0, 0, 0, 0, 0, 
53       0, 0, 0, 0,  1, 0,  0, 0, 0,
54       "sysetm\0" };
55
56
57 uid_t  cfs_curproc_uid(void)
58 {
59     return this_task.uid;
60 }
61
62 gid_t  cfs_curproc_gid(void)
63 {
64     return this_task.gid;
65 }
66
67 uid_t  cfs_curproc_fsuid(void)
68 {
69     return this_task.fsuid;
70 }
71
72 gid_t cfs_curproc_fsgid(void)
73 {
74     return this_task.fsgid;
75 }
76
77 pid_t cfs_curproc_pid(void)
78 {
79     return cfs_current()->pid;
80 }
81
82 int cfs_curproc_groups_nr(void)
83 {
84     return this_task.ngroups;
85 }
86
87 void cfs_curproc_groups_dump(gid_t *array, int size)
88 {
89     LASSERT(size <= NGROUPS);
90     size = min_t(int, size, this_task.ngroups);
91     memcpy(array, this_task.groups, size * sizeof(__u32));
92 }
93
94 int cfs_curproc_is_in_groups(gid_t gid)
95 {
96     return in_group_p(gid);
97 }
98
99 mode_t cfs_curproc_umask(void)
100 {
101     return this_task.umask;
102 }
103
104 char  *cfs_curproc_comm(void)
105 {
106     return this_task.comm;
107 }
108
109 void cfs_cap_raise(cfs_cap_t cap)
110 {
111         this_task.cap_effective |= (1 << cap);
112 }
113
114 void cfs_cap_lower(cfs_cap_t cap)
115 {
116         this_task.cap_effective &= ~(1 << cap);
117 }
118
119 int cfs_cap_raised(cfs_cap_t cap)
120 {
121         return this_task.cap_effective & (1 << cap);
122 }
123
124 cfs_cap_t cfs_curproc_cap_pack(void) {
125         return this_task.cap_effective;
126 }
127
128 void cfs_curproc_cap_unpack(cfs_cap_t cap) {
129         this_task.cap_effective = cap;
130 }
131
132 int cfs_capable(cfs_cap_t cap)
133 {
134         return TRUE;
135 }
136
137 /*
138  * Implementation of linux task management routines
139  */
140
141
142 /* global of the task manager structure */
143
144 TASK_MAN TaskMan;
145
146
147 /*
148  *  task slot routiens
149  */
150
151 PTASK_SLOT
152 alloc_task_slot()
153 {
154     PTASK_SLOT task = NULL;
155
156     if (TaskMan.slab) {
157         task = cfs_mem_cache_alloc(TaskMan.slab, 0);
158     } else {
159         task = cfs_alloc(sizeof(TASK_SLOT), 0);
160     }
161
162     return task;
163 }
164
165 void
166 init_task_slot(PTASK_SLOT task)
167 {
168     memset(task, 0, sizeof(TASK_SLOT));
169     task->Magic = TASKSLT_MAGIC;
170     task->task  = this_task;
171     task->task.pid = (pid_t)PsGetCurrentThreadId();
172     cfs_init_event(&task->Event, TRUE, FALSE);
173 }
174
175
176 void
177 cleanup_task_slot(PTASK_SLOT task)
178 {
179     if (TaskMan.slab) {
180         cfs_mem_cache_free(TaskMan.slab, task);
181     } else {
182         cfs_free(task);
183     }
184 }
185
186 /*
187  *  task manager related routines
188  */
189
190 VOID
191 task_manager_notify(
192     IN HANDLE   ProcessId,
193     IN HANDLE   ThreadId,
194     IN BOOLEAN  Create
195     )
196 {
197     PLIST_ENTRY ListEntry = NULL; 
198     PTASK_SLOT  TaskSlot  = NULL;
199
200     spin_lock(&(TaskMan.Lock));
201
202     ListEntry = TaskMan.TaskList.Flink;
203
204     while (ListEntry != (&(TaskMan.TaskList))) {
205
206         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
207
208         if (TaskSlot->Pid == ProcessId && TaskSlot->Tid == ThreadId) {
209
210             if (Create) {
211 /*
212                 DbgPrint("task_manager_notify: Pid=%xh Tid %xh resued (TaskSlot->Tet = %xh)...\n",
213                          ProcessId, ThreadId, TaskSlot->Tet);
214 */
215             } else {
216                 /* remove the taskslot */
217                 RemoveEntryList(&(TaskSlot->Link));
218                 TaskMan.NumOfTasks--;
219
220                 /* now free the task slot */
221                 cleanup_task_slot(TaskSlot);
222             }
223         }
224
225         ListEntry = ListEntry->Flink;
226     }
227
228     spin_unlock(&(TaskMan.Lock));
229 }
230
231 int
232 init_task_manager()
233 {
234     NTSTATUS    status;
235
236     /* initialize the content and magic */
237     memset(&TaskMan, 0, sizeof(TASK_MAN));
238     TaskMan.Magic = TASKMAN_MAGIC;
239
240     /* initialize the spinlock protection */
241     spin_lock_init(&TaskMan.Lock);
242
243     /* create slab memory cache */
244     TaskMan.slab = cfs_mem_cache_create(
245         "TSLT", sizeof(TASK_SLOT), 0, 0);
246
247     /* intialize the list header */
248     InitializeListHead(&(TaskMan.TaskList));
249
250     /* set the thread creation/destruction notify routine */
251     status = PsSetCreateThreadNotifyRoutine(task_manager_notify);
252
253     if (!NT_SUCCESS(status)) {
254         cfs_enter_debugger();
255     }
256
257     return 0;
258 }
259
260 void
261 cleanup_task_manager()
262 {
263     PLIST_ENTRY ListEntry = NULL; 
264     PTASK_SLOT  TaskSlot  = NULL;
265
266     /* we must stay in system since we succeed to register the
267        CreateThreadNotifyRoutine: task_manager_notify */
268     cfs_enter_debugger();
269
270
271     /* cleanup all the taskslots attached to the list */
272     spin_lock(&(TaskMan.Lock));
273
274     while (!IsListEmpty(&(TaskMan.TaskList))) {
275
276         ListEntry = TaskMan.TaskList.Flink;
277         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
278
279         RemoveEntryList(ListEntry);
280         cleanup_task_slot(TaskSlot);
281     }
282
283     spin_unlock(&TaskMan.Lock);
284
285     /* destroy the taskslot cache slab */
286     cfs_mem_cache_destroy(TaskMan.slab);
287     memset(&TaskMan, 0, sizeof(TASK_MAN));
288 }
289
290
291 /*
292  * schedule routines (task slot list)
293  */
294
295
296 cfs_task_t *
297 cfs_current()
298 {
299     HANDLE      Pid = PsGetCurrentProcessId();
300     HANDLE      Tid = PsGetCurrentThreadId();
301     PETHREAD    Tet = PsGetCurrentThread();
302
303     PLIST_ENTRY ListEntry = NULL; 
304     PTASK_SLOT  TaskSlot  = NULL;
305
306     spin_lock(&(TaskMan.Lock));
307
308     ListEntry = TaskMan.TaskList.Flink;
309
310     while (ListEntry != (&(TaskMan.TaskList))) {
311
312         TaskSlot = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
313
314         if (TaskSlot->Pid == Pid && TaskSlot->Tid == Tid) {
315             if (TaskSlot->Tet != Tet) {
316
317 /*
318                 DbgPrint("cfs_current: Pid=%xh Tid %xh Tet = %xh resued (TaskSlot->Tet = %xh)...\n",
319                          Pid, Tid, Tet, TaskSlot->Tet);
320 */
321                 //
322                 // The old thread was already exit. This must be a
323                 // new thread which get the same Tid to the previous.
324                 //
325
326                 TaskSlot->Tet = Tet;
327             }
328             break;
329
330         } else {
331
332             if ((ULONG)TaskSlot->Pid > (ULONG)Pid) {
333                 TaskSlot = NULL;
334                 break;
335             } else if ((ULONG)TaskSlot->Pid == (ULONG)Pid) {
336                 if ((ULONG)TaskSlot->Tid > (ULONG)Tid) {
337                     TaskSlot = NULL;
338                     break;
339                 }
340             }
341
342             TaskSlot =  NULL;
343         }
344
345         ListEntry = ListEntry->Flink;
346     }
347
348     if (!TaskSlot) {
349
350         TaskSlot = alloc_task_slot();
351
352         if (!TaskSlot) {
353             cfs_enter_debugger();
354             goto errorout;
355         }
356
357         init_task_slot(TaskSlot);
358
359         TaskSlot->Pid = Pid;
360         TaskSlot->Tid = Tid;
361         TaskSlot->Tet = Tet;
362
363         if (ListEntry == (&(TaskMan.TaskList))) {
364             //
365             // Empty case or the biggest case, put it to the tail.
366             //
367             InsertTailList(&(TaskMan.TaskList), &(TaskSlot->Link));
368         } else {
369             //
370             // Get a slot and smaller than it's tid, put it just before.
371             //
372             InsertHeadList(ListEntry->Blink, &(TaskSlot->Link));
373         }
374
375         TaskMan.NumOfTasks++;
376     }
377
378     //
379     // To Check whether he task structures are arranged in the expected order ?
380     //
381
382     {
383         PTASK_SLOT  Prev = NULL, Curr = NULL;
384         
385         ListEntry = TaskMan.TaskList.Flink;
386
387         while (ListEntry != (&(TaskMan.TaskList))) {
388
389             Curr = CONTAINING_RECORD(ListEntry, TASK_SLOT, Link);
390             ListEntry = ListEntry->Flink;
391
392             if (Prev) {
393                 if ((ULONG)Prev->Pid > (ULONG)Curr->Pid) {
394                     cfs_enter_debugger();
395                 } else if ((ULONG)Prev->Pid == (ULONG)Curr->Pid) {
396                     if ((ULONG)Prev->Tid > (ULONG)Curr->Tid) {
397                         cfs_enter_debugger();
398                     }
399                 }
400             }
401
402             Prev = Curr;
403         }
404     }
405
406 errorout:
407
408     spin_unlock(&(TaskMan.Lock));
409
410     if (!TaskSlot) {
411         cfs_enter_debugger();
412         return NULL;
413     }
414
415     return (&(TaskSlot->task));
416 }
417
418 int
419 schedule_timeout(int64_t time)
420 {
421     cfs_task_t * task = cfs_current();
422     PTASK_SLOT   slot = NULL;
423
424     if (!task) {
425         cfs_enter_debugger();
426         return 0;
427     }
428
429     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
430     cfs_assert(slot->Magic == TASKSLT_MAGIC);
431
432     if (time == MAX_SCHEDULE_TIMEOUT) {
433         time = 0;
434     }
435
436     return (cfs_wait_event(&(slot->Event), time) != 0);
437 }
438
439 int
440 schedule()
441 {
442     return schedule_timeout(0);
443 }
444
445 int
446 wake_up_process(
447     cfs_task_t * task
448     )
449 {
450     PTASK_SLOT   slot = NULL;
451
452     if (!task) {
453         cfs_enter_debugger();
454         return 0;
455     }
456
457     slot = CONTAINING_RECORD(task, TASK_SLOT, task);
458     cfs_assert(slot->Magic == TASKSLT_MAGIC);
459
460     cfs_wake_event(&(slot->Event));
461
462     return TRUE;
463 }
464
465 void
466 sleep_on(
467     cfs_waitq_t *waitq
468     )
469 {
470         cfs_waitlink_t link;
471         
472         cfs_waitlink_init(&link);
473         cfs_waitq_add(waitq, &link);
474         cfs_waitq_wait(&link, CFS_TASK_INTERRUPTIBLE);
475         cfs_waitq_del(waitq, &link);
476 }
477
478 EXPORT_SYMBOL(cfs_curproc_uid);
479 EXPORT_SYMBOL(cfs_curproc_pid);
480 EXPORT_SYMBOL(cfs_curproc_gid);
481 EXPORT_SYMBOL(cfs_curproc_fsuid);
482 EXPORT_SYMBOL(cfs_curproc_fsgid);
483 EXPORT_SYMBOL(cfs_curproc_umask);
484 EXPORT_SYMBOL(cfs_curproc_comm);
485 EXPORT_SYMBOL(cfs_curproc_groups_nr);
486 EXPORT_SYMBOL(cfs_curproc_groups_dump);
487 EXPORT_SYMBOL(cfs_curproc_is_in_groups);
488 EXPORT_SYMBOL(cfs_cap_raise);
489 EXPORT_SYMBOL(cfs_cap_lower);
490 EXPORT_SYMBOL(cfs_cap_raised);
491 EXPORT_SYMBOL(cfs_curproc_cap_pack);
492 EXPORT_SYMBOL(cfs_curproc_cap_unpack);
493 EXPORT_SYMBOL(cfs_capable);